Bei einer Vielzahl von Sensoren den Akkustand prüfen

Inzwischen haben sich jede Menge Zigbee-Sensoren angesammelt. Diese halten mit einer Batterie echt lange durch. Viele zwei Jahre und mehr. Trotzdem geht die Batterie irgendwann mal zur Neige und davon möchte ich nicht überrascht werden. Also habe ich einen kleinen Flow in Node-RED, welcher die Akkustände jeden Tag einmal prüft und mich bei Bedarf benachrichtigt.

Um nicht für jeden Sensor neue Nodes ergänzen zu müssen, nutze ich die Möglichkeit, Nachrichten mit node.send(msg); asynchron zu versenden.

Sensoren zentral hinterlegen und einzeln durchgehen

var zigbeesensoren = [2,4,5,6,9,10,11,14,15,16,17,21,23,26,29,30,31,32,33,34,36,38,41,44,45,46,49,50,51,52,53,56,57,58];

zigbeesensoren.forEach(function(val) {
    msg.topic = "deconz.0.Sensors."+val+".battery";
    node.send(msg);
});

return;

Im Array zigbeesensoren sind einfach die abzufragenden Sensornummern (der ioBroker-Objekte) hinterlegt. Die forEach-Schleife sorgt dafür, dass das ganze Array durchgegangen wird und das richtige msg.topic für jeden Sensor gebaut und als Nachricht abgeschickt wird. So kann über „IoB read value“ jeder einzelne Batteriestand ausgelesen und in der Funktion „Batterie leer?“ geprüft werden. Wie gewohnt erstellt „UI Notification“ im Bedarfsfall die Benachrichtigung und leitet sie an das zentrale Benachrichtigungssystem.

Einen ähnlichen Aufbau kann man natürlich auch für beliebige andere Objekte nutzen, die vielfach ausgewertet werden müssen.

Was schon alles kaputt ging …

Nach knapp drei Jahren SmartHome-Spielereien zeigen sich bei den ein oder anderen Sachen erste Ermüdungserscheinungen oder technischen Defekte.

Hier eine Auflistung der bisherigen Defekte: (Stand 27.01.2022)

  • zwei Aqara Motion Sensor (RTCGQ11LM)
    Nach ungefähr zwei Jahren hörten sie von einem auf den anderen Tag auf, verlässlich Bewegungen zu erkennen. (zwei weitere habe ich noch im Einsatz)
  • ein Aqara Mini Schalter
    Kam schon defekt an, ließ sich nicht anlernen. Geld wurde erstattet. (aktuell ein weiterer im Einsatz)
  • ein Shelly 2.5
    Nach knapp zwei Jahr in der Wand fing er an, ununterbrochen ein Relais umzuschalten. Mit dem WLAN verband er sich auch nicht mehr. Allterco Robotics war kulant und ersetzte ihn. (9 weitere habe ich im Einsatz)
  • ein Raspberry Pi 4B 2GB
    Aus unerklärlichen Gründen hielt er zuletzt nur noch wenige Stunden ohne einfrieren durch. Die selbe SD-Karte in einem 3B+ läuft problemlos. Selbst bei einem neu installierten OS auf neuer SD-Karte im Leerlauf konnte ich das Fehlverhalten des 4er beobachten. (ein weiterer 4B läuft problemlos)

WordPress Koko Analytics im SmartHome Dashboard

Um Statistiken über verschiedene WordPress-Websites zu erheben, nutze ich das datenschutzfreundliche Plugin „Koko Analytics“. Leider hat dieses Plugin, wie viele andere auch, keine Schnittstelle, um auf die Statistiken anderweitig zuzugreifen. Möchte man dies trotzdem, um sie zum Beispiel in einem SmartHome Dashboard auszugeben, muss man sich quasi selbst eine kleine Schnittstelle basteln, und die erwünschten Daten direkt aus der Koko-MySQL-Datenbank laden.

Hier mein PHP-Code für die beiden Standardwerte Visitors & Page-Views der letzten 28 Tage – mit Ausgabe als JSON.

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
define('DB_NAME', '____DB_NAME____');
define('DB_USER', '____DB_USER____');
define('DB_PASSWORD', '____DB_PASSWORD____');
define('DB_HOST', 'localhost');

$mysqli = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);

$return = $mysqli->query("SELECT sum(visitors),sum(pageviews) FROM (SELECT visitors,pageviews FROM ____DB_PREFIX_____koko_analytics_site_stats ORDER BY date DESC LIMIT 28) AS subquery;");

$row = $return->fetch_array(MYSQLI_ASSOC);
echo json_encode(array("visitors"=>$row["sum(visitors)"], "pageviews"=>$row["sum(pageviews)"]));

$return->close();
$mysqli->close();
?>

Das Skript muss dafür auf die Datenbank der WordPress-Instanz zugreifen können – klar. Seitens Node-RED ist es nur ein kleiner HTTP-Request. Eine Authentifizierung für den Zugriff lässt sich natürlich auch entsprechend ergänzen.

Dumme Haustechnik einfach smart machen

Alle Angaben ohne Gewähr. Alle Ideen, die aus diesem Artikel entstehen, auf eigene Gefahr.
Die beschriebenen Möglichkeiten sollte man als Mieter gar nicht erst lesen, oder direkt wieder vergessen.

Die Steuergerät meiner Gastherme und der Solarpumpe sind dumm. Natürlich kann man einiges einstellen, aber Schnittstellen, um sie smart zu machen, gibt es nicht. Zwar könnte ich für absurde Beträge zumindest der Gastherme mit einem Zusatzgerät ein wenig Vernetzung einhauchen, aber beim Blick auf die Kosten verzichtete ich darauf. Stattdessen trickse ich die Steuergeräte über ihre Sensoren einfach aus.

Was will ich steuern?

Am Anfang stand die Sorge um die Solarthermie-Anlage. Im Hochsommer bringt sie enorme Erträge und heizt den Warmwasserspeicher (leider unterdimensioniert) so weit und so schnell auf, dass die Gefahr besteht, dass sie in praller Mittagssonne aufgrund der nötigen Temperaturbegrenzung aufhört zu arbeiten, die Solarflüssigkeit sich nicht mehr bewegt und anfängt zu kochen. Das Steuergerät hat keine Funktion, dem zu begegnen. Also wollte ich die Möglichkeit, die Solaranlage bei Bedarf in der Nacht laufen zu lassen, um den Speicher abzukühlen, damit es am nächsten Tag nicht zu Problemen kommt.

Weiter ging es, als ich eigene Sensoren am Warmwasserspeicher hatte, und so in schönen Charts mit ansehen konnte, wie schnell das warme Wasser auch ohne Nutzung wieder kalt wird. Dies galt es effektiver zu gestalten und so wollte ich ein Bestellsystem für Warmwasser aufbauen, welches Komfort und Energieeffizienz unter einen Hut bringt. Das Bestellsystem benötigen wir sowieso eigentlich nur im Winter, weil die überwiegende andere Zeit im Jahr genug Warmwasser durch die Solarthermie-Anlage zusammenkommt.

Wie lässt sich die Steuerung umsetzen? (Theorie)

Die Steuerungen von Therme und Pumpe basiert auf Sensorwerten. Anhand dieser Sensorwerte werden bestimmte konfigurierbare Automatismen ausgelöst. Durch die Manipulation der Sensorwerte kann ich also bestimmen, wann ein Automatismus ausgelöst werden soll, und wann nicht. Voraussetzung dafür ist, dass ich die wahren Sensorwerte kenne, damit ich selbst den Überblick habe.

Da es mir nicht möglich war, die Sensorwerte aus den Hausgeräten auszulesen, habe ich eigene Sensoren (DS18B20) am Speicher und der Solarstation ergänzt und mit den Sensoren der Hausgeräte entsprechend abgeglichen.

Beispiel Solarthermie Steuerung: Die Solarthermie-Steuerung vergleicht die Temperatur im Speicher mit der Temperatur auf dem Dach. Ist die Temperatur auf dem Dach um ein konfiguierbares Offset höher als die im Speicher, startet die Steuerung die Pumpe. Wenn ich also mitten in der Nacht sage: „Hallo Steuerung, im Speicher sind es nur 5°C“, dann ist im Hochsommer die Temperatur auf dem Dach definitiv höher und die Solarpumpe bringt fleißig überschüssige Wärme zurück auf das Dach.

Beispiel Gastherme / Warmwasser: Die Steuerung der Gastherme hält den Speicher in einem konfigurierbaren Zeitraum auf einer gewissen Temperatur. Wenn ich also dem Steuergerät vorspiegele, dass die Speichertemperatur über der Zieltemperatur liegt, sieht sie keinen Handlungsbedarf. Schalte ich auf den realen Sensor um, greift wieder die eingebaute Steuerung und das Aufheizen des Speichers kann beginnen.

Wie lässt sich die Steuerung in der Praxis umsetzen?

Für die technischen Umsetzung muss man sich erst einmal vergegenwärtigen, wie ein Temperatursensor technisch funktioniert. Je nach Temperatur liefert der Sensor einen gewissen elektrischen Widerstand. Dieser unterscheidet sich von Modell zu Modell. Weiter hilft hier das Handbuch des Hausgeräts, in dessen Anhang meist eine Tabelle der Widerstände und zugehörigen Temperaturen zu finden ist. Teils muss man dafür das Installateurs-Handbuch bemühen, aber das findet man auch meist online.

Widerstände des Speichertemperaturfühlers einer Buderus GB172-14

Der erste Schritt ist also den passenden Widerstand für die beabsichtigte Temperatur zu besorgen – natürlich müssen es dabei nicht die exakten Werte aus der Tabelle sein, da es egal ist, ob es bspws. 57,0 oder 57,2°C sind. Der zweite Schritt bringt ein wenig Nervenkitzel ins Spiel, wenn man das Sensorkabel des Hausgeräts möglichst mit gut Luft in beide Richtungen einfach durchschneidet (Gerät vorher abschalten!) – im Ernstfall beeinflusst eine Lüsterklemme den Widerstand/Sensorwert aber auch nicht.

Mit einem herkömmlichen Relaisboard an den GPIO des Raspberry PI richtig verkabelt, hat man dann die Möglichkeit, zwischen echtem Sensorwert und vorbestimmten Sensorwert hin und her zu schalten. Meine Geräte stören sich daran nicht. Nach ausgiebigen Tests landete das ganze dann noch auf einer Platine.

Links das Relaisboard, rechts die Platine mit den Anschlüssen für die Sensorkabel und den Widerständen.

Dashboard / UI

Im Winter bemühen wir also jetzt das Dashboard, wenn es um Warmwasser geht.

Im Dashboard habe ich nach anfänglich komplizierten Überlegungen die Steuerelemente sehr simplifiziert. Für Heute, Morgen und Übermorgen gibt es je die Möglichkeit, Warmwasser für den Morgen, Mittag oder Abend im Voraus zu bestellen. Um Mittnacht rutscht natürlich Morgen ➡ Heute und Übermorgen ➡ Morgen. Weiterhin gibt es neben der aktuellen Speichertemperatur auch eine Bewertung der Lage, inkl. Prognose, wie lange der aktuelle Warmwasserbestand noch für eine ausgiebige Dusche reicht. Für die Berechnung der Prognose habe ich Langzeitdaten über die Abkühlung des Speichers erhoben und ausgewertet.

„Nur halb aufheizen“ kommt zum Einsatz, wenn vrstl. nur wenig Warmwasser benötigt wird. Hier schaltet das Relais schon vor erreichen der Zieltemperatur auf den Fake-Wert um und die Therme sieht ihre Arbeit als erledigt an und hört auf zu heizen.

Auch kann man „Warmwasser jetzt!“ bestellen, dann dauert es durch die Leistung der Gastherme nur gut fünf Minuten, bis man duschen kann. Hat man eine trägere Wärmeerzeugung, ist das natürlich bei allen Überlegungen zu berücksichtigen.

Tipps / Warnhinweise

  1. Die Verkabelung am Relais sollte so erfolgen, dass im Fehlerfall (Raspberry Pi kaputt, Relaisboard ohne Strom, etc.) der reale Wert an das Hausgerät gemeldet wird. So kann man zur Not auch mit „Stecker ziehen“ beim Raspberry Pi den „Normalzustand“ wiederherstellen.
  2. Man sollte versuchen, alle Eventualitäten zu durchdenken. Hat man zum Beispiel eine thermische Desinfektion in seiner Warmwasserbereitung aktiviert, hat man neben dem beeinflussten Sensor-Trigger auch einen zeitlichen Trigger, der das Heizen startet. Hat die Therme in diesem Fall keine realen Speichertemperaturen, heizt sie im Ernstfall ohne Ende.
  3. Wiederum ist es ratsam, einmal in der Woche gut durchzuheizen, um Kontaminationen zu verhindern.
  4. Man sollte die Speichertemperaturen überwachen und mit entsprechenden Regeln reagieren. Steigt die Temperatur im Speicher zu stark an, wird bei mir z.B. automatisch der korrekte Sensorwert der Gastherme bereitgestellt.
  5. Es kann günstig sein, einen zweiten Indikator zur Überwachung mit einzubeziehen, zum Beispiel einen Zwischenstecker mit Power Measurement. So kann man am Stromverbrauch des Gerätes ablesen, wie der Status des Hausgerätes ist und ob Steuerbefehle ausgeführt werden.

ioBroker out / Type / ACK

Was hat es mit dem Type des „ioBroker out“ – Nodes in Node-RED auf sich?

value? command? Was wie wo?

Nachdem ich in den Anfängen meiner SmartHome-Experimente festgestellt hatte, dass Adapter wie ioBroker.deconz oder ioBroker.sonoff die Befehle aus Node-RED nur ausführen, wenn man den Type auf „command“ stellt, machte ich das bis jetzt eigentlich immer so. Dass die Objekte im ioBroker dann teils Rot waren, ignorierte ich, funktionierte ja. Nach einigen Recherchen – ausgelöst durch einen Kommentar zu einem anderen Blogbeitrag – weiß ich jetzt, dass dies nicht unbedingt richtig war.

Was macht der Type im Node „ioBroker out“?

Der Type setzt das ioBroker Attribut ACK (ACKnowledgement = Bestätigung). Dabei steht „value“ für ACK = true, und „command“ für ACK = false.

Warum sollte man ack = false / command setzen?

Viele Adapter verarbeiten Änderungen von Adapter-States, die von anderen Adaptern geändert wurden, nur dann, wenn diese ACK=false haben (auf der Admin-Seite rot dargestellt).

Also werden Werte beispielsweise nur an ein Gerät geschickt, wenn ACK = false ist. Dieses quittiert den Empfang des Befehls auf ihre protokollspezifische Weise, was dann durch ein ACK = true im ioBroker vermerkt wird.

Wann sollte man ack = true / value setzen?

Nutzt man ein State/Objekt nur zum Speichern von Werten (zum Beispiel in 0_userdata), so nutzt man Type = value. Das mache ich jetzt auch häufiger.

Übrigens: In Node-RED hat man im „ioBroker in“ – Node die Wahl, ob nur ACK = true verarbeitet werden soll.

Tasmota OTA auf Shelly flashen

Okay, ich gebe zu: ich bin ein bisschen begeistert. Daher hier erstmal schnell der Disclaimer.

Die nachfolgend beschriebene Methode, einen Shelly auf eine andere Firmware zu flashen, basiert auf einer Fremd-Firmware, auf welche ich keinen Einfluss habe. Die Methode kann deinen Shelly auch kaputt machen.
Dein eigenes Risiko.

Was?

Diese Möglichkeit, Tasmota auf Shelly Geräte zu flashen, funktioniert aktuell NICHT für Shelly Plus (ESP32) Geräte. Leider wurde die Firmware seit Januar 2021 nicht weiterentwickelt, sodass es fraglich ist, ob eine Unterstützung für weitere Geräte noch folgt.

Aktuell werden unterstützt:

  • Shelly 1
  • Shelly 1PM
  • Shelly Plug S
  • Shelly 2
  • Shelly 2.5
  • Shelly RGBW2 (color mode, latest firmware needed)
  • Shelly Dimmer 1
  • Shelly Dimmer 2
  • Shelly EM
  • Shelly Bulb
  • Shelly Vintage
  • Shelly Plug US
  • Shelly Duo
  • Shelly H&T
  • Shelly i3
  • Shelly 1L
  • Shelly Plug 2
  • Shelly Uni
  • Shelly Duo RGBW

Warum?

Ich betreibe meine Shelly 2.5 eigentlich alle mit der original Firmware. (warum steht hier) So hielt ich es auch mit einen Shelly 2.5, den ich nicht als Rolladen-Steuerung einsetze, sondern für einen Doppel-Lichtschalter. Einmal in der Wand verbaut, traten Probleme auf, die ich mit der Shelly Firmware nicht lösen konnte. Außerdem funktioniert das MQTT der Shelly-Firmware nicht mit dem ioBroker Sonoff Adapter, den ich für die Shellies nutze. Und ich will den ioBroker ja schlank halten. Ich ärgerte mich also kräftig, den Shelly nicht vor dem Einbau auf Tasmota umgestellt zu haben. Shelly ausbauen, flashen und wieder einbauen – das muss doch leichter gehen. Und: es geht.

Wie?

Ist der Shelly bereits eingerichtet und mit dem eigenen WLAN Shelly verbunden, geht es verboten einfach. Es gibt eine Mini-Firmware, welche kompatibel zu Mongoose OS (darauf basiert die Shelly-Firmware) ist, dann aber Tasmota (oder eine andere IOT-Firmware) installiert.

Die Firmware findet ihr hier: https://github.com/yaourdt/mgos-to-tasmota

Man benötigt die Shelly-IP und den zur Shelly-Variante passenden Link – welchen ihr auf github findet. Zum Beispiel:

http://shellyip/ota?url=http://dl.dasker.eu/firmware/mg2tasmota-Shelly25.zip 

Ist die Magie abgeschlossen, spannt das Tasmota wie immer ein eigenes WLAN auf und lässt sich darüber konfigurieren/mit dem eigenen WLAN verbinden. Installiert wird die englische Tasmota Version, was sich über ein OTA-Firmware-Upgrade-Funktion in Tasmota aber problemlos auch auf die deutsche oder jede andere Version umstellen lässt. (http://ota.tasmota.com/tasmota/)

Zugegeben: Ich war etwas aufgeregt, da die Erfahrungsberichte in den Issues nicht unbedingt so positiv sind. Bei mir hat es geklappt: ich drücke euch die Daumen.

Eine eigene PHP-Web-API bauen

Um Daten aus dem SmartHome auf eine eigene Website zu bringen, habe ich mir eine Authentifizierung gebaut, die es mir erlaubt, per POST Request Daten bereitzustellen – und zwar nur mir. Einfach nur ein festes Passwort war mir da zu unsicher. Daher habe ich eine zeitbasierte Komponente mit eingebaut.

Zum Einsatz kommt seitens Node-RED node-red-contrib-cryptography.

Ich generiere einen Auth Token, dieser basiert auf der aktuellen Zeit und einem geheimzuhaltenden Passwort, quasi einem Salt.

msg.payload = Math.round(Date.now()/10000) + "dasGeheimePasswort1234!";
msg.headers = {};
msg.headers["Content-Type"] = "application/x-www-form-urlencoded";
return msg;

Beim Token habe ich mich für eine Gültigkeit von 10 Sekunden (daher geteilt durch 10.000) entschieden, dann sind minimale Ungenauigkeiten bei den Uhrzeiten zwischen SmartHome und Webserver nicht so dramatisch. Der Payload wird dann durch die hash-Funktion sha256 gehasht. Anschließend wird der POST Request mit Daten bepackt und der http request abgeschickt.

msg.payload = {
"auth": msg.payload,
"temperatur": msg.temperatur
};
return msg;

Um dem POST Request zu empfangen und zu authentifizieren muss die PHP Gegenstelle den gleichen Token generieren und mit dem mitgeschickten Token abgleichen. Dazu braucht die Gegenstelle natürlich auch den auf 10 Sekunden gerundeten Timestamp und das gleiche geheime Passwort, wie es im Node-RED hinterlegt ist.

<?php
   if($_POST["auth"] == hash('sha256',(round(time()/10))."dasGeheimePasswort1234!")) {
echo "true";
}
?>

Achtung! PHP arbeitet bei den Timestamps in Sekunden, während JavaScript in Millisekunden arbeitet. Daher ist hier nur eine Division durch 10 nötig.

Statt dem echo „true“; kann man natürlich beliebiges mit den mitgeschickten Werten anfangen.

Flot mit min / max / mittel nutzen

Ich schätze Flot als schlankes Tool um ansehnliche Diagramme zu zeichnen. Diese binde ich per iframe in Node-RED Dashboard ein. Bisher war es mir jedoch nicht gelungen, die Daten abseits der Glättung zu aggregieren und die Eingangsdaten-Arten min, max und mittel zu nutzen. Dabei ist es eigentlich einfach und logisch. Im Reiter „Zeit“ muss nur unter „Aggregation“ der Schritttyp auf Sekunden und die Sekunden entsprechend angepasst werden. Für eine tageweise Aggregation zum Beispiel 86400.

Nextcloud CalDAV Error 500

Neben SmartHome Themen, gibt es jetzt vielleicht ab und zu auch ein paar Beiträge zu Nextcloud, zum Beispiel diesen Tipp.

Bei meinem Sohn ging die CalDAV-Synchronisation via DAVx5 nicht mehr. Die App warf immer einen Error 500 (PUT /remote.php/dav/calendars/ […]) aus. Alle anderen Nutzer und Kalender hatten diesen Problem nicht, sodass ein generelles Problem ausgeschlossen werden konnte.

Nach einigem hin und her, konnte das Problem auf einen defekten Serientermin eingegrenzt werden. Nach Löschen & Neuanlegen der Serientermine ging es wieder.

(verwendete Nextcloud Version 21.0.5)

Wetter selbst von yr.no abrufen

Update vom 12.01.2022

Jetzt mit Details zu Dashboard-Ausgabe, inkl. Vorhersage-Chart.

Wetterdaten fürs SmartHome

Rund ums Wetter sammle ich mir eine Vielzahl an Daten aus verschiedenen Quellen. Die Wettervorhersage beziehe ich vom Norwegischen Wetterdienst yr.no, Live-Wetterdaten erhebe ich selbst oder hole sie mir über openSenseMap und Weather.com (Weather Underground) von Wetterstationen aus der Nachbarschaft. Wetterwarnungen kommen vom DWD und ein schickes Niederschlagsradar vom Wetterdienst eines (ehemals) bekannten Wetter-Moderators.

Vorgeschichte

Bisher habe ich für die Wettervorhersage via yr.no den ioBroker-Adapter genutzt. Doch seit der Umstellung der API von xml auf json ist die Anzahl der verfügbaren Werte und damit auch die Anzahl der ioBroker-Objekte explodiert – vieles davon ohne Mehrwert für mich. Dies war mir ein Dorn im Auge, versuche ich doch die Anzahl der Schreibvorgänge auf die SD-Karte klein zu halten.

Also wollte ich die API von yr.no/met.no selbst anzapfen, mit Node-RED ja kein Problem.

So mach ich es

Wenn man die API-Dokumentation aufmerksamer ließt als ich, kann man das ganze recht schnell durchschauen. (Ich brauchte dementsprechend eine Weile.) Man hat die Wahl zwischen dem classic, compact und complete Bericht. Mich interessieren die Temperaturen, die Wetterlage und die erwarteten Niederschlagsmengen. Diese bekomme ich im complete-Bericht.

Man benötigt seine Position als lat/lon. Google Maps verrät beim Rechtsklick auf jeden beliebigen Punkt der Erde die entsprechenden Werte, der erste ist dabei der Breitengrad (lat), der zweite der Längengrad (lon). Ergänzen kann man noch die Höhe über Meeresspiegel – dies ist jedoch optional.

Das Query-String für den Erfurter Dom wäre dann

https://api.met.no/weatherapi/locationforecast/2.0/complete?altitude=194&lat=50.97578937177409&lon=11.023335426472794

Es ist nötig, einen eigenen User-Agent als Identifikation bei der Anfrage mitzusenden, sonst bekommt man einen Fehler „403 Forbidden“. Hier kann man beliebig kreativ sein. Das setzen des Headers geht ganz einfach mit einem Function-Node vor dem HTTP-Request-Node:

msg.headers = {
    "User-Agent": "erfurter-dom-99084"
}
return msg;

Wenn man alles richtig gemacht hat, erhält man als Rückgabe einen wirklich umfangreichen JSON-Datensatz. Dieser enthält Vorhersagedaten für die nächsten 9 Tage. Mich interessieren tatsächlich nur die nächsten 48 Stunden. Auf weiterreichende Wetterentwicklung reagieren meine Flows nicht, und ich habe nicht den Elan, ein allzu umfangreiches Wetter-Dashboard zu bauen. Außerdem ist mir eine weitere Vorhersage eh zu sehr Wahrsagerei.

Die Auswahl der Daten

Da man die API nicht zu oft abfragen darf (und auch nicht will), sollte man die Vorhersagedaten bis zum nächsten API-Abruf zwischenspeichern. Dazu muss man sich überlegen, welche Daten man benötigt.

Beim Stöbern im JSON-Datensatz bin ich darauf gekommen, dass die interessantesten Daten für mich im Bereich der „next_6_hours“ stecken. Sowohl der Symbolcode (= die Wetterlage), als auch die Min-/Max-Temperaturen und die Niederschlagsmenge werden für diese Zeit-Korridore mitgeliefert – und das anfangs stündlich.

{
        "time": "2021-08-30T15:00:00Z",
        "data": {
          "instant": {
            "details": {
              "air_pressure_at_sea_level": 1018.5,
              "air_temperature": 13.8,
              "cloud_area_fraction": 100,
              "cloud_area_fraction_high": 57.8,
              "cloud_area_fraction_low": 100,
              "cloud_area_fraction_medium": 28.1,
              "dew_point_temperature": 12.9,
              "fog_area_fraction": 0,
              "relative_humidity": 94.4,
              "ultraviolet_index_clear_sky": 0,
              "wind_from_direction": 355.9,
              "wind_speed": 2.8
            }
          },
          "next_12_hours": {
            "summary": {
              "symbol_code": "lightrain"
            }
          },
          "next_1_hours": {
            "summary": {
              "symbol_code": "rain"
            },
            "details": {
              "precipitation_amount": 0.3
            }
          },
          "next_6_hours": {
            "summary": {
              "symbol_code": "lightrain"
            },
            "details": {
              "air_temperature_max": 13.9,
              "air_temperature_min": 13.1,
              "precipitation_amount": 0.6
            }
          }
        }
      },

(Nicht verwirren lassen! Alle Zeitangaben sind in UTC)

Die Logik dabei ist:

Zum Zeitpunkt 30.08.2021 17:00 Uhr schaue ich mit „next_6_hours“ auf den Zeitraum zwischen 17:00 und 23:00 Uhr. Auch für den Zeitpunkt 30.08.2021 18:00 Uhr gibt es die „next_6_hours“, welche sich dann auf den Zeitraum 18:00 bis 0:00 Uhr beziehen.

Auf Kosten der Genauigkeit (die bei einer Vorhersage eh relativ ist) und zugunsten der Datensparsamkeit speichere und verarbeite ich also nur jeden sechsten Datensatz bis 42 Stunden in die Zukunft (+6 hours ergibt die 48 Stunden die ich betrachten möchte).

Für diese acht Datensätze (8*6=48 Stunden) habe ich acht Objekte im ioBroker angelegt (bei mir n0, n6, n12, n18, …), in welche ich die inzwischen von JSON in ein JavaScript Objekt konvertierten Daten der „next_6_hours“ als Objekt abspeichere.

Datenaufbereitung

Vor dem Speichern bereite ich die Daten noch ein wenig auf. Ich ordne den Symbolcodes zusätzlich die deutschen Bezeichnungen der Wetterlage zu, ergänze den Wochentag und bereite die Zeit auf, indem ich den Zeitraum errechne, für den diese Werte eine Gültigkeit haben (z.B. Dienstag, 06 – 12 Uhr). Zudem wird der Timestamp des Gültigkeitsstarts errechnet und mit abgelegt.

Nutzung der Wetterdaten

In definierten Regeln

Meine Vorhersage-Objekte (n0 – n42) sind immer aktuell, da ich die Wetterdaten einmal die Stunde abrufe. Somit weiß ich immer, im welchen Objekt welche Zeiträume stecken. Je nachdem wann ein Flow das Wetter abfragt, muss ich also nur den entsprechenden Betrachtungszeitraum festlegen.

Schaut die Rollo-Steuerung zum Beispiel um 9 Uhr, ob sie die südlichen Fenster abschatten sollte, dann schaut sie u.a. nach den Höchstwerten von „n0“, also wie warm es maximal zwischen 9 und 15 Uhr wird. Soll das Haus am Abend Bescheid sagen, dass die Fenster dank kühler Abendluft endlich geöffnet werden können, dann schaut es erst, wie warm es am nächsten und übernächsten Tag wird („n18“, „n42“).

Im Dashboard / UI

Natürlich schauen nicht nur automatische Steuerungen nach dem Wetter – ich gebe die Vorhersage auch im Dashboard aus. Neben der noch ausbaubaren tabellarischen Aufbereitung habe ich dafür inzwischen auch ein Temperatur-Vorhersage Chart.

Da ich die Daten direkt als JavaScript Objekt in das ioBroker Objekt abspeichere, kann ich auch direkt nach dem Auslesen des Objekts auf die Werte zugreifen.

msg.payload.details.air_temperature_max

Die tabellarische Ausgabe basiert somit auf einfachen Abfragen und Textausgaben, da alle Daten ja schon passend aufbereitet wurden.

Die entsprechenden ui_text – Nodes, welche durch CSS Klassen etwas gestaltet werden:

1. und 2. Spalte (n0)
3. Spalte (w0)

Für das Temperatur-Vorhersage-Diagramm müssen alle Objekte (iobroker list Node) geladen und daraus die passende Chart-JSON generiert werden. (siehe Flow Download)

Beispielhafte JSON zur Befüllung eines Node-RED Dashboard Charts

[{"series":["min °C","max °C"],"data":[[-0.6,-0.5,3.7,1.9,0.5,0.6,3.2,3.6],[1,2.5,5.8,3.8,1.3,2.1,5,4]],"labels":[1,7,13,19,1,7,13,19]}]

Da der abzubildende Zeitraum in der Zukunft liegt, können die Werte nicht anhand eines timestamps verortert werden, sondern brauchen feste Bezeichnungen. Hierbei habe ich mich für die Mitte des sechs Stunden Zeitraums entschieden.

Flows als Download

Wer es ausprobieren möchte, braucht im ioBroker unter 0_userdata.0.Vorhersage entsprechende Objekte und kann nach dem Import des folgenden Flows direkt loslegen.