You can add ignoreErrors: true
to the root of CONFIG
Thanks I’ve added it to my config and it seems to be working as intended.
Also I’ll have a look into HLS streaming, there may be a simple say of doing it if a modern browser is used.
Hi there, sorry for bothering and the stupid question.
So I have downloaded the latest from your git repository, went into config folder of my Hass.io and created a www folder. Within www folder I have added tailboard folder, and within that folder I have added all the files downloaded from the git.
Renamed config.example.js to config.js, cleared my browser cache, but when I go to http://localhost:8123/local/tileboard/index.html I get an error 404: not found.
Sorry for the stupid question, my first day using Hass.io and am running it on a dev environment first to play around with and get familiar with it all.
Thanks in advance!
Restart HA.
Wauw… that simple… Thanks buddy for the quick response! keep it up
Hello. I have been using HA for about a month now and happened upon TileBoard a week or so ago after looking for a good, lightweight front end to run on a wall mounted tablet. My whole reason for using HA was to find an easy way for my wife to control the various bulbs and switches (and future sensors and cameras) we have collected without needing several different apps on her phone. A wall mounted tablet gives her single place to control everything. BTW, I picked up an Amazon Fire 8 this past weekend (on sale for $49) and I am running Fully Kiosk on it.
@resoai this is awesome Alexey. I am a web dev but mostly backend stuff and the front end stuff I have done is React. I have not worked with angular before but am starting to get there now. However, I am amazed at how much can just be done with the config file. My goal is to do everything I need there or custom.css without touching the other things, but I am starting to need to branch beyond that with the things I am trying to do.
I have learned a ton both from the project readme and this thread, nearly everything I wanted to do was discussed. I hope to share some things I have learned.
I am looking forward to your take on splitting out some of the config into multiple files @resoai. I have tried a few things but none of them were very clean. I was able to separate out my tile definitions from their usage. I define all my tile entities above the setting of the config variable, something like this:
tiles = {};
tiles.family_room_table_lamp: {
width: 1,
type: TYPES.SWITCH,
id: "light.table_lamp",
states: {
on: "On",
off: "Off"
},
... etc ...
}
along with this function:
function buildTile( position, tileDefinition ){
var tile = angular.copy( tileDefinition );
tile.position = position;
return tile;
}
and then use them like this as items in a group:
groups: [ {
// Primary Lights & Switches
title: '',
width: 2,
height: 3,
items: [
buildTile( [0, 0], tiles.family_room_table_lamp ),
buildTile( [1, 0], tiles.room_basement_mediaroom ),
buildTile( [0, 1], tiles.room_basement_storage ),
buildTile( [1, 1], tiles.familyroom_spaceheater )
]
},
This allows me to use the same tiles in multiple places but only have to type out the definition for them once. Currently I am only applying the position they are used it, but the same approach could be used for width or any other property for that matter.
Initially I tried using the spread operator (which is much cleaner), which worked great on any browser on my laptop but did not work on FireOS because the core browser component is uses is older. So I had to adopt the buildTile function. Basically, the spread operator just splats all the property from the object after the […]. Here is an example of that in case any of you all can use it:
groups: [ {
// Primary Lights & Switches
title: '',
width: 2,
height: 3,
items: [
{ position: [0, 0], ...tiles.family_room_table_lamp },
{ position: [1, 0], ...tiles.room_basement_mediaroom },
{ position: [0, 1], ...tiles.room_basement_storage },
{ position: [1, 1], ...tiles.familyroom_spaceheater }
]
},
Hopefully that gives some of you ideas on how to clean up your config file. I hope to contribute more in the future.
Does anybody know why I keep getting logged out on tileboard?
Nice work, that’s a nice way to be able to reuse tiles as objects, I’ve been looking to clean up my config also as I have different tileboards for different devices. I’ll have to try making a tiles
array.
Up until now I’ve had each tile as a static object, for example
const GARAGE_LIGHT_A = {
position: [0, 1],
type: TYPES.SWITCH,
id: 'light.garage_light_1',
title: 'Light 1',
subtitle: 'Garage',
states: {
on: 'On',
off: 'Off'
},
icon: 'mdi-lightbulb'
}
then I just have GARAGE_LIGHT_A
in my group object, but being able to add the positions in after is so much nicer.
Finally, my camera stream popout seems to have stopped working, I have 2 camera streams and both camera thumbnails work in the tile but the popout has no image at all.
Is there an easy way to disable the camera popout? could I somehow overwrite the ng-click
class for camera tiles only?
I have everything in a tiles object but unlike the example I gave they are grouped like:
tiles: {
lights: {
family_room_table_lamp: { ... etc ... }
family_room_standing_lamp: { etc }
},
switches: { etc },
device_trackers: { etc },
weather: { etc }
}
so I can reference them like tiles.weather.forecast
Nice, having objects within objects is a nice touch.
I’ve found you can expand your build tile function to also be able to adjust the size of the tile too:
function buildTileBig (position, tileDefinition, width, height) {
var tile = angular.copy(tileDefinition);
tile.position = position;
tile.width = width;
tile.height = height;
return tile;
}
This was I’m able to re-use a camera tile for example to be different sizes on different pages, and to use it you just add the width and height values after the tile object name:
buildTileBig( [0, 1], ALL_TILES.CAMS.BACK, 3, 2),
will make a 3x2 sizes camera tile at position 0,1
I still use buildTile
for 1 x 1 sized tiles.
You are on the right track! But what happens when you want to be able to set another property? You either create another function or add another property to the existing function’s arguments list.
This is a little more generic and future-proof:
function buildTile( tileDefinition, options ){
var tile = angular.copy( tileDefinition );
Object.keys( options ).forEach( k => {
tile[ k ] = options[ k ]
} );
return tile;
}
Basically you just pass in an options object with whatever properties you want set on the tile. The function just loops through the properties on options and and then sets the value to a property of the same name on the tile created from the definition. The usage looks like:
buildTile( tiles.lights.room_mediaroom, { position: [0, 0] } ),
buildTile( tiles.lights.room_kitchen, { position: [0, 1], title: "Hello World", width: 2 } ),
// or for a bit more readability
buildTile(
tiles.lights.room_kitchen,
{
position: [0, 1],
title: "Hello World",
width: 2
}
),
With this we are getting back to the crux of how tileboard works except now you can define your defaults for a tile.
Yes this is basically what it does already… if you have just one thing to reuse why not put that in a variable and reuse it in the default tile builder?
I understand what your trying to simplify but to be honest this does not
function $$(tileObject, merge) {
if(merge instanceof Array) {
merge = {position: merge};
}
var copy = mergeObjects({}, tileObject);
return mergeObjects(copy, merge);
}
{
width: 3,
height: 3,
title: 'Scenes',
items: [
$$(TILES.GOOD_MORNING_SCENE, [0, 0]),
$$(TILES.GOOD_NIGHT_SCENE, [1, 0]),
$$(TILES.LIGHTS_OUT_SCENE, [2, 0]),
$$(TILES.MOVIE_SCENE, [0, 1]),
$$(TILES.GAME_SCENE, [1, 1]),
$$(TILES.RELAX_SCENE, [2, 1]),
]
}
True, all fair points.
In my case I have several items, mostly lights and switches, that I use for tiles in multiple places in my dashboard, for instance in an overview section on my home screen, maybe on a specific room page, and then again on a page that lists all lights. In my case being able to simply make a copy of the tile definition that includes most of the options already set and just being able to override the position is enough. And since I treat some tiles like that I want to treat all of them the same way, I do not want some tiles defined inline and some tiles defined as custom tiles, etc.
It does simplify it for me, but what works for me does not work for everyone.
function loadScript(url) {
var req = new XMLHttpRequest();
req.open('GET', url + '?cache=' + Math.random(), false);
req.onreadystatechange = function(){
if (req.readyState === 4) {
var s = document.createElement('script');
s.appendChild(document.createTextNode(req.responseText));
document.head.appendChild(s);
}
};
req.send(null);
}
loadScript('includes/helpers/functions.js');
loadScript('includes/helpers/states.js');
loadScript('includes/helpers/common.js');
loadScript('includes/helpers/events.js');
loadScript('includes/helpers/tiles.js');
If you have a lot of similar tiles on one page, you could could do something like this:
{
title: 'Downstairs',
width: 2,
height: 3,
items: [
['climate.hallway', 'sensor.hallway_heat_demand'],
['climate.av_room', 'sensor.av_room_heat_demand'],
['climate.lounge', 'sensor.lounge_heat_demand'],
['climate.kitchen', 'sensor.kitchen_heat_demand'],
['climate.dining_room', 'sensor.dining_room_heat_demand'],
['climate.utility_room']
].map(function(item, i) {
var y = Math.floor(i / 2);
return $$(TILES.CLIMATE, {
position: [i - y * 2, y],
subtitle: item[1] ? 'Valve at &' + item[1] + '.state' + '%' : false,
id: item[0]
});
})
}
As you can see, I’m also reusing TILE.CLIMATE
.
Nice that allows you to put any property in the array.
With this we are getting back to the crux of how tileboard works except now you can define your defaults for a tile.
I guess if you make after you add lots of changes to then sometimes it’s easier just to make a whole new one, but it’s really handy for me when I have a single camera tile that different sizes depending on which device I’m using Tileboard on.
Yes this is basically what it does already… if you have just one thing to reuse why not put that in a variable and reuse it in the default tile builder?
For me this help as I’ll re-use the tile on multiple tileboard layouts. Eg Phone has a tile layout that is different to my ipad, but they both use the same tiles. It’s great to have this flexability
EDIT: Is anyone else running HA behind 2 proxies? If so do your camera feeds work in popout mode in tileboard?
First of all @resoai thank you for this masterpiece. I have one question: is there any way to implement floorplan to your work? It would be really nice and usefull.
+1 for Floorplan support