TileBoard - New dashboard for Homeassistant

So COVER works well. One advantage of a slider though is that we could set limits and open the blind to the percentage we want.

For example, I can set a limit of 75% on some of the blinds. (we have some large blinds that I would prefer not be opened fully)

Another plus is that the touchscreen is not in the same room as the blinds. So if we want to open the blinds 50% it becomes a bit of guesswork.

Perhaps this could be implemented in the future.

Thanks!

You can create input_number in HA with relevant automation .

I could. But I have lots of blinds. :slight_smile:

I took a look at the code and I think I know why it is doing what it is doing. I guess in Javascript 0’s are treated as false and when doing comparisons it was skipping over them.

I changed getSliderConf to the following and it now functions as I would expect it to. 0’s are reflected on the slider. I am not a JS person so maybe there is a better way. But this works for me.

         //var value = +attrs[def.field] || 0;
         var value = +attrs[def.field] || +entity.state || 0;

         //value: value || +entity.state || def.value || 0, 
         value: (value === 0) ? (0) : (value || +entity.state || def.value || 0),
         

Hi every1,

I’m trying to figure out how to replace the bgSuffix if media_player is not actively playing:

{
    position: [0, 1.5],
    width: 3.7,
    height: 1.5,
    bgOpacity: 0.3,
    id: 'media_player.tv_wohnzimmer',
    type: TYPES.MEDIA_PLAYER,
    title: 'Wohnzimmer TV',
    hideSource: false,
    hideMuteButton: false,
    state: false,
    //state: '@attributes.media_title',
    subtitle: '@attributes.media_title',
    bgSuffix: function(item, entity) {
        if(this.parseFieldValue('&media_player.tv_wohnzimmer.state') != 'playing') {
            return 'local/dashboard/images/tiles/spotify.png';
        } else {
            return '@attributes.entity_picture'
        }
    }
},

This works with the initial background but it will not be replaced by @attributes.entity_picture.

And another question:
Is it possible to create a TYPES.CUSTOM tile that opens up the CAMERA_POPUP to show all available cameras, as I want to have just one single tile (with e.g. CCT MDI icon)?

Andy ideas?

Thanks and best regards

1 Like

Have you tried to use an iframe? not the most elegant, but it should work.

{
	position: [0, 2],
	type: TYPES.POPUP_IFRAME,
	id: {},
	icon: 'mdi-wifi',
	url: 'images/wifiQR.png',
},

obviously set the url to the location of your QR code.

I did that too. Here is an example of TYPES.POPUP. Note that you have to get the latest code from dev branch on GitHub.

{
    position: [0, 3],
    type: TYPES.POPUP,
    id: {},
    title: 'WLAN',
    icon: 'mdi-wifi',
    layout: {
        page: {},
        tiles: [
            {
                position: [0, 0],
                type: TYPES.IMAGE,
                id: { },
                bg: 'images/tiles/guest_wifi_login.png',
            },
            {
                position: [1, 0],
                type: TYPES.IMAGE,
                id: { },
                bg: 'images/tiles/guest_wifi.png',
            }
        ]
    }
}
1 Like

Hello All,
I have been having issue with this weather tile, the title seems to mess up with the wind/humidity. I have the weather and forecast as shown below. Can someone help me on how I may be able to fix that title “Phoenix” appearing above the wind/humidity sensors ? Also i only get forecast for 2 days on the met.mo weather sensor. Any ideas ?

image

Thank You in Advance !

Could you share your tile snippet so that we can take a deeper look into it?

Sure, this is what i have:



groups: [
            {
               title: 'Weather',
               width: 2,
               height: 3,
               items: [
				 {
                     position: [0, 0],
                     width: 2,
					 height:1,
                     type: TYPES.WEATHER,
					   id: 'weather.phoenix',
					   //title: 'Phoenix Weather',
					   state: '&weather.phoenix.state', // label with weather summary (e.g. Sunny)
					   fields: { // most of that fields are optional
						  //icon: '&sensor.dark_sky_icon.state',
						  icon: '&weather.phoenix.state',
						  icons: {
							 'clear-day': 'clear',
							 'clear-night': 'nt-clear',
							 'cloudy': 'cloudy',
							 'sunny': 'clear',
							 'rain': 'rain',
							 'sleet': 'sleet',
							 'snow': 'snow',
							 'wind': 'hazy',
							 'fog': 'fog',
							 'partly-cloudy':'cloudy',
							 'partly-cloudy-day': 'partlycloudy',
							 'partly-cloudy-night': 'nt-partlycloudy'
						  },
						  //summary: '&weather.phoenix.state',
						summary: function() { return this.parseFieldValue("Humidity: " + "&weather.phoenix.attributes.humidity" + " % ") + this.parseFieldValue("Wind Speed: " + "&weather.phoenix.attributes.wind_speed" + " m/s") },

						  temperature: '&weather.phoenix.attributes.temperature',
						  //temperatureUnit: '&sensor.dark_sky_temperature.attributes.unit_of_measurement',
						  temperatureUnit: String.fromCharCode(176) + 'F',
						 
						  //precip: '&sensor.dark_sky_precip.state',
						  //precipIntensity: '&sensor.dark_sky_precip_intensity.state',
						  //precipIntensityUnit: '&sensor.dark_sky_precip_intensity.attributes.unit_of_measurement',
						  //precipProbability: '&sensor.dark_sky_precip_probability.state',
						  //precipProbabilityUnit: '&sensor.dark_sky_precip_probability.attributes.unit_of_measurement',
						  windSpeed: '&weather.phoenix.attributes.wind_speed',
						  //windSpeedUnit: '&sensor.dark_sky_wind_speed.attributes.unit_of_measurement',
						  humidity: '&weather.phoenix.attributes.humidity',
						  //humidityUnit: '&sensor.dark_sky_humidity.attributes.unit_of_measurement',
						  
						  },
						  
                  },
			   
                  {
                   position: [0, 1],
                     type: TYPES.WEATHER_LIST,
                     width: 2,
                     height: 1,
                     title: 'Forecast',
                     id: {},
                     icons: {
                        'clear-day': 'clear',
                        'clear-night': 'nt-clear',
                     },
                     hideHeader: false,
                   list: [0,1].map(function (id) { //do 0,1,2,3,4 for more days..
						   return {
							  date: function () {
								 var d = new Date(Date.now() + (id+1) * 24 * 60 * 60 * 1000);
								 return d.toString().split(' ').slice(1, 3).join(' ');
							  },
							  icon: function() {
								 var sensor = this.states['weather.phoenix'];
								 return sensor.attributes.forecast[id].condition;
							  },
							  primary: function() {
								 var sensor = this.states['weather.phoenix'];
								 var forecast = sensor.attributes.forecast[id].temperature + " C";
								 
								 return forecast;
							  },
							  secondary: function() {
								 var sensor = this.states['weather.phoenix'];
								 var wind = sensor.attributes.forecast[id].wind_speed + " Mph";
								 
								 return wind;
							  },
						   }
					})
                  },
                  {
                     position: [0, 3], // [x, y]
                     width: 1,
                     type: TYPES.SENSOR,
                     id: 'binary_sensor.updater',
                     state: '@attributes.release_notes' // https://github.com/resoai/TileBoard/wiki/Templates
                  }
               ]
            },
],

Is anyone having issues with websocket connection is constantly closing with the new update .113?

Since I have upgraded to .113 the websocket connection closes every minute or so and the logs are filled with the warning.

Had the same issue until I created a token in HA and pasted it in config.js

Hello,
I’m trying to change the tile background to a custom picture of my choice.
In the documentation of tileboard this code should be added in the tile object: bg: ‘@attributes.entity_picture
Where do I add the pic directory e.g “/images/example.jpg” aka how/where do I determine the entity_picture??

Unfortunately that did not fix the issue. Still happening after creating a token.

Hi all, I can’t for the life of of me add a second grouping of tiles. I copy and paste directly in, ensuring it is withing the groups [] and when I refresh the dashboard it keeps saying “entity “unidentified” not found” and no second grouping of tiles. I’ve literally copy and pasted the exact group as above and changed the title and entity, tried leaving it the same, I really don’t get it, i’m stumped. Anyone have any ideas that could help me?

Here is the last item and new group. “second group” won’t show up!

{
                     position: [2, 0],
                     height: 2,
                     width: 1,
                     type: TYPES.SWITCH,
                     id: "switch.nooklightswitch",
                     state: false,
                     title: 'Nook Lights',
                     icons: {'off': 'mdi-lightbulb-off', 'on': 'mdi-lightbulb-on'}
},
{
               title: 'Second group',
               width: 2,
               height: 3,
               items: [
                  {
                     position: [0, 0],
                     width: 1,
                     type: TYPES.SWITCH,
                     id: "switch.nooklightswitch",
                     state: false,
                     title: 'Custom slider',
                     icons: {'off': 'mdi-lightbulb-off', 'on': 'mdi-lightbulb-on'}
                        }
                        ]
 

}
]
}
]
}
]
}


;

Could you try to increase the height of the first tile to 1.5 and check if they overlap?
Another question is what you global configuration section looks like.
Have you made any changes to CSS?

You might want to take a look here?

The image is located in the images folder of tileboard.

It looks to me like you didn’t close your items array with a ] in the first group.

Anyone got an idea how to retrieve the data below “watering_program:”?

device_name: Sprinkler
device_id:
zone_name: Garten
smart_watering_enabled: true
manual_preset_runtime: 3600
sprinkler_type: rotary
program_e: 
enabled: true
name: Smart Watering
is_smart_program: true
watering_program:
  - '2020-07-28T06:00:00+02:00'
  - '2020-07-28T06:32:00+02:00'
  - '2020-07-31T06:00:00+02:00'
  - '2020-07-31T06:32:00+02:00'
  - '2020-08-04T06:00:00+02:00'
  - '2020-08-04T06:32:00+02:00'
  - '2020-08-07T06:00:00+02:00'
  - '2020-08-07T06:32:00+02:00'

What I tried so far was this, but no luck:

{
    title: 'Status',
    icon: 'mdi-check',
    value: function() {
        var consumption = this.parseFieldValue('&sensor.garten_zone_history.attributes.watering_program')
        for(i = 0; i < consumption.length; i++) {
            return consumption[i]
        }
    }
}

I know that it would overwrite until the last item. But this is just a test to get the values out of the array.
Thanks in advance

Hey all, I’m just trying to get started with Tileboard, and I’d really like a way to switch between the Tileboard URL and my basic lovelace interface (this is going to be used on a 7" touchscreen in kiosk mode). I’ve searched a lot, but can’t find a way to have a custom tile that just loads a new URL.

I’ll just make a link back to Tileboard in my normal Lovelace interface to get back when I want to test it.

Any ideas?

Also, are there any good searchable repositories of example code with visual examples to learn from?

Hi Sunny,

Thank you for the response, yes it works fine with 1.5 tile height, but does not look necessary if i could some how fix the overlap. I tried adjusting some CSS but couldn’t get it to fix. Here’s my global config, appreciate your help:

var CONFIG = {
   customTheme: CUSTOM_THEMES.TRANSPARENT, 
   transition: TRANSITIONS.ANIMATED_GPU, 
   entitySize: ENTITY_SIZES.SMALL, 
   tileSize: 150,
   tileMargin:5,
   serverUrl: 'https://hass.home:8123',
   wsUrl: 'wss://hass.home:8123/api/websocket',
   authToken: null, 
   debug: false, 
   pingConnection: true, 

events: [
    {
      command: 'screen_off',
      action: function(e) {
        if (typeof fully !== undefined) {
            fully.startScreensaver();
        }
      },
    },
    {
      command: 'screen_on',
      action: function(e) {
        if (typeof fully !== undefined) {
          fully.stopScreensaver();
          fully.bringToForeground();
        }
      },
    },
    {
      command: 'play_sound',
      action: function(e) {
        playSound(e.sound_url);
      }
    },
    {
      command: 'open_page',
      action: function(e) {
        window.openPage(CONFIG.pages[e.page]);
      }
    }
  ],
   timeFormat: 12, //or 24
   menuPosition: MENU_POSITIONS.LEFT, // or BOTTOM
   hideScrollbar: false, // horizontal scrollbar
   groupsAlign: GROUP_ALIGNS.HORIZONTALLY, // or VERTICALLY
   onReady: function () {},
   screensaver: {// optional. https://github.com/resoai/TileBoard/wiki/Screensaver-configuration
      timeout: 300, // after 5 mins of inactive
      slidesTimeout: 10, // 10s for one slide
      styles: { fontSize: '40px' },
      leftBottom: [{ type: SCREENSAVER_ITEMS.DATETIME }], // put datetime to the left-bottom of screensaver
      slides: [
         { bg: 'images/bg1.jpeg' },
         {
            bg: 'images/bg2.png',
            rightTop: [ // put text to the 2nd slide
               {
                  type: SCREENSAVER_ITEMS.CUSTOM_HTML,
                  html: 'Welcome to <b>Nepal Residence</b>',
                  styles: { fontSize: '40px' }
               }
            ]
         },
         { bg: 'images/bg3.jpg' },
		 { bg: 'images/bg-galaxy.jpg' }
      ]
   },
   pages: [
      {
         title: 'Main page', //page1
         bg: 'images/bg11.jpg',
         //bg: 'images/bg-galaxy.jpg',
		  bgOpacity: '1',
         icon: 'mdi-home-outline', // home icon
		 groupMarginCss: '20px 10px',
		 tileSize: 150,
		    header: { // https://github.com/resoai/TileBoard/wiki/Header-configuration
      right: [
	  {
         type: HEADER_ITEMS.CUSTOM_HTML,
         html: '<b>Nepal Residence!</b>',
         styles: {
			padding: '20px 50px 0px 50px',// top,right,bottom,left
            margin: '0x 0px 0px 0px'
         }
      },
      // Uncomment weather object to get weather in your header.
      {
         type: HEADER_ITEMS.WEATHER,
         styles: {
            padding: '0px 50px 0px 50px', // top,right,bottom,left
         },
         icon: '&weather.phoenix.state',
         icons: {
            'clear-day': 'clear',
            'clear-night': 'nt-clear',
            'cloudy': 'cloudy',
            'rain': 'rain',
            'sleet': 'sleet',
            'snow': 'snow',
			'sunny':'clear',
            'wind': 'hazy',
            'fog': 'fog',
            'partly-cloudy-day': 'partlycloudy',
            'partly-cloudy-night': 'nt-partlycloudy'
         },
         fields: {
            //summary: '&weather.phoenix.state',name.charAt(0).toUpperCase() + name.slice(1)
			 //summary: function() { return this.parseFieldValue("Humidity: " + “&weather.thuis.attributes.humidity” + " % ") + this.parseFieldValue(“Wind Speed: " + “&weather.thuis.attributes.wind_speed” + " m/s”) },
			 
            temperature: '&weather.phoenix.attributes.temperature',
            temperatureUnit: String.fromCharCode(176) + 'F ,'+ '&weather.phoenix.state',
         }
		

      }
	  
	  
	  ],
      left: [
         {
            type: HEADER_ITEMS.DATETIME,
			//timeformat: 'hh:mm:ss a',
            dateFormat: 'EEEE, LLLL dd', //https://docs.angularjs.org/api/ng/filter/date
			styles: {
            padding: '0px 50px 0px 20px', // top,right,bottom,left
         },
         } 
      ]
   },
         groups: [
            {
               title: 'Weather',
               width: 2,
               height: 3,
               items: [
				 {
                     position: [0, 0],
                     width: 2,
					 height:1.5,
                     type: TYPES.WEATHER,
					   id: 'weather.phoenix',
					   //title: 'Phoenix Weather',
					   state: '&weather.phoenix_2.state', // label with weather summary (e.g. Sunny)
					   fields: { // most of that fields are optional
						  //icon: '&sensor.dark_sky_icon.state',
						  icon: '&weather.phoenix_2.state',
						  icons: {
							 'clear-day': 'clear',
							 'clear-night': 'nt-clear',
							 'cloudy': 'cloudy',
							 'sunny': 'clear',
							 'rainy': 'rain',
							 'sleet': 'sleet',
							 'snow': 'snow',
							 'wind': 'hazy',
							 'fog': 'fog',
							 'partly-cloudy':'cloudy',
							 'partly-cloudy-day': 'partlycloudy',
							 'partly-cloudy-night': 'nt-partlycloudy'
						  },
						  //summary: '&weather.phoenix.state',
						summary: function() { return this.parseFieldValue("Humidity: " + "&weather.phoenix_2.attributes.humidity" + " % ") + this.parseFieldValue("Wind Speed: " + "&weather.phoenix_2.attributes.wind_speed" + " m/s") },

						  temperature: '&weather.phoenix_2.attributes.temperature',
						  //temperatureUnit: '&sensor.dark_sky_temperature.attributes.unit_of_measurement',
						  temperatureUnit: String.fromCharCode(176) + 'F',
						 
						  //precip: '&sensor.dark_sky_precip.state',
						  //precipIntensity: '&sensor.dark_sky_precip_intensity.state',
						  //precipIntensityUnit: '&sensor.dark_sky_precip_intensity.attributes.unit_of_measurement',
						  //precipProbability: '&sensor.dark_sky_precip_probability.state',
						  //precipProbabilityUnit: '&sensor.dark_sky_precip_probability.attributes.unit_of_measurement',
						  windSpeed: '&weather.phoenix_2.attributes.wind_speed',
						  //windSpeedUnit: '&sensor.dark_sky_wind_speed.attributes.unit_of_measurement',
						  humidity: '&weather.phoenix_2.attributes.humidity',
						  //humidityUnit: '&sensor.dark_sky_humidity.attributes.unit_of_measurement',
						  
						  },
						  
                  },
			   
                  {
                    position: [0, 1.5],
                     type: TYPES.WEATHER_LIST,
                     width: 2,
                     height: 1,
                     title: 'Forecast',
                     id: {},
                     icons: {
                      		'clear-day': 'clear',
							 'clear-night': 'nt-clear',
							 'cloudy': 'cloudy',
							 'sunny': 'clear',
							 'rainy': 'rain',
							 'sleet': 'sleet',
							 'snow': 'snow',
							 'wind': 'hazy',
							 'fog': 'fog',
							 'partly-cloudy':'cloudy',
							 'partly-cloudy-day': 'partlycloudy',
							 'partly-cloudy-night': 'nt-partlycloudy'
                     },
                     hideHeader: false,
                   list: [0,1,2,3,4].map(function (id) { //do 0,1,2,3,4 for more days..
						   return {
							  date: function () {
								 var d = new Date(Date.now() + (id+1) * 24 * 60 * 60 * 1000);
								 return d.toString().split(' ').slice(1, 3).join(' ');
							  },
							  icon: function() {
								 var sensor = this.states['weather.phoenix_2'];
								 return sensor.attributes.forecast[id].condition;
							  },
							  primary: function() {
								 var sensor = this.states['weather.phoenix_2'];
								 var forecast = sensor.attributes.forecast[id].temperature + " C";
								 
								 return forecast;
							  },
							  secondary: function() {
								 var sensor = this.states['weather.phoenix_2'];
								 var wind = sensor.attributes.forecast[id].condition ;//+ " Mph";
								 
								 return wind;
							  },
						   }
					})
                  },
                  {
                     position: [0, 3.5], // [x, y]
                     width: 1,
                     type: TYPES.SENSOR,
                     id: 'binary_sensor.updater',
                     state: '@attributes.release_notes' // https://github.com/resoai/TileBoard/wiki/Templates
                  }
               ]
            },