[SOLVED] Habpanel dynamic icons for dimmer

Good evening,

I’m working on my dashboard in Habpanel.
I have a custom/template widget with the lights in the living room.
There is one dimmer on the widget, but I’m looking for a smart way of displaying the dynamic image/icon for the slider.
It now only looks for the state of the dimmer, when it’s ‘0’, it shows image1, if it’s not ‘0’, it shows image2.
But, to make is smoother, I would like to use image-00, image-10, image-20 etc etc.
The widget looks like:

image

The code I’m using at the moment is:

 <div ng-if="itemValue('GF_LivingDining_Light')=='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_LivingDining_Light')!='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-100.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','OFF')"/>
          </div>

So it’s a simple if statement used. However, it would be a lot nicer to use the whole range of png’s to get a nicer look.
But I have no clue how to do that in a smart way…
Hope anyone can help me in the right direction!

ps. there are two images with the same if statement for the “eettafel” since this is a double lamp controlled by the dimmer…

Added:
I forgot to mention, for completeness, that except the dimmer, the other lights are controlled by just clicking /tapping the icon, see below:
image

Thanks in advance!
/Jasper

Dynamic icons used in Habpanel must be in .svg format, not .png .
Naming convention must be as described here
I use it in dummy widget and it works, no idea how it should be in HTML.

I had similar case where I want to use PNG as i want to keep detail bitmap picture to show current moon age as following:

<!-- moon age widget -->
<div ng-init="ServerPath='/static/moon-icons'">
</div>


<figure>
  <img ng-src="{{ServerPath}}/{{itemValue('Moon_Phase_MoonAge').split(' ')[0]}}.png" ></img>
  <figcaption> Moon age: <br>{{itemValue('Moon_Phase_MoonAge1')}} days </figcaption>
</figure>
</div>

where Item
Moon_Phase_MoonAge is Number:Time
Moon_Phase_MoonAge1 is Number
and both are updated by astro binding

pictures are in /etc/openhab2/html/moon-icons
names are just numbers 0.png 1.png …28.png.

result :image

cons is you have to create image for any value of slider or i can imagine to have proxy item and rule updating this item with rounded value to 10, 20 etc. and have corresponding pictures.

Thanks @kukulin!

What I will check if I can make a mapping for the dimmer value.
e.g.
0 = 0
1…10 = 10
11…20 = 20

and so on, then use the mapped value to show the correct png…
I’ll post an update asap…

/Jasper

Ok,
I made a new number item, called dimmerScaledValue and “scale” it to a 10th number.
The dimmer.scale file looks like:

[0] = 0
[0.01..0.10] = 10
[0.11..0.20] = 20
[0.21..0.30] = 30
[0.31..0.40] = 40
[0.41..0.50] = 50
[0.51..0.60] = 60
[0.61..0.70] = 70
[0.71..0.80] = 80
[0.81..0.90] = 90
[0.91..1] = 100

and the item is like:

Number dimmerValueScaled "Scaled Dimmer: [SCALE(dimmer.scale):%s]" {channel="zwave:device:lights:node8:switch_dimmer1" }

I tested it in habpanel and it gives me the correct numbers:
image
Now the only trick is to attach the number to the default, with code like:
ceiling-lamp-anim{{itemValue('dimmerValueScaled')}}.png

will give it a try…

Ok, done…
small update on the scale file since 1.0 was not scaled back to 100…so I added another scale:

[0] = 0
[0.01..0.10] = 10
[0.11..0.20] = 20
[0.21..0.30] = 30
[0.31..0.40] = 40
[0.41..0.50] = 50
[0.51..0.60] = 60
[0.61..0.70] = 70
[0.71..0.80] = 80
[0.81..0.90] = 90
[0.91..1] = 100
[1]=100

The item is the same:

Number dimmerValueScaled "Scaled Dimmer: [SCALE(dimmer.scale):%s]" {channel="zwave:device:lights:node8:switch_dimmer1" }

and the widget uses:

<div ng-if="itemValue('GF_LivingDining_Light')=='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_LivingDining_Light')!='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim{{itemValue('dimmerValueScaled')}}.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','OFF')"/>
          </div>

outcome:

Thank you @kukulin for pointing me in the right direction!

/Jasper

1 Like

I’m not sure why you don’t exploit the built-in icon server for sitemap UIs. I’m not a habpanel user, but it supposedly works.
A couple of gotchas are revealed in this thread

Thats a nice little dimmer widget, do you have the code for the actual dimmer item? I find loading dimmer sliders in HabPanel slow and clunky.

hi @dastrix80 / Kris,

It’s a “complete” widget for the lights on the ground floor.
The dimmer part is “just” a column of a table with CSS markup.
Please let me know if you want the complete widget code with CSS or just how to adjust the slider with markup?

Hi Jasper, I’d be keen to see the complete widget or even just 1 dimmer is enough. I’ve struggled with the ones I;ve been using (attached), just too slow and not very responsive.

<div class="widget" ng-if="itemValue('LivingRoomSw1')=='OFF'" ng-click="sendCmd('LivingRoomSw1', 'ON')">
                    <div class="icon off">
                        <svg viewBox="0 0 48 48">
                            <use xlink:href="/static/matrix-theme/matrixicons.svg#off"></use>
                        </svg>
                    </div>
                    <div class="name">Living {{itemValue('LivingRoomSw1')}}</div>
                </div>
                <div class="widget" ng-if="itemValue('LivingRoomSw1')=='ON'" ng-click="sendCmd('LivingRoomSw1', 'OFF')">
                    <div class="icon on">
                        <svg viewBox="0 0 48 48">
                            <use xlink:href="/static/matrix-theme/matrixicons.svg#on"></use>
                        </svg>
                    </div>
                    <div class="name">Living {{itemValue('LivingRoomSw1')}}</div>
                </div>
                <div class="slider-div" ng-init='LivingRoomDim1={"name": "Living Brightness", "item": "LivingRoomDim1", 
                    "floor" : 0,
                    "ceil": 100,
                    "step": 1,
                    "hidelabel" : "true",
                    "hidelimits": "true",
                    }'>
                    <widget-slider ng-model="LivingRoomDim1" />
                </div>
1 Like

Hi Kris,

Ok, so I’ve created a “custom widget” for the lights control on ground floor.
I do not use svg icons, but png’s instead. For the dimmer, I use a “dimmer.scale” file, so I get the correct value for the icon based on 10 different icons… dimmer values 0 till 100% divided by chunks of 10.
Icons are in a separate folder in static/icons
With having this said, here’s my config. Any optimization suggestions are always welcome!

The widget code:

<div ng-init="ServerPath='http://10.0.0.2:8080'; ">
<link rel="stylesheet" type="text/css" href="{{ServerPath}}/static/css/livingroom.css" />

<div class="living-container">
	<div class="living-title">
    <span class="living-title-text">Ground Floor Lighting</span>
  </div>
  <div class="living-divider-div">
  	<div class="divider"></div>
  </div>
  <div class="living-body">
  	<table>
      <tr>
        <td>Voordeur</td>
        <td>Hal</td>
      	<td>TV-Meubel</td>
        <td>Plafond</td>
        <td colspan="2">Eettafel</td>
      </tr>
    	<tr>
        <td>
          <div ng-if="itemValue('GF_Entrace_Light')=='OFF'">
          	<img ng-src={{ServerPath}}/static/icons/wall-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_Entrace_Light','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_Entrace_Light')=='ON'">
          	<img ng-src={{ServerPath}}/static/icons/wall-lamp-anim-100.png height="100" width="100" ng-click="sendCmd('GF_Entrace_Light','OFF')"/>
          </div>
        </td>
        <td>
          <div ng-if="itemValue('GF_Hall_Light')=='OFF'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim.png height="100" width="100" ng-click="sendCmd('GF_Hall_Light','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_Hall_Light')=='ON'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim100.png height="100" width="100" ng-click="sendCmd('GF_Hall_Light','OFF')"/>
          </div>
        </td>
        <td>
          <div ng-if="itemValue('GF_Light_TV')=='OFF'">
          	<img ng-src={{ServerPath}}/static/icons/desk-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_Light_TV','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_Light_TV')=='ON'">
          	<img ng-src={{ServerPath}}/static/icons/desk-lamp-anim-100.png height="100" width="100" ng-click="sendCmd('GF_Light_TV','OFF')"/>
          </div>
        </td>
        
        <td>
          <div ng-if="itemValue('GF_Living_mainLight_Switch')=='OFF'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_Living_mainLight_Switch','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_Living_mainLight_Switch')=='ON'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-100.png height="100" width="100" ng-click="sendCmd('GF_Living_mainLight_Switch','OFF')"/>
          </div>
        </td>
        <td>
          <div ng-if="itemValue('GF_LivingDining_Light')=='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_LivingDining_Light')!='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim{{itemValue('dimmerValueScaled')}}.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','OFF')"/>
          </div>
        </td>
        <td>
          <div ng-if="itemValue('GF_LivingDining_Light')=='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim-000.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','ON')"/>
          </div>
        	<div ng-if="itemValue('GF_LivingDining_Light')!='0'">
          	<img ng-src={{ServerPath}}/static/icons/ceiling-lamp-anim{{itemValue('dimmerValueScaled')}}.png height="100" width="100" ng-click="sendCmd('GF_LivingDining_Light','OFF')"/>
          </div>
        </td>
      </tr>
      <tr>
        <td>
        	<div ng-if="itemValue('GF_Entrace_Light')=='OFF'">
          	OFF
          </div>
        	<div ng-if="itemValue('GF_Entrace_Light')=='ON'">
          	ON
          </div>
        </td>
        <td>
        	<div ng-if="itemValue('GF_Hall_Light')=='OFF'">
          	OFF
          </div>
        	<div ng-if="itemValue('GF_Hall_Light')=='ON'">
          	ON
          </div>
        </td>
      	<td>
        	<div ng-if="itemValue('GF_Light_TV')=='OFF'">
          	OFF
          </div>
        	<div ng-if="itemValue('GF_Light_TV')=='ON'">
          	ON
          </div>
        </td>
        <td>
        	<div ng-if="itemValue('GF_Living_mainLight_Switch')=='OFF'">
          	OFF
          </div>
        	<div ng-if="itemValue('GF_Living_mainLight_Switch')=='ON'">
          	ON
          </div>
        </td>
        <td colspan="2">
          <div style="width: 100%" ng-init='tablelightModel={
                             	name: "percentage",
                             	item: "GF_LivingDining_Light",
                             	floor : 0,
                             	ceil: 100,
                             	selectionBarGradient: {
     														 from: "white",
     														 to: "#FC0"
    												 	}, 
                             	step: 1,
                             	hidelabel : true,
                             	hidelimits: false,
                              vertical: false,
                             	showTicks:true
                                      
                             }'>
     					
            	<widget-slider ng-model="tablelightModel" id="dimmer-slider"></widget-slider>
					</div>
        	
        </td>
      </tr>
    </table>
  </div>
</div>

The css:

.living-container{
    position: absolute;
    left: 0px;
    right: 0px;
    top: 0px;
    bottom: 0px;
    color: white;
    border-radius: 15px;
    border: 2px solid #FFF;
    padding: 1px;
  }

  .living-title{
     left: 0px;
    right: 0px;
    top: 0px;
    color: white;
  
  }
  .living-title-text{
    color: white;
    font-family: Verdana, Geneva, Tahoma, sans-serif;
    font-size: 1.2em;
    font-weight: 900;
    text-shadow: 2px 2px #000000;
  }
  .living-divider-div{
    height: 10px;
  }
  .divider { 
    display:block;
    border:none;
    color:white;
    height:1px;
    background:black;
    background: -webkit-gradient(radial, 30% 30%, 0, 30% 30%, 350, from(#fff), to(#000));
  }   

  #dimmer-slider{
    
  }

  #dimmer-slider .rz-bubble {
    color: white;
 }
  #dimmer-slider .rz-pointer {
    top: -7px;
    width: 14px;
    height: 14px;
    background: #f7f712;
  }
  #dimmer-slider .rz-pointer:after{
      top: 3px;
      left: 3px;
      background: #f7f712;
  }
  #dimmer-slider .rzslider .rz-bar.rz-selection {
    background: linear-gradient(to right, #ffffff, #ffff13);
  }

and finally the dimmer.scale (i think the first and the last entry are wrong according to the rules…checking this):

[0..0] = 0
[0.01..0.10] = 10
[0.11..0.20] = 20
[0.21..0.30] = 30
[0.31..0.40] = 40
[0.41..0.50] = 50
[0.51..0.60] = 60
[0.61..0.70] = 70
[0.71..0.80] = 80
[0.81..0.90] = 90
[0.91..1[ = 100

then I have this item for the scaling:

Number dimmerValueScaled "Scaled Dimmer: [SCALE(dimmer.scale):%s]" {channel="zwave:device:3d4427ff:node8:switch_dimmer1" }

Let me know if this is what you are looking for!

/Jasper

1 Like

Thanks Jasper! Ill have a look through this. Appreciated

1 Like

Most welcome Kris,
Let me know in case of questions…