NEWS
Aufzeichnung Temperatur im History Adapter
-
Hallo Forum,
viele Forumsbeiträge haben mir in den letzten Monaten sehr geholfen und ich konnte einige Fortschritte machen und ein bischen herumspielen, was ja am meisten Spass macht.
Aus aktuellem Anlass möchte ich jetzt meinen Energieverbrauch tracken. Ich habe dazu folgende Sensoren ans Laufen gebracht:
Gas: Xiaomi Fenstersensor. Passte nach Entfernung des Gehäuses direkt in den Aufnahmeschacht meines Gaszählers. Läuft sehr zuverlässigt und überträgt auch über 2000 Impulse am Tag klaglos. 1 Impuls = 10 Liter
Strom: IR Lesekopf (Hichi) an ESP 8266 mit Tasmota. Super einfach und zuverlässig. Das größte Problem war noch die korrekte Ausrichtung des Kopfes.
Außentemperatur: Xiaomi Temperatursensor. Sehr zuverlässig, Batterie hält länger als ein Jahr.
Heizung Vorlauf / Rücklauf: 2 x DS18B20 an ESP 8266 WEMOS mit Tasmota. Unschlagbar günstig! Die Fühler habe ich einfach hinter die Rohrisolierung geschoben. Sehr feinfülig - die Hysterese lässt sich sauber ablesen im Verlauf.
Ich mache bereits ein Datenlogging mit dem Node Red Dashboard, aber das ist ja alles nur temporär, wenngleich ich so auch schon einige Erkenntnisse gewonnen habe.
Das Auslesen der Daten und die Aufbereitung mache ich mit Node Red, möglichst grafisch. Jetzt habe ich mir entsprechende Datenpunkte im iobroker angelegt und schiebe die Daten dorthin.
Für Gas und Strom ist das sehr einfach. Ich habe einen täglichen Trigger auf 23:59 Uhr, der die holt und in die Datenpunkte schiebt.
Bei der Außentemperatur ist das schon schwieriger. Ich möchte hier die mittlere Tagestemperatur loggen um diese dann später mit dem Gasverbrauch ins Verhälnis zu setzen. So möchte ich eine Heizlastkurve für mein Haus ermittel.
Der Temp - Sensor liefert ja immer dann Werte, wenn sich die Temperatur ändert. Eine starke Änderung liefert also viele Werte. Für den Mittelwert eher schlecht. Ich habe dazu in Node Red den Aggregator Node verwendet. In der ersten Stufe je eine Stunde, in der zweiten Stufe je einTag. Die Ergebnisse sehen nicht schlecht aus. Ohne das MIttel über eine Stunde kommt ein um ein paar Zehntel anderes Ergebnis heraus.
Jetzt das Problem: Der Aggregator Node sendet nachdem der Tag abgeschlossen ist. Der Wert kommt ein paar msec nach 24:00 im Datenpunkt an. Der History Adapter fügt diesem Wert jetzt das Datum vom Folgetag zu, das möchte ich nicht.
Meine Fragen:
-
Kann man den Zeitstempel im History Adapter irgendwie überschreiben (z.B. auch auf 23:59) ? Das wäre für mich am einfachsten.
-
Kann man dem Aggrgator Node "beibringen" einen anderen Zeitraum als zur vollen Stunde und zum vollem Tag zu verwenden?
-
Gibt es einen anderen Node der den ungewichteten Mittelwert über einen bestimmten Zeitraum ermittelt?
Ich weiß, es gibt natürlich alle Möglichkeuten wenn man im Funktionsnote selber programmiert, aber das kann ich nicht. Will ich lernen, ist aber nicht mein Focus.
Für Tipps wäre ich euch sehr dankbar!
Viele Grüße aus dem Sauerland, Thomas
-
-
@thomashsk Dies ist eine der wenigen Fälle, wo es keine wirklich geeignete Node gibt und man das selbst programmiert. Sonst vermeide ich function Nodes wo es nur geht. In diesem Fall, wird das auch in dem Node Kontext gespeichert.
Ich hab das schnell für Dich gemacht.
Anstelle der oberen Inject Node (hier 3) flanscht Du die Node dran, die Deine Werte liefert.
Wenn msg.reset = true gesetzt wird, dann wird alles zurückgesetzt und der Mittelwert ausgegeben. Da Du mit der Inject Node selbst triggern kannst, das die um 23:59 jeden Tag triggert - wird somit um 23:59 täglich ein msg.reset = true ausgegeben und damit der Mittelwert ausgegeben.
Hier der Flow:
Der Code ist relativ simple und Du kannst das aktuelle Array im Node-Kontext der Function Node sehen. Hier nur zur Info der Code - ist aber beim Import bereits enthalten:
var arr = context.get("values") || []; if (msg.reset && arr.length > 0) { msg.payload = arr.reduce((/** @type {any} */ total,/** @type {any} */ value) => total + value ) / arr.length; context.set("values", []); return msg; } var value = Number(msg.payload); if (!isNaN(value)){ arr.push(value); context.set("values", arr); }
-
WOW,
prompter Service hier! Ich habe den Flow importiert, errechnet den Mittelwert wie gewünscht. Der Code selber ist aber ein absolutes Rätsel für mich
Nah ja, werde ich auch mal lernen.
Es wird hier ja der arithmetische Mittelwert berechnet, d. h. es werden ALLE Werte berücksichtigt. Ich benötige aber eher das geometrische Mittel über die Zeit. Deswegen werde ich die Temperatur in ein Flow-Variable schreiben und diese alle 5 Minuten in den Funktionsnote schreiben. Das sollte ich hinkriegen.
Kann man die Funktion auch so umschreiben, dass das Maximum und das Minimum ermittelt wird?
Vielen Dank noch mal für die freundliche Hilfe!
Thomas
-
@thomashsk Ich hab 2 Nodes die ich selbst nutze - die geben bei jedem Eingang das Max bzw. Min aus:
Auch hier setzt msg.reset - das Ganze zurück.
Ich setze das auch immer um Mitternacht zurück, um den Kühlschrank zu überwachen:
Falls Du die Ausgabe "-.-" nach dem Zurücksetzen nicht magst musst halt diese Zeile 3 entsprechend ändern:
msg.payload = "-.-";
-
@thomashsk sagte in Aufzeichnung Temperatur im History Adapter:
Deswegen werde ich die Temperatur in ein Flow-Variable schreiben und diese alle 5 Minuten in den Funktionsnote schreiben. Das sollte ich hinkriegen.
Das machst einfach mit einer Change und einer Trigger Node. Wie gesagt über den Kontext der Node kannst Du sehen, welche Werte aktuell im Array stehen.
-
@thomashsk Hier auch nochmal eine Version mit geometrischen und arithmetischem Mittelwert:
Das geometrische Mittel wird einfach berechnet nach indem alle Werte multipliziert werden und die n-te Wurzel gezogen wird, wobei n die Anzahl der Elemente sind.
var arr = context.get("values") || []; if (msg.reset && arr.length > 0) { msg.payload = Math.pow(arr.reduce((/** @type {any} */ total,/** @type {any} */ value) => total * value ), 1 / arr.length); context.set("values", []); return msg; } var value = Number(msg.payload); if (!isNaN(value)){ arr.push(value); context.set("values", arr); }
Zusätzlich noch eine kleine Verbesserung in dem Code - so dass reset beim leeren Array keine Fehler mehr schmeisst.