OpenHAB

Aus Debacher-Wiki
Zur Navigation springenZur Suche springen

Hinweis: Der Text basiert ursprünglich auf der Version 3.1.0 und ich überarbeite ihn gerade mit einer neuen Installation auf 3.4.1.

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.

Im Lauf der Zeit ist dann noch eine Reihe weiterer Anwendungen, meist im Zusammenhang mit Homematic oder Shelly, dazu gekommen. Gerade für die Shelly-Geräte bietet sich die Nutzung von OpenHAB an, dann muss man nicht die Shelly-Cloud nutzen sondern im eigenen Netz bleiben.


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.

Die Reihenfolge der Einträge im Model ist, sofern sie sich nicht aus der Struktur ergibt, alphabetisch. Will man hier eine eigene Reihenfolge festlegen, so braucht man Metadata vom Typ Default Widget Order Index. Hier kann man unter Order in Lists eine Zahl angeben. Ich gehe so vor, dass ich für die Etagen 1000er Nummern vergebe: Dachgeschoss:1000, Obergeschoss:2000 usw. Die Räume variieren in der Hunderter-Stelle und die Geräte in der 10er Stelle.

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.


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://phenx.de/openhab-3-auf-raspberry-installieren-openhabian/ 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.4.0. In der verlinkten Anleitung wird auf die Vorab-Konfiguration des WLAN über die openhabian.conf hingewiesen. Das hat bei mir nicht funktioniert, da man bei 4.3.0 anscheinend die Datei /boot/openhabian.conf benutzen muss.

Das WLAN konnte ich anschließend auch nicht per openhabian-config konfigurieren, ich habe dann raspi-config erfolgreich dafür genutzt. Damit wird die /etc/wpa_supplicant/wpa_supplicant.conf mit folgendem Inhalt versehen:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=DE

network={
       ssid="meinessid"
       psk="meinkey"
}

Weitere Möglichkeiten unter https://www.elektronik-kompendium.de/sites/raspberry-pi/1912221.htm

Folgende Bindings habe ich gleich 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

Einbinden von Things

Nach dem Installieren der benötigten Bindings findet OpenHAB eine Reihe von Geräten, die dann unter Things in der Inbox auftauchen, eventuell muss man auch einige Zeit warten. Dabei ist die Situation je nach Binding unterschiedlich:

Allplay

Im ersten Schritt musste ich das Problem mit der libssl lösen (s.u.) dann tauchten nach einer Wartezeit alle im Netz vorhandenen Geräte auf, die sind ja auch über ihre IP-Adresse erreichbar.

Astro

Es tauchen die Geräte "Lokale Monddaten" und "Lokale Sonnendaten" in der Box auf.

AVM FRITZ!Box

Es taucht erst einmal nur die Fritz!Box als Gerät auf.

Homematic

In der Inbox taucht anfangs nur die CCU auf. Erst wann man diese eingebunden hat, dann tauchen auch die vielen Geräte auf, die die CCU verwaltet. Zusätzlich taucht auch das Gerät GATEWAY-EXTRAS und das Gerät ZENTRALE auf.

HTTP

kein Gerät

Network

kein Gerät

NTP

Das Gerät "Lokale Zeit" taucht auf.

Samsung TV

Der Fernseher taucht korrekt in der Inbox auf.

Shelly

Hier ist es recht unterschiedlich. Die Geräte, die aus dem Stromnetz versorgt werden, tauchten hier automatisch auf. Es gab aber Probleme mit dem Shelly 1 mit Addon, da dort die drei Sensoren den gleichen Namen haben. Man muss sie daher nacheinander einbinden, um sie getrennt und unterscheidbar benennen zu können. Bei den Batteriegeräten wie Shelly H&T klappte die Einbindung immer nur dann, wenn ich vorher auf den Knopf am Gerät gedrückt habe, ansonsten muss man viel Geduld aufbringen.

TR-064

kein Gerät

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 kann einfach die Kopie anstelle der Originalkarte eingesetzt werden.

Besser ist eine automatisierte Sicherung auf einem NAS

OpenHAB Backup-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.


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.

Bei dem Openhabian zu OpenHAB 3.4.0 wurde die Installation des Paketes mit einer Fehlermeldung hinsichtlich nicht auflösbarer Abhängigkeiten abgelehnt. Erfolgreich wurde ich dann mit:

dpkg --force-depends -i libssl1.0.0_1.0.1t-1+deb8u12_armhf.deb 

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


Verschieben von Things im Model

Ein grafisches Drag&Drop für Things im Seitenbaum des Models ist nicht vorgesehen. Es geht aber trotzdem relativ einfach.

Jedes Thing ist Quasi eine Gruppe von Items. Zu jedem Thing gehört daher auch ein Gruppenitem. Dieses Gruppenitem muss man sich unter Items suchen und anklicken.

2023-03-25 13.41.13 192.168.1.95 e0eccac9eb96.png

Hier findet sich unter Direct Parent Groups die übergeordnete Gruppe, hier Esszimmer. Mit einem Klick auf Edit (rechts oben im Fenster) kann man das bearbeiten.

2023-03-25 13.42.11 192.168.1.95 f203e60a8a55.png

Hier kann man jetzt über einen Klick auf Parent Group(s) die Position im Model-Baum verändern und eine andere Eltern-Gruppe auswählen.

2023-03-25 13.52.58 192.168.1.95 83d03fb5ba17.png


Da man hier mehrere Eltern-Elemente auswählen kann, muss man darauf achten bei dem vorherigen Element das Häkchen zu entfernen.

Sowie man auf Schließen und dann auf Save klickt (rechts oben im Fenster) ist die Änderung aktiv.

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.

uid: ud_batterie_status
tags: []
props:
  parameters:
    - context: item
      description: Group Das Item das alles Batterie-Level aggregiert
      label: Batterie Zustands Item
      name: batLevel
      required: true
      type: TEXT
      filterCriteria:
        - value: Group
          name: type
  parameterGroups: []
timestamp: Jan 1, 2022, 2:58:39 PM
component: oh-list-card
config:
  title: '="Eine Batterie Leer: " + ((items[props.batLevel].state === "OFF") ? "Nein" : "Ja")'
slots:
  default:
    - component: oh-repeater
      config:
        fragment: true
        for: item
        sourceType: itemsInGroup
        groupItem: =props.batLevel
        fetchMetadata: widgetOrder,semantics
      slots:
        default:
          - component: oh-list-item
            config:
              icon: '=(loop.item.state === "OFF") ? "oh:battery-90" : "oh:battery-10"'
              title: = loop.item.metadata.semantics.config.isPointOf
              item: =loop.item.name
              badge: '=(loop.item.state === "OFF") ? "Ok" : "Wechseln"'
              badgeColor: '=(loop.item.state === "OFF") ? "green" : "red"'
              footer: =items[loop.item.metadata.semantics.config.isPointOf+"_BatteryState"].state
              action: group
              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:

uid: ud_shellyht_card
tags: []
props:
  parameters:
    - description: Überschrift (wenn leer, dann wird der Name des Gerätes benutzt)
      label: Überschrift
      name: ueberschrift
      required: false
      type: TEXT
    - context: item
      description: Das Gerät (Shelly)
      label: Item
      name: item
      required: true
      type: TEXT
      filterCriteria:
        - name: type     
          value: Group
  parameterGroups: []
timestamp: Jan 5, 2022, 12:20:15 PM
component: oh-label-cell
config:
  header: "=(props.ueberschrift) ? props.ueberschrift : props.item"
  label: = "Temperatur  " + items[props.item + "_Temperatur"].state
  trendItem: = props.item +"_Temperatur"
  action: analyzer
  actionAnalyzerItems: =[props.item +"_Luftfeuchtigkeit", props.item +"_Temperatur"]
  icon: oh:temperature
  footer: = 'Letzte Aktualisierung ' + items[props.item + "_LetzteAktualisierung"].displayState
  subtitle: = "Luftfeuchtigkeit " + items[props.item + "_Luftfeuchtigkeit"].state
  expandable: false
  style:
    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:

uid: Thermostat-Control
tags: []
props:
  parameters:
    - description: Titelzeile
      label: Titel (wenn leer, dann Gerätename)
      name: titel
      required: false
      type: TEXT
    - context: item
      description: Der Thermostat
      label: Item
      name: item
      required: true
      type: TEXT
timestamp: Jan 10, 2022, 5:35:40 PM
component: f7-card
config:
  outline: false
  noBorder: false
  padding: true
  noShadow: false
  style:
    --f7-card-margin-horizontal: 5px
    --f7-card-content-padding-vertical: 0px
    --f7-card-content-padding-horizontal: 16px
    --f7-card-border-radius: 15px
    --f7-card-box-shadow: 0px 5px 10px rgba(0,0,0,0.15)
    --f7-card-header-font-size: 14px
    --f7-card-header-font-weight: 600
slots:
  content:
    - component: oh-label-card
      config:
        noShadow: true
        trendItem: =props.item+"_ActualTemperature"
        action: analyzer
        actionAnalyzerItems: =[props.item+"_ActualTemperature",props.item+"_SetTemperature", props.item+"_ValveState"]
        item: =props.item+"_ActualTemperature"
        title: "=(props.titel) ? props.titel : props.item"
        icon: f7:thermometer
        actionAnalyzerCoordSystem: time
        vertical: false
        footer: = "Ventil " + (items[props.item+"_ValveState"].state) + " / Batterie " + (items[props.item+"_BatteryState"].state)
    - component: oh-stepper-card
      config:
        noShadow: true
        color-theme: gray
        item: =props.item+"_SetTemperature"
        large: false
        autorepeat: true
        fill: false
        noBorder: true
        raised: true
        small: true
        round: true
        min: 5
        max: 30
        step: 0.5
    - component: f7-row
      config:
        class:
          - padding-bottom
          - padding-right
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Auto
                    action: toggle
                    actionItem: =(props.item+"_AutoMode")
                    actionCommand: ON
                    textColor: '=(items[props.item+"_ControlMode"].state === "AUTO-MODE") ? white : red'
                    fill: '=(items[props.item+"_ControlMode"].state === "AUTO-MODE") ? true : false'
                    text: Auto
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Manu
                    action: toggle
                    actionItem: =(props.item+"_ManuMode")
                    actionCommand: =(items[props.item+"_SetTemperature"].state)
                    textColor: '=(items[props.item+"_ControlMode"].state === "MANU-MODE") ? white : red'
                    fill: '=(items[props.item+"_ControlMode"].state === "MANU-MODE") ? true : false'
                    text: Manu
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Boost
                    action: toggle
                    actionItem: =(props.item+"_BoostMode")
                    actionCommand: ON
                    textColor: '=(items[props.item+"_ControlMode"].state === "BOOST-MODE") ? white : red'
                    fill: '=(items[props.item+"_ControlMode"].state === "BOOST-MODE") ? true : false'
                    text: Boost


Temperaturmessung mit Shelly 1 und Addon

Bisher fehlte mir immer eine Möglichkeit, die Temperaturen des Heizungskreislaufes zu verfolgen. Erst jetzt habe ich wahrgenommen, dass es dafür bei Shelly die notwendigen Teile gibt. Am übersichtlichsten sind die entsprechenden Teile bei https://shellyparts.de zu finden. Hier gibt es auch in 3D gedruckte Gehäuse dafür zu kaufen.

Der Shelly 1 ist eigentlich ein Relais, er lässt sich aber mit dem Addon um Sensoren erweitern, bei mir sind das Temperaturfühler DS18B20.

Die Temperaturfühler arbeiten von -55 °C bis +125 °C, die Kabelbelegung ist

1-> rot: VCC
3-> schwarz: GND
2-> gelb: Data


Shelly1-addon.png

Das Addon wird auf das Relais aufgesteckt und dann kann man an den Kabeln Sensoren anschließen. Da die Sensoren alle parallel geschaltet werden, sind Klemmen dabei um bis zu drei Sensoren anschließen zu können.

Dazu muss man vorher die längliche Abdeckung entfernen.

IMG 20221215 170944340.jpg


Es bietet sich aber an, die Stromversorgung vorher anzuschließen, da das Addon einrastet und nur mühsam wieder zu lösen ist.

Sheelly-addon-schnittstelle.jpg


Unter der kleineren Abdeckung befindet sich eine Steckbrücke, mit der man die Stromversorgung des Relais auf 12 V Gleichstrom umstellen kann. Da ich mit dem Shelly nicht schalten, sondern nur messen will, habe ich hier die Umstellung vorgenommen und von einer alten Fritz!Box das 12V Netzteil angeschlossen.

Shelly-jumper.jpg


Es ist relativ schwierig die Steckbrücke aus dem Gehäuse zu bekommen, da die Öffnung so eng ist, dass man mit einer Pinzette kaum greifen kann. Ich habe mir eine Büroklammer zurechtgebogen und die Brücke damit herausbekommen.

Bei der Firma Shellyparts gibt es auch ein Gehäuse für den gesamten Aufbau.

Shelly-gehäuse.jpg

Mit dem Gehäuse kommen auch drei neue Klemmen, mit drei Anschlüssen, da die vierer Klemmen, die zum Addon gehören, zu lang für das Gehäuse sind. Man muss also im Zweifelsfall in einen der Anschlüsse jeweils zwei Kabel klemmen. Das Gehäuse sieht auch keine Zugentlastung vor, ich habe mir mit zwei Kabelbindern geholfen, die das Herausziehen der Kabel erschweren.

Kosten ca. 50€ (Stand Dezember 2022):

  • Shelly1 12,98 €
  • Addon 10,98€
  • 3 DS18B20 8,94 €
  • Gehäuse 8,98 €
  • Netzteil 9,32 € (von Amazon)

Einbindung ins eigene WLAN

Die Einbindung ins WLAN ist bei Shelly-Geräten nicht immer unproblematisch, das betrifft aber vor allem die batteriebetriebenen Geräte. Hier ist das einfacher, mit einem Tablet oder Handy auf den Acces-Point des Shelly verbinden und dann im Browser die IP-Adresse 192.168.33.1 aufrufen.

2022-12-11 13.27.35 192.168.1.111 f5a9bd48b63a.png


In dem Screenshot sieht man schon den Zustand mit zwei angeschlossenen Sensoren.

Im ersten Schritt bindet man das Gerät über Internet & Security -> WIFI MODE - CLIENT ins lokale WLAN ein.


2022-12-11 13.29.41 192.168.1.111 11d89dffc0cf.png

Nach diesem Schritt kann man das Gerät dann mit einer IP-Adresse im eigenen WLAN erreichen. Welche das ist, das kann man in der Regel im Router nachschauen.

Wenn das geklappt hat, dann kann man den WIFI MODE - ACCESS POINT deaktivieren.

Was man nach der Einbindung auf alle Fälle machen sollte, ist ein Update Settings -> FIRMWARE UPDATE auf die neueste Version.

Einbindung in OpenHAB

In OpenHAB war die Einbindung recht einfach, das Shelly-Binding war bei mir ja schon längere Zeit vorhanden. Man geht dann auf Things -> + -> Shelly-Bindung und bekommt eine Reihe der unterstützten Geräte zur Auswahl.

2022-12-11 13.20.36 192.168.1.95 fbf2ff5bcc6a.png


Das Scannen hat bei mir nichts ergeben, aber das gesuchte Gerät ist ja auch an der ersten Stelle zu finden.


2022-12-11 13.22.29 192.168.1.95 949245c645ec.png


Hier muss man eigentlich nur die IP-Adresse des Gerätes angeben und eventuell das Label anpassen, danach ist das Gerät innerhalb von OpenHAB verfügbar.

Auch die installierten Sensoren stehen dann automatisch zur Auswahl zur Verfügung.

Aber hier gibt es ein blödes Problem. Die Temperatur-Sensoren heißen alle gleich und sind damit nur mühsam zu individualisieren. Es gibt dafür folgende Möglichkeiten:

  1. Man schließt die Sensoren nacheinander an und übernimmt sie dann auch entsprechend nacheinander in das Modell. Dabei gibt man dann jeweils dem neu hinzugekommenen Sensor einen Namen, der von der Vorgabe abweicht. Eine Nummerierung langt hier, also Temperatur1, Temperatur2, Temperatur3, später lassen sich die Sensoren umbenennen, nur solange sie alle den gleiche Namen haben haut das nicht hin.
  2. Nach dem Einbinden des Shelly-Gerätes (gleich einen individuellen Namen vergeben) importiert man die Sensoren nicht gleich ins Modell, sondern geht über Things -> Shelle 1... -> Channels -> jeweiliger Sensor -> Add Linkt to item hierbei kann man dann jeweils individuell einen Namen vergeben. Wenn man dann über Create Points from Thing die Sensoren im Modell zum Shelly 1 hinzufügt und dann den im vorherigen Schritt gewählten Namen angibt, dann bekommt man die Warnung, dass der Name schon existiert. Aber genau so soll es sein.

2022-12-19 14.03.01 192.168.1.95 c032bc2046ca.png

Label-Card

Hier mein erster Versuch für eine Label-Card. Am wichtigsten ist mir hierbei das Diagramm mit dem Temperatur-Verlauf:

component: oh-label-card
config:
  title: Heizkreislauf-Temperaturen
  label: = "Rücklauf-Temperatur  " + items.Shelly1Addon_Temperatur1.state
  subtitle: = "Temperatur  " + items.Shelly1Addon_Temperatur2.state
  item: Shelly1Addon_Temperatur1
  footer: = "Vorlauf-Temperatur " + items.Shelly1Addon_Temperatur2.state
  trendItem: Shelly1Addon_Temperatur2
  action: analyzer
  actionAnalyzerItems:
    - Shelly1Addon_Temperatur1
    - Shelly1Addon_Temperatur2

Am liebsten würde ich im Diagramm noch die Differenz der Temperaturen darstellen, aber ich habe bisher noch nicht die entsprechenden Möglichkeiten für berechnete Werte heraus gefunden.

Anzeige der Temperatur-Differenz

Die Anzeige nur von Vorlauf- und Rücklauf- Temperatur allein fand ich nicht so hilfreich. Ich will auch die Temperatur-Differenz mit im Diagramm haben.

Dazu habe ich ein Item angelegt: Einstellungen -> Items -> + -> Add item : HeizkreisTemperaturDiff

2022-12-12 10.08.21 192.168.1.95 302006678c08.png

Um das Item mit Inhalten zu versorgen dient eine Rule:

2022-12-12 10.10.30 192.168.1.95 b212b97be31f.png

die immer dann, wenn sich einer der beiden Messwerte ändert, das folgende Script aufruft:

2022-12-16 10.10.28 192.168.1.95 d43585403933.png

oder in Textform:

var Vorlauf, Ruecklauf, Differenz;

Vorlauf = itemRegistry.getItem('Shelly1Addon_Temperatur2').getState();
Ruecklauf = itemRegistry.getItem('Shelly1Addon_Temperatur1').getState();
Differenz = Vorlauf - Ruecklauf;
Differenz = Differenz * 10;
Differenz = Math.round(Differenz);
Differenz = Differenz / 10;
events.sendCommand('HeizkreisTemperaturDiff', Differenz);

Und dann muss natürlich noch die Label-Card angepasst werden

component: oh-label-card
config:
  title: ="Vorlauf-Temperatur " + items.Shelly1Addon_Temperatur2.state
  label: = "Temperatur-Differenz  " + items.HeizkreisTemperaturDiff.state
  subtitle: = "Temperatur  " + items.Shelly1Addon_Temperatur2.state
  item: Shelly1Addon_Temperatur1
  footer: = "Rücklauf-Temperatur " + items.Shelly1Addon_Temperatur1.state
  trendItem: Shelly1Addon_Temperatur2
  action: analyzer
  actionAnalyzerItems: =["Shelly1Addon_Temperatur1", "Shelly1Addon_Temperatur2", "HeizkreisTemperaturDiff"]

Einbindung von Shelly Duo

Ich habe mir vor ein paar Tagen die Shelly Duo RGBW Smart Home LED Glühbirne Dimmbar E27 gekauft. Diese LED-Lampe wird vom aktuellen Shelly-Binding unterstützt, aber die Unterstützung ist teilweise seltsam. Nach der Einbindung habe ich einen Channel für den Betrieb, also den Power Switch vermisst. Durch einen Hinweis im OpenHAB-Forum bin ich darauf gekommen, dass man dazu die Lampe auf den Color-Betrieb einstellen muss. Nach etwas Wartezeit tauchte dieser Channel beim Thing auch auf und ich konnte ihn in mein Model einbinden. Auch nach dem Zurückstellen auf Weiß blieb der Channel erhalten und nutzbar.


Hilfreiche Links