Show raw openHAB Image Type in HABpanel

Posted by ads' corner on Saturday, 2020-02-22
Posted in [Software]

In our Home Automation system, I read weather data from OpenWeatherMap. I blogged about the implementation before. The weather data provides an icon which can be used to show the current weather:

1
2
3
4
5
6
7
8
9
Image	homeCurrentIcon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:current#icon" }
Image	homef03Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours03#icon" }
Image	homef06Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours06#icon" }
Image	homef09Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours09#icon" }
Image	homef12Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours12#icon" }
Image	homef15Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours15#icon" }
Image	homef18Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours18#icon" }
Image	homef21Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours21#icon" }
Image	homef24Icon		"Icon"		{ channel="openweathermap:weather-and-forecast:home:forecastHours24#icon" }

On the openHAB server side, this reads the picture data into the Item itself:

2020-02-20 00:39:38.476 [vent.ItemStateChangedEvent] - homeCurrentIcon changed from raw type (image/png): 3801 bytes to raw type (image/png): 2773 bytes
2020-02-20 03:59:47.156 [vent.ItemStateChangedEvent] - homeCurrentIcon changed from raw type (image/png): 2773 bytes to raw type (image/png): 2565 bytes
2020-02-20 04:19:48.006 [vent.ItemStateChangedEvent] - homeCurrentIcon changed from raw type (image/png): 2565 bytes to raw type (image/png): 2922 bytes

The really interesting question is: how can I display this icon directly in HABpanel. The available documentation is sparse to non-existent.

There is an openHAB widget named “Image” which can show a single image. However that is meant to show either an URL, or something like a full-size image, in a single panel. That’s not helpful if one wants to design a template, and include the weather icon as part of a larger display. In the end I looked into the source, and figured out what I need in order to display the icon as part of a larger template. Here is the necessary code:

1
<div ng-init="weatherimage = { 'image_source': 'item-image', 'item': 'homeCurrentIcon' }"><widget-image ng-model="weatherimage"></widget-image>

The image_source is defined as item-image, specifying that the data comes directly from the Item, and is not an URL. The item specifies the Item which is defined in openHAB. Easy, so far. Here is a piece of code placing this into a “Template” widget:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<table style="width: 100%; float: center; text-align: center;">
    <tr>
        <th style="width: 50%; text-align: center; font-size: 3em;">
            Weather
        </th>
    </tr>
    <tr>
        <td style="text-align: center;"><div ng-init="weatherimage = { 'image_source': 'item-image', 'item': 'homeCurrentIcon' }"><widget-image ng-model="weatherimage"></widget-image></div></td>
    </tr>
</table>

The result however is surely not what I expected:

Weather Widget
Weather Widget

The small icon (50 x 50 pixel in original) is shown way too largs, overflowing the Template box. Inspecting the CSS shows that the default CSS inflates the image 15 times (zoom = 15). Which means this needs more CSS to bring it back to it’s designated size. It also means that this needs a separate CSS class in order to apply the style, overriding the defaults. I ended up rewriting the Template content as follow:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
.image-content img {
  zoom: 2;
  width: 50;
  height: 50;
  border-style: none;
}
.image-define div {
  border-style: none;
  border-width: 0px;
}
</style>
<table style="width: 100%; float: center; text-align: center;">
    <tr>
        <th style="width: 50%; text-align: center; font-size: 3em;">
            Weather
        </th>
    </tr>
    <tr>
        <td style="text-align: center;"><div class="image-define" ng-init="weatherimage = { 'image_source': 'item-image', 'item': 'homeCurrentIcon', refresh: 1800, 'background': '#223344' }"><widget-image ng-model="weatherimage"></widget-image></div></td>
    </tr>
</table>

This applies an image-define class to the image, and the according CSS is in the <style>. This also adds a background to the image, to get rid of the ugly black box. And the CSS removes the border, along with inflating the image “only” 2 times. It also adds a refresh option to reload the image every 30 minutes. The final result:

Weather Widget
Weather Widget

Now I can add more weather information (like temperature and such).


Categories: [Software]