POST-HTTP Request mit Daten

Da ich mich sehr dumm angestellt habe und ewig brauchte, um mit Node-RED einen HTTP Request inkl. Daten zu versenden, dokumentiere ich hier – nur für mich (weil sich bestimmt niemand so umständlich anstellt) – die funktionierende Lösung.

Der simple Aufbau, ein Function-Node und ein HTTP-Request-Node:

Im Function-Node werden die zu übermittelnden Daten in msg.payload als JSON geschrieben. Außerdem wird
msg.headers["Content-Type"] = "application/x-www-form-urlencoded";
gesetzt.

Der HTTP-Request ist dann kaum zu konfigurieren. Methode = POST eintragen, dann noch die URL und fertig.

Kaputt gespielt – Backup und Wiederherstellung

Was soll ich sagen, irgendwie habe ich mein Raspberry Pi OS (Raspbian) kaputt gespielt. Es fing damit an, dass ich nicht per VNC auf das System kam (für deCONZ). Zeitweise ging nicht mal raspi-config. Und: jedes mal ging nach ein paar Betriebsstunden die CPU Last massiv in die Höhe – ausgelöst durch einen Fehler mit oder durch kworker. Also fiel die Entscheidung: neu aufsetzen. Ein praktischer Präzedenzfall für Backup & Restore.

In meinem Setup waren drei, oder besser vier Dinge zu sichern und zu überspielen. Da ich noch einen Raspberry Pi 4 herumliegen hatte, konnte ich die Systeme parallel laufen lassen, und musste nicht ständig zwischen alt und neu wechseln, sofern mir noch Infos fehlten. Auch konnte ich so die Vollständigkeit der Daten gut prüfen.

Zum Kopieren der Daten zwischen den Raspberrys nutze ich immer WinSCP.

1. deCONZ/Phoscon

Bei Phoscon einfach über die Weboberfläche unter „Gateway“ ein Backup ziehen und an gleicher Stelle auf dem neuen System wieder einspielen. Das Einspielen des Backups habe ich jedoch erst gemacht, als die microSD-Karte mit dem neuen System auch im Raspberry Pi mit dem Conbee II steckte, um mögliche Probleme zu vermeiden.

2. InfluxDB

Hier sollte man zwingend mit den Backup & Restore Befehlen von influxd arbeiten, ein Kopieren der Datenordner führte (zumindest bei mir) nicht zum Erfolg.

Es müssen sowohl der META-STORE als auch die Datenbank(en) gesichert werden.

$ influxd backup <speicherort-fuer-backup>
$ influxd backup -database iobroker <speicherort-fuer-backup>

Das Wiederherstellen ist ähnlich leicht.

$ influxd restore -metadir /var/lib/influxdb/meta <speicherort-des-backups>
$ influxd restore -database iobroker -datadir /var/lib/influxdb/data <speicherort-des-backups>     

Anschließend muss man ggf. noch die Benutzerrechte des Ordners anpassen.

$ sudo chown -R influxdb:influxdb /var/lib/influxdb

3. ioBroker

Bei ioBroker kann man ein komplettes Backup sehr leicht über die Kommandozeile erstellen:

$ cd /opt/iobroker
$ sudo iobroker stop
$ sudo iobroker backup
$ sudo iobroker start

Das Backup liegt dann unter /opt/iobroker/backups/.

Ebenso einfach ist das Wiederherstellen. Das Backup-Archiv muss man dazu in den gleichen Ordner auf dem neuen System kopieren.

$ sudo iobroker stop 
$ sudo iobroker restore 0
$ sudo iobroker start all
$ sudo iobroker start
$ sudo iobroker upload all

(der Befehl „sudo iobroker upload all“ lädt die Webseiten aus den Ordnern „www“ und „admin“ aus den Adaptern in den ioBroker-Dateispeicher hoch)

Nun dauert es je nach Umfang der ioBroker-Installation einige Minuten, bis automatisch wieder alle Adapter installiert sind. Über die Weboberfläche – Instanzen kann man den Prozess rudimentär beobachten.

4. Node-RED

Die Flows werden beim ioBroker-Backup (3.) mitgesichert. Allerdings werden die zusätzlich installierten Node-Module (über „Palette verwalten“) beim Wiedereinspielen nicht automatisch installiert. Hier hilft ein Screenshot der Liste oder eine kurze Notiz der installierten Node-Module. Aber: zur Not lassen sich die auch anhand der Auflistung fehlender Nodes recherchieren und rekonstruieren.

Probleme

Probleme gab es eigentlich gar nicht. Einzig der ioBroker PING Adapter ändert den Objektpfad anhand des Hostnames – wählt man hier bei der neuen Installation einen anderen, muss man sämtliche Pfadangaben des PING Adapters z.B. im Node-RED korrigieren.

Nachtrag 23.06.2021

Inzwischen (?) kann man im PING Adapter einstellen, dass der Hostname nicht im Zustandsnamen verwendet werden soll. Wenn man bei der Einrichtung darauf achtet, kann man beim Backup & Restore dieses Problem umschiffen.

Messungen in einer InfluxDB löschen

Manchmal gibt es Messungen in einer InfluxDB, die zerstören das schöne Bild – verursacht durch Messfehler, Programmierfehler oder Schnittstellenproblemen. Bei mir sind das manchmal fehlerhafte 0-Werte.

Leider gestaltet sich das Löschen von einzelnen Messungen aus einer InfluxDB nicht so einfach, wie der ein oder andere es vielleicht von anderen Datenbanken gewohnt ist, da die Zeit das einzig zugelassene Identifikationsmerkmal einer DELETE Operation ist.

Update 02.10.2022: Inzwischen unterstützt der ioBroker InfluxDB Adapter das Löschen von Messwerten. Dazu einfach den Datensatz auswählen und das Löschicon betätigen.

Hier meine Vorgehensweise (unter Windows):

  1. Über die Software InfluxDB Studio (nur für Windows) mit der Datenbank verbinden.
  2. Über folgenden Befehl und das Anpassen der Zeit (und der Datenbank) die zu löschenden Werte identifizieren.
    SELECT * FROM „coronavirus-statistics.0.Germany.cases“ WHERE time > now() – 5d – 19h AND time < now() – 5d – 17h

    Dabei steht „5d“ für fünf Tage, „19h“ für 19 Stunden, und so weiter.
  3. Werden bei dem SELECT nur noch die Messungen angezeigt, welche gelöscht werden sollen, das “ SELECT * “ durch “ DELETE “ ersetzen und den Befehl ausführen.
  4. Fertig.

Ich übernehme keine Garantie für ungewollte Datenverluste.

delete measurment influxdb

Schnelles Smartphone UI

Ich mag ioBroker, ich mag Node-RED – aber ein User Interface, welches innerhalb von drei Sekunden auf dem Smartphone zur Verfügung steht, ist weder mit vis noch mit Node-RED UI / Dashboad möglich. Vielleicht liegt es am eingesetzten Raspberry PI und eine Monster-Hardware würde es schneller ermöglichen – so ist die Ladezeit je nach Verbindungsqualität (WLAN, VPN) jedoch belastend – gerade für den schnellen Blick auf die Haustechnik (z.B. Solarthermie) oder die Straßenbahn-Abfahrtszeiten.

Einzige Lösung kann eine native App fürs Smartphone sein, dachte ich mir. Doch weder für vis noch für Node-RED UI gibt es entsprechende perfomante Ansätze. Also musste eine weitere Lösung her. Erste Tests mit MQTT Dashboard-Apps waren verheißungsvoll, doch offenbarten sie dann Probleme. Denn bei MQTT muss die App weitgehend online sein, um die aktuellen Werte empfangen zu können. Frisst Akku und Leistung auf Seiten des Smartphones. Ein Abrufen der Werte nach einer längeren Offline-Phase ist nicht ohne weiteres möglich.

Covergestaltung

Dann stolperte ich über die App IOT Dashboard, welche mich gerade sehr begeistert. Die App von Ciprian Savastre ermöglicht es, via REST im JSON-Format Daten abzurufen, und auch Befehle zu senden. Ein paar Nodes in Node-RED ermöglichen sowohl die Auslieferung der Daten an die App, als auch das Empfangen von Befehlen aus der App.

  • Ja, die App ist funktionell noch ausbaufähig. Der Entwickler ist aber nett und ansprechbar für Bugs und Ideen.
  • Ja, es ist nur eine Ergänzung zu einem ausgefeilten UI via vis oder Node-RED Dashboard.
  • Ja, man muss auf dem Smartphone einigen Konfigurationsaufwand betreiben.

Dafür hat man aber in atemberaubender Geschwindigkeit den aktuellen Stand des Smart-Homes auf dem Schirm.

Und so sieht es gerade bei mir aus:

Aktuell benutze ich noch keine Steuerungsfunktionen, sondern nur das reine Auslesen von Werten. Daher sieht es im Node-RED auch bisher sehr einfach aus.

Die Steuerung realisiere ich bisher über Node-RED UI / Dashboard – einige häufig genutzte Funktionen werde ich aber sicher auch in der App IOT Dashboard abbilden – außer es läuft mir etwas besseres über den Weg.

NodeRed UI Design

Das Design von NodeRed Dashboard braucht meiner Meinung nach noch ein wenig „Nachhilfe“. Hier die drei wichtigsten Styles meiner „Nachhilfe“, welche ich über ein ui_template Node in die <head> Section einfüge.

<style>
body {
        font-size:0.8em;
        background-color:#E6F7FF !important;
    }
md-card {
        border-bottom: 1px solid #F2F2F2;
    }
.nr-dashboard-cardpanel > p {
        margin-top: 3px !important;
        margin-bottom: 3px !important;
        min-height: 23px !important;
    }
</style>

Das Ergebnis:

Gedanken zur KWL

Kontrollierte Wohnraumlüftungen (kurz KWL) sind eine feine Sache. Man stelle sich vor, man müsste tagsüber mehrmals lüften … Klar: sie ist keine Klimaanlage. Und doch sollte man nicht nur beim Thema „wärmen“, bzw. Wärme erhalten im Winter (was sie über die Wärmerückgewinnung ja macht) ein paar Dinge beachten.

Standort

Wer die Gelegenheit hat, den Standort des KWL Geräts zu bestimmen, tue dies weise. So sollten sie klar innerhalb der thermischen Hülle des Hauses stehen – für die entsprechende Effizienz im Winter. Erfahrungen zeigen aber auch: der Heizraum ist meist nicht der geeignete Ort für das Gerät – gerade in einer Kombination mit Solarthermie. Die steht im Sommer schließlich fast unbegrenzt zur Verfügung und hebt die Temperatur im Heizraum (wo in der Standardausführung meist auch der Warmwasser-Speicher steht) auf unschöne Höhen. Jegliche Kaltluft, die möglicherweise in der Nacht die KWL dank Bypass ohne Wärmerückgewinnung passieren könnte, wird so stark durch die Heizraumtemperatur beeinflusst, dass nicht mal eine minimale Abkühlung der Räume über die KWL stattfindet. Also: vielleicht gibt es einen Wäscheraum oder einen Kellerraum – sofern man über einen solchen verfügt – in dem die KWL besser aufgehoben ist.

Funktionen / Abhilfe

Eine wichtige Funktion für ein angenehmes Raumklima ist der schon erwähnte Sommer-Bypass. Er leistet – wenn nicht von der Raumtemperatur beeinflusst – einen Beitrag für ein angenehmes kühles Raumklima im Sommer, indem er die Wärmerückgewinnung umgeht. Interessant und wichtig – auch für alle, die das gleiche Dilemma der Interaktion zwischen Solarthermie und Lüftung haben – ist der Fensterlüftungsmodus. Bei ihm wird die Zuluft komplett abgeschaltet, sodass die KWL nur absaugt und das Zuströmen kalter Luft (in der Nacht) durch die Fenster unterstützt.

Beispiel: Pluggit

Bei meinem Lüftungsgerät von Pluggit Avent P310 lässt sich der Fensterlüftungsmodus über die Modbus Schnittstelle aktivieren:

modbus.0.holdingRegisters.40169_prmRamIdxUnitMode

Manuel = 4 / Wochenprogramm = 8 / Start Sommer = 2048 / Ende Sommer = 2048

Leider ist es ein Toggle – sprich man sendet sowohl zum Einschalten, als auch zum Ausschalten „2048“.

UI-Performance – Diagramme von Flot

Auch wenn ich das Node-RED Dashboard sehr mag, eines ging mir gehörig auf den Keks: die Performance. Ursache dafür waren bei mir (diesmal) die Diagramme (chart), die den Ladevorgang eines Tabs teils um 10 Sekunden verlängerten. Daher bin ich auf die Diagramme von Flot umgestiegen, welche als iframe (template Node) eingebunden werden und damit asynchron laden. Das Ergebnis: Der Seitenaufbau ist schnell, das Diagramm braucht halt vielleicht noch kurz …

Um die Flot Diagramme an das Dashboard anzupassen nutze ich folgende Einstellungen:

Die Legende ist sicher je nach Anwendungsfall nötig oder nicht nötig. Auch die Höhe des Diagramms sollte je nach Art der Werte angepasst werden.

Das Ergebnis kann sich sehen lassen.

Ladevorgang läuft …
Geladen.

Die Nutzung von Flot hat noch weitere Vorteile:

  • auch nach einem Neustart von Node-RED habe ich noch „volle“ Diagramme
  • die Farben der Linien bleiben auch nach einem Neustart gleich
  • es lassen sich einfach zusätzliche Linien/Marken in die Diagramme einzeichnen
  • man kann die Kurven falls nötig leicht glätten

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/