OpenHAB
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:
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.
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
Ü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
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 ):
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:
Klickt man dann auf die hervorgehobene Zeile mit dem LOWBAT-Item, oder gibt die URL ein:
so ergibt sich folgendes Bild:
Erweitert man den Link um folgenden Parameter
sieht man die Daten des Items und die Metadaten aus dem Element semantics
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:
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.
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.
Das zugehörige Programm ist dann mit der grafischen Entwicklungs-Umgebung schnell erstellt:
Rule Kopplung
Nun noch ein kleines Programm für die Kopplung zweier Geräte auf eine andere Taste gelegt.
Rule Ausschalten
Und ein weiteres Programm zum Ausschalten der Geräte
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.
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.
Es erscheint jetzt eine Seite mit der Liste der Direct Group Members
Zum Bearbeiten der Liste klickt man auf die Zeile mit den Members, worauf ein Popup mit der Liste aller Items zur Auswahl erscheint.
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.
1uid: ud_batterie_status
2tags: []
3props:
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: []
15timestamp: Jan 1, 2022, 2:58:39 PM
16component: oh-list-card
17config:
18 title: '="Eine Batterie Leer: " + ((items[props.batLevel].state === "OFF") ? "Nein" : "Ja")'
19slots:
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.
Und dann das Popup, wenn man eines der Battrie-Items angeklickt hat:
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.
Man kann hier eine Überschrift angeben und muss ein Shelly-Plug auswählen, mehr nicht. Das Element hat dann folgendes Aussehen.
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:
- 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.
- 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:
Klickt man auf diese Karte, so erscheint das folgende Diagramm:
OpenHAB hat hier die Prozentangabe noch einmal durch 100 geteilt, na gut.
Dazu gehört dann der folgende YAML-Code:
1uid: ud_shellyht_card
2tags: []
3props:
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: []
20timestamp: Jan 5, 2022, 12:20:15 PM
21component: oh-label-cell
22config:
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.
Und hier das Listing zu dem Widget:
1uid: Thermostat-Control
2tags: []
3props:
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
16timestamp: Jan 10, 2022, 5:35:40 PM
17component: f7-card
18config:
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
31slots:
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.
Ü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)