Ein Temperatur-Minimax der letzten 24 Stunden

Für meine neue HomeMatic-Installation bastele ich mir einen rudimentären 24-Stunden-Verlauf ohne Datenbankanbindung

Lassen Sie mich ausholen.

Der Kombisensor begleitet meine ursprüngliche HomeMatic-Installation fast so lange, wie ich sie habe. Wobei man das einschränken muss: Die ersten beiden haben nicht mehr als zwei oder drei Jahre gehalten, der dritte zeigt jetzt nach rund sieben Jahren erste Ausfallerscheinungen.

Die Daten schreibe ich in eine MySQL-Datenbank auf meinen Server im Keller, der dadurch inzwischen mehrere Jahre nutzloser, unkalibrierter Wetterdaten enthält. Na gut, halb nutzlos: Immerhin habe ich dadurch eine Wetterstation auf meiner Webseite und auf einem alten iPad im Schrank.

Weil ich weiterhin anhand von Wind, Temperatur und Regen die Heizung regeln und vor allem die Fenster schließen wollte, wurde das letzte Exemplar des Kombisensors ersetzt, und weil ich eh keine Windrichtung brauche, hat der HomeMatic-Kombisensor einem Wettersensor Plus aus der HomeMatic-IP-Reihe Platz gemacht. Glücklicherweise kann man ja die HomeMatic-IP-Komponenten auch an einer alten CCU2 anlernen.

So ganz kaputt ist der alte freilich noch nicht: Helligkeit, Regenmenge und Temperatur funktionieren noch leidlich und das Gehäuse ist bei der Demontage nur zum Teil zerbrochen. Darum habe ich ihn kurzerhand in unserer Zweitwohnung an den Balkon geschraubt, damit er dort in der neuen HomeMatic-Installation zum Einsatz kommen kann. Von weitem sieht man auch nicht das halbe Pfund Heißkleber, mit dem ich die Basis zusammengeklebt habe. Hoffentlich fällt er auf unsere Seite des Balkons, wenn er fällt, nicht auf den Nachbarbalkon.


HomeMatic-Kombisensor an seinem neuen Standort

Weil ich in der Zweitwohnung bisher keinen Server mit Datenbank herumstehen habe (jedenfalls nicht im Dauerbetrieb), gibt es auch keine schnelle Möglichkeit, die Frage zu beantworten, was die Minimal- und Maximaltemperaturen der letzten 24 Stunden waren und wieviel es geregnet hat. Werte für gestern und heute wären kein Problem – da hatte ich schon mal was –, aber Werte für 24 Stunden ohne Datenbank-Protokollierung: problematisch.

Und darum habe ich mal was geschrieben.

Neue Script-Funktionen

Mit Firmware 2.29.22 wurden neue Funktionen in der Scriptsprache der CCU eingeführt, die auf dieser Seite genutzt werden. Achten Sie darauf, als Logikschicht-Version in den Systemeinstellungen der CCU nicht „Legacy“ zu wählen.

Wenn Sie eine ältere Firmware verwenden oder als Logikschicht-Version „Legacy“ ausgewählt haben, werden Sie Script-Fehler angezeigt bekommen, wenn Sie diese Anleitung umsetzen. Die Programme werden nicht funktionieren.

Aktualisieren Sie die Firmware Ihrer CCU! Wählen Sie „Standard“ als Logikschicht-Version aus!

Variablen in HomeMatic-Scripten

Die CCU hatte früher ein Limit von maximal 200 Variablen, das mit Firmware-Version 2.29.18 aufgehoben wurde. Dieses Limit bezog sich auf alle Variablen, die in allen Scripten verwendet werden. Gemeint sind Variablen, die direkt im Script definiert werden: object x; object y; var z;

Wenn Scripte nicht mehr funktionieren und bei der Prüfung unerklärliche Syntax-Fehler auftreten, sollte versuchsweise dieses Programm wieder gelöscht oder deaktiviert werden – oder, noch besser, auf die aktuelle Firmware-Version aktualisiert werden.

Strings in HomeMatic-Scripten

Durch String-Verwendung in HomeMatic-Scripten kann die CCU fehlerhaft arbeiten, instabil werden oder sogar abstürzen. Grundsätzlich gilt: Je öfter mit Strings hantiert wird, desto eher führt dies zu Problemen.

Ich empfehle daher, nach Umsetzung dieser Anleitung die CCU unter Beobachtung zu halten.

String-Verlängerung

In den Scripten auf dieser Seite werden Strings verlängert (x = x # y). Dies führt oft zu Störungen bei der Ausführung von Programmen:

  • Scripte in Programmen werden nicht mehr ausgeführt
  • bei der Fehlerprüfung erscheinen unerklärliche Syntax-Fehler

Durch einen Neustart werden diese Probleme (vorübergehend) behoben. Auch hier hängt die Dauer, bis es zu Störungen kommt, davon ab, wie häufig diese Programmschritte ausgeführt werden.

Programmlogik

Die Idee hinter diesem Programm ist folgende: In einer Systemvariable speichere ich die Minimum-/Maximum-Werte der letzten 24 Stunden. Jedes Mal, wenn der Kombisensor einen Wert sendet, wird die Variable aktualisiert:

Maximal- und Minimalwert aus der gesamten Reihe sind dann Maximal- und Minimalwert für 24 Stunden.

Der Einfachheit halber verwende ich die Stunde der aktuellen Uhrzeit als Index für die Zeichenkette. Damit habe ich automatisch Werte für 24 Stunden – jedenfalls fast: Strenggenommen sind es 22 bis 23 Stunden, denn eine der 24 Stunden wird immer gerade aktualisiert und eine weitere wird immer gerade zurückgesetzt. Aber damit kann ich leben.

Systemvariable

Als erstes lege ich wie immer die benötigten Systemvariablen an.

Für die Zwischenspeicherung der Werte brauche ich eine Zeichenkette. Diese nenne ich Außentemperatur 24h.

Damit ich Minimum und Maximum beim Kombisensor anzeigen oder in Programmen verwenden kann, gibt es noch zwei Werte, die den Temperaturbereich des Kombisensors (-30 °C bis +60 °C) abdecken.

Außentemperatur min und Außentemperatur max ordne ich dem Gerät Kombisensor zu. Dadurch werden die Variablen dann in der WebUI direkt beim Gerät angezeigt.

Wenn ich die Variablen in Programmen verwenden will, greife ich ebenfalls über das Gerät darauf zu – nur in Scripten gehe ich weiter über die Namen Außentemperatur min und Außentemperatur max.

WebUI-Programm

Die eigentliche Arbeit wird ein Script erledigen, aber um ein Script auszuführen, brauche ich natürlich ein kleines WebUI-Programm

Die Programmlogik ist einfach: Immer, wenn der Kombisensor eine gültige Temperatur meldet, wird das Script ausgeführt. Wichtig ist, dass das Programm bei Aktualisierung ausgelöst wird, damit entsprechend der Logik von WebUI-Programmen bei jeder Temperaturmeldung das Script ausgeführt wird.

Die Beschränkung auf den Temperaturbereich zwischen -30 und +60 °C habe ich eingebaut, weil mein sterbender Kombisensor gerne mal stundenlang 80 °C meldet. In diesen Fällen lasse ich meine Minimal- und Maximaltemperaturen einfach nicht aktualisieren.

Die Verzögerung von 5 Sekunden wäre für das hier vorgestellte Programm eigentlich nicht nötig. Ich lasse die Werte allerdings auch über die PHP-DB in eine Datenbank eintragen, und weil da natürlich auch andere Werte des Kombisensors festgehalten werden, entzerre ich die Aktualisierung an dieser Stelle.

Ausgeführtes Script

Das Script, das hier ausgelöst wird, ist etwas länger.

! HomeMatic-Script
! EIN TEMPERATUR-MINIMAX DER LETZTEN 24 STUNDEN
! http://www.christian-luetgens.de/homematic/programmierung/garten/tagesverlauf/24-Stunden-Wetter.htm

object o_temp = dom.GetObject ("$src$");

if (o_temp) {

  r_temp = o_temp.Value();

  object o_verlauf = dom.GetObject ("Außentemperatur 24h");
  string s_verlauf_alt = o_verlauf.Value();
  string s_verlauf_neu = "";

  integer i_now = system.Date ("%H").ToInteger();
  real r_temp_min = 60.0;
  real r_temp_max = -30.0;

  string s_delimiter = "";
  integer i = 0;
  real r_max;
  real r_min;
  string s;

  while (i < 24) {
    if (i == ((i_now + 1) % 24)) {
      s = "60.0:-30.0";
    } else {
      s = s_verlauf_alt.StrValueByIndex (";", i);
      r_min = s.StrValueByIndex (":", 0).ToFloat();
      r_max = s.StrValueByIndex (":", 1).ToFloat();
      if (i == i_now) {
        r_min = r_min.Min (r_temp);
        r_max = r_max.Max (r_temp);
      }
      s = r_min.ToString (1) # ":" # r_max.ToString (1);
      r_temp_min = r_temp_min.Min (r_min);
      r_temp_max = r_temp_max.Max (r_max);
    }
    s_verlauf_neu = s_verlauf_neu # s_delimiter # s;
    s_delimiter = ";";
    i = i + 1;
  }  

  o_verlauf.State (s_verlauf_neu);
  dom.GetObject ("Außentemperatur min").State (r_temp_min);
  dom.GetObject ("Außentemperatur max").State (r_temp_max);
}

!  Ende des Scripts

Die einzelnen Programmschritte sehen wie folgt aus:

  1. Als erstes wird der Datenpunkt ermittelt, in dem die Temperatur gemeldet wird. $src$ wird immer mit dem Datenpunkt gefüllt, der das Programm auslöst – in diesem Fall also die Temperatur des Kombisensors.
  2. Das weitere Programm wird nur ausgeführt, wenn ein Datenpunkt gefunden wird. Bei manueller Auslösung oder bei Auslösung durch den Neustart der CCU ist $src$ leer; so verhindere ich, dass in diesen Fällen Nullwerte festgehalten werden.
  3. Ich sammle meine Werte und Systemvariablen ein: r_temp als aktuelle Temperatur des Kombisensors, s_verlauf_alt als bisheriger Wert der Systemvariablen Außentemperatur 24h. Die Stunde der aktuellen Uhrzeit wird in i_now gespeichert.
  4. Die Variablen für die neue 24-Stunden-Zeichenkette sowie Minimal- und Maximalwerte werden initialisiert.
  5. Als nächstes kommen einige Variablen für die while-Schleife, in der die eigentliche Arbeit stattfindet, indem für jede Stunde des Tages s_verlauf_neu ausgefüllt wird.
  6. In der while-Schleife iteriert das Script durch die Stunden des Tages: Für die nächste Stunde nach i_now werden Minimum und Maximum zurückgesetzt, um nach dem nächsten Stundenwechsel aktualisiert werden zu können. Anderenfalls werden Minimum und Maximum in r_min und r_max ausgelesen und für die aktuelle Stunde aktualisiert. Außerdem werden die Variablen r_temp_min und r_temp_max mit dem 24-Stunden-Minimum und -Maximum befüllt. Am Ende wird die neue Zeichenkette stundenweise ergänzt.
  7. Nachdem die 24 Stunden eines Tages abgearbeitet wurden, wird der neue Tagesverlauf abgespeichert. Außerdem werden Außentemperatur min und Außentemperatur max mit den Werten befüllt, die für die vergangenen 24 Stunden errechnet wurden.

In der Systemvariablen Außentemperatur 24h kann man nach den ersten 24 Stunden verfolgen, wie die Werte protokolliert werden.

Für jede Stunde gibt es einen Minimal- und einen Maximalwert, getrennt durch einen Doppelpunkt. Die Werte der einzelnen Stunden sind durch Semikolons getrennt. Auf diese Weise kann ich mittels StrValueByIndex() darauf zugreifen und ein bisschen so tun, als sei mein String ein Array.

Wer ganz genau hinsieht, erkennt an dieser Stelle auch, warum meine Minimum- und Maximum-Werte eigentlich keine 24 Stunden abbilden, sondern nur 22 bis 23. Irgendwo in der Mitte werden die Werte auf 60.0:-30.0 gesetzt – das ist die Initialisierung für die Folgestunde. Das Doppel 13.1:13.2 davor ist Minimum und Maximum der aktuellen Stunde.

Sehr viel besser sehen natürlich die Minimum- und Maximum-Werte in der WebUI beim Kombisensor aus:

Ich habe auf dem Screenshot einige Datenpunkte ausgeblendet, damit die beiden Systemvariablen in der letzten Zeile voll zur Geltung kommen.

Optionen

Außentemperatur speichern

Da ich weitere Fehlfunktionen meines Kombisensors erwarte und dessen Werte darum besser nicht direkt in Programmen verwenden möchte, habe ich eine Systemvariable Außentemperatur erstellt, die ich ebenfalls bei Aktualisierung befülle und die ich in anderen Programmen ansprechen kann.

Das mache ich durch eine einzelne zusätzliche Zeile, die am Anfang des Scripts eingefügt wird:

[...]
if (o_temp) {
  r_temp = o_temp.Value();
  dom.GetObject ("Außentemperatur").State (r_temp);
  [...]

Gleichzeitig wird es damit sehr viel einfacher, wenn ich den Kombisensor irgendwann gegen einen anderen Sensor austauschen muss oder die Temperatur anders berechne: Ich muss nicht alle Programme anfassen, die die Temperatur verwenden, sondern nur dieses.

PHP-DB aktualisieren

Wie schon bei der Vorstellung des WebUI-Programms angekündigt, lasse ich die Temperatur auch in eine Datenbank bei bplaced eintragen. Das erledigen zwei Zeilen am Ende des Scripts sowie mein Mini-Framework.

  [...]
  o_verlauf.State (s_verlauf_neu);
  dom.GetObject ("Außentemperatur min").State (r_temp_min);
  dom.GetObject ("Außentemperatur max").State (r_temp_max);

  dom.GetObject ("PHP-DB Table").State ("Temperatur");
  dom.GetObject ("PHP-DB Value").State (r_temp);
}

Nach einigen Tagen der Datensammlung habe ich schon eine ansehnliche Statistik.

utc_time min_val avg_val max_val
2021-04-25 6.90 11.51 17.40
2021-04-26 0.00 8.94 14.80
2021-04-27 3.80 10.56 18.00
2021-04-28 5.40 13.02 19.80
2021-04-29 11.80 15.56 23.40
2021-04-30 12.10 17.27 24.20
2021-05-01 13.00 19.62 26.00
2021-05-02 13.10 16.21 20.20

Gut zu erkennen, dass ich am 26.04. irgendwas am System gefummelt habe und darum eine störende Null in der Datenbank gelandet ist. Danach habe ich dann das Script geändert, so dass es mit $src$ arbeitet, um solche Nulleinträge zu verhindern.

Ebenfalls gut zu erkennen, dass keine 80-Grad-Werte eingetragen wurden. Entweder der Kombisensor funktioniert – oder meine Workarounds.

 

Navigation