Stromkosten mit unterschiedlichen Preisen im nachhinein berechnen

Hallo,
ich habe hier ein Skript zusammengebastelt, was der ein oder andere vielleicht brauchen kann.
Das Skript nimmt eine Zählervariable (kWh) aus dem Archiv und berechnet die Kosten (ohne Grundgebühr) über die Zeit und schreibt das Ergebnis in eine neue Variable (Euro). Diese lässt sich dann als Balkengrafik schön im Webfront darstellen.

Es sind noch ein paar Änderungen geplant, aber ob und wann diese kommen, kann ich nicht sagen, daher der aktuelle Stand des Skripts hier zum ausprobieren.

<?php
// Achtung!!! Daten der Zielvariable werden vollständig gelöscht! 
$debug = FALSE;
$SourceID = 37629 ; // Variable mit Zählerwert in kWh
$TargetID = 22726; // Zielvariable Float mit Profil ~Euro
$ArchiveList = IPS_GetInstanceListByModuleID("{43192F0B-135B-4CE7-A0A7-1475603F3060}"); // Archivinstanzen abrufen
$ArchiveID = $ArchiveList[0]; // !!! Es wird die erste gefundene Archivinstanz verwendet
$PriceArray=[['01.01.2021','0.2388'],['01.02.2021','0.2375'],['01.03.2021','0.24'],['01.04.2021','0.2401'],['01.05.2021','0.2394'],['01.06.2021','0.2479'],['01.07.2021','0.259'],['01.08.2021','0.2692'],['01.09.2021','0.2865'],['01.10.2021','0.35']]; // Es wird keine Sortierung des Arrays vorgenommen - Daten müssen mit dem Datum aufsteigend eingetragen werden
$StartDate="01.01.2021";

// -------------------------------- Ende Konfigurationsteil -----------------------------------------

$totaldiff = 0.0;
$eurovalue = 0.0;
$oldvalue = 0.0;
$price = 0.0;
$d = 0;

$beginn = microtime(true); 
$start = new DateTimeImmutable($StartDate);
$starttime = strtotime($start->format('Y-m-d H:i:s'));

AC_DeleteVariableData($ArchiveID, $TargetID, 0, 0);
AC_SetLoggingStatus($ArchiveID , $TargetID, true);

while ($starttime < strtotime('today')){

    for ($cnt = 0;$cnt < count($PriceArray);$cnt++ ){
        $pricedate = strtotime($PriceArray[$cnt][0]);
        if ($pricedate >= $starttime){
            $price = $PriceArray[$cnt][1];
            break;
        }
    }


    $datetime = $start->modify('+'.$d.' day');
    $starttime = strtotime($datetime->format('Y-m-d H:i:s'));
    $datetime = $datetime->modify('+1 day');
    $endtime = strtotime($datetime->format('Y-m-d H:i:s'));

    if ($debug){echo "Starttime: ".date('d.m.Y H:i:s', $starttime).PHP_EOL;};

    $logData = AC_GetLoggedValues($ArchiveID, $SourceID,  $starttime, $endtime, 0); //Datensätze abfragen

    $entries = count($logData);// Anzahl der Werte

    if ($debug){echo "Einträge: ".$entries.PHP_EOL;};
    
    if ($entries >0) {
        if ($debug){echo "Oldvalue: ".$oldvalue.PHP_EOL;};
        if ($debug){echo "Kleinster: ".$logData[$entries-1]['Value'].PHP_EOL;};
        if ($debug){echo "Größter: ".$logData[0]['Value'].PHP_EOL;};
  
        for ($i = $entries; $i > 2; $i--){
            if ($oldvalue == 0 ) {
                $oldvalue = $logData[$i-1]['Value'];
            }

            $diff1 = $logData[$i - 2]['Value']-$oldvalue;
            if ($diff1 >= 1){
            
                if ($debug){echo "Diff: ".$diff1.PHP_EOL;};
                if ($debug){echo "Oldvalue: ".$oldvalue.PHP_EOL;};
            
                $timestamp = $logData[$i - 2]['TimeStamp'];
                $oldvalue = $logData[$i - 2]['Value'];
                $eurovalue = $eurovalue + $diff1*$price;
                $totaldiff = $totaldiff + $diff1;
                AC_AddLoggedValues ($ArchiveID, $TargetID, [['TimeStamp' => $timestamp,'Value' => $eurovalue]]);

            }
        }
    }
    
    $d++;
    if ($debug){echo "-------------------------------".PHP_EOL;};
}

// Letzte differenz
if ($debug){echo "Letzte Diff: ".$diff1.PHP_EOL;};
$timestamp = $logData[$i - 2]['TimeStamp'];
$oldvalue = $logData[$i - 2]['Value'];
$eurovalue = $eurovalue + $diff1*$price;
$totaldiff = $totaldiff + $diff1;
AC_AddLoggedValues ($ArchiveID, $TargetID, [['TimeStamp' => $timestamp,'Value' => $eurovalue]]);


if ($debug){echo "Totaldiff: ".$totaldiff.PHP_EOL;};
if ($debug){echo "Gesamtkosten: ".$eurovalue.PHP_EOL;};
SetValueFloat($TargetID,$eurovalue);
AC_SetAggregationType ($ArchiveID, $TargetID, 1);
AC_ReAggregateVariable ($ArchiveID, $TargetID);
$dauer = round(microtime(true) - $beginn,2); 
echo "Verarbeitung des Skripts: $dauer Sek.";
?>

@Dustin723
das wär doch was für dein Problem

1 „Gefällt mir“

Moin,
das trifft es schon ziemlich gut.
Aber irgendwie hoffe ich doch noch, das mal ein Modul für „Strom zu Euro“ kommt.

Ich habe so 20 Zähler die kwh messen dann in Euro umrechnen müssen.

Ich frage mich echt, ob ich da der enzige bin der sowas macht und das lieber richtig sauber gelöst haben möchte?

Schick, gefällt mir. allerdings werde ich mir das wohl etwas umschreiben und nur die letzten beiden Werte der Zählervariable benutzen und dann in die neue, die auch als Zähler aggregiert wird schreiben. Ich denke, dass man gerade wenn sehr viele Daten zu bearbeiten sind, das Skript hier immer langsamer wird.

Das Skript ist auch ausschließlich dafür gedacht die alten Daten einmalig aufzubereiten. Danach sollte man mit der Aktualisierung der Zählervariable den Wert der Kosten neu schreiben.
Hier ist eine Verbesserung drin, welche das Skript hier deutlich verbessern würde. Es werden die Daten Tageweise erst in ein Array gepackt und anschließend pro Tag geschrieben. Das macht das Skript um Welten schneller…

https://community.symcon.de/t/es-werden-immer-wieder-mal-doppelte-archiv-eintraege-eingetragen/130307/10