Design your SVG floorplan or dashboard for HABPanel with Inkscape

That how I´m doing it for showing/hiding layers… Works like a charm!

1 Like

Hi All,
I was inspired by the SVG integration in OpenHab Widgets and wanted to start with a simple “winamp” like title scrolling label to able to show longer texts in a small window (smartphones).
I hope the idea is inspiring for others.
The ‘static text’ is working ok (although some more customization dreams to make it useful for larger audience (fi: colour picker etc).

Unfortunately i’m a bit stuck to make the config parameters dynamic. The idea is to adjust the duration & shift parameters based on the (dynamic) text. I’m targeting to build this in the OpenHab rules, so would like to avoid/limit usage of JavaScript (not supported?) or angularjs (not familiar with).
(general design concept is to put all my logic in the OpenHab rules)

Can you help me with the syntax or help to be able to change the duration like we can change the text?

(attached the widgets so far … and the challenge below)
dur=“itemState(’{{config.txtOpenHabSVGDuration}}’) + " s”" ==> NOT WORKING
ng-bind=“itemState(’{{config.txtOpenHabSVGString}}’)” ==> OK

Note: ideally I would like to keep all the code in the widget itself, but i’m ok to load CSS or supporting files if required.

Thanks a lot

image

I try to open a browser window when clicking a SVG shape embedded into a HABPanel widget. I tried setting the standard SVG onclick attribute to “window.open(“myhtmlpage”);” and it is working fine when opening the SVG file in a browser. Once this SVG is embedded in the HABPanel widget, it does not work (no error in the logs neither). I tried ng-click too, using the same script, but do not get the HTML page displayed either.

What is it I do wrong? Thanks!

Latest openHAB 2.5.2 and Safari browser

Hi All,

Meanwhile I was able to solve my little challenge with the great support from MDAR.
Happy to share the current results. Now able to update scrolling speed/length the text and colour through openhab items and dynamically adjustable through openhab rules.

It’s still not very user friendly but meeting my needs. Feel free to improve the basic code and share an advanced version.

Please find the current draft release:
AnimatedStaticLabel.widget.json (1.6 KB)

AnimatedDynamicLabel.widget.json (1.6 KB)

or Wetransfer (till 06Mar19)

1 Like

Hello

By any chance…

Have any of you any ideas how I / we can get an itemValue to affect an sodipodi:end attribute of an arc?

@Kim_Andersen and I are trying just trying to create a nice little gauge in an SVG.

There is this fabulous gauge widget for HabPanel that works perfectly, which I guess uses something similar to the rotation technique described earlier in this thread.

Which might have to be what we settle for.

EDIT: I made some adjustments and moved to the modal, as defined in this link, and it works as expected.

I swear I had this working, but… if I want to use an angular variable (as opposed to using an OpenHab switch) to activate a modal defined in the custom template, ex: <div ng-click="Item_Modal=true">clicky</div>, how would I format the ng-click on an item in the svg? Just having Item_Modal=true in the svg value doesn’t seen to do it.

Thanks!

I know openHAB 3 will bring many changes to the UIs, specifically, that some or all of them will be merged into a new universal UI.

Does anyone in the know have any insight into how that will affect our ability to display SVGs in a HABPanel style as we have in the past? I’m really hoping that kiosk mode will remain available.

hello, always work with lights and UP&DOWN rollershutters
I would like to intert a kind of slider for rullershutters position (read-only)
Is there an object or I’m thinking about a “line” and trasform: scaleX or scaleY on % of the roller position (itemState) : can anybody help me?

PS: I have tryed scaleX on chrome but the line moves in a strange and non-standard way

hello, I would like to share my solution: this is my living room and my kitchen whit lamps and rollershutters.
The up and down button are green if the position is 0%(opened) and red if is 100% (closed) and normally black from 1% to 99%.

3 Likes

What app did you use to draw the floorplan? Looks very nice!

Sweethome 3d
Very easy

1 Like

Apparently, it’s possible to add interactive elements with SweetHome3D that work with openHAB2.

+1 for SweetHome 3D. I prefer the 2D floor plan but it’s very easy to export the SVG elements and edit them in Inkscape.

Thanks to @ysc and all, for this wonderful SVG dashboard design.
But is there a way one can navigate between the buttons on a dashboard using only the arrows keys on a keyboard? and also click by using the enter key? eg move focus using a keyboard.

1 Like

Thank you all very much for this tutorial - I have something working, with a rough outline of my house and my first lightbulb icon controlling a switch! When I tried to add more, I ran into a problem…

I moved the svg file on my server to floorplan.svg.old, and uploaded a new version to my server that I saved from inkscape. When I reloaded habpanel, I still have the previous version of the svg file. I tried restarting openhab2, but it still shows the old version of the floorplan. Any idea where my problem might be?

I have also had this problem.

I guess it’s a cache issue somewhere, but gave up after 5 minutes. Instead, I just save with a new name, and adjust the reference to the SVG file in HABPanel to point to the new name. This is a minor annoyance during development, but it’s a workaround…!

I’ve found the clearing the cache usually fixes this. Occasionally I need to restart the browser as well.

This problem is about the browser cache. The new file is not pulled again, instead the browser uses the svg already loaded.

Harry

Thank you all - copying the URL, closing the browser tab, and opening a new tab seems to have fixed the problem. Back to the matter of the day - getting light bulb icons to change color…

I did a little research and came up with this keyboard navigation that works on Habpanel using AngularJS. https://stackoverflow.com/questions/18086865/angularjs-move-focus-to-next-control-on-enter
https://stackoverflow.com/questions/14833326/how-to-set-focus-on-input-field?rq=1
You can navigate the grid of items using the arrow keys. You also have to make your items focusable.
Finally, you load or reload the page with the focus set on one item.
HTML below

<div oc-lazy-load="['/static/app1.js']">
<style>
g:focus {
  outline: none !important;
}
</style>
<body ng-app="App">

<svg width="1500px" height="500px"  xmlns="http://www.w3.org/2000/svg">
<g  next-focus=""  auto-focus="" id="recta0" >
<rect  x="10" y="20" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta0.focusin" end="recta0.focusout" to="red"/>
 <set attributeName="width" begin="recta0.focusin" end="recta0.focusout" to="200"/>
</rect>
<text x="42" y="58" fill="white"  font-weight="20" font-weight=normal >Raspberry Pi
<set attributeName="font-size" begin="recta0.focusin" end="recta0.focusout" to="25"/>
<set attributeName="font-weight" begin="recta0.focusin" end="recta0.focusout" to="bold"/>
</text>
</g>

<g  next-focus id="recta1" >
<rect  x="250" y="20" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta1.focusin" end="recta1.focusout" to="red"/>
 <set attributeName="width" begin="recta1.focusin" end="recta1.focusout" to="200"/>
</rect>
<text x="280" y="58" fill="white"  font-weight="20" font-weight=normal >Strawberry Pi
<set attributeName="font-size" begin="recta1.focusin" end="recta1.focusout" to="25"/>
<set attributeName="font-weight" begin="recta1.focusin" end="recta1.focusout" to="bold"/>
</text>
</g>


<g  next-focus="" id="recta2" >
<rect   x="490" y="20" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta2.focusin" end="recta2.focusout" to="red"/>
 <set attributeName="width" begin="recta2.focusin" end="recta2.focusout" to="200"/>
</rect>
<text x="532" y="58" fill="white"  font-weight="20" font-weight=normal >Blueberry Pi
<set attributeName="font-size" begin="recta2.focusin" end="recta2.focusout" to="25"/>
<set attributeName="font-weight" begin="recta2.focusin" end="recta2.focusout" to="bold"/>
</text>
</g>

<g  next-focus="" id="recta3" >
<rect   x="10" y="120" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta3.focusin" end="recta3.focusout" to="red"/>
 <set attributeName="width" begin="recta3.focusin" end="recta3.focusout" to="200"/>
</rect>
<text x="42" y="152" fill="white"  font-weight="20" font-weight=normal >Cranberry Pi
<set attributeName="font-size" begin="recta3.focusin" end="recta3.focusout" to="25"/>
<set attributeName="font-weight" begin="recta3.focusin" end="recta3.focusout" to="bold"/>
</text>
</g>

<g  next-focus="" id="recta4" >
<rect   x="250" y="120" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta4.focusin" end="recta4.focusout" to="red"/>
 <set attributeName="width" begin="recta4.focusin" end="recta4.focusout" to="200"/>
</rect>
<text x="280" y="152" fill="white"  font-weight="20" font-weight=normal >Blackberry Pi
<set attributeName="font-size" begin="recta4.focusin" end="recta4.focusout" to="25"/>
<set attributeName="font-weight" begin="recta4.focusin" end="recta4.focusout" to="bold"/>
</text>
</g>


<g  next-focus="" id="recta5" >
<rect   x="490" y="120" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta5.focusin" end="recta5.focusout" to="red"/>
 <set attributeName="width" begin="recta5.focusin" end="recta5.focusout" to="200"/>
</rect>
<text x="512" y="152" fill="white"  font-weight="20" font-weight=normal >Huckleberry Pi
<set attributeName="font-size" begin="recta5.focusin" end="recta5.focusout" to="25"/>
<set attributeName="font-weight" begin="recta5.focusin" end="recta5.focusout" to="bold"/>
</text>
</g>


<g  next-focus="" id="recta6" >
<rect   x="10" y="220" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta6.focusin" end="recta6.focusout" to="red"/>
 <set attributeName="width" begin="recta6.focusin" end="recta6.focusout" to="200"/>
</rect>
<text x="35" y="252" fill="white"  font-weight="20" font-weight=normal >Gooseberry Pi
<set attributeName="font-size" begin="recta6.focusin" end="recta6.focusout" to="25"/>
<set attributeName="font-weight" begin="recta6.focusin" end="recta6.focusout" to="bold"/>
</text>
</g>


<g  next-focus="" id="recta7" >
<rect   x="250" y="220" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta7.focusin" end="recta7.focusout" to="red"/>
 <set attributeName="width" begin="recta7.focusin" end="recta7.focusout" to="200"/>
</rect>
<text x="290" y="252" fill="white"  font-weight="20" font-weight=normal >Mulberry Pi
<set attributeName="font-size" begin="recta7.focusin" end="recta7.focusout" to="25"/>
<set attributeName="font-weight" begin="recta7.focusin" end="recta7.focusout" to="bold"/>
</text>
</g>


<g  next-focus="" id="recta8" >
<rect   x="490" y="220" fill="blue"  width="190" height="60"   >
 <set attributeName="fill" begin="recta8.focusin" end="recta8.focusout" to="red"/>
 <set attributeName="width" begin="recta8.focusin" end="recta8.focusout" to="200"/>
</rect>
<text x="522" y="252" fill="white"  font-weight="20" font-weight=normal >Pineberry pi
<set attributeName="font-size" begin="recta8.focusin" end="recta8.focusout" to="25"/>
<set attributeName="font-weight" begin="recta8.focusin" end="recta8.focusout" to="bold"/>
</text>
</g>

<g  next-focus="" id="recta9" >
<rect   x="10" y="320" fill="blue"  width="130" height="40"   >
 <set attributeName="fill" begin="recta9.focusin" end="recta9.focusout" to="red"/>
 <set attributeName="width" begin="recta9.focusin" end="recta9.focusout" to="150"/>
</rect>
<text x="30" y="345" fill="white"  font-weight="20" font-weight=normal >Next Page
<set attributeName="font-size" begin="recta9.focusin" end="recta9.focusout" to="25"/>
<set attributeName="font-weight" begin="recta9.focusin" end="recta9.focusout" to="bold"/>
</text>
</g>

</svg>

</body>
</div>

app1.js

var App = angular.module('App', []);
App.directive("nextFocus", nextFocus);
    function nextFocus() {
      var directive = {
        restrict: 'A',
        link: function($scope, elem, attrs) {       
          elem.bind('keydown', function(e) {
            var partsId = attrs.id.match(/recta(\d{1})/);
            var currentId = parseInt(partsId[1]);

            var code = e.keyCode || e.which;
            if (code === 39) {
              e.preventDefault();
              document.querySelector('#recta' + (currentId + 1)).focus();
            }
            
            if (code === 37) {
              e.preventDefault();
              document.querySelector('#recta' + (currentId - 1)).focus();
            }
            
            if (code === 40) {
              e.preventDefault();
              document.querySelector('#recta' + (currentId + 3)).focus();
            }
            
            if (code === 38) {
              e.preventDefault();
              document.querySelector('#recta' + (currentId - 3)).focus();
            }
            
          });
        }
      };
      return directive;

    }  
 App.directive('autoFocus', function($timeout) {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            $timeout(function(){
                _element[0].focus();
            }, 1);
        }
    };
});

I guess someone can improve on the code by minimizing it using style.