ich habe im Forum schon einige Beispiele gefunden, die versuchen mittels AC_GetLoggedValues und dem Summieren und anschließendem Teilen der Werte einen Durchschnitt zu bilden.
Was leider dort vergessen wird ist, dass eine Temperaturvariable nicht zwingend alle x Minuten geloggt wird, sondern bei jeder Änderung. Daher wird bei der Berechnung der Zeitfaktor völlig außen vor gelassen.
Extrembeispiel:
12:00 Uhr = 20 °C
16:00 Uhr = 21 °C
16:05 Uhr = 60 °C
16:10 Uhr = 21 °C
Der berechnete Durchschitt wäre 30 °C, obwohl die 5 Minuten die 60 °C waren zu vernachlässigen wären. Der echte Durchschnitt mit Zeitberücksichtigung liegt bei 20,8 °C.
Hat jemand eine Idee, wie man das lösen kann? Mir fehlt momentan jede Idee dazu.
wenn ich dein Script richtig lese, nimmst du die Zeit zwar mit rein, aber die erste Zeit ist immer unveränderlich.
Müsste es nicht so sein, dass der Abstand zweier Messungen als Zeitfaktor mit eingerechnet wird? Also innerhalb der Schleife ermitteln wie viele Sekunden der Wert gültig war und diese Zeit in den Teiler aufsummieren.
Ich werde mal versuchen an diesem Ansatz anzuknüpfen. Mal sehen ob mein PHP Verständnis bis dahin ausreicht.
Probier den Code einfach mal aus. Der Zeitwert ist nicht konstant. Vielmehr berechnet das Programm für jeden Messwert die Zeitdifferenz zum vorigen Messwert in Sekunden und unterteilt diese ggf. variable Differenz in konstante Intervalle (hier jeweils eine Minute). Zum Schluss wird aus der die Summe der Temperaturwerte und der (vereinheitlichten) Intervalle der Durchschnitt gebildet …
Das ist ein klassisches Problem der Datenverarbeitung. Das Problem ist hier nicht wirklich das ungleiche Zeitintervall sondern die Präsenz von Ausreißern, die den Durchschnittswert fälschen.
Ein üblicher und einfacher Ansatz ist zuerst, wie in Swifty’s Vorschlag, ein „resampling“ der Daten mit konstantem Intervall und danach ein Filtern der Ausreißer. Ausreißer rausfiltern geht schnell indem alle Werte die z.B. 2 mal über der Standardabweichung der Daten sind, ignoriert werden.
ich habe gerade entdeckt, dass mein Sript die Daten in der falschen Reihenfolge verarbeitet. Der Datenpunkt „0“ im Array $buffer ist nicht der älteste, sondern der aktuellste Wert.
Auch habe ich festgestellt, dass IPS die Zeitdifferenz zum nächsten Wert als ‚Duration‘ archiviert. Mein kleines Skript habe ich daher wie folgt angepasst:
<?
$archiveID=33024 /*[Archive Handler]*/;
$objectID=15580 /*[Wetter\HM Temeratur Sensor Garten\HM_Temperatursensor (OTH)\TEMPERATURE]*/;
/* Beispiel für aktuellen Tag
$start=strtotime("now 00:00:00"); // heute 00:00 Uhr
$ende = time(); // JETZT
*/
// Beispiel für die letzten 6 Stunde
$zeit=localtime(time(),0);
$h_anfang = $zeit[1]+360;
$start=strtotime("-". $h_anfang. "minutes". " -". $zeit[0]. "seconds");
$ende=strtotime("-". $zeit[1]. "minutes". " -". $zeit[0]. "seconds");
$buffer = AC_GetLoggedValues($archiveID, $objectID, $start, $ende, 0);
$anzahl = count($buffer)-1; // Index startet bei 0 (z.B. 0 bis 9 = 10 Datensätze)
$Summe_Interv=0;
$Summe_Temp=0
Foreach ($buffer as $wert)
{
$VTemp=$wert['Value'];
$TTemp=$wert['Duration']; // Differenz zum nächsten Datenpunkt in Sekunden
$Summe_Temp=$Summe_Temp + ($VTemp * $TTemp);
$Summe_Interv=$Summe_Interv + $TTemp;
}
$Ergebnis=$Summe_Temp/$Summe_Interv;
echo "Die Durchschnittstemperatur von ". date('d.m.y H:i:s', $start)." bis ". date('d.m.y H:i:s', $ende). " beträgt: ". $Ergebnis. "°C";
print_r($buffer)
?>
Gruß
Swifty
PS:
Jetzt muss ich nur noch die Ausreißer herausfiltern. Ich kann jedoch mit dem Begriff Standartabweichung nichts anfangen.
Ich stelle mir das herauzsfiltern so vor, dass ich hier zunächst ermittle, wie hoch die absolute Temperaturdifferenz je Zeiteinheit ist (z.B. xx°C/10min). Jetzt muss ich dem Programm nur noch sagen, dass diese Differenz nicht größer als yy°C/10min sein darf, sonst wird der Datenpunkt verworfen und die Gültigkeitsdauer des letzten Datenpunktes um die des verworfenen Datenpunktes „verlängert“. Jetzt stellt sich nur noch die Frage, was für Werte man hier als Grenze ansetzen kann… z.B. 5°C/10 min oder einen anderen Wert?
vielen Dank, funktioniert super.
Habe dein Script einfach so als Funktion in mein bestehendes Script eingeflochten und damit meine alte Funktion ersetzt.
Die Werte haben sich auch geändert, auch wenn nicht so stark wie erwartet.
Es gibt wohl doch genügend Aktualisierungen.