Skip to content

openHAB: widget with multiple different background colors

Previously I blogged about how the washing machine and the dryer are integrated into the openHAB home automation system.

For a while I had a standard "Dummy" widget in HABpanel, but that didn't look very nice, was very standard, and the different icons for different states don't really work. When I started integrating another Raspberry Pi with a touch screen (blog post to come), I refreshed the HABpanel, added another dashboard, and along the way I wrote a new "Template" widget for the washing machine and the dryer.

This project had a number of small goals:

  1. Make the headline (the name) bigger - in the dummy it seems to be hardcoded, and very small
  2. Use the proper icon for every Item state (running, finished, standby)
  3. Change the background color of the widget according to the state of the Item

 

Turned out that 1) and 2) are easy to do, but 3) is a challenge. Every example I found was using a ? ternary operator, which allows for 2 modes: if-then-else. Three or more states can't be handled that way.

In the end, my solution was to define different background classes in a <style> element, and use "ng-class" to select the right class. Let's look at this in detail. The mapping and the rules for the washing machine are specified here. Based on that, style classes are defined:

<style>
  .off { background: rgb(34, 51, 68) }
  .standby { background: rgb(34, 51, 68) }
  .unknown { background: rgb(34, 51, 68) }
  .running { background: rgba(221, 112, 62, 0.3) }
  .finished { background: rgba(11, 160, 90, 0.2) }
</style>

These styles cover all known states, three of them use the HABpanel default colors, whereas "running" and "finished" use a red and a green color, plus 30% respectively 20% opaqueness. That is realised by specifying the colors as RGB codes (using the rgb() function) and the alpha channel (using the rgba() function).

These CSS classes are used in the <div> as background color, using the "ng-class" selector:

<div
class="box-content dummy"
ng-class="{off: itemValue('Washingmachine_State')=='Off', 
           standby: itemValue('Washingmachine_State')=='Standby', 
           unknown: itemValue('Washingmachine_State')=='Unknown', 
           running: itemValue('Washingmachine_State')=='Running',
           finished: itemValue('Washingmachine_State')=='Finished'}"
style="top:5px;bottom:5px;left:5px;right:5px;position:absolute;height:auto">

I also specify a border of 5 pixel on every side of the widget, which will not be colored. That gives a nicer look.

Inside of the <div> follows the "real" content, the header, the icon, and the Item state:

    <div class="dummy-content">
        <span class="ng-binding ng-scope" ng-style="{ 'font-size': '24pt' }">Washing Machine</span>
        <br class="ng-scope" />
        <br class="ng-scope" />
        <div ng-if="itemValue('Washingmachine_State')=='Off'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="0" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <div ng-if="itemValue('Washingmachine_State')=='Standby'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="3" class="ng-scope ng-isolate-scope"></widget-icon>
            </div>
        <div ng-if="itemValue('Washingmachine_State')=='Running'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="1" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <div ng-if="itemValue('Washingmachine_State')=='Finished'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="2" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <div ng-if="itemValue('Washingmachine_State')=='Unknown'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="0" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <br class="ng-scope" />
        <span ng-style="{ 'font-size': '32pt' }" class="value ng-binding">{{ itemValue('Washingmachine_State') }}</span>
    </div>

Using "ng-if" I select the desired icon for every state of the washing machine, "ng-if" will simply hide the <div> if the condition is not true. Every icon in openHAB might have different versions for different states. However they don't match across the board, the icons for the dryer state are different from the ones for the washing machine state. Please figure out which icon matches the state you have for your Item.

 

As a summary, here is the complete widget code:

<style>
  .off { background: rgb(34, 51, 68) }
  .standby { background: rgb(34, 51, 68) }
  .unknown { background: rgb(34, 51, 68) }
  .running { background: rgba(221, 112, 62, 0.3) }
  .finished { background: rgba(11, 160, 90, 0.2) }
</style>
<div
class="box-content dummy"
ng-class="{off: itemValue('Washingmachine_State')=='Off', 
           standby: itemValue('Washingmachine_State')=='Standby', 
           unknown: itemValue('Washingmachine_State')=='Unknown', 
           running: itemValue('Washingmachine_State')=='Running',
           finished: itemValue('Washingmachine_State')=='Finished'}"
style="top:5px;bottom:5px;left:5px;right:5px;position:absolute;height:auto">
    <div class="dummy-content">
        <span class="ng-binding ng-scope" ng-style="{ 'font-size': '24pt' }">Washing Machine</span>
        <br class="ng-scope" />
        <br class="ng-scope" />
        <div ng-if="itemValue('Washingmachine_State')=='Off'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="0" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <div ng-if="itemValue('Washingmachine_State')=='Standby'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="3" class="ng-scope ng-isolate-scope"></widget-icon>
            </div>
        <div ng-if="itemValue('Washingmachine_State')=='Running'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="1" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <div ng-if="itemValue('Washingmachine_State')=='Finished'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="2" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <div ng-if="itemValue('Washingmachine_State')=='Unknown'">
            <widget-icon size="'128'" iconset="'eclipse-smarthome-classic'" icon="'washingmachine_2'" state="0" class="ng-scope ng-isolate-scope"></widget-icon>
        </div>
        <br class="ng-scope" />
        <span ng-style="{ 'font-size': '32pt' }" class="value ng-binding">{{ itemValue('Washingmachine_State') }}</span>
    </div>
</div>

 

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

No comments

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
To leave a comment you must approve it via e-mail, which will be sent to your address after submission.
Form options