Archiv Werte von 0:00 in eine neue Variable schreiben

Hi, ich würde gerne von einer geloggten Variable_A die Werte von 0:00 auslesen und in das Archive einer neuen Variable_B schreiben. Dies möchte ich nur einmalig machen und dann zukünftig würde ich dann immer um 0:00 den Wert von Variable_A in Variable_B abspeichern. Es geht auch nur um den Zeitraum der letzten 4 Wochen.

Ich weiß aber nicht so recht, wie ich das bewerkstelligen soll.

Mein Ansatz wäre jetzt in einer Schleife mit
AC_GetAggregatedValues (int $InstanzID, int $VariablenID, int $Aggregationsstufe, int $Startzeit, int $Endzeit, int $Limit) wobei Startzeit 23:30 ist und Endzeit 23:59 wäre und den Tag müsste ich dann hochzählen. Aus diesem Bereich würde ich dann den Mininmalen Wert nehmen (weil es sich um den SOC eines Speichers handelt) und dann mit
AC_AddLoggedValues (int $InstanzID, int $VariableID, array $Datensätze) diese Werte in das Archiv von Variable_B schreiben.

Könnte man das so in etwa machen?

Bitte beschreib mal die Aufgabe, die du lösen möchtest. Also wirklich die Aufgabenstellung, nicht deinen angedachten Lösungsweg.

Ich habe mal schnell was zusammengeklöppelt in der Hoffnung, die Aufgabe richtig verstanden zu haben.

ACHTUNG: wenn der Quellwert die Aggregation „Zähler“ hat, dann bekommst du hier immer die ÄNDERUNG des Zählerstandes in den abgefragten 5-Minuten-Intervallen und nicht den Zählerstand, dementsprechend ist das Minimum daraus dann typisch der Wert 0. Funktioniert also nur bei „normaler“ Aggregation, nicht bei Zähler.

// Endwert kurz vor Mitternacht ermitteln, in Archiv schreiben in eine andere Variable, rückwirkend für xx Tage

$oneday = 24*60*60; // Sekunden pro Tag

// Anzahl der Tage, die wir rückwirkend auswerten
$num_days = 14;

$archivID = 18193;
$sourceID = 23082;
$targetID = 51826;

// alte Werte in $targetID löschen
AC_DeleteVariableData($archivID, $targetID, strtotime("now")-2000*$oneday, strtotime("now"));
IPS_Sleep(1000);

for ($offset = 0; $offset < $num_days; $offset++) {

  $timestart = strtotime("yesterday 23:30") - $offset*$oneday;
  $timestop  = strtotime("yesterday 23:59") - $offset*$oneday;

  // echo sprintf ("%s bis %s \n", date("d.m.y H:i:s", $timestart), date("d.m.y H:i:s", $timestop));
  
  $werte = AC_GetAggregatedValues($archivID,$sourceID, 5, $timestart, $timestop, 0);
  // print_r ($werte);

  $neu = $werte[0]['Min'];

  AC_AddLoggedValues($archivID, $targetID,[
  [
    'TimeStamp' => $timestop,
    'Value' => $neu
  ]
  ]);

}

IPS_Sleep(500);
AC_ReAggregateVariable($archivID,$targetID);

Hallo Volker, das ist ja wirklich toll! Ganz lieben Dank dafür.

Für mich sieht das schon mal genau nach dem aus, was ich haben möchte :slight_smile:

Und zwar möchte ich mir ein Diagramm erstellen auf dem ich den SOC meines Batteriespeichers jeweils zum Tageswechsel darstelle. Und wie ich es verstanden habe, kann ich mir nicht einfach den Wert um 23:59 aus dem Archiv holen, weil da ja nicht zwingen zu dem Zeitpunkt ein Wert im Archiv steht. Oder wird dann einfach der letzte Stand von vor dem Zeitraum geholt? Daher der Zeitraum von 30min. Ich frage mich nur gerade wie das ist, wenn der SOC schon vor 23:30 auf dem minimalen Wert von 20% steht. Dann könnte es ja sein, dass in dem Zeitraum auch keine Werte im Archiv abgespeichert wurden :man_shrugging:

Ich werde deinen Code auf jeden Fall am Wochenende mal testen! Freue mich schon drauf :hugs:

Ich bin mir auch nicht ganz sicher, schalte also mal die auskommentierte Ausgabe mit print_r wieder an und schaue was da an Daten im Zeitintervall erscheint. Ich vermute das wird aus den Rohdaten lückenlos im gewählten 5-Minuten-Raster berechnet, aber ganz sicher bin ich nicht.

Für zukünftige Werte ist es sicherlich einfacher, den Wert per zyklischem Ereignis zu kopieren ganz ohne Archivwerte abzufragen.

Das habe ich auch vor. Will mir initial nur einmal die Werte der letzten 5 Wochen holen um nicht bei 0 anzufangen.

Hallo Volker,

dein Skript hat super funktioniert und ich hab wieder einiges gelernt :slight_smile:
Ich habe den Zeitraum noch auf 23:00 bis 23:59 geändert, und hole mir nur die stündliche Aggregation. Dann bekomme ich das gleiche Ergebnis, habe aber nur einen Wert.

Und es geht auch, wenn in dem abgefragten Zeitraum gar keine Werte ins Archiv geschrieben wurden. Dann wird einfach der letzte Wert, der z.B. um 19:23 geloggt wurde genommen.

Eine Frage hätte ich noch zu der Zeile

 $neu = $werte[0]['Min'];

Ich hab das auch schon ohne [0] gesehen und verwendet. Warum wird in diesem Fall der Index 0 benötigt?

Kann es sein, dass wenn man es ohne [0] verwendet vorher das ausführen muss?

foreach($werte as $werte) 

Grüße André

Gut beobachtet, das führt dazu dass wegen Index 0 immer der zeitlich erste Wert ausgewertet ist, das wollen wir gar nicht. Mein Fehler, ich habe das aus einem anderen Skript zu unkritisch übernommen!

Aber ohne [0] bekomme ich die folgende Fehlermeldung und das Skript funktioniert auch nicht. Daher dachte ich, dass [0] in diesem Fall gebraucht wird.

Warning: Undefined array key "Min" in C:\ProgramData\Symcon\scripts\53172.ips.php on line 28

Warning: Cannot auto-convert value for parameter Value (Type is not supported) in C:\ProgramData\Symcon\scripts\53172.ips.php on line 30

Ja, du bekommst ein Array zurück, da braucht es einen Index. Aber du möchtest das letzte Element ansprechen, nicht das erste (Index 0). Da lassen wir jetzt mal die PHP-Profis ran, ich selbst bin Python-Nutzer und tue mich schwer mit PHP.

Wer kann aushelfen?

1 „Gefällt mir“

Vielleicht @Nall-chan oder @pitti ?

Ich habe mir mal von ChatGPT helfen lassen, das war eine Premiere und führte tatsächlich zum Ziel.

  $werte = AC_GetAggregatedValues($archivID,$sourceID, 5, $timestart, $timestop, 0);
  // print_r ($werte);

  $last_dataset = end($werte);
  $last_value = $last_dataset['Min'];

  AC_AddLoggedValues($archivID, $targetID,[
  [
    'TimeStamp' => $timestop,
    'Value' => $last_value
  ]
  ]);