OpenHAB

Aus Debacher-Wiki
Wechseln zu:Navigation, Suche

Hinweis: Dieser Text ist eine allererste Arbeitsversion. Ich fange hier aktuell an meine Erfahrungen fest zu halten. Wenn ich einigermaßen am Ziel bin, dann werde ich eine neue Installation vornehmen und diesen Text verfollständigen und glätten.

Eigentlich spiele ich schon lange mit dem Gedanken in meinem Netzwerk OpenHAB zu nutzen um nicht nur die Homematic-Geräte bequemer steuern zu können.

Aktuell ist das aber sehr dringend geworden, da Panasonic seine Kunden verärgert. Wir haben im Haus mehrere Geräte der Panasonic AllPlay-Reihe. Diese Geräte kann man von Handy und Tablet aus steuern. Das funktioniert auch weiterhin. Zusätzlich konnte man aber auch Rundfunksender aufrufen und auf Programmtasten am Gerät speichern. Dabei ist man aber auf die App AllPlay Radio angewiesen in der die entsprechenden Senderstreams hinterlegt sind. Leider hat Panasonic im Jahr 2020 die App abgekündigt und inzwischen haben sich immer mehr Adressen von Senderstreams geändert.

Wir haben uns dann ein kleines DAB+-Radio gekauft, aber ist ärgerlich die ja recht teuren Panasonic-Geräte stehen zu haben und sie nur gelegentlich mit Spotify zu nutzen, statt wie bisher regelmäßig als gekoppelte Internetradio-Receiver. Es ist recht umständlich über die Panasonic Music Streaming zu gehen.

Mein Ansatz war die Sender über die Homematic-Fernbedienung starten und stoppen zu können und dazu brauche ich OpenHAB.

Konzepte von OpenHAB

Am Anfang ist es nicht ganz einfach das Konzept von OpenHAB nachzuvollziehen. Das folgende Bild zeigt mein Verständnis davon, das ich aus Diskussionen mit Rich Koshak gewonnen habe:

Bildschirmfoto von 2021-12-09 18-41-38.png

Am Anfang (im Bild rechts) stehen immer die Geräte (Devices), wie ein Homematic Heizkörper-Thermostat, ein Samsung TV oder ein Shelly-Plug. Diese Geräte unterschiedlichster Hersteller werden über Bindigs in die OpenHAB-Welt eingebunden. Bindings sind im Prinzip Software-Schnittstellen, die OpenHAB erweitern. Über das Binding wird die zugehörige Hardware erkannt und als Thing in die Oberfläche übernommen. Jedes Thing besitzt dann eine Reihe von Channels, über die bestimmte Einstellungen abgefragt bzw. geändert werden können.

Mit den Things und Channels selber beschäftigt man sich in OpenHAB aber kaum.

Zentral in OpenHAB sind die Items, das sind meist Links auf Channels (die Points). Es gibt aber auch Items, die andere Items zusammenfassen, gruppieren. Wenn diese Items auf Links zu Channels basieren, dann wird damit ein Equipment beschreiben, ein Ausrüstungsgegenstand. Das Equipment kann auf einem Device beruhen, muss aber nicht. Es können Channels fehlen, oder Channels von anderen Devices mit verlinkt werden. Neben diesen Gruppen-Items vom Typ Equipment gibt es Items vom Typ Location, die im weitesten Sinne Räume beschreiben, wobei dann auch wieder mehrere Räume zu einem Gruppen-Item z.B. einer Etagen-Location zusammengefasst werden können.

Den Zusammenhang zwischen den Items der unterschiedlichen Typen:

  • Location
  • Equipment
  • Point

wird im Model definiert.

Bildschirmfoto von 2021-12-17 19-50-11.png

Ergeschoss (FirstFloor) und Esszimmer (DiningRoom) sind hier Items vom Type Location. Fenster.Esszimmer.01 und Shelly Plug-S (SHPLG-S) sind dann Items (die Bezeichner sind nicht glücklich, weil teilweise zusammengesetzt mit Location), vom Typ Equipment in der Location Esszimmer.

Das Shelly Plug verfügt dann über eine Reihe von Items des Typs Point, die auf den Kanälen des Devices beruhen. Von den 17 Channels des Devices haben aber nur 9 eine Entsprechung als Point des Equipments

Es ist sinnvoll, das Model für OpenHAB sehr sauber und ordentlich zu strukturieren. Das erleichtert die Konfiguration der Pages, über die dann die Funktionalität von OpenHAB realisiert wird. Auf den Pages bindet man dazu vordefinierte oder selbst erstellte Widgets ein.

Etwas verdeutlicht werden die Zusammenhänge auch unter Einstellungen -> Model

Bildschirmfoto von 2021-12-19 20-46-31.png

Über den Menüpunkt Create Equipment from Thing würde man, bei ausgewählter Location, ein neues Equipment basierend auf einem Thing hinzufügen. Will man nur einen einzelnen Point, z.B. einen der nicht genutzten 8 Channels beim Shelly hinzufügen, so würde man das Equipment Item auswählen und Create Point from Thing anwählen.

Es gibt übrigens auch Things, die nicht auf irgendeinem Device basieren. Dazu gehören z.B. die Online-Tests mittels Ping.

Für ein neues solches Thing geht man unter Things auf das Plus-Icon rechts unten auf der Seite. Im ersten Schritt muss man das Binding auswählen, dass man nutzen möchte, hier also das Network-Binding. Im nächsten Schritt kann man mit Scan das Binding suchen lassen, was es im Netz so an Geräten und Diensten findet, oder man geht direkt auf Add Manually -> Pingable Netzwerkgerät

Bildschirmfoto von 2021-12-19 21-37-23.png

Mit einen Klick auf Create Thing ist das entsprechende Thing erzeugt und kann ganz normal in das Model eingebunden werden.


Rest API

Eine Reihe von zusätzlichen Möglichkeiten bietet die Rest API von OpenHAB, die man über den API Explorer benutzen kann (dazu rechts oben auf Try it out klicken, wird dann zu Cancel ):

Bildschirmfoto von 2021-12-23 16-38-10.png

Etwas übersichtlicher wird es im Browser, die URL ist im API Explorer zu sehen (nicht jeder Broswer zeigt die Json-Ergebnisse so übersichtlich an, wie hier Firefox)

zeigt folgenden Inhalt:

Bildschirmfoto von 2021-12-23 09-45-09.png

Klickt man dann auf die hervorgehobene Zeile mit dem LOWBAT-Item, oder gibt die URL ein:

so ergibt sich folgendes Bild:

Bildschirmfoto von 2021-12-23 09-49-32.png

Erweitert man den Link um folgenden Parameter

sieht man die Daten des Items und die Metadaten aus dem Element semantics

Bildschirmfoto von 2021-12-23 09-51-36.png

Interessant ist hier vor allem die Zeile:

isPointOf	"FensterGasteklo01"

hier wird also auf das Elternelement Equipment verwiesen.

Beim Elternelement (dem Fenster) würde an entsprechender Stelle stehen

hasLocation	"Gaesteklo"

Der Raum ist ja eine Location.

In einem Widget kann man, zumindest in oh-repeater Strukturen, auf diese Felder Bezug nehmen mittels:

<Item>.metadata.semantics.config.isPointOf

bzw.

<Item>.metadata.semantics.config.hasLocation

Hat man andere metaElemente angelegt, so kann man auch die abfragen mit folgenden Parametern

  •  ?metadata=widgetOrder
  •  ?metadata=stateDescription
  • ...

Da man auch eigene Metadata-Namespaces erstellen kann, gibt es hier sicherlich umfangreiche Möglichkeiten.

Installation

Es bietet sich an openHAB auf einem extra Rechner zu installieren, dafür eignet sich ein Raspi als Gerät. Ich habe mich dabei an der Beschreibung von https://bloggingwelt.de/raspberry-pi-installation-von-openHAB orientiert. Leider wird dort nicht auf die Entscheidung für 32Bit oder 64Bit System eingegangen. Nach etwas Recherche auf den openHAB Seiten habe ich mich dann für die 32Bit-Version entschieden von Version 3.1.0. Folgende Bindings habe ich bei der Installation mit installiert:

  • AllPlay Binding
  • AstroBinding
  • AVM FRITZ!Box Binding
  • Homematic Binding
  • HTTP Binding
  • Network Binding
  • NTP Binding
  • Samsung TV Binding
  • Shelly Binding
  • TR-064 Binding

Weitere hilfreiche Links:

Anfangs-Probleme

Leider wird der Einstieg in OpenHAB nicht ganz leicht gemacht. Es gibt zwar eine umfangreiche Dokumentation unter https://www.openhab.org/docs/ mir fehlen aber schöne Einstiegs-Beispiele. Viel gelernt habe ich dann über https://community.openhab.org/ aber es bleibt mühsam.

In diesem Abschnitt sammle ich meine ersten Probleme und ihre Lösung.

Problem mit AllPlay Binding

Das Binding wollte bei mir nicht funktionieren. Nach etwas Recherche bin ich auf den Hinweis gestoßen, dass dies mit der OpenSSL Bibliothek zusammen hängt. Das AllPlay Binding kann mit der aktuellen Version nichts anfangen und benötigt eine ältere Version.

wget http://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u12_armhf.deb
apt install ./libssl1.0.0_1.0.1t-1+deb8u12_armhf.deb 

Lädt und installiert die ältere Version. Der Teil ...db8u12... kann sich verändert haben.

Mit

ldconfig -p | grep libssl 

habe ich mich dann überzeugt, dass die Bibliothek installiert wurde.

	libssl3.so (libc6,hard-float) => /lib/arm-linux-gnueabihf/libssl3.so
	libssl.so.1.1 (libc6,hard-float) => /lib/arm-linux-gnueabihf/libssl.so.1.1
	libssl.so.1.0.0 (libc6,hard-float) => /lib/arm-linux-gnueabihf/libssl.so.1.0.0

Zum Abschluss habe ich dann den Raspi neu gestartet. Danach erschienen dann auch die AllPlay Things in der Inbox.

User anlegen

Für die normale Benutzung benötigt man User ohne besondere Admin-Rechte. Ich habe in der Oberfläche überall nach einer Möglichkeit gesucht. Erst über den Artikel https://community.openhab.org/t/is-openhab-3-multiuser/111277/21 ist mir klar geworden, dass es in der GUI (noch) keine Option dafür gibt.

Ich habe mich also ganz normal per SSH am Raspi angemeldet. Dann nach Beschreibung unter https://www.openhab.org/docs/administration/console.html

ssh -p 8101 openhab@localhost

Das dann notwendige Passwort ist habopen .

Dort habe ich dann den User benutzer angelegt mittels

add benutzer password user

Löschen von Pages

Beim Testen legt man immer mal wieder Pages an. Wie man diese Seiten wieder löscht, konnte ich nicht sofort finden. Man geht dazu auf Einstellungen -> Pages. Jetz erschein die Liste der vorhandenen Seiten und in der oberen rechten Fensterecke das Wort Select. Klickt man darauf, so erscheint vor jeder Seite ein Auswahlkästchen und wenn man eines der Kästchen angeklickt hat, dann erscheint unten auf der Seite ein Link Remove.

Zeitsteuerung für Rules

Die Rules genannten Programme werden in Abhängigkeit von Trigger-Ereignissen ausgelöst. Ein Trigger kann das Ändern einer Temperatur, das Drücken eines Buttons, aber auch eine Zeitsteuerung sein.

triggers:
  - id: "1"
    configuration:
      cronExpression: 0 0 * ? * *
    type: timer.GenericCronTrigger

Die Definition des Cronjobs ist für mich ungewöhnlich, es macht Sinn den Generator unter https://www.freeformatter.com/cron-expression-generator-quartz.html zu nutzen um die Einstellung nachvollziehen zu können.

0 0 * ? * * 	steht für Every hour
0 * * ? * * 	für Every minute
* * * ? * * 	für Every second

AllPlay Radioempfang steuern mit der Homematic-Fernbedienung

Für die AllPlay-Geräte haben wir uns ursprünglich entschieden, weil sie im täglichen Betrieb auch ohne App bedienbar waren. Nachdem Panasonic diesen Vorteil nun zunichte gemacht hat kam die Idee auf, die vorhandene Homematic-Fernbedienung für diesen Zweck zu nutzen.


Homematic-Fernbedienung

Die Fernbedienung verfügt über 20 Kanäle und die Möglichkeit die zugehörige Funktion auf dem internen Display anzuzeigen. Für die Nutzung muss man bei Homematic unter Geräte ein paar Einstellungen für die Kanäle vornehmen:

Bildschirmfoto von 2021-10-02 12-29-10.png

Im Screenshot sieht man den Text, den ich für den Kanal eingetragen habe. Außerdem musste ich für jeden Kanal ein Programm anlegen, damit die Belegung auf die Fernbedienung übertragen wird.

Bildschirmfoto von 2021-10-02 12-38-14.png

Ich habe hier nur eine Bedingung eingetragen, nämlich dass die entsprechende Taste gedrückt wird, aber keine Aktion. Die soll ja innerhalb von OpenHAB erfolgen.

Rule NDR2

Innerhalb von openHAB taucht die Taste dann als Thing auf und ich habe mir eine Rule erstellt.

Bildschirmfoto von 2021-10-02 12-44-27.png

Das zugehörige Programm ist dann mit der grafischen Entwicklungs-Umgebung schnell erstellt:

Bildschirmfoto von 2021-10-02 12-47-52.png

Rule Kopplung

Nun noch ein kleines Programm für die Kopplung zweier Geräte auf eine andere Taste gelegt.

Bildschirmfoto von 2021-10-02 13-41-05.png

Rule Ausschalten

Und ein weiteres Programm zum Ausschalten der Geräte

Bildschirmfoto von 2021-10-02 13-44-51.png

Hier werden nicht wirklich die Geräte ausgeschaltet, das machen die Apps auch nicht, sondern den Geräten wird nur übermittelt dass sie nichts zu spielen haben. Dann schalten sie sich nach einiger Zeit selber ab.

Arbeiten mit Gruppen

Ein weiteres Ziel war es auf einer Übersichtsseite anzeigen zu können, ob alle Fenster im Haus geschlossen sind.

Mein erster Ansatz bestand darin mir von der Homematic über GATEWAY-EXTRAS die vorhandene Variable Offene_Fenster zu holen. Leider ist es so, dass diese Daten nicht oder nur mühsam aktualisierbar sind. Es dauerte mir immer viel zu lange, bis eine Aktualisierung möglich war. Ich hatte zwar gefunden, dass man mit

 events.sendCommand('GATEWAYEXTRAS_ReloadAllFromGateway', 'ON');

die Aktualisierung anstossen kann, aber dann werden anscheinend viele Daten aktualisiert, was dauert, selbst ein

java.lang.Thread.sleep(10000);

vor der Aktualisierung hat da nicht ausgereicht

Nach vielen Versuchen habe ich eine recht flexible Lösung gefunden. Dazu habe ich unter Items über ein neues Item angelegt (Add Item). Dieses Item hat von mir den Namen GruppeFenster bekommen und den Type Group.

Bildschirmfoto von 2021-11-08 17-43-15.png

Wichtig sind hier die Einstellungen im unteren Bereich:

  • Member Base Type: Contact

Von dieser Auswahl ist die nächste Einstellmöglichkeit betroffen:

  • Aggregation Function: One OPEN then OPEN else CLOSED

Sowie also ein einziges Fenster offen ist, so zeigt die Gruppe das auch, nur wenn alle Fenster geschlossen sind, dann hat die Gruppe auch diese Eigenschaft.

Nun muss man noch die Fenster dieser Gruppe hinzufügen. Das kann man umständlich von jedem Fenster einzeln aus machen, oder von der neuen Gruppe. Speichert man die eben getroffenen Einstellungen mit Save, so landet man wieder im Item-Fenster und kann dort über einen Click auf Change die Fenster auswählen.

Bildschirmfoto von 2021-11-08 17-50-36.png

Es erscheint jetzt eine Seite mit der Liste der Direct Group Members

Bildschirmfoto von 2021-11-08 17-54-40.png

Zum Bearbeiten der Liste klickt man auf die Zeile mit den Members, worauf ein Popup mit der Liste aller Items zur Auswahl erscheint.

Bildschirmfoto von 2021-11-08 17-59-36.png

Wichtig ist, dass man hier nicht die Fenster auswählt, sondern ihren Zustand. Mit einem Klick auf Schließen und danach noch Apply werden die Einstellungen übernommen.

In meiner Übersichtsseite habe ich dann eine Label-Card erstellt mit folgendem YAML

comp''Kursiver Text''onent: oh-label-card
config:
  title: Fenster
  item: GruppeFenster
  background: '=(items.GruppeFenster.state === "OPEN")  ? "red" : "lightgreen"'
  icon: oh:window
  action: popup
  actionModal: page:page_32a98b1708
  label: '=(items.GruppeFenster.state === "CLOSED")  ? "Alle zu" : "offen"'

Dieser Code hat drei Funktionen. Es wird also je nach Zustand ein unterschiedlicher Text angezeigt und die Hintergrundfarbe ist vom Zustand abhängig. Zusätzlich wird durch einen Klick auf diese Card eine weitere Page als Popup geöffnet, auf dieser Seite sind dann alle Fensterzustände einzeln zu erkennen.


Meine Widgets

Schon lange möchte ich eigene Widgets erstellen, einfach um schönere Darstellungen und Darstellungen mit weniger Aufwand zu erreichen.

Unter https://community.openhab.org/c/marketplace/ui-widgets/75 findet sich eine Zusammenstellung von Widgets, die kann man benutzen und als Anregung verwenden. Es gibt zwar unter https://next.openhab.org/docs/tutorial/custom_widgets.html ein Tutorial, das lässt aber viele Fragen offen. Wichtig im Zusammenhang mit eigenen Widgets ist mir die Wiederholstruktur, die es ebenfalls gibt und die unter https://next.openhab.org/docs/ui/components/oh-repeater.html "dokumentiert" ist.

ud_batterie_status

Hier nun das erste Widget, das ich selbst erstellt habe. Es zeigt den Batteriestatus aller Geräte an, die in einer Batterie-Gruppe zusammengefasst sind.

 1 uid: ud_batterie_status
 2 tags: []
 3 props:
 4   parameters:
 5     - context: item
 6       description: Group Das Item das alles Batterie-Level aggregiert
 7       label: Batterie Zustands Item
 8       name: batLevel
 9       required: true
10       type: TEXT
11       filterCriteria:
12         - value: Group
13           name: type
14   parameterGroups: []
15 timestamp: Jan 1, 2022, 2:58:39 PM
16 component: oh-list-card
17 config:
18   title: '="Eine Batterie Leer: " + ((items[props.batLevel].state === "OFF") ? "Nein" : "Ja")'
19 slots:
20   default:
21     - component: oh-repeater
22       config:
23         fragment: true
24         for: item
25         sourceType: itemsInGroup
26         groupItem: =props.batLevel
27         fetchMetadata: widgetOrder,semantics
28       slots:
29         default:
30           - component: oh-list-item
31             config:
32               icon: '=(loop.item.state === "OFF") ? "oh:battery-90" : "oh:battery-10"'
33               title: = loop.item.metadata.semantics.config.isPointOf
34               item: =loop.item.name
35               badge: '=(loop.item.state === "OFF") ? "Ok" : "Wechseln"'
36               badgeColor: '=(loop.item.state === "OFF") ? "green" : "red"'
37               footer: =items[loop.item.metadata.semantics.config.isPointOf+"_BatteryState"].state
38               action: group
39               actionGroupPopupItem: =loop.item.metadata.semantics.config.isPointOf

Mit den letzten Zeilen wird aus dem list-item quasi ein Button, über den ein Popup mit den Eigenschaften des zugehörigen Gerätes aufgerufen wird.

Mit dem folgenden YAML-Code ist das Widget dann in eine Spalte einer Page eingebunden.

 component: widget:ud_batterie_status
 config:
  batLevel: GruppeBatterieZustand

Der folgende Screenshot vermittelt einen Eindruck davon, wie das Widget auf der Seite aussieht.

Bildschirmfoto von 2022-01-01 16-38-58.png

Und dann das Popup, wenn man eines der Battrie-Items angeklickt hat:

Bildschirmfoto von 2022-01-01 17-00-59.png

Benutzt wird hier das Standard-Geräte Widget von OpenHAB.

Sicher kann man hier noch eine ganze Menge optimieren. Was mich am meisten ärgert ist die Tatsache, dass ich nicht ganz einfach an die anderen Datenfelder (Points) heran komme. Bei einigen Geräten wird auch die Batteriespannung gemeldet, diese Information würde ich auch gern mit anzeigen lassen.

Ein weiterer noch nicht ganz klarer Punkt für mich ist die Frage der Reihenfolge. Momentan scheinen die Geräte in der Reihenfolge zu stehen, in der ich sie in die Gruppe aufgenommen habe. Falls das stabil stimmt wäre das eine Möglichkeit. Schöner wäre eine direkte Möglichkeit der Sortierung. Inzwischen habe ich eine Möglichkeit für die Sortierung gefunden. Man muss bei den Batterie-Items jeweils Metadata vom Typ Default Widget Order Index hinzufügen. Dort gibt man eine "Zahl" an, die aber nach Textkriterien sortiert wird, also 10 < 2. Ich habe daher Tausender-Zahlen benutzt:

  • Tausender-Stelle: Etage
  • Hunderter-Stelle: Raum
  • Zehner-Stelle: Equipment
  • Einer-Stelle: Item

Im nächsten Schritt wollte ich erreichen, dass ich vom Batterie-Item aus auch das Gerät und den Raum bestimmen kann. Die Diskussion in der Community hat mir deutlich gemacht, dass es nicht trivial ist, aber möglich.

Eine interessante Möglichkeit habe ich in diesem Zusammenhang kennen gelernt. Es ist möglich Daten von einem Widget zum nächsten zu übergeben

ud_shellyplug

An dem folgenden Widget habe ich längere Zeit gebastelt und bin wohl auch über ein paar Fehler in OpenHAB gestolpert. Über die Diskussion in der OpenHAB Community habe ich viel dazu gelernt.

Ziel war es ein Widget zu bauen, das die wichtigsten Werte und Funktionen meiner Shelly-Plugs nutzbar macht und möglichst einfach nutzbar ist.

Bildschirmfoto von 2021-12-06 13-24-37.png

Man kann hier eine Überschrift angeben und muss ein Shelly-Plug auswählen, mehr nicht. Das Element hat dann folgendes Aussehen.

Bildschirmfoto von 2021-12-08 18-51-22.png

Hier sieht man schon eine Merkwürdigkeit. Die LEDs beim Plug sind dann an, Wenn xxxLEDaus OFF ist. Viel Aufwand hatte ich daher damit, das entsprechende Toggle-Element auf Grün zu setzen, wenn das zugehörige Element OFF ist und Rot bei ON.

(Grün bedeutet immer in Betrieb, Rot ausgeschaltet. Die WiFi-LED ist also aus und die Betriebs-LED an, zumindest wenn der Strom-Schalter in Betrieb ist.)

Die üblichen Zeilen wie

 color: '=(items[props.item + "_Betrieb"].state == "ON") ? "green" : "red"'

funktionieren nämlich nicht. Der inaktive Zustand wird immer in Grau dargestellt. Insofern kann man sich die Fallunterscheidung auch schenken.

Folgender Workaround funktioniert aber

 color: green
 style:
   --f7-toggle-inactive-color: "#e64a19"

Der komische Hex-Wert für Rot ist von OpenHAB abgeschaut, ebenfalls der für Grün (s.u.).

uid: ud_shellyplug_grid
tags: []
props:
  parameters:
    - description: Überschrift (wenn leer, dann wird der Name des Schalters benutzt)
      label: Überschrift
      name: ueberschrift
      required: false
      type: TEXT
    - context: item
      description: Der Schalter (Shelly Plug)
      label: Item
      name: item
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Dec 8, 2021, 6:19:50 PM
component: oh-list-card
config:
  title: '="Zustand von " + ((props.ueberschrift) ? props.ueberschrift : props.item)'
slots:
  default:
    - component: oh-toggle-item
      config:
        title: = "In Betrieb:"
        item: = props.item + "_Betrieb"
        color: green
        style:
          --f7-toggle-inactive-color: "#e64a19"
        badgeColor: red
    - component: oh-toggle-item
      config:
        title: ="BetriebsLED aus:"
        item: = props.item + "_BetriebsLEDaus"
        style:
          --f7-toggle-active-color: "#e64a19"
          --f7-toggle-inactive-color: "#4cd964"
    - component: oh-toggle-item
      config:
        title: ="Wi-Fi LED aus:"
        item: = props.item + "_StatusLEDaus"
        style:
          --f7-toggle-active-color: "#e64a19"
          --f7-toggle-inactive-color: "#4cd964"
    - component: oh-list-item
      config:
        title: "Gerätetemperatur:"
        badge: =items[props.item + "_Geratetemperatur"].state
    - component: oh-list-item
      config:
        title: "Gesamtverbrauch:"
        badge: =items[props.item + "_Gesamtverbrauch"].state
    - component: oh-list-item
      config:
        title: "Läuft seit:"
        badge: =dayjs().subtract(Number.parseInt(items[props.item + "_Laufzeit"].state), 's' ).format('D.MM.YY HH:mm')
    - component: oh-list-item
      config:
        title: "Leistung:"
        badge: =items[props.item + "_Leistung"].state
    - component: oh-list-item
      config:
        title: "Signalstärke:"
        badge: =items[props.item + "_Signalstarke"].state
        badgeColor: '=(Number.parseInt(items[props.item + "_Signalstarke"].state) < 1 ) ? "red" : ((Number.parseInt(items[props.item + "_Signalstarke"].state) > 2) ? "green" : "yellow")'

Jetzt sieht das Listing recht einfach und übersichtlich aus, aber an der richtigen Syntax für die Nutzung der Elemente habe ich dann doch eine Weile gesessen.

Für mich gibt es hier noch zwei Probleme, an denen ich arbeiten muss:

  1. Auf Android-Geräten hat das Toggle-Element eine kleinen Fehler. Der weiß Kreis (der Schalter) nimmt im Zustand ON die Farbe des Hintergrund (also Rot oder Grün) an. Das ist aber auch bei den Standard-Widget der Fall.
  2. Ich suche eine Möglichkeit durch alle Eigenschaftsfelder zu iterieren, damit könnte man die vielen Wiederholungen vermeiden und das Widget würde universeller.

Für das zweite Problem gibt es eine einfache Lösung. Ein Equipment wird immer durch ein Item repräsentiert, welches eine Gruppe darstellt. Damit kann man einfach über die Gruppe iterieren:

    - component: oh-repeater
      config:
        fragment: true
        for: item
        sourceType: itemsInGroup
        groupItem: =props.batLevel
        fetchMetadata: widgetOrder

Problem mit Tags

Aus der Diskussion im Forum hat sich dieses Code-Fragment entwickelt. Es war überraschend, dass hier hinter itemTags nur ein Komma steht und andere Kombinationen nicht funktionierten.

    - component: oh-repeater
      config:
        for: witem
        sourceType: itemsWithTags
        itemTags: ,
        fetchMetadata: semantics,stateDescription,widgetOrder
        fragment: true

Inzwischen habe ich gefunden, dass das Komma wie ein Und wirkt und nicht wie ein Oder. Wenn man mehrere Tags aufführt, dann werden nur Elemente gewählt, die alle Tags besitzen. Der Wert darf aber anscheinen auch nicht einfach leer bleiben, daher das Komma. Ein Und mit zwei leeren Eingaben.


Shelly H&T

Der Shelly H&T ist ein relativ preiswerter kleiner Sensor, der Temperatur und Feuchtigkeit per WLAN zur Verfügung stellt. Er meldet sich aber nur dann, wenn eine Änderung seiner Werte erfolgt, von daher ist es sinnvoll auch die Zeit der letzten Aktualisierung mit zu betrachten:

Bildschirmfoto von 2022-01-05 13-30-39.png

Klickt man auf diese Karte, so erscheint das folgende Diagramm:

Bildschirmfoto von 2022-01-05 13-33-00.png

OpenHAB hat hier die Prozentangabe noch einmal durch 100 geteilt, na gut.

Dazu gehört dann der folgende YAML-Code:

 1 uid: ud_shellyht_card
 2 tags: []
 3 props:
 4   parameters:
 5     - description: Überschrift (wenn leer, dann wird der Name des Gerätes benutzt)
 6       label: Überschrift
 7       name: ueberschrift
 8       required: false
 9       type: TEXT
10     - context: item
11       description: Das Gerät (Shelly)
12       label: Item
13       name: item
14       required: true
15       type: TEXT
16       filterCriteria:
17         - name: type     
18           value: Group
19   parameterGroups: []
20 timestamp: Jan 5, 2022, 12:20:15 PM
21 component: oh-label-cell
22 config:
23   header: "=(props.ueberschrift) ? props.ueberschrift : props.item"
24   label: = "Temperatur  " + items[props.item + "_Temperatur"].state
25   trendItem: = props.item +"_Temperatur"
26   action: analyzer
27   actionAnalyzerItems: =[props.item +"_Luftfeuchtigkeit", props.item +"_Temperatur"]
28   icon: oh:temperature
29   footer: = 'Letzte Aktualisierung ' + items[props.item + "_LetzteAktualisierung"].displayState
30   subtitle: = "Luftfeuchtigkeit " + items[props.item + "_Luftfeuchtigkeit"].state
31   expandable: false
32   style:
33     background: '=(items[props.item + "_Luftfeuchtigkeit"].state.split(" ")[0] > 60) ? "red" : "lightblue"'

Ein paar Erläuterungen zu dem Code:

  • In den ersten 15 Zeilen werden hauptsächlich die Konfigurationseinstellungen festgelegt. Es muss ein Item ausgewählt werden und es kann eine Überschrift festgelegt werden.
  • Mit den Zeilen 16 bis 18 will ich eigentlich erreichen, dass nur Gruppen (also vor allem Equipment) ausgewählt werden können. Leider funktioniert das nicht.
  • In Zeile 23 wird festgelegt, dass als Header die eingegebene Überschrift, oder falls keine angegeben wurde, der Gerätename genutzt wird.
  • In Zeile 24 wird die Temperatur-Ausgabe erzeugt, als Hauptinformation. (Mir ist nicht klar, warum ich da nicht "Temperatur:" schreiben kann, der Doppelpunkt wird moniert)
  • Zeile 25 erzeugt die blaue Temperatur-Kurve im Hintergrund
  • Zeile 26 und 27 konfigurieren den Effekt beim Anklicken der Card. Hinter actionAnalyserItems wird eine Array erwartet, daher die eckigen Klammern. Dafür sind auch mehrere Elemente möglich
  • Die nächsten Zeilen sind recht üblich, auch hier darf ich meinen Text nicht mit einem Doppelpunkt versehen.
  • Mit den Zeile 32 und 33 will ich erreichen, dass bei einer Luftfeuchtigkeit von mehr als 60 % der Hintergrund rot wird. Um die Zahlen vergleichen zu können muss von der Luftfeuchtigkeit die Einheit (%) entfernt werden, daher die Split-Funktion.


Homematic Heizungs-Thermostat

Von Thorsten habe ich die Ausgangsversion dieses Widgets bekommen, er hat sich dabei anregen lassen von dem Diskussionsstrang unter https://community.openhab.org/t/oh3-item-widget-switch-with-multiple-buttons/112671. Ich habe dann nur das Interface an meine Vorstellungen angepasst, so dass relativ wenige Angaben notwendig sind, wenn man es auf einer Page einbinden möchte. Zwingend ist nur die Auswahl des Gerätes selber.

Bildschirmfoto von 2022-01-11 19-52-11.png

Und hier das Listing zu dem Widget:

  1 uid: Thermostat-Control
  2 tags: []
  3 props:
  4   parameters:
  5     - description: Titelzeile
  6       label: Titel (wenn leer, dann Gerätename)
  7       name: titel
  8       required: false
  9       type: TEXT
 10     - context: item
 11       description: Der Thermostat
 12       label: Item
 13       name: item
 14       required: true
 15       type: TEXT
 16 timestamp: Jan 10, 2022, 5:35:40 PM
 17 component: f7-card
 18 config:
 19   outline: false
 20   noBorder: false
 21   padding: true
 22   noShadow: false
 23   style:
 24     --f7-card-margin-horizontal: 5px
 25     --f7-card-content-padding-vertical: 0px
 26     --f7-card-content-padding-horizontal: 16px
 27     --f7-card-border-radius: 15px
 28     --f7-card-box-shadow: 0px 5px 10px rgba(0,0,0,0.15)
 29     --f7-card-header-font-size: 14px
 30     --f7-card-header-font-weight: 600
 31 slots:
 32   content:
 33     - component: oh-label-card
 34       config:
 35         noShadow: true
 36         trendItem: =props.item+"_ActualTemperature"
 37         action: analyzer
 38         actionAnalyzerItems: =[props.item+"_ActualTemperature",props.item+"_SetTemperature", props.item+"_ValveState"]
 39         item: =props.item+"_ActualTemperature"
 40         title: "=(props.titel) ? props.titel : props.item"
 41         icon: f7:thermometer
 42         actionAnalyzerCoordSystem: time
 43         vertical: false
 44         footer: = "Ventil " + (items[props.item+"_ValveState"].state) + " / Batterie " + (items[props.item+"_BatteryState"].state)
 45     - component: oh-stepper-card
 46       config:
 47         noShadow: true
 48         color-theme: gray
 49         item: =props.item+"_SetTemperature"
 50         large: false
 51         autorepeat: true
 52         fill: false
 53         noBorder: true
 54         raised: true
 55         small: true
 56         round: true
 57         min: 5
 58         max: 30
 59         step: 0.5
 60     - component: f7-row
 61       config:
 62         class:
 63           - padding-bottom
 64           - padding-right
 65       slots:
 66         default:
 67           - component: f7-col
 68             slots:
 69               default:
 70                 - component: oh-button
 71                   config:
 72                     title: Auto
 73                     action: toggle
 74                     actionItem: =(props.item+"_AutoMode")
 75                     actionCommand: ON
 76                     textColor: '=(items[props.item+"_ControlMode"].state === "AUTO-MODE") ? white : red'
 77                     fill: '=(items[props.item+"_ControlMode"].state === "AUTO-MODE") ? true : false'
 78                     text: Auto
 79           - component: f7-col
 80             slots:
 81               default:
 82                 - component: oh-button
 83                   config:
 84                     title: Manu
 85                     action: toggle
 86                     actionItem: =(props.item+"_ManuMode")
 87                     actionCommand: =(items[props.item+"_SetTemperature"].state)
 88                     textColor: '=(items[props.item+"_ControlMode"].state === "MANU-MODE") ? white : red'
 89                     fill: '=(items[props.item+"_ControlMode"].state === "MANU-MODE") ? true : false'
 90                     text: Manu
 91           - component: f7-col
 92             slots:
 93               default:
 94                 - component: oh-button
 95                   config:
 96                     title: Boost
 97                     action: toggle
 98                     actionItem: =(props.item+"_BoostMode")
 99                     actionCommand: ON
100                     textColor: '=(items[props.item+"_ControlMode"].state === "BOOST-MODE") ? white : red'
101                     fill: '=(items[props.item+"_ControlMode"].state === "BOOST-MODE") ? true : false'
102                     text: Boost

Sichern der Installation

Wenn man einige Zeit an dem System gearbeitet hat, dann wäre ein Datenverlust schon sehr ärgerlich. Für das Backup gibt es mehrere Möglichkeiten.

  • Kopieren der Speicherkarte
  • Benutzen der OpenHAB Backup-Funktion

Kopieren der Speicherkarte

Das Kopieren der Speicherkarte ist schnell erledigt, mit Hilfe von DD auf dem Arbeitsplatzrechner. Damit wird die komplette Karte kopiert und im Notfall kan einfach die Kopie anstelle der Originalkarte eingesetzt werden.

OpenHAB Backaup-Funktion

OpenHAB verfügt über eine eingebaute Backup-Funktionalität. Ist man auf dem Raspi angemeldet, so kann man die Funktion aufrufen mittels:

sudo $OPENHAB_RUNTIME/bin/backup

Über die Variable löst der Befehl auf zu

sudo /usr/share/openhab/runtime/bin/backup

Das Backup wird dann mit Datum erzeugt und lokal abgelegt unter z.B.:

/var/lib/openhab/backups/openhab-backup-22_01_09-16_44_58.zip

bzw.

$OPENHAB_BACKUPS/openhab-backup-22_01_09-16_44_58.zip

Für das Zurückspielen gilt dann entsprechend

sudo systemctl stop openhab
sudo $OPENHAB_RUNTIME/bin/restore $OPENHAB_BACKUPS/openhab-backup-22_01_09-16_44_58.zip
sudo systemctl start openhab


Sollte es sich um ein neu installiertes System handeln und das Backup-Verzeichnis noch nicht vorhanden sein, so legt man es an und kopiert die Sicherung dort hinein.

Ein Android Tablet als Display

Ein normales Android-Tablet eignet sich hervorragend als Display für die Steuerung mittels OpenHAB. Dazu müssen aber mehrere Dinge konfiguriert werden:

  • OpenHAB-App
  • Fully Remote App
  • Rules zum Schulen der Apps von OpenHAB aus

OpenHAB

Ich habe mir die App OpenHAB Beta auf dem Tablet installiert. Diese App startet normalerweise mit einer Sitemap im alten OpenHAB 2 Stil. Man kann aber in den Einstellungen auswählen, dass mit der OpenHAB 3 UI gearbeitet wird. Dann startet bei mit die Layout-Seite Overview.

Fully Remote App

Die Android-Geräte haben das Problem, dass sie immer nach einer gewissen Zeit an Inaktivität das Display abschalten. Ich möchte aber erreichen, dass die OpenHAB-App aber immer aktiv bleibt. Dafür gibt es eine Reihe von Apps. Zusätzlich möchte ich aber das Display auch von OpenHAB aus Ein- und Ausschalten können. Erst einmal nur zeitgesteuert, später auch von Alarmen aus.

Dazu habe ich mit Fully Single App Kiosk eine passende App gefunden. Für diese App gibt es unter https://www.fully-kiosk.com/ eine sehr umfangreiche, aber dadurch auch verwirrende Dokumentation. Übersichtlicher ist die Anleitung unter https://www.schlaue-huette.de/wandtablet/tablet-dimmen-und-aufwecken/ .

Die Bedienung ist nicht unbedingt sofort einsichtig, zumal es sich um ein Kiosk-System handelt.

Wenn man die App startet, dann sieht man nur zwei Einstellmöglichkeiten: - Auswahl der zu startenden App (OpenHAB) - Eingabe einer PIN

Danach kann man dann den Kiosk-Modus starten. Die App bietet hier einen Testmodus, aus dem sie automatisch nach einer Minute wieder aussteigt.Verzichtet man auf den Testmodus und startet den wirklichen Kiosk-Modus, so kann man den beenden, indem man 7ml schnell hintereinander auf das Display tappt. Wenn man schnell genug war, dann erscheint ein Fenster zum PIN eingeben. War man erfolgreich, so landet man wieder im Startbildschirm.

Will man an die weiteren Konfigurationseinstellungen kommen, so muss man von links nach rechts wischen.

Bei den Einstellungen ergibt es Sinn die Remote-Administration zu erlauben, dazu muss man dann auch ein Passwort anlegen. Danach kann man im lokalen Netz remote auf das Display zugreifen. Über das Burger-Menü kann man dann auch auf die Einstellungen zugreifen.

Bildschirmfoto von 2021-11-29 20-56-34.png

Über die hier vorhandenen Funktionen kann man das Display auch Ein- und Ausschalten. Das geht recht einfach über die URLs:

http://192.168.1.16:2323/?cmd=screenOn&password=<geheim>

und

 http://192.168.1.16:2323/?cmd=screenOff&password=<geheim>

Damit eignet sich die App auch gut zur Nutzung in OpenHAB Rules und Scripts.

Rules zum Steuern der Apps

Ich habe mir zwei Rules mit Zeitsteuerung erstellt. Die eine Rule schaltet das Display morgens um 7 Uhr ein und die andere schltet es um 23.30 Uhr wieder aus. Das zugehörige Script (zum Einschalten) besteht nur aus zwei Zeilen:

var HttpUtil = Java.type("org.openhab.core.io.net.http.HttpUtil")
HttpUtil.executeUrl("GET", "http://192.168.1.16:2323/?cmd=screenOn&password=<geheim>", 2000)


Hilfreiche Links