Examining the openhab_static_examples

Before you start this chapter, look at the previous chapter Installing the openhab_static_examples.

This tutorial examines the openhab_static_examples. So you should get a deeper understanding to the openHAB Item Types.

Motivation

In openHAB items are usually created bound. This means that there is usually a physically existing device. About an appropriate binding to this device (sometimes it is also any online accounts), then a Thing is created. This Thing makes it possible to create corresponding items via channels, which can be used in openHAB to operate the device.

Detached from any devices, bindings, things or channels, it is possible to create so-called unbound items, which can also be called virtual items. There are various application examples for this. For example, you can create a switch item that triggers only one rule, which would then serve multiple devices.

The goal of this tutorial is to provide an example of how to create an example for each Item Type independently of Things. This is to give an understanding of how individual Items and openHAB work. We are talking about static examples here, because by rules each of these examples should have a value assigned to it.

Note: I like to use such Hello World examples in the development of various programs, such as an MQTT event bus, a bridge between openHAB and ROS, a CRUD via the REST API or an SSE client for item events via the REST API and much more.

The Hello World Problem

In many programming languages there is an example for Hello World. This example shows the typical characteristics of this programming language. I will show an example how to create such a program for Java, because openHAB is written in Java:

public class HelloWorld 
{
 
       public static void main (String[] args)
       {
             String hello = "Hello World!"
             System.out.println(hello);
       }
}

I have slightly adjusted the output of the string "Hello World!" in this Hello World example, so that this string is stored in a variable beforehand. Because this is exactly what cannot be done in openHAB like this. The Items are often mistakenly understood as variables. But actually Items are objects. The most important attribute for value assignment is state. If an Item object is created, however, I cannot assign values to state. Other attributes like name, label or icon I can set. Or even assign an item to a group, which in turn is another item.

What does this mean in concrete terms? The following syntax applies to the item definition:

itemtype itemname "labeltext [stateformat]" <iconname> (group1, group2, ...) ["tag1", "tag2", ...] {bindingconfig}

The state of an item is not set when the item is defined or when the item object is instantiated! Typically a thing or a rule changes it.

If I would take my example from above from the Java program, the most I can do is to use a

String hello "[%s]"

out of it. A value assignment like

String hello="Hello World!" "[%s]"

or

String hello state="Hello World!" "[%s]"

or whatever it should look like then, is not possible!

By the way you can see by {bindingconfig} if an item is bound or not. In the {} either a binding directly or a channel of a thing would have to be accessed. With an unbound item this is completely omitted.

However, the Hello World problem not only points out that many are looking for some kind of value assignment, but also an output. To represent openHAB simplified:

Type

Description

By

Where

Object instantiation

To create an item, this object must first be created. Similar to classical programming you can pass different values (name, label, icon, ...) to the constructor.

Items

main UI, .items file or via the REST API

Attribute value assignment

Under attributes I call all attributes except state. Classically, many attributes are already set when the item is created. But for the display in the UI by sitemaps, I can override e.g. attributes like label or icon. Optionally, I can also use Rules to override an attribute like label, for example.

Items, Sitemaps, Rules

main UI, .items file or via the REST API, as well as in the .sitemaps file or in .rules files

Value assignment of states

Normally, the state is set by a thing or its channel as soon as a device is served. Also an event in openHAB (like operating a UI element) changes the state. But Events can also be used to trigger a Rule. Via sendCommand or postUpdate value assignments of States can also take place in Rules.

Things, Sitemaps, Rules

main UI, .things file or via the REST API, as well as in the .sitemaps file or in .rules files

output

An output of items is done in the UI. Classically only in sitemaps. Theoretically there is still an output in the Karaf console and by Rules you could additionally log the Items. Events for the Items are logged automatically.

Sitemaps, Karaf Console

main UI, .sitemaps file or via the REST API, as well as in the Karaf Console.


We therefore limit ourselves to instantiating an Item object in a .items file, then assigning the values of States in a .rules file, and defining their output through a .sitemaps file.

Object instantiation

As described above, the objects of the items are created in a .items file.

Group

We want to create a parent group, i.e. a group item. An item of type group does not have a state. In fact, for ease of use, we only need to specify the name of this group:

Group Static

It would also be possible that this Group would be subordinated to another Group. You can also specify a Label or an Icon.

Color

In the case of a Color Item, only the name of this Item needs to be specified for a minimalistic example. However, since we have already created a Group Item before, we want to subordinate this Item to our Group. We will also do this for all other Items later.

Color testColor (Static)

We can do without Label and Icon in a simple example!

Contact

The next Item we want to create is a Contact Item. This Item classically indicates whether, for example, a door is OPEN or CLOSED if a corresponding sensor would be used. For a later output in our Sitemap we have to set a Label here:

Contact testContact "[%s]" (Static)

The [%s] later adds the state of the item as a string. Without this specification it would not be visible whether a Contact Item has the State CLOSED or OPEN. You can also enter any String in the Labels in general. Thus also a prefix or postfix would be conceivable. This could be e.g. units. But this is not needed here. The reason why you have to parse the State to a String is that OPEN and CLOSED are treated as own datatypes by openHAB, which will play a role later in the Rules.

An icon is not used in this example!

DateTime

With a DateTime Item the Label is used again, so that one formats the Timestamp into a desired output format. This is needed because in different countries one specifies a date or time in different ways. Also it is conceivable that one specifies only the date or only the time. In the following example, only the time is to be output from the last recorded timestamp, i.e., the time is to be output in hours and minutes (HH:MM):

DateTime testDateTime "[%1$tH:%1$tM]" (Static)

The timestamp refers to the recorded time. It now depends on the rule what is considered as the last timestamp. More will be said about this later in the Rules. A DateTime Item is used in different ways. Mostly there are some sensor values and the DateTime Item then indicates when the last time a change of these sensor values has been recorded.

An Icon is not used in this example!

Dimmer

A 'dimmer' is classically used to dim something. This example is most familiar with lamps and their brightness. Typically, the states here are between 0 and 100, which would mean completely dark or completely bright in the previously mentioned example. This is a percentage. Another example might be a volume control. The Item are in a rudimentary example as follows:

Dimmer testDimmer (Static)

You can do without label and icon in a simple example!

Image

In openHAB an Image Item is used to display images. This can be any kind of image. No matter if formats like JPG, PNG, if it is about photos or snapshots, single frames, wallpapers or for example an album cover for music. Whatever should be represented by an image. Only GIFs are not possible. Also a video stream would be only theoretically conceivable, in which one represents the frames one after the other.

Image testImage (Static)

You can do without Label and Icon in a simple example!

Location

With a Location Item some kind of location is to be represented. The State contains GPS coordinates with longitude, latitude and the altitude. There are several application examples. For example, you could use your own weather station and it would have to be configured first or record where it is located. Maybe one has a robot (e.g. a lawn mowing robot) that has GPS or via a binding the vehicle would be linked to the smart home and as soon as one leaves the house the windows are locked.

Location testLocation "HS Furtwangen" <house> (Static)

Later we want to specify the coordinates of Furtwangen University as an example. Therefore we need the label HS Furtwangen. We can do without an icon, but since the university is a building, we use a house as Ìcon.

Number

With a number item you can represent any kind of numbers. Again, a label is needed for formatting. For example, it is important how many decimal places should be displayed or whether one should be displayed at all. Also the number can refer to any unit, like m, kmh or °C. In the following we want to represent an integer (integer), which in the end would be nothing else than a floating point number (float) without a decimal place:

Number testNumber "[%.0f]" (Static)

As you can see, % is used as a placeholder for the number and at the end you define the data type like float with f and the decimal places (here: 0). A temperature in degrees Celsius could be specified with "[%.2f °C]". More information about units can be found in the openHAB documentation!

We do without an icon in this simple example

Player

An Item of the type Player is used for example if you want to play music or a video. You can play, pause, fast forward or rewind this medium. It is also conceivable that the next or previous medium would be played.

Player testPlayer (Static)

You can do without Label and Icon in a simple example!

Rollershutter

The Rollershutter Item is not only used for roller shutters, but also for awnings or blinds. After all, they work almost the same way in principle. They are either retracted or extended. Optionally there is a value somewhere in between, because you have stopped the retraction or extension.

Rollershutter testRollershutter (Static)

You can do without Label and Icon in a simple example!

String

A String Item does exactly what you expect. You pass some kind of string to this Item, consequently this State is a String. In principle, you can also treat a single character or char as a string. The String Item is used very versatile. It can be the title of a medium, the last message of a news feed, a selected mode of a device and much more. Strings can also be formatted in any dense way. To fully display a string you have to define the label accordingly as well:

String testString "[%s]" (Static)

Logically, you could also convert a numeric value to a string. But then you are actually using the wrong data type.

An icon can be omitted in a simple example!

Switch

I honestly love the Switch Item! It is a simple switch that has the states ON and OFF. Besides whether a device is switched on, you can also use it to activate individual rules. Typically this is also used to activate or deactivate individual functionalities on a device. Or if you have a good style with rules, you can divide them into several parts and control them with several Switch Items in a row.

Switch testSwitch (Static)

You can do without Label and Icon in a simple example!

Total items

This then results in our .items file, which looks like this:

Group Static

Color testColor (Static)
Contact testContact "[%s]" (Static)
DateTime testDateTime "[%1$tH:%1$tM]" (Static)
Dimmer testDimmer (Static)
Image testImage (Static)
Location testLocation "HS Furtwangen" <house> (Static)
Number testNumber "[%.0f]" (Static)
Player testPlayer (Static)
Rollershutter testRollershutter (Static)
String testString "[%s]" (Static)
Switch testSwitch (Static)

Value assignment of states

Since we assume here a static example, i.e. that the values do not change, you can execute this Rule when you start openHAB. The <TRIGGER_CONDITION> System started is a so-called system-based trigger.

rule "Started"
when
    System started
then
    ...
end

In concrete terms, this means that as soon as openHAB is started, the Items should receive their values.

Color

For a Color Item, values in HSB format are expected for the State:

testColor.postUpdate("120, 100, 100") // hue, saturation, brightness

This would correspond to "0, 255, 0" in RGB!

Contact

For a Contact Item we simply assume that at system start the State is CLOSED:

testContact.postUpdate(CLOSED)

As we can see, in the rule we can use the state CLOSED directly and not mistakenly as a string "CLOSED". We should remember this for all state representations! A sendCommand would not be possible for a Contact Item!

DateTime

In most programming languages there is the possibility to create a date object in which a string is converted to a timestamp (often called string to time). In openHAB we ultimately do nothing else:

testDateTime.postUpdate(now.toLocalDateTime().toString())

In this case, however, we have taken our input from a date object that returns us the current time. This means that we have to convert the returned value to a string. For this we use toString(). A function that can often be useful in Rules.

Dimmer

With a Dimmer you only have to make sure that you use an integer between 0 and 100:

testDimmer.postUpdate(30)

Image

Images are definitely a special case. I cant just take any string and pass it. In openHAB an Image Item does not work either by specifying the path to an image. One could perhaps assume that I can use an image by specifying only its path. In this case it might not matter if I specify an absolute and local path or if the path points to an online source. In openHAB an image is stored and used as an image. This has been implemented in such a way that many devices can also deliver images. You have to assume that a device sends an image and not that you just include any image without any context and use in openHAB. Similar to many other sensor values, this is useful data.

However, since we are not using such an image, such as a frame from a camera, the following script shows how to add an image from an online source:

var userImageDataBytes = newByteArrayOfSize(0)
var url = new URL("http://127.0.0.1:8080/static/webapps/Image.jpg") // please use the IP to your openHAB instance
var byteStreamOutput = new ByteArrayOutputStream()
var urlConnection = url.openConnection()
var userpass = "openhabian" + ":" + "openhabian";
var basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
urlConnection.setRequestProperty ("Authorization", basicAuth);
var inputStream = urlConnection.getInputStream()
var n = 0
var buffer = newByteArrayOfSize(1024)
do {
    n = inputStream.read(buffer)
    if (n > 0) {
        byteStreamOutput.write(buffer, 0, n)
    }
} while (n > 0)
userImageDataBytes = byteStreamOutput.toByteArray()

var String encodedString = Base64.getMimeEncoder().encodeToString(userImageDataBytes).replaceAll("\\r\\n", "")
var ImageTMP = "data:image/jpg;base64," + encodedString

testImage.postUpdate(ImageTMP)  

In this example we use the HTML directory (/etc/openhab/html) of openHAB. To extend this a bit, I created the subdirectory webapps and put an image.jpg in it. So if I want to add a local image from my server running openHAB, I would rather recommend to link a symbolic link into the HTML directory and proceed as above. Of course you can also add images using Java functions. This possibility allows you to add an image from other computers in the same network.

It is important that you work with Streams and that the image at the end is Base64 encoded as a string and updated as State! Also a sendCommand is not possible with images!

Location

As we have already noticed from the label, we want to use the GPS coordinates of Furtwangen University as State for the Location Item. This is also done by a string. However, we have to pass this to a PointType object:

// 48.051437316054006, 8.207755911376244
// latitude: 48.0501442
// longitude: 8.2014192
// altitude/elevation: 857.0
testLocation.postUpdate(new PointType("48.051437316054006, 8.207755911376244, 857.0"))

Number

For a Number Item it does not matter in the end which number you assign. The important thing is that a State can contain e.g. a floating point number and in the Sitemap you still format to an integer! If one should access this state, one would have to consider this e.g. in a rule then:

testNumber.postUpdate(50)

Player

For a player we can use States like PLAY, PAUSE, REWIND, FASTFORWARD, PREVIOUS or NEXT:

testPlayer.postUpdate(PAUSE)

Again, don't specify this as a string!

Rollershutter

Likewise, Rollershutter Items do not use strings with their Commands. As an example, however, we want to set a state:

testRollershutter.postUpdate(0)

String

As already mentioned, a string can be a classic string or contain a single character. The whole thing is processed as a string. As we know from many programming languages (here still Java), a string is nothing else than an array of characters or in other words an array of characters:

testString.postUpdate("Hello World")

Switch

A switch can have either the state ON or OFF:

testSwitch.postUpdate(OFF)

Total Rules

This then results in the following rule:

import java.util.Base64
import java.io.ByteArrayOutputStream
import java.net.URL

rule "Started"
when
    System started
then
    testColor.postUpdate("120, 100, 100")
    testContact.postUpdate(CLOSED)
    testDateTime.postUpdate(now.toLocalDateTime().toString())
    testDimmer.postUpdate(30)
    testNumber.postUpdate(50)
    testPlayer.postUpdate(PAUSE)
    testRollershutter.postUpdate(0)
    testString.postUpdate("Hello World")
    testSwitch.postUpdate(OFF)

    // 48.051437316054006, 8.207755911376244
    // latitude: 48.0501442
    // longitude: 8.2014192
    // elevation: 857.0
    testLocation.postUpdate(new PointType("48.051437316054006, 8.207755911376244, 857.0"))

    var userImageDataBytes = newByteArrayOfSize(0)
    var url = new URL("http://127.0.0.1:8080/static/webapps/Image.jpg") // please use the IP to your openHAB instance
    var byteStreamOutput = new ByteArrayOutputStream()
    var urlConnection = url.openConnection()
    var userpass = "openhabian" + ":" + "openhabian";
    var basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
    urlConnection.setRequestProperty ("Authorization", basicAuth);
    var inputStream = urlConnection.getInputStream()
    var n = 0
    var buffer = newByteArrayOfSize(1024)
    do {
        n = inputStream.read(buffer)
        if (n > 0) {
            byteStreamOutput.write(buffer, 0, n)
        }
    } while (n > 0)
    userImageDataBytes = byteStreamOutput.toByteArray()

    var String encodedString = Base64.getMimeEncoder().encodeToString(userImageDataBytes).replaceAll("\\r\\n", "")
    var ImageTMP = "data:image/jpg;base64," + encodedString

    testImage.postUpdate(ImageTMP)      
end

Output

You can add each item individually to a sitemap and you can also subdivide it as you like. No matter if this is organized in Frames or also in Groups. You can also set a (new) label or icon for each item. Unlike with Items, different representations can be considered, such as Chart or Webview. More about this can be found in the openHAB documentation at Sitemaps.

Entire sitemaps

Since we wanted a simple example for each item, we do not even have to experiment with many possibilities of the sitemap. It is enough for us to represent the whole thing by a Group Item:

sitemap Sitemap label="Sitemap" {
    Frame label="Static" {
        Group item=Static
    }
}

The finished sitemap looks like this:

https://raw.githubusercontent.com/Michdo93/openhab_static_examples/master/sitemap.png

Value change

To change the States you can write another Rule besides operating the elements in the Sitemap. So that I can test my applications, I decided to write a Rule with a Cron trigger of one minute. It actually works exactly the same as the rule that statically sets the values:

import java.util.Base64
import java.io.ByteArrayOutputStream
import java.net.URL

rule "Cron every minute"
when
    Time cron "0 0/1 * * ?"   // every minute
then
    testColor.postUpdate(NULL)
    testContact.postUpdate(NULL)
    testDateTime.postUpdate(NULL)
    testDimmer.postUpdate(NULL)
    testNumber.postUpdate(NULL)
    testPlayer.postUpdate(NULL)
    testRollershutter.postUpdate(NULL)
    testString.postUpdate(NULL)
    testSwitch.postUpdate(NULL)
    testLocation.postUpdate(NULL)
    testImage.postUpdate(NULL)

    testColor.postUpdate("120, 100, 100")
    testContact.postUpdate(CLOSED)
    testDateTime.postUpdate(now.toLocalDateTime().toString())
    testDimmer.postUpdate(30)
    testNumber.postUpdate(50)
    testPlayer.postUpdate(PAUSE)
    testRollershutter.postUpdate(0)
    testString.postUpdate("Hello World")
    testSwitch.postUpdate(OFF)

    // 48.051437316054006, 8.207755911376244
    // latitude: 48.0501442
    // longitude: 8.2014192
    // elevation: 857.0
    testLocation.postUpdate(new PointType("48.051437316054006, 8.207755911376244, 857.0"))

    var userImageDataBytes = newByteArrayOfSize(0)
    var url = new URL("http://127.0.0.1:8080/static/webapps/Image.jpg") // please use the IP to your openHAB instance
    var byteStreamOutput = new ByteArrayOutputStream()
    var urlConnection = url.openConnection()
    var userpass = "openhabian" + ":" + "openhabian";
    var basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
    urlConnection.setRequestProperty ("Authorization", basicAuth);
    var inputStream = urlConnection.getInputStream()
    var n = 0
    var buffer = newByteArrayOfSize(1024)
    do {
        n = inputStream.read(buffer)
        if (n > 0) {
            byteStreamOutput.write(buffer, 0, n)
        }
    } while (n > 0)
    userImageDataBytes = byteStreamOutput.toByteArray()

    var String encodedString = Base64.getMimeEncoder().encodeToString(userImageDataBytes).replaceAll("\\r\\n", "")
    var ImageTMP = "data:image/jpg;base64," + encodedString

    testImage.postUpdate(ImageTMP)      
end

The next chapter continues with Examining the openhab_msgs.

Wiki: openhab_bridge/Tutorials/ExaminingTheOpenHABStaticExamples (last edited 2022-10-27 15:47:18 by Michdo93)