Autor: Andreas
openHAB XIV: System-Update für Idioten
Mit dem Wort „Idioten“ im Titel meine ich explizit mich. Denn ich könnte diesen Artikel sehr kurz schreiben, wenn ich einfach nur zu mir selbst sagen würde: Mach es halt ordentlich, dann funktioniert es auch.
Okay, etwas länger soll es dann doch sein.
Die folgenden Schritte werden alle per SSH in der Konsole durchgeführt. Zuerst mache ich ein Backup, mit diesem Befehl:
sudo $OPENHAB_RUNTIME/bin/backup
Dann aktualiere ich die Update-Verzeichnisse, das ist ganz wichtig. Warum, erkläre ich später. Und ja, wir brauchen beide Zeilen bzw. beide Befehle.
sudo apt-get update sudo apt update
Dann öffne ich das openHAB-Konfigurations-Tool:
sudo openhabian-config
Hier wähle ich Punkt 2, Upgrade System. Und dann rödelt das System hoffentlich ohne Fehler, und alles klappt. Hoffentlich.
Und nun komme ich zu dem (langen) Weg, der mich zu diesen kurzen Schritten gebracht hat.
Tag 1: Lass uns doch mal updaten
Man sollte alle Software immer aktuell halten. Das gilt ganz generell, und das gilt natürlich auch für openHAB. Also möchte ich mein System von der Version 3.0.1 auf die neueste Version aktualisieren (3.3.0).
Glücklicherweise habe ich ja mal einen Guide zum Update auf openHAB 3.0 geschrieben, daran kann ich mich gut orientieren. Ich öffne ich das openHAB-Konfigurations-Tool:
sudo openhabian-config
Hier wähle ich Punkt 2, Upgrade System. Aber leider bricht es immer wieder ab. Es wird gesagt, wenn du diesen Fehler siehst, geh doch mal auf diese Seite: https://github.com/openhab/openhabian/blob/main/docs/openhabian-DEBUG.md. Okay, Debugging anschalten, das mache ich dann mal. Ich navigiere mich zu /etc/
:
sudo nano openhabian.conf
Ja, natürlich habe ich das sudo
zuerst vergessen und mich gewundert, warum ich nicht speichern kann. Ich sagte ja, „Idiot“. Jedenfalls ändere ich debugmode=off
zu debugmode=maximum
(und später schalte ich es natürlich wieder aus).
Und dann klicke ich etwas rum. Ich aktualisiere eigentlich alles, was so geht. Ich reboote. Ich wähle verschiedene Branches. Ich mache alles Mögliche, aber es funktioniert nicht.
Da muss ich mir wohl doch mal das Debugging ansehen. Seltsam, da gibt es diese Zeile:
E: Failed to fetch http://raspbian.raspberrypi.org/raspbian/pool/main/b/base-files/base-files_10.3+rpi1+deb10u10_armhf.deb 404 Not Found [IP: 93.93.128.193 80]
Okay, copy-paste nach Google, und ich lande hier: https://forum-raspberrypi.de/forum/thread/47483-apt-get-probleme/. Anscheinend ist das Problem, dass der Updater nach Updates auf Servern sucht, die es nicht mehr gibt. So ein Mist, wie sage ich dem Ding denn, dass es an der richtigen Stelle suchen soll – und was ist die richtige Stelle?
Das steht zum Glück auch dort.
sudo apt-get update
Und nochmal von vorne, und leider scheitert das openHAB-Update erneut. Also lese ich den Thread weiter und finde:
sudo apt update
Mache ich auch, und versuche nochmals ein Update. Und jetzt funktioniert es!
openHAB XIII: Weihnachtsbeleuchtung mit Twinkly
In der Adventszeit wurde es Zeit für ein neues Projekt. Ich möchte gerne Lichterketten in mein Smart Home integrieren. Grundsätzlich sind mir dafür zwei Strategien eingefallen:
- Lichterketten an schaltbare Steckdosen anschließen, dann kann ich sie an- und ausschalten
- Smarte Lichterketten nutzen, die vielleicht noch mehr können als „nur“ an oder aus
Ich habe mich für die zweite Variante entschieden und zwei Lichterketten von Twinkly, genauer gesagt Twinkly Strings 400 RBG,1einmal für 98,99€ bei click-licht.de, und einmal für 129,90€ bei lampenwelt.de organisiert.
Tag 1: Die Einbindung
Grundsätzlich ist die Installation der Twinkly-Lichterketten simpel. Es sollte aber erwähnt werden, dass eine App und ein Account benötigt werden. Möglicherweise ist diese Lösung daher nicht datensparsam – damit habe ich mich noch nicht auseinander gesetzt. Jedenfalls kann man die Lichterketten über eine spezielle App ein- und ausschalten, Farben ändern, Animationen wählen, das ist schon ziemlich cool. Es gibt auch eine Zeitschalt-Funktion, allerdings kann man damit die Lichterkette nur einmal pro Tag an- und einmal ausschalten. Und es ist auch eine feste Uhrzeit, zum Beispiel geht die Lichterkette jeden tag um 16:30 Uhr an.
Ich möchte aber mehr.
Ich möchte, dass die Lichterkette morgens an- und ausgeht, und abends ebenfalls an und aus. Und außerdem soll der Beginn und das Ende helligkeitsabhängig sein. Also werde ich die Twinkly-Lichterkette in openHAB einbinden. Leider gibt es kein Binding dafür, aber trotzdem ein gutes Tutorial. Hinter diesem Link versteckt sich ein Python-Skript, das ich jetzt erst einmal hier dokumentieren möchte.
import sys import json import urllib.request import codecs ARG_ON = 'on' ARG_OFF = 'off' ARG_STATE = 'state' ARG_BRIGHT = 'brightness' ARG_IP = sys.argv[1] ARG_ACTION = sys.argv[2] URL = "http://" + ARG_IP + "/xled/v1/" LOGIN_URL = URL + "login" VERIFY_URL = URL + "verify" MODE_URL = URL + "led/mode" BRIGHT_URL = URL + "led/out/brightness" AUTH_HEADER = 'X-Auth-Token' AUTHENTICATION_TOKEN = 'authentication_token' CHALLENGE_RESPONSE = 'challenge-response' MODE = 'mode' MODE_ON = 'movie' MODE_OFF = 'off' HEADERS = {'Content-Type': 'application/json'} LOGIN_DATA = {'challenge': 'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8='} TURN_ON_DATA = {MODE: MODE_ON} TURN_OFF_DATA = {MODE: MODE_OFF} if len(sys.argv) > 3: #check if the thirth argument is given, save it in a variable and create the brightness data variable ARG_ACTION2 = int(sys.argv[3]) BRIGHTNESS_DATA = {'value': ARG_ACTION2, 'type': 'A'} def formatData(data): return json.dumps(data).encode('utf8') def processRequest(request): return urllib.request.urlopen(request) def processRequestJSON(request): loginResponse = processRequest(request) reader = codecs.getreader("utf-8") return json.load(reader(loginResponse)) # login to api - get challenge response and auth token loginRequest = urllib.request.Request(url = LOGIN_URL, headers = HEADERS, data = formatData(LOGIN_DATA)) loginData = processRequestJSON(loginRequest) challengeResponse = loginData[CHALLENGE_RESPONSE] authToken = loginData[AUTHENTICATION_TOKEN] HEADERS[AUTH_HEADER] = authToken verifyData = {CHALLENGE_RESPONSE: challengeResponse} # verify token by responding with challenge response verifyRequest = urllib.request.Request(url = VERIFY_URL, headers = HEADERS, data = formatData(verifyData)) verifyData = processRequestJSON(verifyRequest) def turnOn(): onRequest = urllib.request.Request(url = MODE_URL, headers = HEADERS, data = formatData(TURN_ON_DATA)) processRequest(onRequest) print(1) def turnOff(): offRequest = urllib.request.Request(url = MODE_URL, headers = HEADERS, data = formatData(TURN_OFF_DATA)) processRequest(offRequest) print(0) def setBrightness(): brightRequest = urllib.request.Request(url = BRIGHT_URL, headers = HEADERS, data = formatData(BRIGHTNESS_DATA)) processRequest(brightRequest) def getState(): modeRequest = urllib.request.Request(url = MODE_URL, headers = HEADERS) modeData = processRequestJSON(modeRequest) if modeData[MODE] != MODE_OFF: print(1) else: print(0) if ARG_ACTION == ARG_ON: turnOn() elif ARG_ACTION == ARG_OFF: turnOff() elif ARG_ACTION == ARG_STATE: getState() elif ARG_ACTION == ARG_BRIGHT: setBrightness()
Ganz ehrlich, ich kann kein Python, ich weiß nicht genau, was dieses Skript macht. Ich kann nur sagen, dass es funktioniert. Wie? Dazu kommen wir jetzt.
Als erstes habe ich dieses Skript als twinkly.py
im Ordner /var/lib/openhab/
abgespeichert. Dann habe ich mir über das openHAB-Benutzerinterface ein neues Item Lichterketten
vom Typ Switch
angelegt.
Und dann habe ich mir folgende lichterkette.rules
gebastelt:
rule "Twinkly Christmas Tree Power State" when Item Lichterketten received command then if (receivedCommand == ON) { executeCommandLine("python3","twinkly.py","x.x.x.37","on") executeCommandLine("python3","twinkly.py","x.x.x.43","on") } else { executeCommandLine("python3","twinkly.py","x.x.x.37","off") executeCommandLine("python3","twinkly.py","x.x.x.43","off") } end
Hier sind zwei Dinge zu beachten. Erstens benötigt man die IP von jeder Lichterkette. Ich habe in meinem Fritzbox-Router feste IP-Adressen für die Lichterketten hinterlegt, damit dieser hart gecodede Befehl funktioniert. Zweitens ist bei dieser Rule die Syntax extrem wichtig. Ursprünglich habe ich die folgende, nicht funktionierende Zeile benutzt:
executeCommandLine("python3 twinkly.py 192.168.0.209 on")
Aber damit erhält man eine Fehlermeldung: File or directory not found when running executeCommandLine
. Man muss wirklich darauf achten, dass die einzelnen Befehls-Elemente mit ","
voneinander getrennt sind. Das ist ganz wichtig!
So, abschließend habe ich noch den Switch auf meiner openHAB-Startseite eingebunden. Damit bin ich erst einmal zufrieden.
Tag 2: Zeitgesteuertes Ein- und Ausschalten
ich möchte ja, dass die Lichterketten morgens und abends jeweils an- und wieder aus gehen. Dazu nutze ich Sonnenauf- und -untergang, die zugehörigen Daten fallen aus dem Astro-Binding. Das muss ich noch dokumentieren, hier gibt es erst einmal nur die Code-Schnipsel.
Für die lichterkette.rules
rule "Lichterketten morgens an" when Item Tageszeit changed to "Morgen" then Lichterketten.sendCommand(ON) end rule "Lichterketten morgens aus" when Item Tageszeit changed to "Tag" then Lichterketten.sendCommand(OFF) end rule "Lichterketten abends an" when Item Tageszeit changed to "Vorabend" then Lichterketten.sendCommand(ON) end rule "Lichterketten abends aus" when Item Tageszeit changed to "Nacht" then Lichterketten.sendCommand(OFF) end
Und dann gibt es noch die tageszeit.rules
, welches das oben genutzte Item Tageszeit
verändert:
rule "Es wird morgen" when Item Sonne_Hohenwinkel changed then if (Sonne_Hohenwinkel.state == NULL || Sonne_Hohenwinkel.state > -12|"°") { if (Tageszeit.state == "Nacht") { Tageszeit.sendCommand("Morgen") } } end rule "Es wird Vormittag" when Channel "astro:sun:local:rise#event" triggered START then Tageszeit.sendCommand("Vormittag") end rule "Es wird Tag" when Item Sonne_Hohenwinkel changed then if (Sonne_Hohenwinkel.state == NULL || Sonne_Hohenwinkel.state > 3|"°") { if (Tageszeit.state == "Vormittag") { Tageszeit.sendCommand("Tag") } } end rule "Es ist Tag" when Time cron "0 0 12 ? * * *" then Tageszeit.sendCommand("Tag") end rule "Es wird Vorabend" when Item Sonne_Hohenwinkel changed then if (Sonne_Hohenwinkel.state == NULL || Sonne_Hohenwinkel.state < 3|"°") { if (Tageszeit.state == "Tag") { Tageszeit.sendCommand("Vorabend") } } end rule "Es wird Abend" when Item Sonne_Hohenwinkel changed then if (Sonne_Hohenwinkel.state == NULL || Sonne_Hohenwinkel.state < -2|"°") { if (Tageszeit.state == "Vorabend") { Tageszeit.sendCommand("Abend") } } end rule "Es ist Nacht 1" when Time cron "0 15 22 ? * * *" then Tageszeit.sendCommand("Nacht") end rule "Es ist Nacht 2" when Time cron "0 0 4 ? * * *" then Tageszeit.sendCommand("Nacht") end rule "Debugging" when Item Tageszeit changed then logWarn("Tageszeit", "Tageszeit changed. Ist jetzt: {}", Tageszeit.state) end
Und es funktioniert. Wie durch Magie gehen die Lichterketten in der Morgen- und Abenddämmerung an und wieder aus. Jeden Tag zu einer leicht anderen Uhrzeit, immer so, dass es gerade dunkel ist.
Tag 3: Nächstes Jahr
Die obigen Schritte habe ich im Jahr 2021 durchgeführt (aber den Artikel nie veröffentlicht). Irgendwann nach Weihnachten habe ich damals die Lichterketten wieder abgebaut und die lichterkette.rules
entfernt. Jetzt ist November 2022, und ich habe die Lichterketten wieder aufgehängt. Und sie sollen auch bitte wieder funktionieren, also lade ich die unveränderte lichterkette.rules
wieder auf meinen openHAB-Server. Und siehe da, ich kann die Lichterketten immer noch ausschalten.
Aber nur ausschalten. Anschalten funktioniert nicht mehr. Das ist sehr seltsam.
Ich gehe in den Debugging-Modus, versuche herauszufinden, ob das if-else-Konstrukt der lichterkette.rules
funktioniert. Und was soll ich sagen, daran liegt es nicht, denn es funktioniert. Also muss ja die twinkly.py
defekt sein, denn was soll es sonst sein? Aber, oh Schreck, ich kann ja immer noch kein Python, was mache ich denn jetzt?
Naja, ich nutze Google. Ich finde andere Menschen mit dem gleichen Problem, aber leider ohne Lösung. Das wäre ja auch zu einfach gewesen.
Ich finde ein (inoffizielles) Twinkly-Binding, hier. Das ist doch vielversprechend, aber leider unterstützt es erst openHAB ab Version 3.2, und ich bin ja noch bei 3.0.1. - ich sollte sowieso updaten. Wie das geht, beschreibe ich in einem anderen Artikel, denn hier habe ich wieder ziemlich geflucht. Aber jetzt kommt die Magie: Nach dem Update auf openHAB 3.3 funktioniert twinkly.py
wieder problemlos. Anscheinend hat das Update alles gelöst, und ich muss das Binding nicht ausprobieren. Und mein Garten erstrahlt wieder im Twinkly-Glanz.