From adbb95c6b8dfdf05850e842b583d677e9e9fbb5b Mon Sep 17 00:00:00 2001 From: "belevo\\mh" Date: Fri, 8 May 2026 08:42:09 +0200 Subject: [PATCH] no message --- Heizung_x_Stufig/README.md | 67 ++++++++++ Heizung_x_Stufig/form.json | 121 +++++++++++++++++ Heizung_x_Stufig/module.json | 12 ++ Heizung_x_Stufig/module.php | 243 +++++++++++++++++++++++++++++++++++ 4 files changed, 443 insertions(+) create mode 100644 Heizung_x_Stufig/README.md create mode 100644 Heizung_x_Stufig/form.json create mode 100644 Heizung_x_Stufig/module.json create mode 100644 Heizung_x_Stufig/module.php diff --git a/Heizung_x_Stufig/README.md b/Heizung_x_Stufig/README.md new file mode 100644 index 0000000..b059e3a --- /dev/null +++ b/Heizung_x_Stufig/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/Heizung_x_Stufig/form.json b/Heizung_x_Stufig/form.json new file mode 100644 index 0000000..0d6157c --- /dev/null +++ b/Heizung_x_Stufig/form.json @@ -0,0 +1,121 @@ +{ + "elements": [ + { + "type": "Label", + "caption": "Konfiguration der nötigen Schaltkontakte und Nennleistungen" + }, + { + "type":"Select", + "name":"Boilertemperatur_glätten", + "caption":"Boilertemperatur glätten", + "options":[ + { + "caption":"Ja", + "value":true + }, + { + "caption":"Nein", + "value":false + } + ] + }, + { + "type": "NumberSpinner", + "name": "ZeitKonstante", + "caption": "Zeit Konstante", + "suffix": "" + }, + { + "type": "NumberSpinner", + "name": "Interval", + "caption": "Intervall Neuberechnung der Werte Erst für spätere Versionen, aktuell auf 5 lassen!", + "suffix": "Sekunden" + }, + { + "type": "NumberSpinner", + "name": "IdleCounterMax", + "caption": "Zyklen zwischen zwei Leistungsänderungen (Multipliziert sich mit Interval)", + "suffix": "" + }, + { + "type":"List", + "name":"LeistungsStufen", + "caption":"Anzahl Stufen mit den dazugehörigen Leistungen", + "add":true, + "delete":true, + "columns":[ + { + "caption":"Stufe(n)", + "name":"Stufe", + "width":"200px", + "add":"Stufe", + "edit":{ + "type":"NumberSpinner" + } + }, + { + "caption":"Leistung in W", + "name":"Leistung", + "width":"300px", + "add":0, + "edit":{ + "type":"NumberSpinner" + } + }, + { + "caption":"Schaltkontakt", + "name":"Schaltkontakt_Stufe", + "width":"400px", + "add":0, + "edit":{ + "type":"SelectVariable" + } + } + + ] + }, + { + "type": "NumberSpinner", + "name": "Boilervolumen", + "caption": "Boilervolumen", + "suffix": "Liter" + }, + { + "type": "SelectVariable", + "name": "Boilerfuehler_PT1", + "caption": "Variable für Boilerfühler PT1", + "test": true + }, + { + "type": "List", + "name": "Zeitplan", + "caption": "Zeitplan für Solltemperaturen", + "columns": [ + { + "caption": "Uhrzeit", + "name": "Uhrzeit", + "width": "150px", + "add": "00:00", + "edit": { + "type": "ValidationTextBox" + } + }, + { + "caption": "Solltemperatur", + "name": "Solltemperatur", + "width": "150px", + "add": 0, + "edit": { + "type": "NumberSpinner" + } + } + ], + "add": true, + "delete": true, + "sort": { + "column": "Uhrzeit", + "direction": "ascending" + } + } + ] +} \ No newline at end of file diff --git a/Heizung_x_Stufig/module.json b/Heizung_x_Stufig/module.json new file mode 100644 index 0000000..ab2ecd6 --- /dev/null +++ b/Heizung_x_Stufig/module.json @@ -0,0 +1,12 @@ +{ + "id": "{3FD5E282-FF4F-D02A-8665-2B40DF65F3BB}", + "name": "Heizung_x_Stufig", + "type": 3, + "vendor": "Belevo AG", + "aliases": [], + "parentRequirements": [], + "childRequirements": [], + "implemented": [], + "prefix": "GEF", + "url": "" +} \ No newline at end of file diff --git a/Heizung_x_Stufig/module.php b/Heizung_x_Stufig/module.php new file mode 100644 index 0000000..ee33aa5 --- /dev/null +++ b/Heizung_x_Stufig/module.php @@ -0,0 +1,243 @@ +RegisterPropertyString("LeistungsStufen", json_encode([])); + $this->RegisterPropertyInteger("ZeitKonstante", 120); + $this->RegisterPropertyInteger("Heizungsfuehler_PT1", 0); + $this->RegisterPropertyBoolean("Heizungstemperatur_glätten", false); + $this->RegisterPropertyInteger("Interval", 5); + $this->RegisterPropertyFloat("Hysterese", 0.1); + + // Heizung spezifische Variablen + $this->RegisterVariableInteger("Mindesttemperatur", "Mindesttemperatur", "", 45); + $this->RegisterVariableInteger("Maximaltemperatur", "Maximaltemperatur", "", 60); + $this->RegisterVariableFloat("Heizungstemperatur", "Heizungstemperatur", "", 0); + + // Variablen für Kommunikation mit Manager + $this->RegisterVariableInteger("Sperre_Prio", "Sperre_Prio"); + $this->RegisterVariableInteger("PV_Prio", "PV_Prio"); + $this->RegisterVariableBoolean("Idle", "Idle", "", 0); + $this->RegisterVariableInteger("Aktuelle_Leistung", "Aktuelle_Leistung", "", 0); + $this->RegisterVariableFloat("Bezogene_Energie", "Bezogene_Energie", "", 0); + $this->RegisterVariableString("PowerSteps", "PowerSteps"); + $this->RegisterVariableInteger("Power", "Power", "", 0); + $this->RegisterVariableBoolean("Is_Peak_Shaving", "Is_Peak_Shaving", "", true); + $this->RegisterVariableInteger("Leistung_Delta", "Leistung_Delta", "", 0); + + // Hilfsvariablen für Idle-Zustand + $this->RegisterPropertyInteger("IdleCounterMax", 2); + $this->RegisterVariableInteger("IdleCounter", "IdleCounter", "", 0); + $this->SetValue("IdleCounter", 0); + + $this->SetValue("Idle", true); + + $this->RegisterTimer( + "Timer_Do_UserCalc_Heizung", + $this->ReadPropertyInteger("Interval") * 1000, + 'IPS_RequestAction(' . $this->InstanceID . ', "Do_UserCalc", "");' + ); + } + + public function ApplyChanges() + { + parent::ApplyChanges(); + + $this->SetTimerInterval( + "Timer_Do_UserCalc_Heizung", + $this->ReadPropertyInteger("Interval") * 1000 + ); + } + + public function RequestAction($Ident, $Value) + { + switch ($Ident) { + case "SetAktuelle_Leistung": + $this->SetValue("Power", (int)$Value); + break; + + case "GetCurrentData": + $this->SetValue("Is_Peak_Shaving", (bool)$Value); + break; + + case "Do_UserCalc": + $this->SetAktuelle_Leistung($this->GetValue("Power")); + $this->GetCurrentData($this->GetValue("Is_Peak_Shaving")); + break; + + default: + throw new Exception("Invalid Ident"); + } + } + + private function LadeUndSortiereLeistungen() + { + $this->leistungArray = [0]; + + $json = $this->ReadPropertyString("LeistungsStufen"); + $leistungsStufen = json_decode($json, true); + + if (is_array($leistungsStufen)) { + foreach ($leistungsStufen as $stufe) { + $this->leistungArray[] = (int)($stufe['Leistung'] ?? 0); + } + } + + sort($this->leistungArray); + } + + public function SetAktuelle_Leistung(int $power) + { + $this->LadeUndSortiereLeistungen(); + + foreach ($this->leistungArray as $leistung) { + $kontaktID = $this->GetKontaktIDZuLeistung($leistung); + + if ($kontaktID > 0 && IPS_VariableExists($kontaktID)) { + SetValue($kontaktID, ($leistung === $power)); + } elseif ($kontaktID > 0) { + IPS_LogMessage("ERROR", "KontaktID $kontaktID existiert nicht oder ist ungültig!"); + } + } + + $lastPower = GetValue($this->GetIDForIdent("Aktuelle_Leistung")); + + if ($power != $lastPower) { + $this->SetValue("Idle", false); + $this->SetValue("IdleCounter", $this->ReadPropertyInteger("IdleCounterMax")); + } + + $this->SetValue("Aktuelle_Leistung", $power); + + $this->SetValue( + "Bezogene_Energie", + $this->GetValue("Bezogene_Energie") + + ($this->GetValue("Aktuelle_Leistung") * ($this->ReadPropertyInteger("Interval") / 3600)) + ); + + $this->ProcessIdleCounter(); + } + + private function GetKontaktIDZuLeistung(int $leistung): int + { + $json = $this->ReadPropertyString("LeistungsStufen"); + $leistungsStufen = json_decode($json, true); + + if (is_array($leistungsStufen)) { + foreach ($leistungsStufen as $stufe) { + if ((int)($stufe['Leistung'] ?? 0) === $leistung) { + return (int)($stufe['Schaltkontakt_Stufe'] ?? 0); + } + } + } + + return 0; + } + + public function GetCurrentData(bool $Peak) + { + $this->LadeUndSortiereLeistungen(); + + $heizungstemperaturGlaetten = $this->ReadPropertyBoolean("Heizungstemperatur_glätten"); + $heizungsFuehlerPT1ID = $this->ReadPropertyInteger("Heizungsfuehler_PT1"); + + if ($heizungsFuehlerPT1ID > 0 && IPS_VariableExists($heizungsFuehlerPT1ID)) { + $heizungPT1 = GetValue($heizungsFuehlerPT1ID); + } else { + $heizungPT1 = 0.0; + } + + if ($heizungstemperaturGlaetten) { + $heizungTempAlt = $this->GetValue("Heizungstemperatur"); + + $timeConstant = $this->ReadPropertyInteger("ZeitKonstante"); + $deltaT = $this->ReadPropertyInteger("Interval"); + + $alpha = $deltaT / ($timeConstant + $deltaT); + $newHeizungTemp = $heizungTempAlt + $alpha * ($heizungPT1 - $heizungTempAlt); + + $this->SetValue("Heizungstemperatur", $newHeizungTemp); + } else { + $this->SetValue("Heizungstemperatur", $heizungPT1); + } + + $heizungTemp = $this->GetValue("Heizungstemperatur"); + $minTemp = $this->GetValue("Mindesttemperatur"); + $maxTemp = $this->GetValue("Maximaltemperatur"); + $hysterese = $this->ReadPropertyFloat("Hysterese"); + + $vollLeistung = max($this->leistungArray); + + if ($Peak) { + if ($heizungTemp < $minTemp) { + $this->SetValue("PowerSteps", json_encode($this->leistungArray)); + } elseif ( + $heizungTemp < $minTemp + $hysterese && + $this->IstEineStufeAktiv() + ) { + $this->SetValue("PowerSteps", json_encode($this->leistungArray)); + } else { + $this->SetValue("PowerSteps", json_encode([0])); + } + } else { + if ($heizungTemp < $minTemp) { + $this->SetValue("PowerSteps", json_encode([$vollLeistung])); + } elseif ( + $heizungTemp < $minTemp + $hysterese && + $this->IstEineStufeAktiv() + ) { + $this->SetValue("PowerSteps", json_encode([$vollLeistung])); + } elseif ($heizungTemp < $maxTemp - $hysterese) { + $this->SetValue("PowerSteps", json_encode($this->leistungArray)); + } elseif ( + $heizungTemp < $maxTemp && + $this->IstEineStufeAktiv() + ) { + $this->SetValue("PowerSteps", json_encode($this->leistungArray)); + } else { + $this->SetValue("PowerSteps", json_encode([0])); + } + } + } + + private function IstEineStufeAktiv(): bool + { + $json = $this->ReadPropertyString("LeistungsStufen"); + $leistungsStufen = json_decode($json, true); + + if (is_array($leistungsStufen)) { + foreach ($leistungsStufen as $stufe) { + $kontaktID = (int)($stufe['Schaltkontakt_Stufe'] ?? 0); + + if ($kontaktID > 0 && IPS_VariableExists($kontaktID)) { + if (GetValue($kontaktID) === true) { + return true; + } + } + } + } + + return false; + } + + private function ProcessIdleCounter() + { + $idleCounter = $this->GetValue("IdleCounter"); + + if ($idleCounter > 0) { + $this->SetValue("Idle", false); + $this->SetValue("IdleCounter", $idleCounter - 1); + } else { + $this->SetValue("Idle", true); + } + } +} + +?> \ No newline at end of file