nachträgliches Ändern von geloggten Daten

Hi Mädels,

ich hatte neulich einen Stromausfall, danach hat sich der Zählerstand vom EKM-868 zurückgesetzt. Nun ist der Zählerstand (in der IPS-Variable) nach dem Stromausfall natürlich geringer als vor dem Stromausfall (ideal wäre eine Pufferbatterie im EKM-868 so dass die gespeicherten Werte nicht verloren gehen). Fast könnte ich damit leben - wenn nicht diese Durchschnittsberechnungen wären, das führt natürlich zu ziemlich blödsinnigen Werten. Und man kommt immer wieder ins straucheln wenn man den IPS-Zählerstand mit dem des realen Stromzählers vergleicht…

genug der Vorworte, worauf ich hinaus will: ist es möglich, die nach einem Stromausfall geloggten Werte nachträglich mit einem Delta-Wert upzudaten und wenn ja: kann mir jemand aufzeigen wie man da vorgeht?

Ich würde das gern per Script lösen da ich derartige Vorfälle mehrmals im Jahr habe

Wenn per IPS loggst und den Modus Zäher aktiviert hast, dann kann dir das egal sein :). IP-Symcon sammelt dann nämlich nur die positiven Deltas. (Dein Zählerrücksprung wird übergangen)

Ich habe bei mir für diesen Fall einfach eine zweite Variable angelegt und ein Aktionsskript, welches ungefähr so aussieht:


SetValue($id, 1234.56+$IPS_VALUE/1000);

Das Berechnet dann den Zählerstand :). Wenn wieder was passieren sollte, kannst du 1234.56 wieder aktualisieren.

paresy

Das mit dem Korrekturwert ist allgemein eine gute Sache weil man damit auch die minimalen Abweichungen korrigieren kann die sich im laufe der Zeit einschleichen.

Hi paresy,

so ungefähr hatte ich das vor ein paar Monaten mal gemacht. Das die Zähler-Logik damit umgehen kann habe ich auch schon festgestellt. Wie oben beschrieben habe ich das Problem dann trotzdem wenn ich Durchschnittswerte berechnen will.
Das Beispiel funktioniert aber nur, wenn man zeitnah den Fehler bemerkt und das gleich korrigiert. Bei mir sind vom letzten Zwischenfall bis heute ca 2 Wochen vergangen. Dafür suche ich nach einer Script-Lösung

Warum? Sofern du die aggregierten Werte nutzt, kannst du doch fehlerfrei die Summen bilden?

paresy

dann hab ich dich noch nicht verstanden. Hier mal beispielhaft die Datenreihe aus dem Gedächtnis meiner Variable - die als Zähler loggt:

07.09.2011 19:45:01 887,1
07.09.2011 19:46:01 887,6
07.09.2011 19:47:01 888,4 <- Stromausfall
07.09.2011 21:00:01 888,5 <- erster Datensatz nach Stromausfall
07.09.2011 21:01:01 436,7 <- zweiter Datensatz nach Stromausfall
07.09.2011 21:02:01 437,2

wenn ich diese Daten im Zeitraum der Durchschnittsermittlung drin habe beklomme ich - je nach Zeitraum auch schon mal negativ-Durchnittswerte. Natürlich kann ich das Delta zwischen 888,5 und 436,7 durch eine Formel aufaddieren lassen, es wird aber immer ein variabler Zeitraum entstehen in dem ich unkorrigierte Daten logge (ich muss den Fehler ja erstmal feststellen und dann per Script-Anpassung korrigieren).

paresy: ich vermute, Du meinst was ganz anderes?:wink:

AC_GetLoggedValues sind die Rohdaten… Bau das mal auf AC_GetAggregatedValues um, dann sparst du dir diese komplette Problematik. Und dein Skript wird bestimmt auch einige Zeilen kürzer. Und es spart deine CPU Ressourcen. :slight_smile:

paresy

ich habs mir gedacht, genau sowas wollte ich hören:D prima, Feedback kommt heut Abend.

PS: das mit der CPU-Last ist mir nicht entgangen;)

Dabei fällt mir ein: das wäre doch ein Ansatz, die Stromausfall-Problematik zu umgehen? -> man setzt eine unabhängige Zähler-variabe, stellt manuell einmalig den Zählerstand ein und lässt ab dann nur noch die AggregatedValues aus der originalen EKM-Variable aufaddieren. Wenn dann mal wieder der EKM stromlos ist spielt doch das keine Rolle mehr?! -> bin ich richtig unterwegs?

Nimm einfach die Jahrestabelle von AggregatedValues und addiere sie einmal die Stunde auf und schreib sie in eine Variable. Fertig :slight_smile:

paresy

Servus,

gibt es von den AC_ -Funktionen auch eine Beschreibung?:confused:

Hi paresy,

was die Datenstruktur angeht schaue ich noch wie ein Schwein ins Uhrwerk (auf Deutsch: ich habs noch nich kapiert).

Kannst Du mal eine Beispielsyntax posten?

so, bin jetzt ein Stück weiter, zumindest die ABfrage des gestrigen Verbrauchs über AC_GetAggregatedValues bekomme ich hin. Übrigens eine für mich sehr interessante IPS-Funktion :D.


$archiveID = IPS_GetInstanceIDByName("Archive Handler", 0);   // Archive-Handler-ID
$objectID = 12130 /*[Smart Metering\IPS EKM-868\EKM-868 I Hausverteilung\EKM-868 #01 Zentraleinspeisung\Energieverbrauch]*/ ; // Variablen-ID der Zähler-Variable
$ende = time(); // JETZT
$verbrauch_akt=getvalue($objectID);
$start_30d = strtotime(date("d.m.Y",strtotime("-30 day"))." 00:00:00"); //Startzeit vor 30Tagen
$start_gestern = strtotime(date("d.m.Y",strtotime("-1 day"))." 00:00:00"); //Startzeit gestern
$ende_gestern = strtotime(date("d.m.Y",strtotime("-1 day"))." 23:59:59"); //Endzeit gestern


// Abfrage Verbrauch gestern
$temp = AC_GetAggregatedValues($archiveID, $objectID, 1, $start_gestern, $ende_gestern, 1);
$verbrauch = ($temp[0]['Avg']);
echo "Verbrauch gestern: $verbrauch kWh
";
print_r($temp[0]); // gesamtes Array ausgeben
setvalue(37465 /*[Smart Metering\IPS EKM-868\Statistik\30d\gestern]*/ , number_format($verbrauch,2,",", "."));

Ergebnis:


Verbrauch gestern: 18.5 kWh
Array
(
    [Avg] => 18.5
    [Duration] => 86119
    [LastTime] => 1317074399
    [Max] => 0.32600000000002
    [MaxTime] => 1317018653
    [Min] => 0
    [MinTime] => 1317068473
    [TimeStamp] => 1316988000
)

was ich jetzt nooch nicht kapiert hab und auch nicht hinbekomme: Abfrage des Durchschnitt-Verbrauchs der letzten 30 Tage. Ich hab mal die Startzeit um 30 Tage zurückverlegt, klappt leider nicht (kommt der selbe Wert wie in der Abfrage für gestern raus). Hat jemand nen Tipp für mich?

na das wird lustig: wieder ein Stück weiter, hab jetzt kapiert wie ich mit AC_GetAggregatedValues Tages-, Monats- und Jahreswerte ermitteln kann. Da es dazu keine Doku gibt:

der Parameter 3 in AC_GetAggregatedValues (AggregationType) legt die Granularität fest:

1 = Tag
2 = Monat
3 = Jahr

jetzt hab ich aber ein neues Problem (ich = Array-Blindfisch): wenn ich den gleitenden Durchschnitt der verg. 30Tage ermitteln will kann ich mit AC_GetAggregatedValues (AggregationType 1) die letzten 30 Tage ausgeben lassen, Ergebnis sieht so aus:


Array
(
    [0] => Array
        (
            [Avg] => 18.5
            [Duration] => 86119
            [LastTime] => 1317074399
            [Max] => 0.32600000000002
            [MaxTime] => 1317018653
            [Min] => 0
            [MinTime] => 1317068473
            [TimeStamp] => 1316988000
        )

    [1] => Array
        (
            [Avg] => 21.25
            [Duration] => 86400
            [LastTime] => 1316987999
            [Max] => 0.32900000000007
            [MaxTime] => 1316941132
            [Min] => 0.0080000000000382
            [MinTime] => 1316901737
            [TimeStamp] => 1316901600
        )

    [2] => Array
        (
            [Avg] => 19.56
            [Duration] => 86400
            [LastTime] => 1316901599
            [Max] => 0.32600000000002
            [MaxTime] => 1316853346
            [Min] => 0.0079999999999245
            [MinTime] => 1316819795
            [TimeStamp] => 1316815200
        )

hier fehlt mir jetzt PHP/Array knowHow: wie kann ich die [AVG]-Werte extrahieren um daraus einen Durchschnitt zu bilden?

Wenn ich mich nicht ganz irre, sollte das so gehen:

foreach ($array as $item) {
	echo $item['Avg'];
}			

Grüße, Benjamin

hi benige,

das ist schon ein Schritt weiter, ich versuchs parallel mit Google - ich bekomm’s aber nicht gebacken: Deine Foreach-Schleife wirft jeden der 30 [AVG]-Werte aus. Nun hab ich mir gedacht ich summier die Werte mit array_sum. Klappt aber nicht, weil es keine Werte in einem Array sind (sondern Einzelwerte. Sorry, ich stehe hier echt auf dem Schlauch. Gibt es nicht die Möglichkeit, innerhalb der Schleife bei jedem Durchlauf die ermittelten Werte zu addieren und die Summe durch die Anzahl der Werte zu teilen?

mach doch:


$sum = 0;
foreach ($array as $item) { 
    $sum = $sum + $item['Avg']; 
}

echo $sum;

ahja… g
Gruß :wink:

Du kannst die Werte in ein Array packen und dann mit dem array_sum rechnen (hab ich nicht getestet, aber so in etwa sollte das aussehen):


foreach ($array as $item) { 
    $youravgs[] = $item['Avg']; 
}  
$overallavgval = array_sum($youravgs) / count($youravgs);
echo $overallavgval;

Hoffe das hilft Dir weiter … :slight_smile:

Hey Leute, sorry für die schwere Geburt - ich muss mir mal jemanden suchen der mir das array-Thema auf der Tonspur erklärt. Ich hab zwischenzeitlich Eure Beiträge gelesen, gegoogelt und probiert. Letztendlich hab ich mir diesen Code zusammengeklaut (original Guttenberg-Methode), wobei der Code von bengie eleganter und effizienter aussieht:


for($i = 0; $i < count($temp); $i++)
	{
		$summe += $temp[$i]['Avg'];
	}
echo "
 Gesamt: $summe
";
$durchschnitt = $summe/$i;
echo "Durchschnitt: $durchschnitt
";

Ergebnis:


Gesamt: 548.83
Durchschnitt: 18.294333333333

Ergebnis passt und ist plausibel, aber ich fühle mich wirklcih schlecht weil ich die Array-PHP-Logik noch nicht kapiert hab. Vielleicht hilft auch Routine…

Danke Euch jedenfalls für Mühe und Geduld (vielleicht wäre der Thread was für „IPS for Dummies“)

Für alle Anderen: wenn ich die komplette Statistik fertig hab stelle ich das hier ein - versprochen:D

Der Code aus Deinem Post stammt vermutlich von Jemandem der viel C programmiert hat (hab ich früher auch).
Das man auf diese Art in PHP noch mit Arrays umgehen kann finde ich auch ganz sympathisch, aber es geht inzwischen manchmal halt auch bequemer (der C nahe Weg ist manchmal jedoch auch heute noch bedeutend schneller in der Laufzeit). :slight_smile:

tja, ich hab meinen ersten Kontakt mit Programmierung im Oktober 2010 gehabt: mit IPS-PHP. Hab halt „ein klein wenig Nachholbedarf“ :rolleyes: