Code Monkey home page Code Monkey logo

tileboard's Introduction

TileBoard

This is a simple yet highly customizable dashboard for Home Assistant. The main goal of this project was to create a simple dashboard with an easy way to edit and add functionality with minimum knowledge of javascript and html. Should you have any ideas or questions please post them on the home-assistant forum or create an issue on github.

Links

Screenshots

screen screen screen screen

How to use

There are a couple of alternative ways of running TileBoard. The options are listed in the recommended order. First being the easiest and the most user friendly.

Run as a Home Assistant addon

By far the easiest option that also provides auto-update through Home Assistant Supervisor.

Installation instructions: refer to https://github.com/resoai/TileBoard-addon/blob/main/README.md#installation

Check the instructions within the addon on how to edit and customize the configuration.

Run within a standalone server through Docker

Runs a standalone local HTTP server, independently from the Home Assistant itself.

Setup instructions: refer to https://github.com/resoai/TileBoard/blob/master/docker/README.md

Run within the public Home Assistant www directory

  1. Download the latest release zip file (Tileboard.zip) from https://github.com/resoai/TileBoard/releases and unpack to a directory of your choice. (Alternatively you can checkout the repo and build the app manually. Check CONTRIBUTING for more info.)
  2. In chosen directory rename config.example.js to config.js and adjust it for your needs
  3. Optionally create an empty styles/custom.css file. Everything will work without it but there will be a network request error logged in the console which can be annoying to some.
  4. Create a directory called tileboard inside www directory in HA's config path and copy all unpacked files there.
  5. TileBoard will be available at http://HASS_IP:8123/local/tileboard/index.html and will prompt you for your login credentials after restarting Home Assistant.

!!!WARNING!!!

Files served from the www folder (/local/ url), aren't protected by the Home Assistant authentication. Files stored in this folder, if the URL is known, can be accessed by anybody without authentication. Please make sure that your HA instance is not exposed via Internet or at least that long-lived token is not hardcoded in the config.

Configure

config.js will initialize a global CONFIG object. If you want to have several config files, you can create another one next to config.js and name it for example bedroom.js. The specific config will be available at http://HASS_IP:8123/local/tileboard/index.html?config=bedroom.

This config object has the following fields:

var CONFIG = {
   /* customTheme: specify a custom theme for your dashboard
    * Valid options: null, CUSTOM_THEMES.TRANSPARENT, CUSTOM_THEMES.MATERIAL, CUSTOM_THEMES.MOBILE, CUSTOM_THEMES.COMPACT, CUSTOM_THEMES.HOMEKIT, CUSTOM_THEMES.WINPHONE, CUSTOM_THEMES.WIN95 or a custom theme you have created
    * Default: null. Array supported
    */
   customTheme: null,
   /* transition: The transition effect used between Pages
    * Valid options: TRANSITIONS.ANIMATED, TRANSITIONS.ANIMATED_GPU, TRANSITIONS.SIMPLE
    */
   transition: TRANSITIONS.ANIMATED,
   /* tileSize: The default size (in pixels) of a tile */
   tileSize: Number,
   /* tileMargin: The default margin (in pixels) between tiles */
   tileMargin: Number,
   /* entitySize: Enum size of tile's content (SMALL, NORMAL, BIG)*/
   entitySize: ENTITY_SIZES.NORMAL,
   /* groupMarginCss: CSS margin statement to override the default margin for groups */
   groupMarginCss: '20px 40px',
   /* serverUrl: The URL to your HomeAssistant server */
   serverUrl: 'http://hassio.local:8123',
   /* wsUrl: The URL to your HomeAssistant Websocket connection.
    * If HomeAssistant is behind SSL, replace ws:// with wss://
    */
   wsUrl: 'ws://hassio.local:8123/api/websocket',

   /* authToken: Optional Long live token that you can create in your HomeAssistant. You should never add this if HA is exposed via internet.
    */
   authToken: null,
   /* pingConnection: Set to false disable pinging of the websocket connection.
    * Otherwise, a ping will be sent every five seconds, and if a response is not received in 3 seconds,
    * a reconnect will be attempted. If not included in the config file, setting defaults to true.
    */
   pingConnection: true,
   /* locale: locale used for date and number formats - available locales: it, de, es, fr, pt, ru, nl, pl, en-gb, en-us (default).
    * The system uses localization files from the package angular-i18n.
    * You can add your own locale, if it is not included already, by adding the corresponding file from the angular-i18n
    * package into the 'locales' folder (rename the file so that the file name has format locale_code.js).
    */
   locale: 'en-us',
   /* debug: Toggle for extra debugging information.
    * If enabled, will print info about state changes and entities to console.
    */
   debug: Boolean,
   /* timeFormat: 12 for AM/PM marker, 24 for 24 hour time (default) */
   timeFormat: Number,

   /* googleApiKey: Google API key is required if you are using device tracker tiles along with Google Maps.
    * More info here: https://developers.google.com/maps/documentation/maps-static/usage-and-billing
    */
   googleApiKey: null,
   /* A Mapbox token is required if you are using device tracker tiles along with Mapbox.
    * More info here: https://www.mapbox.com/maps/
    */
   mapboxToken: null,
   /* mapboxStyle: Enter a style URL to change the mapbox style for device tracker tiles.
    * The format of the url is: mapbox://styles/username/style-id
    * If no style URL is entered, the style will default to mapbox/streets-v11.
    */
   mapboxStyle: null,
   /* menuPosition: LEFT (default) or BOTTOM */
   menuPosition: MENU_POSITIONS.LEFT,
   /* hideScrollbar: Hiding horizontal scrollbar */
   hideScrollbar: false,

   /* groupsAlign: Align groups HORIZONTALLY (default) VERTICALLY or GRID
    * The GRID alignment allows you to divide the groups on several lines; in this case it is necessary
    * to specify the row index on which you want to place the group. Each row will contain all the groups
    * with the corresponding index for which the maximum width of the screen will be that of the widest row.
    * With this alignment you will be able to use the screen space to the maximum without having
    * to define groups with a very large height. Group 'row' setting is ignored for HORIZONTALLY and VERTICALLY alignments
    * GRID alignment is not available for MOBILE and WINPHONE themes; if selected fallback to HORIZONTALLY alignment */
   groupsAlign: GROUP_ALIGNS.HORIZONTALLY,

   /* Called when connected to API and fetched the state.
    * Can be called multiple times in case of reconnecting.
    */
   onReady: function () {},

   /* pages: A list of page objects. See documentation on Pages below */
   pages: [],
   /* events: A list of events. See documentation on Events below */
   events: [],
   /* screensaver: A digital picture frame with a clock. Appears when
    * the dashboard has been idle
    * https://github.com/resoai/TileBoard/wiki/Screensaver-configuration
    * (optional)
    */
   screensaver: {
     /* timeout: Idle time (in seconds) before the screensaver will show */
     timeout: 300,
     /* slidesTimeout: Amount of time (in seconds) to show each slide */
     slidesTimeout: 10,

     styles: { fontSize: '40px' },

     /* read more in wiki */
     leftBottom: [{ type: SCREENSAVER_ITEMS.DATETIME }],
     /* slides: Array of paths to pictures and, optionally, associated CSS classes. */
     slides: [
       {bg: 'images/bg1.jpeg', classes:['-slide1']},
       {bg: 'images/bg2.png', classes:['-slide2']},
       {bg: 'images/bg3.jpg', classes:['-slide3']}
     ]
   },

   /* header: object of header. Will be applied globally
    * https://github.com/resoai/TileBoard/wiki/Header-configuration
    * (optional)
    */
   header: DEFAULT_HEADER,

   /* footer: Matching functionality of header, but at the bottom instead of the top
    * https://github.com/resoai/TileBoard/wiki/Header-configuration
    * (optional)
    */
   footer: DEFAULT_HEADER,
}

Pages

Page object can have the following fields:

{
  /* title: The page title (not currently used) */
  title: 'Page title',
  /* bg: Link to the background image */
  bg: 'images/bg1.jpeg',
  /* icon: Page icon for the side menu */
  icon: 'mdi-home-outline', // icon of page (for the side menu)
  /* header: object of header for current page
   * https://github.com/resoai/TileBoard/wiki/Header-configuration
   */
  header: DEFAULT_HEADER,
  /* tileSize: Override the global tileSize value for the current page
     (optional)
   */
  tileSize: Number,
  /* groupMarginCss: Override global groupMarginCss for the current page
   * (optional)
   */
  groupMarginCss: '20px 40px',
  /* hidden: hide page (optional)
   * can be boolean or function that return boolean
   */
  hidden: Boolean | Function,
  /* groups: A list of tile groups. See documentation on Tile Groups below */
  groups: [] // list of tile groups
}

Tile Groups

We divide tiles (cells) into groups on every page. Group object can have the following fields:

{
  /* title: Title to display above the group */
  title: 'Group title',
  /* width: Number of tiles horizontally
   * (optional) Can be calculated automatically
   */
  width: 3,
  /* height: Number of tiles vertically
   * (optional) Can be calculated automatically
   */
  height: 4,
  /* row: Used for positioning the group when using GRID alignment. See description in 'groupsAlign'.
   * (optional) default = 0
   */
  row: 0,
  /* groupMarginCss: Override default margin of tiles for the current group
   * (optional)
   */
  groupMarginCss: '20px 40px',
  /* custom function called on initial layout and when the items are added or removed dynamically.
   * Can be used to adjust items size/position if implementing some dynamic layouts, for example.
   * (optional)
   */
  onLayout: function(page, group) {},
  /* hidden: hide group (optional)
   * can be boolean or function that return boolean
   */
  hidden: Boolean | Function,
  /* items: A list of Tile objects. See documentation on Tiles below */
  items: [],
}

Tiles

Tile Object. Click here for some real-life examples

{
  /* position: The x,y position of the tile inside the group */
  position: [1, 0],
  /* type: The type of a tile. Valid types are listed below */
  type: TYPES.DEVICE_TRACKER,
  /* id: The entity_id of the device from HomeAssistant (e.g. switch.xyz or light.family_room) */
  id: 'device_tracker.google_maps_228',
  // OPTIONAL
  /* title: Title for the entity. It will use the friendly_name from HomeAssistant if not specified
   * (optional)
   */
  title: 'Tile title',
  /* subtitle: A subtitle to display on the tile
   * (optional)
   */
  subtitle: 'Tile subtitle', // subtitle
  /* width: How many tiles wide this tile should be
   * (optional) (default=1)
   */
  width: 2,
  /* height: How many tiles tall this tile should be
   * (optional) (default=1)
   */
  height: 2,
  /* states: Map a state from HomeAssistant to a different value for TileBoard to display.
   * (optional)
   */
  states: {on: 'Enabled', off: 'Disabled'}, // Object example
  states: function (item, entity) {return entity.state}, // Function example
  /* state: Set a custom state for the tile.
   * (optional)
   */
  state: 'Working', // String example
  state: function (item, entity) {return entity.state}, // Function example
  state: false, // Set to false to disable state
  /* icons: Set the icon for a tile
   * You can use any of the material design icons from https://materialdesignicons.com/
   * as long as they have been published in the [latest npm package](https://github.com/templarian/materialdesign-svg).
   * Use an object or function to map states to icons
   * Note: handling differs for Weather tile. See details in TILE_EXAMPLES.md#weather.
   */
  icons: {on: "mdi-volume-high", off: "mdi-volume-off"}, // Object example
  icons: function (item, entity) {return entity.attributes.icon}, // Function example
  /* icon: Set a static icon for a tile
   * You can use any of the material design icons from https://materialdesignicons.com/
   * as long as they have been published in the [latest npm package](https://github.com/templarian/materialdesign-svg).
   * Note: handling differs for Weather tile. See details in TILE_EXAMPLES.md#weather.
   */
  icon: 'mdi-phone',
  /* customHtml: Replace the icon by a custom HTML content
   * If you define this option, simple tiles will not show the icon. They will show your custom HTML instead.
   * You can use an anonymous function here, or a string that will be interpreted as a template
   */
  customHtml: function (item, entity) {return '<b>' + entity.state + '</b>';},
  customHtml: '<b>&group.lights.state</b>',
  /* bg: Link to a background image for the tile
   * @ and & prefixes are explained below
   */
  bg: '@attributes.entity_picture',
  /* bgSuffix: Same as bg, but with the serverUrl included */
  bgSuffix: '@attributes.entity_picture',
  /* bgOpacity: A decimal between 0 and 1 for the background opacity */
  bgOpacity: 0.5,
  /* theme: Override default theme for the tile */
  theme: TYPES.SWITCH,
  /* slides: A list of slide images to use for the background
   * Currently a maximum of 3 slides are supported
   * (optional)
   */
  slides: [{}, {bg: 'images/slide.jpg'}],

  /* action: Define a custom action on click
   * You can override the default action for any tile type.
   * This function will be evaluated, when the user clicks the tile.
   * Set this to false to disable the default action.
   */
  action: function(item, entity) {return this.$scope.openPopupIframe(item, entity);}
  action: false,
  /* secondaryAction: Define a custom secondary action (on long press)
   * You can override the default secondary action for any tile type.
   * This function will be evaluated, when the user long-presses the tile.
   * Set this to false to disable the default secondary action.
   */
  secondaryAction: function(item, entity) {return this.$scope.openPopupIframe(item, entity);}
  secondaryAction: false,

  /* hidden: hide tile (optional)
   * can be boolean or function that return boolean
   */
  hidden: Boolean | Function,
  /*** TILE SPECIFIC SETTINGS ***/
  /** type: SCRIPT **/
  /* variables: Provides extra variables to the script
   * Can be a function which will be evaluated when script is called.
   */
  variables: {},
  variables: function(item, entity) {return { dynamicVar: true };},
  /** type: SENSOR **/
  /* value: Override sensor value */
  value: '&sensor.bathroom_temp.state',
  /* unit: Override default unit of measurement */
  unit: 'kWh',
  /* filter: Function for filtering/formatting the entity value
   * Is used by default to format a timestamp as time ago, e.g., for the uptime sensor.
   */
  filter: function (value, item, entity) {return Math.round(value);},
  filter: function (value, item, entity) {return timeAgo(value, true);}, // true = exclude the word 'ago'
  /** type: DEVICE_TRACKER **/
  /* slidesDelay: Delay before slide animation starts (optional) */
  slidesDelay: 2,
  /* map: Map provider for showing position inside tile
   * Valid options: 'google', 'mapbox', 'yandex'
   */
  map: 'google',

  /* zoomLevels: zoom levels of map in slides
   * left only one if you what one slide (e.g. [9])
   * (optional)
   */
  zoomLevels: [9, 13],

  /* hideEntityPicture: hide entity picture if you want only maps */
  hideEntityPicture: false,
  /** type: TEXT_LIST **/
  /* list: List of objects with a title, icon, and value */
  list: [{title: 'Kitchen temp', icon: 'mdi-home', value: '&sensor.kitchen_temp.state'}],
  /** type: MEDIA_PLAYER **/
  /* hideSource: Whether the source selector should be hidden
   * Value options: true, false
   */
  hideSource: false,
  /* textSource: localized/customized text for 'Source'
   * (optional)
   */
  textSource: 'Audio Input',
  /** type: SLIDER **/
  /* filter: Function for filtering/formatting the value */
  filter: function (value) {return value},
  /* button: Puts slider at the bottom
   * Valid options: true, false
   */
  bottom: true,
  /* slider: Object with slider config. See slider documentation below */
  slider: {}
  /** type: CAMERA **/
  /* bgSize: CSS background-size property */
   bgSize: 'cover',  // 'cover', 'contain', 'auto' (defaults to 'cover')
   /* filter: Function for filtering/formatting the camera URL */
   filter: function (url) {return url},
   /* fullscreen: object of type CAMERA to show it in fullscreen */
   fullscreen: {},
   /* refresh: Number in milliseconds (or function returning a time) to set the
    * interval for refreshing the camera image
    */
   refresh: Number || Function,
    /* hideFromList: hide camera from the list in the popup, defaults to false */
   hideFromList: true,
   /** type: LIGHT **/
   /* sliders: list of slider object. See slider documentation below */
   sliders: [{}],
   /* colorpicker: whether or not the color picker should be shown.
    * Valid options: true, false, function. Default: auto-detected
    */
   colorpicker: false,
   /** type: POPUP_IFRAME **/
   url: String || Function,
   /* optional */
   iframeStyles: Object || Function,
   /* optional */
   iframeClasses: Array || String || Function,
   /** type: DIMMER_SWITCH **/
   /* optional (main toggle function)*/
   action: Function,
   /* optional (function will be called with context)*/
   actionPlus: Function,
   actionMinus: Function,
   /** type: WEATHER **/
   /* fields: Object mapping available fields and their values.
    * Full documentation on fields is below
    */
   fields: {},
   /** type: WEATHER_LIST **/
   /** defines the date format used in the date column */
   dateFormat: 'MMM d',  // See https://docs.angularjs.org/api/ng/filter/date for info on formatting syntax.
   /** type: HISTORY **/
   entity: 'sensor.temperatur_innen_gefiltert', // Entity ID (or an array of IDs) to render history for. Default: entity `id` of the tile itself
   offset: 24*3600*1000*5, // Start point of the history counting from now(). Default: one day
   options: { elements: {point: {radius: 3}}}, // Chart options. Refer to https://www.chartjs.org/.
   /** type: GAUGE **/
   /* Object containing gauge settings. Refer to https://ashish-chopra.github.io/angular-gauge/#!#documentation */
   settings: {
      size: 200, // Defaults to 50% of either height or width, whichever is smaller
      type: 'full', // Options are: 'full', 'semi', and 'arch'. Defaults to 'full'
      min: 0, // Defaults to 0
      max: 25000, // Defaults to 100
      cap: 'round', // Options are: 'round', 'butt'. Defaults to 'butt'
      thick: 8, // Defaults to 6
      label: 'My Gauge', // Defaults to undefined
      append: '@attributes.unit_of_measurement', // Defaults to undefined
      prepend: '$', // Defaults to undefined
      duration: 1500, // Defaults to 1500ms
      thresholds: { 0: { color: 'green'}, 80: { color: 'red' } },  // Defaults to undefined
      labelOnly: false, // Defaults to false
      foregroundColor: 'rgba(0, 150, 136, 1)', // Defaults to rgba(0, 150, 136, 1)
      backgroundColor: 'rgba(0, 0, 0, 0.1)', // Defaults to rgba(0, 0, 0, 0.1)
      fractionSize: 0 // Number of decimal places to round the number to. Defaults to current locale formatting
   },
   /** type: POPUP **/
   /* popup: object containing the popup definition.
      The popup is basically a single page with a single group. */
   popup: { // can contain page or group settings, e.g.:
      tileSize: 50, // size of tiles in popup
      width: 2, height: 2, // size of the popup
      items: {}, // definition of tiles in the popup
   },

   /* classes: A list of classes to be appended to the tile element
    * Useful for custom CSS styles.
    * This can be a string of space-separated classes, an object like {myclass: true/false}, or an array of such strings and objects.
    * Can also be generated by an anonymous function or a template.
    * Use CLASS_BIG, CLASS_SMALL or CLASS_MICRO to change the size of a tile.
    * The TYPES.WEATHER tile supports '-compact' class for a compact (1x1) tile
    * (optional)
    */
   classes: ['-compact'],
   classes: {'-compact': true},

   /* customStyles: Additional styles. Enables tile customisation based on state.
    * Can be used both as a object `{ 'background-color': '#FF0000' }` or,
    * as a function function (item, entity) { return { 'background-color': '#FF0000' } }
    * (optional)
    */
   customStyles: Object || Function,

   /* Object containing history settings */
   history: { // If this is present in a tile, a history popup is created on secondary action
      entity: 'sensor.temperatur_innen_gefiltert', // Entity ID (or an array of IDs) to render history for. Default: entity id of the tile itself
      offset: 24*3600*1000*5, // Start point of the history counting from now(). Default: one day
      options: { elements: {point: {radius: 3}}}, // Chart options. Refer to https://www.chartjs.org/.
      styles: { border: '1px solid red'}, // Styles to apply to the <div> containing the chart. Default according to main.css
      classes: 'clock--colon', // Classes to apply to the history popup. Default according to main.css
   },

}

Every anonymous function will call with context

{
   states: {}, // list of current states
   $scope: {}, // angular scope
   parseFieldValue: Function, // parser function (for parsing HA states)
   api: {}, // The Api service. Refer to Api.js for what it exposes.
   apiRequest: Function // parser function (args: data, callback=func)
}

At the moment following entity types have been implemented:

var TYPES = {
   DEVICE_TRACKER: 'device_tracker',
   SCRIPT: 'script',
   AUTOMATION: 'automation',
   SENSOR: 'sensor',
   SENSOR_ICON: 'sensor_icon',
   SWITCH: 'switch',
   LOCK: 'lock',
   COVER: 'cover',
   COVER_TOGGLE: 'cover_toggle',
   FAN: 'fan',
   INPUT_BOOLEAN: 'input_boolean',
   LIGHT: 'light',
   TEXT_LIST: 'text_list',
   INPUT_NUMBER: 'input_number',
   INPUT_SELECT: 'input_select',
   INPUT_DATETIME: 'input_datetime',
   CAMERA: 'camera',
   SCENE: 'scene',
   SLIDER: 'slider',
   IFRAME: 'iframe',
   DOOR_ENTRY: 'door_entry',
   WEATHER: 'weather',
   CLIMATE: 'climate',
   MEDIA_PLAYER: 'media_player',
   CUSTOM: 'custom',
   ALARM: 'alarm',
   WEATHER_LIST: 'weather_list',
   VACUUM: 'vacuum',
   POPUP_IFRAME: 'popup_iframe',
   DIMMER_SWITCH: 'dimmer_switch',
   GAUGE: 'gauge',
   IMAGE: 'image',
};

Example of slider config used for LIGHT:

{
   title: "Color temp",
   field: "color_temp",
   max: 588,
   min: 153,
   step: 15,
   request: {
      type: "call_service",
      domain: "light",
      service: "turn_on",
      field: "color_temp"
   }
}

Supported weather fields

{
   summary: '&sensor.dark_sky_summary.state',
   temperature: '&sensor.dark_sky_temperature.state',
   temperatureUnit: '&sensor.dark_sky_temperature.attributes.unit_of_measurement',
   highTemperature: '&sensor.dark_sky_daytime_high_temperature.state',
   highTemperatureUnit: '&sensor.dark_sky_daytime_high_temperature.attributes.unit_of_measurement',
   //highTemperatureLabel: 'High',
   lowTemperature: '&sensor.dark_sky_overnight_low_temperature.state',
   lowTemperatureUnit: '&sensor.dark_sky_overnight_low_temperature.attributes.unit_of_measurement',
   //lowTemperatureLabel: 'Low',
   windSpeed: '&sensor.dark_sky_wind_speed.state',
   windSpeedUnit: '&sensor.dark_sky_wind_speed.attributes.unit_of_measurement',
   humidity: '&sensor.dark_sky_humidity.state',
   humidityUnit: '&sensor.dark_sky_humidity.attributes.unit_of_measurement',
   pressure: '&sensor.dark_sky_pressure.state',
   pressureUnit: '&sensor.dark_sky_pressure.attributes.unit_of_measurement',

   list: [ // array of strings
      // custom line
      'Feels like '
         + '&sensor.dark_sky_apparent_temperature.state'
         + '&sensor.dark_sky_apparent_temperature.attributes.unit_of_measurement',
      // another custom line
      '&sensor.dark_sky_precip_probability.state'
         + '&sensor.dark_sky_precip_probability.attributes.unit_of_measurement'
         + ' chance of rain'
   ]
}

@/& Prefixes

As you may notice that we use @/& prefixes to get a value inside objects (entities). @ is relative to the current entity (@attributes.friendly_name) and & is for global (&sensor.kitchen_temp.state). This may not work everywhere, but you may give it a go. Read more in our wiki article.

Events

Events can be fired from Home Assistant to control TileBoard. Useful for automation to do things like opening a camera view if it detects motion, or turning the screen off on a tablet at night or when everyone leaves.

Events in HomeAssistant must be fired with tileboard as the event type, and a command included in the event data.

events: [
    /* Example: Start the screensaver on a tablet with Fully Kiosk Browser */
    {
      /* command: The command sent from Home Assistant */
      command: 'screen_off',
      /* action: Function to execute when the command is received
       * The variable e contains the full event_data from HomeAssistant
       */
      action: function(e) {
        if (window.fully) {
            window.fully.startScreensaver();
        }
      },
    },
    /* Example: End the screensaver and make sure Fully Kiosk Browser is in
     * the foreground.
     */
    {
      command: 'screen_on',
      action: function(e) {
        if (window.fully) {
          window.fully.stopScreensaver();
          window.fully.bringToForeground();
        }
      },
    },
    /* Example: Play a sound file
     * Include sound_url in the event_data from Home Assistant
     */
    {
      command: 'play_sound',
      action: function(e) {
        window.playSound(e.sound_url);
      }
    },
    /* Example: Open a specific TileBoard page
     * Include a page field in the event_data from Home Assistant
     * that matches the id: of a page in the TileBoard CONFIG
     */
    {
      command: 'open_page',
      action: function(e) {
        window.openPage(CONFIG.pages[e.page]);
      }
    }
  ],

Example to fire an event in a Home Assistant automation. This example will make 'TileBoard' return to page 0 when a specific binary_sensor state change from off to on. Tip: The page number is determinate by the order of the pages in your TileBoard CONFIG file, the first one is 0.

- alias: aquarium_ok
  initial_state: true
  trigger:
    platform: state
    entity_id: binary_sensor.seneye_param_status
    from: 'on'
    to: 'off'
  action:
    - event: tileboard
      event_data:
        page: 0
        command: 'open_page'

Notifications

TileBoard has built-in support for toast notification popups in the lower right corner. To set them up, add the following to events in CONFIG:

{
   command: 'notify',
   action: function(e) {
      window.Noty.addObject(e);
   }
}

Example to fire a notification in a Home Assistant automation. This example will fire a persistent red notification on TileBoard when a specific binary_sensor state change from on to off.

  • Tip: To remove the persistent notification, resend the same one (or another one) with the same id: with the lifetime: 1 added at the end of the event_data.*
- alias: PC2_offline
  initial_state: true
  trigger:
    platform: state
    entity_id: binary_sensor.pc2
    from: 'on'
    to: 'off'
  action:
    - event: tileboard
      event_data:
        command: 'notify'
        id: 'PC2'
        icon: 'mdi-desktop-tower'
        type: 'error'
        title: 'Status - PC2'
        message: 'PC2 is offline, restart the left computer (big one)'

id: Notification ID. Sending multiple notifications with the same id will overwrite each other.

type: Type of notification (for style purposes). Valid types are error, info, success, warning

lifetime: Length of time (in seconds) for the notification to persist before automatically dismissing. Leave a lifetime out of the event_data for persistent messages.

Custom CSS Styles

Several classes are added to each tile depending on the type of tile and state. Custom CSS styles can be applied by creating a custom.css file in the styles directory. Tip: If no style is applied after adding the file, make sure to disable cache in the browser as it may cache the previous empty custom.css file for a while.

Tablet and mobile configuration

For the tablet configuration use COMPACT custom theme and reduce padding. For the mobiles check out wiki article.

License

MIT License

tileboard's People

Contributors

airthusiast avatar akloeckner avatar alexarch21 avatar alphasixtyfive avatar bjw-s avatar brmo avatar cgarwood avatar danhounshell avatar dependabot[bot] avatar evgeny- avatar foosel avatar frankwah avatar gerard33 avatar inxaos avatar jeroenterheerdt avatar jiayuandeng avatar mariuszluciow avatar mathijsmeulendijks avatar mikyjazz avatar mouth4war avatar mpopti0n avatar mrsbh avatar rchl avatar refineryx avatar renovate[bot] avatar rogersmj avatar rosskyl avatar sbrandsborg avatar sgoudsme avatar timota avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tileboard's Issues

Feature Request: lock

I have an August lock. Could you add support for entity types of lock?

The two states are locked and unlocked. Let me know if there is any other information that would be useful. Once there is support for locks and covers (garage doors), then my whole house can be represented with this awesome dashboard! Can't wait!

image

RTL

I managed to align right a question, how do I change the position of the table (where my photos and my wife it will be on the right)

https://imgur.com/a/cvtgYxx

MDI toggle icons don't display properly

I have the following config:

{
                     position: [1, 1],
                     width: 1,
                     title: 'Guests',
                     classes: [CLASS_BIG],
                     type: TYPES.INPUT_BOOLEAN,
                     id: 'input_boolean.guests',
                     icons: {
                        on: 'mdi-toggle-switch',
                        off: 'mdi-toggle-switch-off-outline'
                     },
                     states: {
                        on: "On",
                        off: "Off"
                     }
                  }

This is how the tile renders for on, which isn't quite right:
image

And off it doesn't show anything:
image

The correct markup is in the html, but it just doesn't show the icon:
image

size iPad

What is the size of the iPad?

I need to adjust the information to the iPad, you can direct me how to change the scale

Feature Request: Widget Background Colors

It would be great to be able to define background colors for widgets with a function or state map. For example, if a door sensor is on or open have a red background, as opposed to a green background if it is off or closed

Likewise, being able to simply set background colors for different entities would be useful, for example, color coding light widgets based on room or type

Google Maps API key

using google maps for locator does not work. Every request fails with http 403 (forbidden).

The detailed message (from developer tools) is: "The Google Maps Platform server rejected your request. You must use an API key to authenticate each request to Google Maps Platform APIs. For additional information, please refer to http://g.co/dev/maps-no-account"

So bottom line, there has to be a place where a user can add an API key in config.js

Feature Request: Support for fans

Add support for turning fans on/off and setting speed. Perhaps tapping the tile can toggle it on/off and holding on the tile can bring up a list to select the speed? Most (possibly all?) fan. entities have a defined list of speeds, it can't be set to an arbitrary number or % so I don't think a slider would work.

Here's a state/attribute dump from one of my fans:

state: on
speed_list: auto,lowest,low,medium,high
model_name: Ceiling Fan
supported_features: 5
friendly_name: Living Room Fan
device_manufacturer: home_decorators
manufacturer_device_model: home_decorators_home_decorators_fan
speed: low

Cover arrows are not representing state

The down/up arrow are still highlighted when cover is closed/open - that isn’t the case for a standard cover on HA which disables and dims the down/up arrows.

Scene type tile not showing

Im having trouble setting up a scene tile. I have a scene titled Movie_Night in home assistant and added the following to config.js
{
position:[0,1],
id: 'scene.Movie_Night',
type: TYPES.SCENE,
state: false,
icon: 'mdi-movie-roll',
},
however when I load the dashboard no tile shows up. Any ideas?

TEXT_LIST and unit_of_measurement

When setting up a text_list that includes sensors, there's no way to include the unit_of_measurement as part of the value:

edit: #55 could be a solution for this

Input_Number not following changes in other interfaces

When I move the slider in TileBoard, the new setting is reflected in Home Assistant dashboard (value and slider position), but when the silder is moved in Home Assistant, only the value is changed in TileBoard, the slider stays the same.
It can be a configuration problem or is it a bug?

Feature request: functions for list values

I want to be able to render other text in the list for sensors that have "on/off" state. For example:

{
                           title: 'Garage (1)',
                           icon: 'mdi-garage',
                           value: function() {
                             var val='&binary_sensor.garage_single_bay.state';
                             if(val=="On") {
                               return "Open";
                             } else {
                               return "Closed";
                             }
                           }
                        }

This doesn't seem to work right now, it just tries to render the function as a string:

image

Having this would be a very powerful addition to lists.

Feature Request: Javascript Tile

A standard tile like a light, script, switch, etc tile, but when tapped fires a custom defined Javascript function.

I would use this in combination with Fully Kiosk Browser to launch other apps, such as Netflix or Plex, from my dashboard, or to add a button to turn on/off the tablet's motion detection or screen.

head / clock font size and margins

On an Amazon Fire HD8 tablet, the clock in the header is much too large for the screen. It also runs into the tiles. Removing the header by commenting out the head parameter in config.js works fine, however I was wondering if there are less drastic options. Could the font size and margin for the clock be configurable in config.js (similar to the groupMarginCss option)?

Feature_request: meta CSS settings for mobile devices

Would be really nice if it was possible to get some sample configuration for mobile devices.

Its way to zoomed in by default and menu icons lapse over tiles when scrolling.

Im not a CSS genius but to have meta site locked to for example 70% zoom would really help.

Cheers

Feature Request: RGB Slider or Wheel for lights

Hi Im not sure if this is possible already or not but having a slider or wheel to set the color of lights is about the only thing I am missing on this dashboard. Thanks for all the work you have put into this!

Customized state not added as css class

I have the following on my climate device:

{
  position: [0, 0],
  width: 2,
  type: TYPES.CLIMATE,
  id: "climate.hallway",
  title: 'Thermostat',
  state: function () {
    return this.states['sensor.hallway_thermostat_hvac_state'].state;
  }
},

The actual state of climate.hallway is cool, the state of this.states['sensor.hallway_thermostat_hvac_state'].state is cooling

The generated HTML tag contains the state of climate.hallway, but not the state generated by the state: function() {} statement.

<div ng-style="itemStyles(item, entity)" class="item ng-scope -climate -cool -th-climate" ng-click="entityClick(page, item, entity)" on-long-press="entityLongClick($event, page, item, entity)" ng-if="entity = getItemEntity(item)" ng-class="itemClasses(item)" style="width: 286px; height: 140px; left: 0px; top: 0px;">

sensors.js missing

According to index.html it's used in development, but it's not included in the git repo.

Support for "range" style thermostats in auto mode

I have an ecobee 3 thermostat, and the current Climate tile doesn't work with it because the "temperature" attribute on the ecobee in HA is null if the thermostat is in Auto mode (more info here):

image

I am working on a solution for displaying the range of temps; I altered the climateTarget function to do this:

   $scope.climateTarget = function (item, entity) {
      var value = entity.attributes.temperature;

      if(value == null) {
        //This is a thermostat that has high/low target temps
        value = entity.attributes.target_temp_low + " - " + entity.attributes.target_temp_high;
      }

      if(item.filter) return item.filter(value);

      return value;
   };

Which works fine. The problem is handling the temperature adjustment. In Home Assistant it looks like this:

image

I don't think cramming two "+/-" button sets onto a single tile is a good idea. Too many opportunities for accidental taps. Interested in everyone's ideas on how to handle this...perhaps a popup with the adjustment buttons?

Feature_request: color customization

Would be nice to be able to assign text/icon color for specific tiles/entities. For example my Sonos media_players use albumpictures as background and when its a light background the controls are hard to see.

TypeError: Cannot read property '_c' of undefined

I'm seeing one of these errors for each state change that comes by:

TypeError: Cannot read property '_c' of undefined
    at b.MainController.$scope.getSliderConf (main-controller.js:474)
    at fn (eval at compile (angular.min.js:241), <anonymous>:4:393)
    at m.$digest (angular.min.js:147)
    at updateView (main-controller.js:1298)
    at handleEvent (main-controller.js:1282)
    at handleMessage (main-controller.js:1270)
    at main-controller.js:1171
    at api.js:138

Feature Request: Turn_on_action for media_players

For my TV i use a command called Turn_on_action which basicly launches a WOL script i wrote.

Can this field be implemented into a media_player as optional?

turn_on_action:
  service: switch.turn_on
  data:
    entity_id: switch.LGTV

Cheers

Equivalent for sub_entity?

I use it for a sensor, but maybe it can be applied to other widgets types.
Is there a similar function?

Cross origin errors: failed to load head and tile

I'm trying to run TileBoard locally on my Mac, just by opening up index.html in my browser (as suggested in the Community thread) and have it talk to Hass.io running on a RPi. It is receiving events from HA just fine.

However, it's throwing errors about cross-origin requests and I don't get anything showing on my board:

image

I'm guessing this is because it's being run from a file:// protocol. If that's going to be a problem, the project should maybe be bundled with a really simple web server?

Placeholder page for unavailable media_players

One of my mediaplayers is configured like this:

        {
          position: [0, 0],
          width: 2,
          id: 'media_player.kodi_bedroom',
          type: TYPES.MEDIA_PLAYER,
          state: '@attributes.media_title',
          bgSuffix: '@attributes.entity_picture', // show picture of current media as a background
          bgOpacity: 0.5,
        },

This works, however, if it is offline it shows a transparant tile and the title is set to @attributes.media_title since there is none.
It would be nicer if we could have configure some kind of placeholder instead (like HA webinterface has)

Feature Request: Custom Events for Audio and Notifications

Another feature I hacked into my HADasboard setup...

Listen for a custom event on the Home Assistant event bus and play and audio file with an optional toast notification or modal popup.

I've used this feature to play a chime when a door opens or closes, as well as playing an alert tone if certain weather alerts are issued or a smoke/co detector goes off. A door chime could pop up a toast notification with which door was opened or closed, and something like a smoke alarm activation could pop up a larger modal dialog with more information.

Map slideshow zoom levels

Another enhancement request from me :)
The zoom levels on maps are not very useful for my family, especially zoom level 9. I would be good if it could be configured. Also the first blank/grey view in the slideshow should be removable.

screenshot_2018-06-28-17-40-11

State

New state attribute is not working if I define the states mapping.
I think the previous behavior was better.

Feature Request: Tile opacity and 'group' backgrounds

Feature Request:

Consider allowing each tile background image to have an opacity set within the config.js

Consider allowing a background image to be defined in config.js for each group and for that too to have an optional opacity value.

XML Parsing Error: not well-formed in tile.html

I'm seeing this error on the console with the demo TileBoard

XML Parsing Error: not well-formed
Location: file:///C:/Users/zzz/Documents/Dev/TileBoard/tile.html
Line Number 45, Column 46:

It appears to be pointing to this line:

      <div ng-if="!hasTrackerCoords(entity) && entity.attributes.entity_picture"
           class="item-background" ng-style="trackerBg(entity)"></div>

Node/npm project

I would like to suggest making this into a simple node/npm project. The benefits would be:

  • built-in web server that can be started easily (with npm start command for example)
  • possibility to not expose a configuration/password to the world
  • optional auto-reloading of tileBoard on configuration change
  • ...

It would complicate the code some as outgoing requests and incoming events would need to go through the TileBoard backend and then be passed to the client (or vice versa).

Possibly compatibility with just running html file from local drive could be kept but it would probably complicate things. And it's not really proper way to run it (triggers warnings and does not support get connecting to HA instance on the web).

Feature Request: Screensaver

Add a screensaver option. After x seconds of inactivity, switch to essentially a digital picture frame with a clock and possibly weather overlay. Tapping on the screen would take you back to either the main dashboard or the previous dashboard.

I hacked this in to my HADashboard install and it looked like this:
img_2923

Feed it a JSON list of pictures and it will loop through them every 5s or so. I did end up adding a full-screen weather slide at the beginning of the loop as well (that hides the big clock overlay) that includes the current weather conditions and forecast for the next couple days. I had issues with image retention on the Kindle Fire 8" screens where you'd see a faint outline of the clock. Adding the full-screen weather slide that hid the clock helped quite a bit with that.

I'm willing to share code or help program it in, but I've never worked with Angular before, so that will be a bit of a learning curve.

Feature_request: Define Unit_of_Measurement for sensor

Trying to implement my SNMP bandwith montoring sensors but cant figure out how to customize my code to get it to work. Would be nice to be able to define this for sensors

https://www.home-assistant.io/components/sensor.snmp/

{
   position: [7, 2],
   width: 2,
   height: 1,
   title: '',
   id: {}, // since we are binding each list item to different sensor, so we simply use an empty object
   type: TYPES.TEXT_LIST,
   state: false,
   list: [
      {
         title: 'Internet Speed IN',
         icon: 'mdi-speedometer',
         value: '&sensor.internet_speed_in.state'
      },
	  {
         title: 'Internet Speed OUT',
         icon: 'mdi-speedometer',
         value: '&sensor.internet_speed_out.state'
      },
	  {
         title: 'WAN Download Average',
		 icon: 'mdi-download',
         value: '&sensor.wan_traffic_in_mean.attributes.unit_of_measurement',
	  },
	  {
         title: 'WAN Upload Average',
         icon: 'mdi-upload',
         value: '&sensor.wan_traffic_out_mean.state'
      },
      ]
},

console
unit_of_measurements
unit_of_measurements_ha

RTL

Is it possible to add code to rtl?

Camera will not show fullscreen

Here is the issue you asked me to create.

and part of my config that contains the cameras.

pages: [
      {
         title: 'Main page',
         bg: 'images/bg1.jpeg',
         icon: 'mdi-home-outline', // home icon
         head: 'head.html', // clock
         groups: [
            {
               title: '',
               width: 2,
               height: 3,
               items: [
                  {
					 position: [4, 0],
					 id: 'camera.koket',
					 type: TYPES.CAMERA_THUMBNAIL,
					 bgSize: 'cover',
					 width: 2,
					 state: false,
					 fullscreen: {
					 type: TYPES.CAMERA,
					 refresh: 1500, // can be number in milliseconds
					 bgSize: 'contain'
					 },
					 refresh: function () { // can also be a function
					 return 3000 + Math.random() * 1000
					 }
				  },
				  {
					 position: [2, 0],
					 id: 'camera.clara',
					 type: TYPES.CAMERA_THUMBNAIL,
					 bgSize: 'cover',
					 width: 2,
					 state: false,
					 fullscreen: {
					 type: TYPES.CAMERA,
					 refresh: 1500, // can be number in milliseconds
					 bgSize: 'contain'
					 },
					 refresh: function () { // can also be a function
					 return 3000 + Math.random() * 1000
					 }
				 }

               ]
            },

           

Issues with entity_picture and light background

Having an issue where my entity_pictures for device_tracker wont show.. maps shows just fine

also when i add a light i only see "title", no device shows, and log shows no errors.

no icon light and no entity_picture

Here is for example one of my device_trackers
ha

{
					 position: [2, 0],
					 type: TYPES.DEVICE_TRACKER,
					 id: 'device_tracker.micaela',
					 map: 'google',
					 states: {
					 home: "Home",
					 not_home: "Away",
					 },
					 slidesDelay: 2
				  },
				  {
					 position: [3, 0],
					 type: TYPES.DEVICE_TRACKER,
					 id: 'device_tracker.cjas_iphone_7',
					 map: 'google',
					 states: {
					 home: "Home",
					 not_home: "Away",
					 },
					 slidesDelay: 2
				  },

and here is the light config.

{
					 position: [2, 1],
					 title: 'Library',
					 subtitle: 'Lounge',
					 id: 'light.library',
					 type: TYPES.LIGHT,
					 states: {
						on: "On",
						off: "Off"
					 },
					 icons: {
						on: "mdi-lightbulb-on",
						off: "mdi-lightbulb"
					 },
					 sliders: [
					 {
					 title: 'Brightness',
					 field: 'brightness',
					 max: 255,
					 min: 0,
					 step: 5,
					 request: {
					 type: "call_service",
					 domain: "light",
					 service: "turn_on",
					 field: "brightness"
					 }
					},
					 {
					 title: 'Color temp',
					 field: 'color_temp',
					 max: 588,
					 min: 153,
					 step: 15,
					 request: {
					 type: "call_service",
					 domain: "light",
					 service: "turn_on",
					 field: "color_temp"
         }
      },

Cheers

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.