Wetterradar im Dashboard

Ich wollte gern ein Wetterradar im Dashboard haben. Doch an solche grafischen Darstellungen kommt man ja nicht immer ohne weiteres (kostenlos) ran – und der DWD bietet nur eine Drei-Länder-Darstellung.

Also musste etwas CSS her, um mittels eines Node-RED template Node nur einen Bildausschnitt darzustellen.

<div style="position:absolute;width: 296px;height: 250px; background-color: #BEBEBE;overflow: hidden;">
<img src="https://www.dwd.de/DWD/wetter/radar/radfilm_thu_akt.gif" style="position: absolute;top:-250px;	overflow: hidden;" />
</div>

Ich definiere einen Container mit overflow:hidden; sodass alles was nicht reinpasst auch nicht angezeigt wird. Mittels top und left kann ich das Bild entsprechend vertikal und horizontal verschieben.

Update 2021

Inzwischen bin ich auf das Radar eines anderen Wetterdienstes umgestiegen. Da dieser bei der Fremd-Verwendung nicht so freigiebig ist, wie der DWD, erwähne ich dessen Namen hier nicht und sagen nur so viel: mit einem simuliertem Website-Zugriff (http request-Node) und der Übermittlung des Cookies und des richtigen Referer-Headers beim Abruf der Radar-Grafik ist so manche unwirksame Sperre überwindbar. Die Grafik speichere ich dabei lokal zwischen (httpStatic).

Ein change-Node zwischen simuliertem Website-Zugriff und Grafik-Abruf

Warum ich meine Shelly 2.5 nicht mehr mit MQTT steuere

Bisher habe ich die Shelly 2.5, welche ich zur Rolladensteuerung einsetze, über iobroker + MQTT gesteuert. Ich nutze bei ihnen die original Firmware, weil ich die Positionskontrolle, die Kalibierierung und die Hindernis-Erkennung sehr schätze. Darum steuere ich jetzt nicht mehr per MQTT:

Scheinbar ein Firmware Bug

Disclaimer: dieser Artikel ist schon etwas älter. Ob es ein Bug war und ob es diesen potentiellen Bug noch gibt, weiß ich nicht. Ich komme mit der Nicht-MQTT Steuerung sehr gut klar, daher habe ich dies beibehalten.

Ab und zu kommt es bei meinen Shellys dazu, dass die WLAN Verbindung abbricht. Dies liegt einfach an der Reichweite des WLANs, die in mancher Wand im Grenzbereich liegt. Dies ist normalerweise kein Problem, da sich die Shellys recht zuverlässig wieder mit dem Router verbinden. Doch manchmal öffnen sich nach der Wiederverbindung wie von Geisterhand die Rollos – also sie fahren unvermittelt nach oben. Viele Tests später ist meine Theorie, dass dies am MQTT liegt, und es hier scheinbar einen Bug in der Firmware gibt.

MQTT + iobroker Objekte

Zweiter Grund: Von NodeRED kommt die Logik meines SmartHomes. So auch die Rolladensteuerung. Über das Setzen/Ändern von iobroker Objekten, sendet man die Befehle per MQTT. Ein Problem: hat das Objekt bereits den gleichen Wert, wie den, den man setzen will, wird der Befehl nicht übertragen. Wurde also zum Beispiel zuletzt das Rollo auf 60% gestellt, das Rollo danach per Wandtaster wieder hochgefahren, kann man es nicht erneut auf 60% einstellen, weil das Befehls-Objekt noch auf 60 steht. Man muss also umständlich auslesen, welcher Wert gerade im Objekt steht, und ggf. z.B. 61 übermitteln.

Darum nutze ich jetzt die HTTP API

Umgestiegen bin ich auf die HTTP API. Über sie rufe ich peridoisch den aktuellen Status ab (tags öfter als nachts) und sende Befehle. Die Vorteile:

  • Ich habe einen Adapter weniger im iobroker, spart Arbeitsspeicher.
  • Ich umgehe den möglichen Firmware Bug und habe (bisher) keine geisterhaft öffnenden Rollos mehr.
  • Ich kann Befehle senden, ohne diese vorher mit dem aktuellen Status abgleichen zu müssen.
  • Ich bekomme über den HTTP StatusCode (200) direktes Feedback, ob ein Befehl angekommen ist.

So mache ich es

Zum einen habe ich in Node-RED einen HTTP in-Node erstellt, bei dem sich die Shellys über die I/O URL Actions melden, wenn sie stoppen – also die Rollos eine neue Position eingenommen haben. Der dann angestoßene Abruf der Position hält den Wert im iobroker aktuell.

Zum anderen habe ich einen Subflow erstellt, welcher die Befehle an die Shellys übermitteln. Er benötigt als Argument die IP des betroffenen Shellys und einen Befehl. Dabei verarbeitet der Subflow sowohl Open, Close und Stop als Textbefehle als auch Integer-Werte – zwischen 0 und 100 – für die Position des Rollos in „Prozent geöffnet“. (100% = ganz offen)

Hier das Flow:

Sommerzeit/Winterzeit

Noch gibt es sie, die Sommerzeit und die Winterzeit. Gerade bei der Rolladensteuerung habe ich deutliche Auswirkungen der Zeitumstellung festgestellt. Daher musste eine Sommerzeit/Winterzeit-Unterscheidung her.

Der Funktionsblock muss auf zwei Ausgänge gestellt werden. Oben ist die Winterzeit, unten die Sommerzeit. Unter msg.yeartime ist auch die entsprechende Zeit hinterlegt.

var today = new Date();
var monat = today.getMonth()+1;
var tag = today.getDate();
var thisYearS;
var thisYearW;
var thisYearSDays = 0;
var thisYearWDays = 0;

function isLeapYear( year ) {
	if ( ( year % 4 === 0 && year % 100 !== 0 ) || year % 400 === 0 ) return true;
	else return false;
}
function calcLeapYear( year, days ) {
	if ( isLeapYear( year ) ) return ++days;
	else return days;
}
function subToSunday( myDate, year, days, prevMonthDays ) {
	for ( i = myDate.getDay() ; i > 0 ; i-- ) {
		days--;
	}
	days -= prevMonthDays;
	days = isLeapYear( year ) ? --days : days;
	return days;
}

	year = today.getFullYear();
	thisYearS = new Date( year,  3, 0, 0, 0, 0 );
	thisYearW = new Date( year, 10, 0, 0, 0, 0 );
	thisYearSDays = nextYearSDays = 90;
	thisYearWDays = nextYearWDays = 304;

	thisYearSDays = calcLeapYear( year, thisYearSDays );
	thisYearWDays = calcLeapYear( year, thisYearWDays );

	thisYearSDays = subToSunday( thisYearS, year, thisYearSDays, 59 );
	thisYearWDays = subToSunday( thisYearW, year, thisYearWDays, 273 );
	
	node.status({fill:"grey",shape:"ring",text:thisYearSDays + ".03." + year + " - " + thisYearWDays + ".10." + year});
	
	
if((monat < 4 && tag < thisYearSDays) || monat < 3 || monat > 10 || (monat > 9 && tag > thisYearWDays)) { // Winterzeit
            msg.yeartime = "Winterzeit";
            return [msg, null];
}
else {  // Sommerzeit 
        msg.yeartime = "Sommerzeit";
        return [null, msg];
}

Das JavaScript basiert auf dem Script von https://www.kostenlose-javascripts.de/javascripts/datum-und-uhrzeit/zeitumstellung/

Gefrorener Raspberry Pi

Nein, in diesem Beitrag geht es leider nicht um ein leckeres Dessert. Es geht um ein Problem, welches ich in letzter Zeit immer wieder beobachtet habe: der Raspberry Pi, der mein Smart Home steuert, hängt sich auf.

Das Phänomen

Manchmal, wenn ich einen drahtlosen Zigbee Schalter (Xiaomi/Aqara) betätigt habe, war in der Folge der Raspberry Pi nicht mehr erreichbar, hatte sich aufgehängt – weder über die verschiedenen Ports (1880, 8081, 8082) noch per Ping gab er ein Lebenszeichen von sich.

Die Analyse

Die Problemanalyse lief tatsächlich recht schleppend, tröstete ich mich damit, dass ich das System wohl mal neu aufsetzen muss. Irgendwann fiel mir dann aber ein Muster auf.

Das Muster

Das Problem trat nur auf, wenn ein Zigbee Schalter einen Zigbee Aktor schalten sollte. (Logik via Node-RED) Sollte der Zigbee Schalter einen WLAN Aktor schalten, trat das Problem nicht auf. Sprich: wenn der Conbee II (Phoscon, Dresden Elektronik) zuerst ein Signal empfangen und Sekundenbruchteile später ein Signal senden sollte.

Die (vorläufige) Lösung

Die vorläufige Lösung, die seit zwei Wochen Ausfälle wirkungsvoll verhindert hat, ist ein Verzögerung (delay) zwischen Empfang und Senden des Signals. Aktuell experimentiere ich mit einer halben Sekunden – ist nicht unbedingt schön, aber scheinbar wirkungsvoll.

Verflixte GPIOs (2)

Fortsetzung von Verflixte GPIOs

Die Freude über die Lösung mit dem exec-Node und wiringPi währte nur kurz, denn wiringPi wird nicht weiterentwickelt (wiringPi – deprecated…) und unterstützt so den Raspberry Pi 4 nicht.

Ersatz (hoffentlich langfristig) habe ich (natürlich) in einem NodeRED Node gefunden:

node-red-node-pi-gpio

Funktioniert wunderbar.

MQTT/Tasmota ALIVE?

Beim MQTT-Adapter und SONOFF-Adapter im ioBroker gibt es eigentlich bei jedem Gerät auch eine ALIVE/online Variable, die nach meinem Verständnis eigentlich darüber Auskunft geben sollte, ob das Gerät „am Leben“, also online und erreichbar ist. Irgendwie ist diese Anzeige aber sehr unzuverlässig/zeitverzögert.

Daher nutze ich den PING Adapter, um im Minutentakt zu erfahren, ob ein Gerät offline ist, und um dann entsprechende Warnungen im Dashboard ausgeben zu können, oder bei kritischen Aktoren eine Warnmeldung per E-Mail zu versenden.

Alle 60.000 ms – also eine Minute – reicht für meine Zwecke.

Verflixte GPIOs

Über die GPIOs des Raspberry Pi habe ich ein Relais-Board angeschlossen. Es manipuliert den Temperatursensor des Solar-Steuerung, um eine automatische Abkühlung des Warmwasserspeichers in der Nacht zu ermöglichen. So versuche ich auch in Hitze-Phasen eine Stagnation in der Solaranlage zu verhindern.

Zur Steuerung kam der ioBroker-Adapter RPI-Monitor (rpi2) zum Einsatz. Nach irgendeinem Update bekam ich diesen aber nicht mehr zum Laufen.

Ständig nur folgender Log-Eintrag:

GPIO is not initialized!

(Das Problem scheint nicht nur bei mir aufzutreten, ein Bug-Report findet sich bei GitHub.)

Einige Stunden Recherche und Probieren später, war ich es leid, und da ein Neuaufsetzen aktuell nicht zur Debatte steht, suchte ich eine andere Möglichkeit. Diese fand ich im exec-Node und wiringPi.

Hinweis: wiringPi wird leider nicht mehr weiterentwickelt, sodass diese Lösung nur mit Raspberry Pi’s bis Modell 3B+ funktioniert. Eine weiter Lösung gibts unter Verflixte GPIOs (2)

Nicht die schönste Variante, aber einfach und wirkungsvoll.

Über die Kommandozeile habe ich einmalig den Modus des entsprechenden GPIO auf „out“ gesetzt.

gpio -g mode 23 out

Nun kann ich über den exec-Node den Status des GPIO auslesen und auch setzen.

Fehlersuche in NodeRED

Macht man seine ersten – oder auch schon etwas intensivere – Schritte im NodeRED, geht nicht alles sofort glatt. Bei mir zumindest.

Häufige Fehler bei mir:

1. Ich baue Endlosschleifen – und nichts geht mehr.

Gerade im Zusammenhang mit NodeRED Dashboard ist es mir immer wieder passiert, dass ich Endlosschleifen gebaut habe.

Allein dieser Aufbau birgt schon das Risiko einer Endlosschleife.

Abhilfe ist einfach. Beim Laden des Variablenwertes den Modus auf „block unless value changes“ setzen.

An anderer Stelle kann auch der report-by-exception – Node (rbe) hilfreich sein. Hier wird jede msg aufgehalten, bis der payload sich unterscheidet.

2. Ich setze statt change ein switch

Eigentlich sind switch und change sehr leicht auseinanderzuhalten. Nur liegen sie in der Palette halt direkt nebeneinander, haben ähnliche Symbole, die gleich Farbe, und möchte man ein Change (ich ändere den Wert einer Variable) einsetzen und setzt stattdessen ein Switch (if then else) fällt auch das Properties Menü kaum negativ auf, sofern man nur kurz die payload verändern will. Mir schon mehrmals passiert – hier lohnt sich ein genauer Blick.

3. Datentypen

Im ioBroker-Adapter NodeRED ist standardmäßig eingestellt, dass alle aus dem ioBroker gelesen Werte in String (Text) umgewandelt werden.

Versucht man dann mit den Werten zu arbeiten, zu rechnen, true und false zu vergleichen, merkt man schnell, entweder muss die Option im Adapter umgestellt werden, oder man muss mit Datentypen jonglieren. In diesem Fall wird der JavaScript function-Node dein Freund.

Zum Beispiel zum Umwandeln einer Zahl (string) in eine „wirkliche“ Zahl (float).

msg.payload=parseFloat(msg.payload);

Wird sicher fortgesetzt …

Shelly & Tasmota OTA Update anstoßen

Ab einer gewissen Zahl von WLAN Komponenten, wird es zur Herausforderung, die Firmware der Geräte auf dem aktuellen Stand zu halten. Zu diesem Zweck habe ich mir ein Tab in meinem Node-RED Dashboard eingerichtet.

Das grüne Herz zeigt, dass der Shelly online ist.

Die Abkürzung OTA steht für „Over The Air“, auf deutsch „über die Luft“. Es handelt sich dabei um eine drahtlose Methode, Updates auf Geräte zu übertragen.

Tasmota Firmware

Die aktuelle Tasmota Version, lässt sich durch einen automatisierten Abruf des GitHub-Feeds auslesen:

https://github.com/arendst/Tasmota/releases.atom

[{"id":"83b36f5b.0b8b","type":"xml","z":"c083a756.a72f18","name":"","property":"payload","attr":"","chr":"","x":370,"y":660,"wires":[["9fef7d11.d2a7c"]]},{"id":"390fe0f3.da48","type":"http request","z":"c083a756.a72f18","name":"","method":"GET","ret":"txt","paytoqs":false,"url":"https://github.com/arendst/Tasmota/releases.atom","tls":"","persist":false,"proxy":"","authType":"","x":710,"y":620,"wires":[["83b36f5b.0b8b"]]},{"id":"3a9bb870.4e0158","type":"inject","z":"c083a756.a72f18","name":"TASMOTA VERSION","topic":"","payload":"","payloadType":"date","repeat":"21600","crontab":"","once":true,"onceDelay":0.1,"x":400,"y":620,"wires":[["390fe0f3.da48"]]},{"id":"9fef7d11.d2a7c","type":"function","z":"c083a756.a72f18","name":"HIER Feed Version filtern","func":"msg.version = msg.payload[\"feed\"][\"entry\"][0][\"title\"][0];\nnode.status({text:msg.version});\nmsg.version = msg.version.replace(\"Tasmota v\",\"\");\nmsg.version = msg.version.replace(\"Tasmota\",\"\");\nmsg.version = msg.version.substring(0,6)\nreturn msg;","outputs":1,"noerr":0,"x":550,"y":660,"wires":[["e8c6fe5.7a082"]]},{"id":"e8c6fe5.7a082","type":"change","z":"c083a756.a72f18","name":"","rules":[{"t":"set","p":"tasmotaversion","pt":"global","to":"version","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":660,"wires":[["18e34f71.edaca1"]]}]

Die Tasmota Version steht immer aktuell in den MQTT Daten im ioBroker. Alternativ lässt sie sich über das Tasmota Command „Status“ auslesen.

Um bei einem Tasmota Geräte den Firmware-Update-Vorgang zu starten, reicht ein simpler HTTP-Aufruf von:

http://192.168.xx.xx/cm?cmnd=upgrade%201&user=BENUTZERNAME&password=PASSWORT

Auch die OtaUrl lässt sich per simplem HTTP-Aufruf anpassen. Leerzeichen oder Sonderzeichen in der OtaURL müssen durch ihre jeweiligen ASCII-Hex-Codes ersetzt werden. Dem Hex-Code muss ein Prozentzeichen % vorangestellt werden (z. B. %3B).

http://192.168.xx.xx/cm?cmnd=OtaUrl%20URL&user=BENUTZERNAME&password=PASSWORT

Mehr Infos zu Tasmota Commands

Shelly.cloud Firmware

Bei der Original Shelly Firmware, ist es ähnlich leicht, aber ein wenig anders. Die aktuell zur Verfügung stehende Firmware Version lese ich aus der JSON-Datei der offiziellen API:

https://api.shelly.cloud/files/firmware

Hier findet man auch die Download-Urls zu den Firmwares für die Shelly Geräte. Die aktuelle Firmware, hier für den Shelly 2.5, liegt zum Beispiel hier:

https://repo.shelly.cloud/firmware/SHSW-25_build.zip

Die Shellys verraten mit folgendem Kommando ihre aktuelle Version:

http://BENUTZERNAME:PASSWORT@192.168.xx.xx/status/

Den Update-Vorgang kann man mit folgendem Kommando starten:

http://BENUTZERNAME:PASSWORT@192.168.xx.xx/ota?update=1

Möchte man eine andere Shelly-Firmware-Version flashen, lässt sich hier auch eine Firmware-URL übergeben. Soweit ich weiß ist das Flashen auf eine alternative Firmware (Tasmota) so jedoch nicht möglich.

http://BENUTZERNAME:PASSWORT@192.168.xx.xx/ota?url=https://repo.shelly.cloud/firmware/SHSW-25_build.zip

Mehr Infos zur Common HTTP API der Shellys

Update: 25.10.2021

Seit Version 10.0.0 von Tasmota braucht man natürlich beim Filtern der Feed Version natürlich ein substring(0,6) – etwas unflexibel, sollte ich mal ändern.

Hallo Welt!

Ich baue mir mein eigenes SmartHome. Da ich dies nicht während eines Neubaus, sondern in einer (unserer) Bestandsimmobilie tue, sind die meisten Lösungen auf Funkbasis.

Ich versuche beim Bau einigen Grundsätzen zu folgen:

  • kein Smartphone Zwang – alle wichtigen Funktionen wie Licht und Rollläden müssen auch über die normalen Schalter bedienbar sein.
  • keine Insellösung – das Festlegen auf einen einzelnen Hersteller schränkt nur unnötig ein und verteuert es.
  • my home is my castle – das SmartHome läuft bei mir zuhause – nicht in der Cloud.
  • Open Source – soweit es geht. Bei der Firmware (gerade von Zigbee-Geräten) stößt man hier natürlich an seine Grenzen.
  • kein „Alexa“, kein „Hey Google“ – Daten fallen in einem SmartHome wahre Unmengen an. Doch die bleiben bei mir.
  • es hat auch Grenzen: zumindest sage ich das jetzt noch.

Ich bin in dem Bereich kein Profi. Vor gut einem Jahr habe ich mit ioBroker und NodeRED angefangen. Trotzdem gibt es vielleicht die ein oder andere Erkenntnis, die ich hier teilen kann.