(gelöst) Rechnen mit Timestamps

Begonnen von peewag, 16 Januar 2020, 20:44:58

Vorheriges Thema - Nächstes Thema

peewag

Hallo zusammen,

ich habe da anscheinend einen Knopf im Hirn, ich hoffe ihr könnt mir da weiter helfen.

Ich habe zwei Dummys:
1. PV_current_sensor --> MQTT Sensor --> liefert alle paar Sekunden einen neuen Stromwert
2. battery --> MQTT Sensor --> liefert auch alle paar Sekunden eine nee Spannung

Zusätzlich habe ich ein Notify:
calc_DC_PV_power:
PV_current_sensor.* {
my $power = ReadingsVal("PV_current_sensor","current",0) * ReadingsVal("battery","total_voltage",0);;
fhem("set PV_power $power");;
}


Dieses setzt bei einer Stromänderung den Wert eines dritten Dummys PV_power. Das funktioniert auch so weit.

Jetzt wollte ich gerne die Energie mit loggen, sprich: den vorigen Leistungs-Wert mit der vergangenen Zeit multiplizieren und aufsummieren. Aber ich schaffe es einfach nicht die Sekunden seit dem letzten Aufrufen des notifies heraus zu bekommen. OldTimestamp, OldReadingsAge oder ReadingAge liefern immer nur den aktuellen Timestamp oder gleich den Default-Wert egal ob ich sie auf eines der Dummys anwende oder auf das Notify.

Kann mir da bitte wer einen Tipp geben, wie ich da weiter komme?

vielen Dank schon mal,

lg Peter

MadMax-FHEM

#1
Ich würde ja im 3ten Dummy (wobei eh fraglich ist: braucht es 3 Dummy!? ;)  ) statt set ein:

setreading PV_power power $power
machen, dann kannst du doch da mittels:

ReadingsAge("PV_power","power",0)

Die Sekunden seit dem letzten Setzen abfragen!?

EDIT: evtl. würde ich auch das RegEx des notify etwas "enger" fassen. PV_current_sensor.* "hört" auf jeden Event des Devices... Interessant wäre aber ja nur "current"!?

EDIT2: evtl. auch statt ReadingsVal auf ReadingsNum "umstellen", da ist dann sichergestellt, dass nur "numerische" Werte zurückgeliefert werden (sollten [mal] Einheiten etc. dabei sein)...

Gruß, Joachim
FHEM PI3B+ Bullseye: HM-CFG-USB, 40x HM, ZWave-USB, 13x ZWave, EnOcean-PI, 15x EnOcean, HUE/deCONZ, CO2, ESP-Multisensor, Shelly, alexa-fhem, ...
FHEM PI2 Buster: HM-CFG-USB, 25x HM, ZWave-USB, 4x ZWave, EnOcean-PI, 3x EnOcean, Shelly, ha-bridge, ...
FHEM PI3 Buster (Test)

KernSani

Nur zur Sicherheit, Attribut oldteadings ist gesetzt?


Kurz, weil mobil
RasPi: RFXTRX, HM, zigbee2mqtt, mySensors, JeeLink, miLight, squeezbox, Alexa, Siri, ...

Otto123

#3
Ich weiß nicht genau ob das trifft, ich hatte letztens mal sowas begonnen:
defmod n_Lueftung notify Fenster.*:(open|closed) setreading n_Lueftung time_$EVENT {(time)}
attr n_Lueftung userReadings Diff:time_closed.* {int(ReadingsNum($name,"time_closed",0) - ReadingsNum($name,"time_open",0))}

Bei jedem Aufruf des notify wird die Zeit zwischen open und closed gemessen und die Differenz ins userReadings geschrieben.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

peewag

Vielen Dank für die schnellen Antworten!

Erstes Problem war:
ZitatNur zur Sicherheit, Attribut oldteadings ist gesetzt?
hab ich natürlich übersehen  ::)

und das zweite Problem, dass es nur einen OldValue, bzw. ein Age gibt, wenn sich der Wert auch ändert! In der Nacht ist der PV-Strom hald immer 0A  ::) somit gibt es noch keine alten Werte.

Momentan sieht mein Notify so aus:
PV_current_sensor.* {
my $power = ReadingsVal("PV_current_sensor","current",0) * ReadingsVal("battery","total_voltage",0);;
my $duration = OldReadingsAge("PV_current_sensor","current",0);;
fhem("set PV_power $power");;
fhem ("setreading PV_power duration $duration");;
}


Vielen Dank für eure schnellen Antworten,

ich werde das morgen nochmals überarbeiten und dann von meinem Erfolg berichten!  8)

peewag

So ich habe ja versprochen, ich Berichte von meinem Erfolg   8)


PV_current_sensor.* {
my $power = ReadingsNum("PV_current_sensor","current",0) * ReadingsNum("battery","total_voltage",0);;
my $duration = OldReadingsAge("PV_current_sensor","current",0);;
my $energy = ReadingsNum("PV_power", "energy",0);;
if ($power >= 2.0 && $duration < 120)
{
$energy = $energy + ($power * $duration / 3600.0);;
}
fhem("set PV_power $power");;
fhem ("setreading PV_power duration $duration");;
fhem ("setreading PV_power energy $energy");;
}


Kurze Erlärung:
Jedes mal wenn ein neuer Stromwert per MQTT rein kommt, wird diese Funktion aufgerufen.
Dann wird die aktuelle Leistung berechnet und in die Variable power gespeichert.
Außerderm wird das alter des letzten Stromwertes abgefragt und unter der Variable duration gespeichert.
Und die bereits aufsummierte Energie wird auch ausgelesen und unter energy abgespeichert.
Jetzt wir überprüft, ob die aktuelle Leistung über 2 W ist und ob der letzte Stromwert eh nicht älter als 120 Sekunden ist.
Trifft das zu, wird in die Variable energy ihr eigener Wert plus die aktuelle Leistung mal den vergangenen Stunden (Sekunden/3600) gespeichert.
Auschließend wird die aktuelle Leistung, die Dauer und die aufsummierte Energie abgespeichert.

Die Abfrage mit 120s habe ich eingefügt, um bei Fehlern (z.B.: wenn der Stromsensor länger keinen Wert sendet und somit der "alte" einfriert und dieser dann für eine lange Zeit gewertet wird) nichts aufzuaddieren. Leistungen unter 2W werden auch ignoriert.

Es gibt dann noch ein Notify, welches um genau 00:00:00 das Reading energy auf 0Wh setzt.

Ich hoffe es kann wer was damit anfangen  ::)

peewag

So, jetzt stehe ich natürlich schon vor dem nächsten Problem!

Das Age eines Readings gibt immer an, wann sich der Wert das letzte mal geändert hat, und nicht, wann er das letzte mal upgedatet wurde.

Das heißt:

Uhrzeit    Wert    Age    Ergebnis    erwünschtes Ergebnis 
00:00:00    3    1    3    3 
00:00:01    4    1    4    4 
00:00:02    3    1    3    3 
00:00:03    3    2    6    3 
00:00:04    3    3    9    3 
00:00:05    3    4    12    3 
00:00:06    2    1    2    2 

Wenn nun, wie in der Tabelle ersichtlich, sich der Wert von 3 auf 4 ändert, steht als Age 1 - was auch erwartet wird.
Wenn nun aber, der Wert gleich bleibt (weil z.B.: der gleiche Strom als zuvor gemessen wurde), dann erhöht sich age um die Zeitdifferenz.

Das Problem ist nun aber, dass beim regelmäßigen aufaddieren, dass der Wert mit der Zeit multipliziert wird und das in jeder Zeile. Bleibt nun der Wert gleich, so wird dieser mit einer größeren Zeitdifferenz multipliziert obwohl seit dem letzten mal Multiplizieren wieder nur eine Sekunde vergangen ist.

Gibt es eine Möglichkeit nicht OldReadingsAge() und somit die Zeitdifferenz seit der letzten Änderung des Wertes zu bekommen, ich möchte lieber die Zeitdifferenz, wenn der Wert das letzte mal upgedatet wurde!?

Ich werd mal ein bisschen weiter stöbern, dafür wirds doch eine Lösung geben  :)

Otto123

Zitat von: peewag am 24 Januar 2020, 13:20:50
wann sich der Wert das letzte mal geändert hat, und nicht, wann er das letzte mal upgedatet wurde.
Hast Du event-on-change-reading gesetzt?

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

peewag

ja das wars, ich habe jetzt beim PV_current_sensor das Attribut event-on-change-reading auf current gesetzt und jetzt funktioniert es wunderbar.


crusader

Wäre auch einfacher gegangen mit dem für diese Aufgabe vorgesehenen Zauberwort:


attr userReadings energy integral {ReadingsVal($name,"power",0)/3600}