diff --git a/Energy_Pie/module.php b/Energy_Pie/module.php index 0e0a229..1e962de 100644 --- a/Energy_Pie/module.php +++ b/Energy_Pie/module.php @@ -153,96 +153,49 @@ class Energy_Pie extends IPSModule $this->RecalculateAndPush(); return $this->GetVisualizationTile(); } -private function readDelta(int $varId, int $tStart, int $tEnd, array &$dbg): float -{ - $dbg = [ - 'varId' => $varId, - 'archiveId' => 0, - 'count' => 0, // hier: wie viele AC-Calls erfolgreich Werte lieferten (nicht Anzahl Rohwerte) - 'vStart' => null, - 'vEnd' => null, - 'tsStart' => null, - 'tsEnd' => null - ]; - - if ($varId <= 0 || !IPS_VariableExists($varId)) { - return 0.0; - } - - $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0] ?? 0; - $dbg['archiveId'] = $archiveID; - if ($archiveID <= 0) { - return 0.0; - } - - // Liefert den letzten geloggten Wert <= $toTs. - // Wir starten mit einem kleinen Suchfenster (1 Tag) und vergrößern bei Bedarf. - $getLastUpTo = function (int $toTs) use ($archiveID, $varId): ?array { - $windows = [ - 86400, // 1 Tag - 7 * 86400, // 1 Woche - 31 * 86400, // 1 Monat - 365 * 86400, // 1 Jahr + private function readDelta(int $varId, int $tStart, int $tEnd, array &$dbg): float + { + $dbg = [ + 'varId' => $varId, + 'archiveId' => 0, + 'count' => 0, + 'first' => null, + 'last' => null, + 'vStart' => null, + 'vEnd' => null ]; - - foreach ($windows as $w) { - $from = $toTs - $w; - if ($from < 0) $from = 0; - - // Limit = 1: wir wollen nur einen Wert - $vals = @AC_GetLoggedValues($archiveID, $varId, $from, $toTs, 1); - if (!empty($vals)) { - // In der Praxis liefert Symcon bei Limit=1 den "letzten" im Bereich. - // Wir nehmen trotzdem defensiv den Eintrag mit dem größten TimeStamp. - $best = $vals[0]; - $bestTs = (int)$best['TimeStamp']; - foreach ($vals as $v) { - $ts = (int)$v['TimeStamp']; - if ($ts > $bestTs) { $bestTs = $ts; $best = $v; } - } - return $best; - } + if ($varId <= 0 || !IPS_VariableExists($varId)) { + return 0.0; } - - // letzter Versuch: gesamtes Archiv bis toTs (kann bei "total" groß sein, aber passiert nur wenn oben nix gefunden wurde) - $vals = @AC_GetLoggedValues($archiveID, $varId, 0, $toTs, 1); - if (!empty($vals)) { - $best = $vals[0]; - $bestTs = (int)$best['TimeStamp']; - foreach ($vals as $v) { - $ts = (int)$v['TimeStamp']; - if ($ts > $bestTs) { $bestTs = $ts; $best = $v; } - } - return $best; + $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0] ?? 0; + $dbg['archiveId'] = $archiveID; + if ($archiveID <= 0) { + return 0.0; } - - return null; - }; - - // vStart = letzter Wert <= tStart - $a = $getLastUpTo($tStart); - if ($a !== null) { - $dbg['count']++; - $dbg['vStart'] = (float)$a['Value']; - $dbg['tsStart'] = (int)$a['TimeStamp']; - } else { - return 0.0; + $values = @AC_GetLoggedValues($archiveID, $varId, $tStart - 86400, $tEnd + 86400, 0); + if (empty($values)) { + return 0.0; + } + usort($values, static fn($a, $b) => (int)$a['TimeStamp'] <=> (int)$b['TimeStamp']); + $dbg['count'] = count($values); + $dbg['first'] = (float)$values[0]['Value']; + $dbg['last'] = (float)$values[count($values) - 1]['Value']; + $vStart = null; + $vEnd = null; + foreach ($values as $v) { + $ts = (int)$v['TimeStamp']; + if ($ts <= $tStart) $vStart = (float)$v['Value']; + if ($ts <= $tEnd) $vEnd = (float)$v['Value']; + if ($ts > $tEnd) break; + } + if ($vStart === null) $vStart = $dbg['first']; + if ($vEnd === null) $vEnd = $dbg['last']; + $dbg['vStart'] = $vStart; + $dbg['vEnd'] = $vEnd; + $diff = $vEnd - $vStart; + return ($diff < 0) ? 0.0 : (float)$diff; } - // vEnd = letzter Wert <= tEnd - $b = $getLastUpTo($tEnd); - if ($b !== null) { - $dbg['count']++; - $dbg['vEnd'] = (float)$b['Value']; - $dbg['tsEnd'] = (int)$b['TimeStamp']; - } else { - return 0.0; - } - - $diff = (float)$dbg['vEnd'] - (float)$dbg['vStart']; - return ($diff < 0) ? 0.0 : $diff; -} - private function getLastLogTimestamp(int $varId): int { if ($varId <= 0 || !IPS_VariableExists($varId)) {