Today a friend using Home Assistant showed me ha-floorplan - basically a way to display interactive SVGs in the web UI. Some skilled people got very creative with it - this goes far beyond floorplans since you can design your dashboard entirely with SVG!
But did you know you can already achieve a similar result for your openHAB system with HABPanel?
SVG can be included in templates without problems using ng-include!
Install Inkscape from https://inkscape.org/ (Linux users will find it in their distributionās package repositories, Windows 10 users can also install it from the Microsoft Store)
Create a new document, go to File > Document properties and change to an appropriate size (for instance 1024x768). You can also create the document with File > New from templateā¦ and use the Desktop template with your preferred size.
Design your floorplan.
Now, Iām no Inkscape guru so I wonāt get into details too much here, but there are a lot of resources on the Internet on that subject. You can import SVG icon files from e.g. flaticon.com with File > Import or add entire packs into Inkscape with this repository: https://github.com/Xaviju/inkscape-open-symbols
Use the double-curly braces notation: {{itemState('Your_Item_Name')}}
Your expression will be displayed on the drawing while youāre editing itā¦ it can be little bit annoying;
Put a generic placeholder as you see fit for editing purposes, and use the ng-bind directive:
a. Open the XML Editor with Edit > XML Editor (or use Ctrl-Shift-X);
b. Click on your text;
c. Add a new attribute named āng-bindā and put in the code you would place inside the double curly braces, like this:
d. Donāt forget to click āSetā or use Ctrl-Enter to commit the change!
Similarly, here is how you could make a simple switch - this is a little painful, but surely writing an AngularJS directive and lazy-loading it would work too (and be a little easier):
Open the XML Editor with Edit > XML Editor (or use Ctrl-Shift-X);
Click on your shape;
(note that this works on any shape, not only icons but also the entire room if you wish!)
Add a āng-classā attribute with the value below (adapt with your itemās name) and click Set: {"light-on": itemState('Your_Switch_Item') == 'ON' }
This will apply the light-on CSS class to the element whenever the state of the item is equal to ON. Weāll define this class later.
Add a āng-clickā attribute with the value below (adapt with your itemās name) and click Set: sendCmd('Your_Switch_Item', (itemState('Your_Switch_Item') == 'ON') ? 'OFF' : 'ON')
This will send either the command OFF to the item if its state is equal to ON, or the command ON otherwise.
Add a cursor attribute with this value: pointer and click Set;
Finally, create a CSS file and put in conf/html/floorplan.css with the content below - you can do lots of complex things, but this will simply define the CSS class light-on with a yellowish fill color (!important is here to override whatever fill color Inkscape would have applied directly to the element or its children):
.light-on {
fill: #ffe600 !important;
}
When youāre happy with your design, save your SVG file in conf/html/floorplan.svg
You can keep working on the SVG and the CSS file in conf/html, and simply reload the HABPanel page to pick up the changes! There are a lot of things in the CSS and SVG specs to render animations, color gradients, glow effects and shadows etc. For instance, take a look at the Filter menu in Inkscape. It will define filters and reference them in the style attribute. You can then use for example ng-style to add or remove a filter depending on a condition. Inkscape allows importing PDFs or images and embedding them in the SVG too.
Hope it helps - if you build something with SVG, please show off your results here!
Great work! I tried to create my own floorplan and it worked well thanks to your good tutorial.
I had not problem using the double-curly braces notation. However, when I alternatively try to use the placeholder with the ng-binding, I cannot format my output.
itemValue('rweTemp5a6130') +" Ā°C"
shows too many decimals. I would like to show my room temperature with only one decimal. With double-curly braces notation this looks like
{{itemValue('rweTemp5a6130') | number:1}} Ā°C
and works. When I want to use ng-bind, how do I need to adapt this? I tried same expression with and without double-curly braces, but neither works.
Any idea?
You can use parentheses to apply a filter only to a certain part of an expression (the ng-bind value or the contents inside the double curly braces), like this:
@ysc hey man, could u please share a code of how to make the light glow when on?
I try to follow This Link but itās for HA, I have no idea of how to make this css thing work, thanks!
You can however add an angular-clock, already built into HABPanel and used for clock widgets, on top of it. You would need to position it and style it manually with CSS, unfortunately.
Add something like this below the <div ng-include="(your SVG)"></div> in your template:
Is there any way to get ng-click to interact with another element/layer?! IĀ“d like to add some kind of overlay message if theres a click on a certain area.
SVG is a Document Object Model much like HTML, therefore all of AngularJSā directives that arenāt designed to work with specific HTML elements will work on SVG elements as well.
I tried to place some elements for blind control ā¦ Up, Stop, Downā¦
However the whole SVG is too crowded and I would rather use a Slider for this.
Can a slider be used in the SVG?
Thanks!
Current:
Would like to:
maybe a slider like thisā¦ which could replace the āwindowā itself and could control the blind and the same time show the current %state
This is just plain awesome! I have a question about having an item react to an update from OpenHAB. For example, I have door sensors on all exterior doors, is there a way that I can make the object for my doors fill red when the door is opened?
I created a āng-classā attribute for:
When I open the door, the panel does not changeā¦ I did not create an ng-click for a send command, because I donāt want to be able to click on the door and turn the sensor on, I would prefer it to react from an update from the device itself. Is this possible?
@jsable This is perfectly possible and your css and ng-class looks good already.
Maybe, you have a svg group selected instead of only one specific element?! If so, then you can simply assign ng-class to all of the grouped elements and it should work.
Thanks for the encouragement! I figured it out, forgot I had a translation set, so the āONā didnāt work for me, had to change it to āis Openā and they all started glowing red like I wanted!
itemState(itemname, [ignoreTransform]): retrieves the state of an item by its name;
ignoreTransform (optional, false by default) will return the raw state (e.g. āCLOSEDā) instead of the transformed state (āzuā)
So if you have transformations you can explicitely ignore them: itemState('ContactOfficeDoor', true) == 'ON'
(note the ātrueā as 2nd argument)
Iām a little stuck and Iām hoping you can point out what mistake Iām making. I created the .css file just as shown above and I created a really simple file: