From b55e8c67af4499a190548defa2415418791fb54d Mon Sep 17 00:00:00 2001 From: "belevo\\mh" Date: Wed, 17 Dec 2025 07:05:42 +0100 Subject: [PATCH] no message --- Energy_Pie/README.md | 67 +++++++++++ Energy_Pie/form.json | 11 ++ Energy_Pie/module.html | 171 ++++++++++++++++++++++++++ Energy_Pie/module.json | 11 ++ Energy_Pie/module.php | 267 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 527 insertions(+) create mode 100644 Energy_Pie/README.md create mode 100644 Energy_Pie/form.json create mode 100644 Energy_Pie/module.html create mode 100644 Energy_Pie/module.json create mode 100644 Energy_Pie/module.php diff --git a/Energy_Pie/README.md b/Energy_Pie/README.md new file mode 100644 index 0000000..e3abe65 --- /dev/null +++ b/Energy_Pie/README.md @@ -0,0 +1,67 @@ +# Manager_1 +Beschreibung des Moduls. + +### Inhaltsverzeichnis + +1. [Funktionsumfang](#1-funktionsumfang) +2. [Voraussetzungen](#2-voraussetzungen) +3. [Software-Installation](#3-software-installation) +4. [Einrichten der Instanzen in IP-Symcon](#4-einrichten-der-instanzen-in-ip-symcon) +5. [Statusvariablen und Profile](#5-statusvariablen-und-profile) +6. [WebFront](#6-webfront) +7. [PHP-Befehlsreferenz](#7-php-befehlsreferenz) + +### 1. Funktionsumfang + +* + +### 2. Voraussetzungen + +- IP-Symcon ab Version 7.1 + +### 3. Software-Installation + +* Über den Module Store das 'Manager_1'-Modul installieren. +* Alternativ über das Module Control folgende URL hinzufügen + +### 4. Einrichten der Instanzen in IP-Symcon + + Unter 'Instanz hinzufügen' kann das 'Manager_1'-Modul mithilfe des Schnellfilters gefunden werden. + - Weitere Informationen zum Hinzufügen von Instanzen in der [Dokumentation der Instanzen](https://www.symcon.de/service/dokumentation/konzepte/instanzen/#Instanz_hinzufügen) + +__Konfigurationsseite__: + +Name | Beschreibung +-------- | ------------------ + | + | + +### 5. Statusvariablen und Profile + +Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. + +#### Statusvariablen + +Name | Typ | Beschreibung +------ | ------- | ------------ + | | + | | + +#### Profile + +Name | Typ +------ | ------- + | + | + +### 6. WebFront + +Die Funktionalität, die das Modul im WebFront bietet. + +### 7. PHP-Befehlsreferenz + +`boolean GEF_BeispielFunktion(integer $InstanzID);` +Erklärung der Funktion. + +Beispiel: +`GEF_BeispielFunktion(12345);` \ No newline at end of file diff --git a/Energy_Pie/form.json b/Energy_Pie/form.json new file mode 100644 index 0000000..ea6acca --- /dev/null +++ b/Energy_Pie/form.json @@ -0,0 +1,11 @@ +{ + "id": "{{28A05FF5-582D-8F15-4CCF-A18402C4BC2B}}", + "name": "Energy_Pie", + "type": 3, + "vendor": "Custom", + "aliases": [ + "Energy_Pie", + "Energie-Kreisdiagramm" + ], + "url": "" +} diff --git a/Energy_Pie/module.html b/Energy_Pie/module.html new file mode 100644 index 0000000..d70fa9d --- /dev/null +++ b/Energy_Pie/module.html @@ -0,0 +1,171 @@ +
+
+ + + + + + + +
+ +
+
+ +
+
+ +
+
Aufteilung
+
+
+
+
+ + diff --git a/Energy_Pie/module.json b/Energy_Pie/module.json new file mode 100644 index 0000000..c654e30 --- /dev/null +++ b/Energy_Pie/module.json @@ -0,0 +1,11 @@ +{ + "id": "{{97BFC43B-9BE5-AB7D-EC5A-E31BB54878E0}}", + "name": "Energy_Pie", + "type": 3, + "vendor": "Custom", + "aliases": [ + "Energy_Pie", + "Energie-Kreisdiagramm" + ], + "url": "" +} diff --git a/Energy_Pie/module.php b/Energy_Pie/module.php new file mode 100644 index 0000000..059149c --- /dev/null +++ b/Energy_Pie/module.php @@ -0,0 +1,267 @@ +RegisterPropertyInteger('VarProduction', 0); + $this->RegisterPropertyInteger('VarConsumption', 0); + $this->RegisterPropertyInteger('VarFeedIn', 0); + $this->RegisterPropertyInteger('VarGrid', 0); + + $this->RegisterPropertyString('DefaultRange', 'day'); + + // UI state + $this->RegisterAttributeString(self::ATTR_RANGE, 'day'); + $this->RegisterAttributeString(self::ATTR_DATE, date('Y-m-d')); + + // Enable HTML-SDK visualization tile + $this->SetVisualizationType(1); + } + + public function ApplyChanges(): void + { + parent::ApplyChanges(); + + // Initialize attributes if needed + $range = $this->ReadAttributeString(self::ATTR_RANGE); + if ($range === '') { + $this->WriteAttributeString(self::ATTR_RANGE, $this->ReadPropertyString('DefaultRange')); + } + + $date = $this->ReadAttributeString(self::ATTR_DATE); + if ($date === '' || !$this->isValidDate($date)) { + $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); + } + + public function RequestAction($Ident, $Value): void + { + switch ($Ident) { + + case 'SetRange': + $range = (string)$Value; + if (!in_array($range, ['day', 'week', 'month', 'total'], true)) { + throw new Exception('Invalid range: ' . $range); + } + + $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); + } + } + + private function RecalculateAndPush(): void + { + $range = $this->ReadAttributeString(self::ATTR_RANGE); + $date = $this->ReadAttributeString(self::ATTR_DATE); + + [$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; + + $payload = [ + 'range' => $range, + 'date' => $date, + 'tStart' => $tStart, + 'tEnd' => $tEnd, + 'values' => [ + 'Produktion' => (float)$prod, + 'Verbrauch' => (float)$cons, + 'Einspeisung' => (float)$feed, + 'Netz' => (float)$grid + ] + ]; + + $this->UpdateVisualizationValue($payload); + } + + 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'); + } + + switch ($range) { + case 'day': + $start = $base; + $end = $start + 86400; + return [$start, $end]; + + case 'week': + // Mo–So: start = Monday 00:00:00, end = next Monday 00:00:00 + $dow = (int)date('N', $base); // 1=Mon..7=Sun + $start = $base - (($dow - 1) * 86400); + $end = $start + (7 * 86400); + return [$start, $end]; + + case 'month': + $start = strtotime(date('Y-m-01 00:00:00', $base)); + $end = strtotime('+1 month', $start); + return [$start, $end]; + + default: + return [$base, $base + 86400]; + } + } + + private function ShiftDate(string $action): void + { + $range = $this->ReadAttributeString(self::ATTR_RANGE); + + if ($range === 'total') { + return; + } + + if ($action === 'Today') { + $this->WriteAttributeString(self::ATTR_DATE, date('Y-m-d')); + 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'); + } + + $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; + } + + $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)); + } + + private function isValidDate(string $ymd): bool + { + if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $ymd)) { + return false; + } + [$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', true); +} +?> \ No newline at end of file