diff --git a/Energy_Pie/module.php b/Energy_Pie/module.php
index a1b14a6..4f07bef 100644
--- a/Energy_Pie/module.php
+++ b/Energy_Pie/module.php
@@ -19,11 +19,11 @@ class Energy_Pie extends IPSModule
$this->RegisterPropertyString('DefaultRange', 'day');
- // UI state
+ // UI state (internal, no object tree clutter)
$this->RegisterAttributeString(self::ATTR_RANGE, 'day');
$this->RegisterAttributeString(self::ATTR_DATE, date('Y-m-d'));
- // Enable HTML-SDK visualization tile
+ // Enable HTML-SDK visualization
$this->SetVisualizationType(1);
}
@@ -31,9 +31,7 @@ class Energy_Pie extends IPSModule
{
parent::ApplyChanges();
- // Initialize attributes if needed
- $range = $this->ReadAttributeString(self::ATTR_RANGE);
- if ($range === '') {
+ if ($this->ReadAttributeString(self::ATTR_RANGE) === '') {
$this->WriteAttributeString(self::ATTR_RANGE, $this->ReadPropertyString('DefaultRange'));
}
@@ -42,17 +40,15 @@ class Energy_Pie extends IPSModule
$this->WriteAttributeString(self::ATTR_DATE, date('Y-m-d'));
}
- // Push initial data
$this->RecalculateAndPush();
}
public function GetVisualizationTile(): string
{
$path = __DIR__ . '/module.html';
- if (!file_exists($path)) {
- return '
module.html fehlt
';
- }
- return file_get_contents($path);
+ return file_exists($path)
+ ? file_get_contents($path)
+ : 'module.html fehlt
';
}
public function RequestAction($Ident, $Value): void
@@ -62,60 +58,48 @@ class Energy_Pie extends IPSModule
case 'SetRange':
$range = (string)$Value;
if (!in_array($range, ['day', 'week', 'month', 'total'], true)) {
- throw new Exception('Invalid range: ' . $range);
+ return;
}
-
$this->WriteAttributeString(self::ATTR_RANGE, $range);
-
- // UX: if switching to week, snap date to Monday (Mo–So)
if ($range === 'week') {
$this->snapDateToWeekMonday();
}
-
- // For total, date is irrelevant but we keep it stored
- $this->RecalculateAndPush();
break;
case 'SetDate':
$date = (string)$Value;
if (!$this->isValidDate($date)) {
- // ignore invalid date instead of crashing the UI
return;
}
-
$this->WriteAttributeString(self::ATTR_DATE, $date);
-
- // If currently in week mode, snap to Monday immediately
if ($this->ReadAttributeString(self::ATTR_RANGE) === 'week') {
$this->snapDateToWeekMonday();
}
-
- $this->RecalculateAndPush();
break;
case 'Prev':
case 'Next':
case 'Today':
$this->ShiftDate($Ident);
-
- // If week mode, always keep Monday
if ($this->ReadAttributeString(self::ATTR_RANGE) === 'week') {
$this->snapDateToWeekMonday();
}
-
- $this->RecalculateAndPush();
break;
case 'Refresh':
- // optional manual refresh (keeps handy for debugging)
- $this->RecalculateAndPush();
break;
default:
- throw new Exception('Unknown Ident: ' . $Ident);
+ return;
}
+
+ $this->RecalculateAndPush();
}
+ /* ========================================================= */
+ /* ===================== CORE LOGIC ======================== */
+ /* ========================================================= */
+
private function RecalculateAndPush(): void
{
$range = $this->ReadAttributeString(self::ATTR_RANGE);
@@ -123,16 +107,10 @@ class Energy_Pie extends IPSModule
[$tStart, $tEnd] = $this->getRange($range, $date);
- // --- PLACEHOLDER ---
- // Replace later with archive delta calculations:
- // $prod = $this->readDelta($this->ReadPropertyInteger('VarProduction'), $tStart, $tEnd);
- // $cons = $this->readDelta($this->ReadPropertyInteger('VarConsumption'), $tStart, $tEnd);
- // $feed = $this->readDelta($this->ReadPropertyInteger('VarFeedIn'), $tStart, $tEnd);
- // $grid = $this->readDelta($this->ReadPropertyInteger('VarGrid'), $tStart, $tEnd);
- $prod = 12.3;
- $cons = 8.7;
- $feed = 3.1;
- $grid = 5.6;
+ $prod = $this->readDelta($this->ReadPropertyInteger('VarProduction'), $tStart, $tEnd);
+ $cons = $this->readDelta($this->ReadPropertyInteger('VarConsumption'), $tStart, $tEnd);
+ $feed = $this->readDelta($this->ReadPropertyInteger('VarFeedIn'), $tStart, $tEnd);
+ $grid = $this->readDelta($this->ReadPropertyInteger('VarGrid'), $tStart, $tEnd);
$payload = [
'range' => $range,
@@ -140,48 +118,42 @@ class Energy_Pie extends IPSModule
'tStart' => $tStart,
'tEnd' => $tEnd,
'values' => [
- 'Produktion' => (float)$prod,
- 'Verbrauch' => (float)$cons,
- 'Einspeisung' => (float)$feed,
- 'Netz' => (float)$grid
+ 'Produktion' => $prod,
+ 'Verbrauch' => $cons,
+ 'Einspeisung' => $feed,
+ 'Netz' => $grid
]
];
$this->UpdateVisualizationValue(json_encode($payload, JSON_THROW_ON_ERROR));
-
}
+ /* ========================================================= */
+ /* ===================== TIME RANGES ======================= */
+ /* ========================================================= */
+
private function getRange(string $range, string $dateYmd): array
{
$now = time();
if ($range === 'total') {
- // Later: use oldest log timestamp as start
return [0, $now];
}
- $base = strtotime($dateYmd . ' 00:00:00');
- if ($base === false) {
- $base = strtotime(date('Y-m-d') . ' 00:00:00');
- }
+ $base = strtotime($dateYmd . ' 00:00:00') ?: strtotime('today');
switch ($range) {
case 'day':
- $start = $base;
- $end = $start + 86400;
- return [$start, $end];
+ return [$base, $base + 86400];
case 'week':
- // Mo–So: start = Monday 00:00:00, end = next Monday 00:00:00
- $dow = (int)date('N', $base); // 1=Mon..7=Sun
+ $dow = (int)date('N', $base); // 1=Mon
$start = $base - (($dow - 1) * 86400);
- $end = $start + (7 * 86400);
- return [$start, $end];
+ return [$start, $start + 7 * 86400];
case 'month':
$start = strtotime(date('Y-m-01 00:00:00', $base));
- $end = strtotime('+1 month', $start);
- return [$start, $end];
+ return [$start, strtotime('+1 month', $start)];
default:
return [$base, $base + 86400];
@@ -201,50 +173,73 @@ class Energy_Pie extends IPSModule
return;
}
- $date = $this->ReadAttributeString(self::ATTR_DATE);
- $base = strtotime($date . ' 00:00:00');
- if ($base === false) {
- $base = strtotime(date('Y-m-d') . ' 00:00:00');
- }
+ $base = strtotime($this->ReadAttributeString(self::ATTR_DATE) . ' 00:00:00') ?: strtotime('today');
+ $dir = ($action === 'Prev') ? -1 : 1;
- $sign = ($action === 'Prev') ? -1 : 1;
-
- switch ($range) {
- case 'day':
- $base = strtotime(($sign === -1 ? '-1 day' : '+1 day'), $base);
- break;
-
- case 'week':
- $base = strtotime(($sign === -1 ? '-7 day' : '+7 day'), $base);
- break;
-
- case 'month':
- $base = strtotime(($sign === -1 ? '-1 month' : '+1 month'), $base);
- break;
- }
+ match ($range) {
+ 'day' => $base = strtotime(($dir === -1 ? '-1 day' : '+1 day'), $base),
+ 'week' => $base = strtotime(($dir === -7 ? '-7 day' : '+7 day'), $base),
+ 'month' => $base = strtotime(($dir === -1 ? '-1 month' : '+1 month'), $base),
+ default => null
+ };
$this->WriteAttributeString(self::ATTR_DATE, date('Y-m-d', $base));
}
private function snapDateToWeekMonday(): void
{
- $date = $this->ReadAttributeString(self::ATTR_DATE);
- if (!$this->isValidDate($date)) {
- $date = date('Y-m-d');
- $this->WriteAttributeString(self::ATTR_DATE, $date);
- }
-
- $base = strtotime($date . ' 00:00:00');
- if ($base === false) {
- $base = strtotime(date('Y-m-d') . ' 00:00:00');
- }
-
- $dow = (int)date('N', $base); // 1=Mon..7=Sun
- $monday = $base - (($dow - 1) * 86400);
-
- $this->WriteAttributeString(self::ATTR_DATE, date('Y-m-d', $monday));
+ $base = strtotime($this->ReadAttributeString(self::ATTR_DATE) . ' 00:00:00') ?: strtotime('today');
+ $dow = (int)date('N', $base);
+ $this->WriteAttributeString(self::ATTR_DATE, date('Y-m-d', $base - (($dow - 1) * 86400)));
}
+ /* ========================================================= */
+ /* ===================== ARCHIVE READ ====================== */
+ /* ========================================================= */
+
+ private function readDelta(int $varId, int $tStart, int $tEnd): float
+ {
+ if ($varId <= 0 || !IPS_VariableExists($varId)) {
+ return 0.0;
+ }
+
+ $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0] ?? 0;
+ if ($archiveID <= 0) {
+ 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) => $a['TimeStamp'] <=> $b['TimeStamp']);
+
+ $vStart = null;
+ $vEnd = null;
+
+ foreach ($values as $v) {
+ if ($v['TimeStamp'] <= $tStart) {
+ $vStart = (float)$v['Value'];
+ }
+ if ($v['TimeStamp'] <= $tEnd) {
+ $vEnd = (float)$v['Value'];
+ }
+ if ($v['TimeStamp'] > $tEnd) {
+ break;
+ }
+ }
+
+ if ($vStart === null || $vEnd === null) {
+ return 0.0;
+ }
+
+ $diff = $vEnd - $vStart;
+ return ($diff < 0) ? 0.0 : round($diff, 3);
+ }
+
+ /* ========================================================= */
+
private function isValidDate(string $ymd): bool
{
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $ymd)) {
@@ -253,18 +248,5 @@ class Energy_Pie extends IPSModule
[$y, $m, $d] = array_map('intval', explode('-', $ymd));
return checkdate($m, $d, $y);
}
-
- public function TestPush(): void
- {
- $this->RecalculateAndPush();
- }
}
-
-// Action helper for form.json button
-function EP_TestPush(int $id): void
-{
- IPS_RequestAction($id, 'Refresh', 1);
-}
-
-
?>
\ No newline at end of file