Wassererwaermer-Konfiguration vereinfachen
Tests / test (push) Successful in 46s

This commit is contained in:
dh
2026-09-17 08:29:49 +00:00
parent 9869d99641
commit 4514ccb557
8 changed files with 312 additions and 277 deletions
+47 -99
View File
@@ -1,9 +1,5 @@
{
"elements": [
{
"type": "Label",
"caption": "Mehrstufiger Warmwassererwaermer nach Enelix-2-Vertrag 3.0"
},
{
"type": "ExpansionPanel",
"caption": "Manager und Zeitverhalten",
@@ -12,13 +8,13 @@
{
"type": "NumberSpinner",
"name": "PrioritaetPV",
"caption": "Prioritaet PV",
"caption": "Priorität PV",
"minimum": 0
},
{
"type": "NumberSpinner",
"name": "PrioritaetPeak",
"caption": "Prioritaet Peak",
"caption": "Priorität Peak",
"minimum": 0
},
{
@@ -52,7 +48,7 @@
},
{
"type": "ExpansionPanel",
"caption": "Leistungsstufen",
"caption": "Speichereinstellungen",
"expanded": true,
"items": [
{
@@ -94,38 +90,37 @@
}
}
]
},
{
"type": "SelectVariable",
"name": "Boilerfuehler_PT1",
"caption": "Boilerfühler"
},
{
"type": "CheckBox",
"name": "LegionellenfunktionAktiv",
"caption": "Legionellenschaltung aktiv"
},
{
"type": "NumberSpinner",
"name": "LegionellenMinimalintervallTage",
"caption": "Frühestens nach",
"suffix": " Tagen",
"minimum": 1
},
{
"type": "NumberSpinner",
"name": "LegionellenMaximalintervallTage",
"caption": "Spätestens nach",
"suffix": " Tagen",
"minimum": 1
}
]
},
{
"type": "ExpansionPanel",
"caption": "Temperatur und Speicher",
"expanded": true,
"caption": "Erweiterte Speichereinstellungen",
"items": [
{
"type": "SelectVariable",
"name": "Boilerfuehler_PT1",
"caption": "Boilerfuehler"
},
{
"type": "NumberSpinner",
"name": "TemperaturMaxAlter",
"caption": "Maximales Messwertalter",
"suffix": " s",
"minimum": 1
},
{
"type": "CheckBox",
"name": "BoilertemperaturGlaetten",
"caption": "Boilertemperatur mit PT1 glaetten"
},
{
"type": "NumberSpinner",
"name": "ZeitKonstante",
"caption": "PT1-Zeitkonstante",
"suffix": " s",
"minimum": 1
},
{
"type": "NumberSpinner",
"name": "Boilervolumen",
@@ -141,21 +136,10 @@
"minimum": 0.1,
"digits": 1
},
{
"type": "CheckBox",
"name": "EinstellungenInVisu",
"caption": "Temperatursollwerte in der Visualisierung anzeigen und bedienen"
}
]
},
{
"type": "ExpansionPanel",
"caption": "Zeitplan",
"items": [
{
"type": "List",
"name": "Zeitplan",
"caption": "Naechste Solltemperatur vorausberechnen",
"caption": "Zeitplan für Solltemperaturen",
"add": true,
"delete": true,
"sortable": true,
@@ -179,7 +163,7 @@
"minimum": 0,
"maximum": 100,
"digits": 1,
"suffix": " C"
"suffix": " °C"
}
}
]
@@ -188,60 +172,36 @@
},
{
"type": "ExpansionPanel",
"caption": "Legionellenfunktion",
"caption": "Erweiterte sonstige Einstellungen",
"items": [
{
"type": "NumberSpinner",
"name": "TemperaturMaxAlter",
"caption": "Maximales Messwertalter",
"suffix": " s",
"minimum": 1
},
{
"type": "CheckBox",
"name": "LegionellenfunktionAktiv",
"caption": "Legionellenfunktion aktiv"
"name": "BoilertemperaturGlaetten",
"caption": "Boilertemperatur mit PT1 glätten"
},
{
"type": "NumberSpinner",
"name": "LegionellenIntervallTage",
"caption": "Intervall",
"suffix": " Tage",
"minimum": 1
},
{
"type": "NumberSpinner",
"name": "LegionellenHaltezeit",
"caption": "Haltezeit auf Legionellentemperatur",
"suffix": " s",
"minimum": 0
},
{
"type": "NumberSpinner",
"name": "LegionellenMaximaldauer",
"caption": "Maximaldauer",
"name": "ZeitKonstante",
"caption": "PT1-Zeitkonstante",
"suffix": " s",
"minimum": 1
},
{
"type": "NumberSpinner",
"name": "NachtstartStunde",
"caption": "Nachtbeginn",
"suffix": " Uhr",
"minimum": 0,
"maximum": 23
"type": "CheckBox",
"name": "EinstellungenInVisu",
"caption": "Temperatursollwerte in der Visualisierung anzeigen und bedienen"
},
{
"type": "NumberSpinner",
"name": "NachtendeStunde",
"caption": "Nachtende",
"suffix": " Uhr",
"minimum": 0,
"maximum": 23
}
]
},
{
"type": "ExpansionPanel",
"caption": "Diagnose",
"items": [
{
"type": "CheckBox",
"name": "DiagnosevariablenAnzeigen",
"caption": "Diagnosevariablen anzeigen"
"caption": "Diagnosevariablen anlegen"
},
{
"type": "CheckBox",
@@ -251,18 +211,6 @@
]
}
],
"actions": [
{
"type": "Button",
"caption": "Regelung jetzt ausfuehren",
"onClick": "IPS_RequestAction($id, 'Regelzyklus', false);"
},
{
"type": "Button",
"caption": "Aktuellen Status einmalig ins Debug-Log schreiben",
"onClick": "IPS_RequestAction($id, 'LogStatus', true);"
}
],
"status": [
{
"code": 102,
@@ -277,7 +225,7 @@
{
"code": 202,
"icon": "error",
"caption": "Konfiguration ungueltig"
"caption": "Konfiguration ungültig"
},
{
"code": 203,
+154 -153
View File
@@ -55,11 +55,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->RegisterPropertyInteger('TemperaturMaxAlter', 30);
$this->RegisterPropertyFloat('Hysterese', 5.0);
$this->RegisterPropertyBoolean('LegionellenfunktionAktiv', true);
$this->RegisterPropertyInteger('LegionellenIntervallTage', 7);
$this->RegisterPropertyInteger('LegionellenHaltezeit', 0);
$this->RegisterPropertyInteger('LegionellenMaximaldauer', 86400);
$this->RegisterPropertyInteger('NachtstartStunde', 22);
$this->RegisterPropertyInteger('NachtendeStunde', 7);
$this->RegisterPropertyInteger('LegionellenMinimalintervallTage', 4);
$this->RegisterPropertyInteger('LegionellenMaximalintervallTage', 7);
$this->RegisterPropertyBoolean('DiagnosevariablenAnzeigen', false);
$this->RegisterVariableFloat('Boilertemperatur', 'Boilertemperatur', '~Temperature', 100);
@@ -73,31 +70,25 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->EnableAction('Maximaltemperatur');
$this->EnableAction('Legionellentemperatur');
$this->RegisterVariableBoolean('TemperaturGueltig', 'Temperatur gueltig', '~Switch', 200);
$this->RegisterVariableBoolean('NachladenAktiv', 'Nachladen aktiv', '~Switch', 210);
$this->RegisterVariableBoolean(
'LegionellenbetriebAktiv',
'Legionellenbetrieb aktiv',
'~Switch',
220
);
$this->RegisterVariableInteger('LegioCounter', 'Zeit seit Legionellenabschluss', '', 230);
$this->RegisterVariableBoolean('Idle', 'Idle', '~Switch', 240);
$this->RegisterVariableInteger('IdleCounter', 'Idle Counter', '', 250);
$this->RegisterAttributeBoolean('InitialwerteGesetzt', false);
$this->RegisterAttributeInteger('RegistrierteFuehlerID', 0);
$this->RegisterAttributeInteger('LetzteBerechnung', 0);
$this->RegisterAttributeInteger('LetzteVorgabeZeit', 0);
$this->RegisterAttributeInteger('LetzteManagerID', 0);
$this->RegisterAttributeInteger('LetzterLegionellenabschluss', 0);
$this->RegisterAttributeInteger('LegionellenStart', 0);
$this->RegisterAttributeInteger('LegionellenSeitZiel', 0);
$this->RegisterAttributeFloat('Glaettungswert', 0.0);
$this->RegisterAttributeBoolean('GlaettungInitialisiert', false);
$this->RegisterAttributeString('Leistungsangebot', '[]');
$this->RegisterAttributeString('Schaltfehler', '');
$this->RegisterAttributeString('Legionellenfehler', '');
$this->RegisterAttributeBoolean('ZustandSollwertGueltig', false);
$this->RegisterAttributeBoolean('ZustandVerfuegbar', false);
$this->RegisterAttributeBoolean('ZustandAenderungMoeglich', false);
$this->RegisterAttributeBoolean('ZustandTemperaturGueltig', false);
$this->RegisterAttributeBoolean('ZustandNachladenAktiv', false);
$this->RegisterAttributeBoolean('ZustandLegionellenbetriebAktiv', false);
$this->RegisterAttributeInteger('ZustandLegioCounter', 0);
$this->RegisterAttributeBoolean('ZustandIdle', true);
$this->RegisterAttributeInteger('ZustandIdleCounter', 0);
$this->RegisterTimer(
'Regelzyklus',
@@ -121,7 +112,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
parent::ApplyChanges();
$this->initialisiereTemperaturen();
$this->aktualisiereSichtbarkeit();
$this->aktualisiereVariablen();
try {
$this->pruefeKonfiguration();
@@ -129,8 +120,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->SetTimerInterval('Regelzyklus', 0);
$this->SetTimerInterval('Meldezyklus', 0);
$this->SetTimerInterval('RueckmeldungVerzoegert', 0);
$this->SetValue('Verfuegbar', false);
$this->SetValue('AenderungMoeglich', false);
$this->setzeZustand('Verfuegbar', false);
$this->setzeZustand('AenderungMoeglich', false);
$this->SetStatus(self::STATUS_KONFIGURATION_UNGUELTIG);
$this->protokolliere('Konfiguration', $fehler->getMessage());
return;
@@ -191,9 +182,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->ManagerdatenEmpfangen($daten);
return;
case 'LogStatus':
$this->protokolliereStatus(true);
return;
}
throw new InvalidArgumentException('Unbekannte Aktion: ' . $ident);
@@ -222,7 +210,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->WriteAttributeInteger('LetzteManagerID', $managerID);
$this->WriteAttributeInteger('LetzteVorgabeZeit', time());
$this->SetValue('Sollleistung', $sollleistung);
$this->SetValue('SollwertGueltig', true);
$this->setzeZustand('SollwertGueltig', true);
$this->regelzyklus(false);
// Verhindert eine synchrone Manager-Verbraucher-Endlosschleife.
@@ -240,24 +228,24 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
[$angebot, $aenderungMoeglich, $verfuegbar, $zwangsleistung] =
$this->bestimmeLeistungsangebot($temperaturGueltig, $jetzt);
$this->WriteAttributeString('Leistungsangebot', json_encode($angebot, JSON_THROW_ON_ERROR));
$this->SetValue('Verfuegbar', $verfuegbar);
$this->SetValue('AenderungMoeglich', $aenderungMoeglich);
$this->setzeZustand('Verfuegbar', $verfuegbar);
$this->setzeZustand('AenderungMoeglich', $aenderungMoeglich);
$letzteVorgabe = $this->ReadAttributeInteger('LetzteVorgabeZeit');
if ($letzteVorgabe <= 0
|| $jetzt - $letzteVorgabe > $this->ReadPropertyInteger('VorgabeTimeout')
) {
$this->SetValue('SollwertGueltig', false);
$this->setzeZustand('SollwertGueltig', false);
}
$ziel = 0;
if ($verfuegbar) {
if ($zwangsleistung !== null) {
$ziel = $zwangsleistung;
} elseif ((bool) $this->GetValue('SollwertGueltig')) {
} elseif ((bool) $this->leseZustand('SollwertGueltig')) {
$ziel = (int) $this->GetValue('Sollleistung');
if (!in_array($ziel, $angebot, true)) {
$this->SetValue('SollwertGueltig', false);
$this->setzeZustand('SollwertGueltig', false);
$ziel = 0;
}
}
@@ -271,8 +259,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
}
} catch (Throwable $fehler) {
$this->WriteAttributeString('Schaltfehler', $fehler->getMessage());
$this->SetValue('Verfuegbar', false);
$this->SetValue('AenderungMoeglich', false);
$this->setzeZustand('Verfuegbar', false);
$this->setzeZustand('AenderungMoeglich', false);
$this->SetValue('Stoerung', true);
$this->SetValue('Stoertext', $fehler->getMessage());
$this->SetStatus(self::STATUS_SCHALTFEHLER);
@@ -284,18 +272,18 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
{
$fuehlerID = $this->ReadPropertyInteger('Boilerfuehler_PT1');
if ($fuehlerID <= 0 || !IPS_VariableExists($fuehlerID)) {
$this->SetValue('TemperaturGueltig', false);
$this->setzeZustand('TemperaturGueltig', false);
return false;
}
$variable = IPS_GetVariable($fuehlerID);
if (time() - (int) $variable['VariableUpdated'] > $this->ReadPropertyInteger('TemperaturMaxAlter')) {
$this->SetValue('TemperaturGueltig', false);
$this->setzeZustand('TemperaturGueltig', false);
return false;
}
$rohwert = GetValue($fuehlerID);
if (!is_int($rohwert) && !is_float($rohwert)) {
$this->SetValue('TemperaturGueltig', false);
$this->setzeZustand('TemperaturGueltig', false);
return false;
}
@@ -318,7 +306,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
}
$this->SetValue('Boilertemperatur', $temperatur);
$this->SetValue('TemperaturGueltig', true);
$this->setzeZustand('TemperaturGueltig', true);
return true;
}
@@ -330,7 +318,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
{
$stufen = WarmwasserRegler::dekodiereLeistungsstufen($this->ReadPropertyString('LeistungsStufen'));
if (!(bool) $this->GetValue('Aktiv') || !$temperaturGueltig || $stufen === []) {
$this->SetValue('NachladenAktiv', false);
$this->setzeZustand('NachladenAktiv', false);
return [[], false, false, 0];
}
@@ -339,16 +327,25 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$temperatur = (float) $this->GetValue('Boilertemperatur');
$minimum = (float) $this->GetValue('Mindesttemperatur');
$maximum = (float) $this->GetValue('Maximaltemperatur');
[$minimum, $maximum] = WarmwasserRegler::legionellenTemperaturgrenzen(
$this->ReadPropertyBoolean('LegionellenfunktionAktiv'),
max(0, $jetzt - $this->ReadAttributeInteger('LetzterLegionellenabschluss')),
$this->ReadPropertyInteger('LegionellenMinimalintervallTage'),
$this->ReadPropertyInteger('LegionellenMaximalintervallTage'),
$minimum,
$maximum,
(float) $this->GetValue('Legionellentemperatur')
);
$hysterese = $this->ReadPropertyFloat('Hysterese');
$aktuelleLeistung = (int) round((float) $this->GetValue('Istleistung'));
$nachladen = (bool) $this->GetValue('NachladenAktiv');
$nachladen = (bool) $this->leseZustand('NachladenAktiv');
if ($temperatur < $minimum) {
$nachladen = true;
} elseif ($temperatur >= $minimum + $hysterese) {
$nachladen = false;
}
$this->SetValue('NachladenAktiv', $nachladen);
$this->setzeZustand('NachladenAktiv', $nachladen);
$zeitplanErfordertHeizen = false;
$naechster = WarmwasserRegler::naechsterZeitplaneintrag(
@@ -365,7 +362,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
);
}
if ((bool) $this->GetValue('LegionellenbetriebAktiv') || $nachladen || $zeitplanErfordertHeizen) {
if ($nachladen || $zeitplanErfordertHeizen) {
return [[$maximalleistung], false, true, $maximalleistung];
}
if ($temperatur >= $maximum) {
@@ -380,54 +377,21 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
private function aktualisiereLegionellenstatus(bool $temperaturGueltig, int $jetzt): void
{
$aktiviert = $this->ReadPropertyBoolean('LegionellenfunktionAktiv');
$letzterAbschluss = $this->ReadAttributeInteger('LetzterLegionellenabschluss');
$this->SetValue('LegioCounter', max(0, $jetzt - $letzterAbschluss));
$sekundenSeitAbschluss = max(0, $jetzt - $letzterAbschluss);
if (!$this->ReadPropertyBoolean('LegionellenfunktionAktiv')) {
$this->SetValue('LegionellenbetriebAktiv', false);
$this->WriteAttributeInteger('LegionellenStart', 0);
$this->WriteAttributeInteger('LegionellenSeitZiel', 0);
$this->WriteAttributeString('Legionellenfehler', '');
return;
}
$aktiv = (bool) $this->GetValue('LegionellenbetriebAktiv');
$faellig = $jetzt - $letzterAbschluss >= $this->ReadPropertyInteger('LegionellenIntervallTage') * 86400;
if (!$aktiv && $faellig && $this->istNachtstunde((int) date('G', $jetzt))) {
$aktiv = true;
$this->WriteAttributeInteger('LegionellenStart', $jetzt);
$this->WriteAttributeInteger('LegionellenSeitZiel', 0);
}
if ($aktiv && $jetzt - $this->ReadAttributeInteger('LegionellenStart')
> $this->ReadPropertyInteger('LegionellenMaximaldauer')
) {
$aktiv = false;
$this->WriteAttributeInteger('LetzterLegionellenabschluss', $jetzt);
$this->WriteAttributeString(
'Legionellenfehler',
'Legionellenprogramm innerhalb der Maximaldauer nicht abgeschlossen.'
);
}
if ($aktiv && $temperaturGueltig
if ($aktiviert && $temperaturGueltig
&& (float) $this->GetValue('Boilertemperatur') >= (float) $this->GetValue('Legionellentemperatur')
) {
$seitZiel = $this->ReadAttributeInteger('LegionellenSeitZiel');
if ($seitZiel <= 0) {
$seitZiel = $jetzt;
$this->WriteAttributeInteger('LegionellenSeitZiel', $seitZiel);
}
if ($jetzt - $seitZiel >= $this->ReadPropertyInteger('LegionellenHaltezeit')) {
$aktiv = false;
$this->WriteAttributeInteger('LetzterLegionellenabschluss', $jetzt);
$this->WriteAttributeInteger('LegionellenStart', 0);
$this->WriteAttributeInteger('LegionellenSeitZiel', 0);
$this->WriteAttributeString('Legionellenfehler', '');
}
$this->WriteAttributeInteger('LetzterLegionellenabschluss', $jetzt);
$sekundenSeitAbschluss = 0;
}
$this->SetValue('LegionellenbetriebAktiv', $aktiv);
$fruehestensFaellig = $aktiviert
&& $sekundenSeitAbschluss >= $this->ReadPropertyInteger('LegionellenMinimalintervallTage') * 86400;
$this->setzeZustand('LegioCounter', $sekundenSeitAbschluss);
$this->setzeZustand('LegionellenbetriebAktiv', $fruehestensFaellig);
}
private function schalteLeistung(int $zielLeistung): void
@@ -468,7 +432,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->WriteAttributeString('Schaltfehler', '');
$this->SetValue('Istleistung', (float) $zielLeistung);
$this->SetValue('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
$this->setzeZustand('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
$this->SetValue('AktiveStufe', $zielStufe);
$this->verarbeiteIdle(true);
$this->protokolliere('Leistungsstufe', ['Leistung_W' => $zielLeistung, 'Stufe' => $zielStufe]);
@@ -494,14 +458,14 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
private function verarbeiteIdle(bool $geaendert): void
{
$counter = (int) $this->GetValue('IdleCounter');
$counter = (int) $this->leseZustand('IdleCounter');
if ($geaendert) {
$counter = $this->ReadPropertyInteger('IdleCounterMax');
} elseif ($counter > 0) {
--$counter;
}
$this->SetValue('IdleCounter', $counter);
$this->SetValue('Idle', $counter === 0);
$this->setzeZustand('IdleCounter', $counter);
$this->setzeZustand('Idle', $counter === 0);
}
private function aktualisiereEnergie(int $jetzt): void
@@ -537,10 +501,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
if ($this->ReadAttributeString('Schaltfehler') !== '') {
$stoerungen[] = $this->ReadAttributeString('Schaltfehler');
}
if ($this->ReadAttributeString('Legionellenfehler') !== '') {
$stoerungen[] = $this->ReadAttributeString('Legionellenfehler');
}
$this->SetValue('Stoerung', $stoerungen !== []);
$this->SetValue('Stoertext', implode("\n", array_values(array_unique($stoerungen))));
if ($this->ReadAttributeString('Schaltfehler') !== '') {
@@ -572,9 +532,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
/** @return array<string, mixed> */
private function baueVerbraucherdaten(int $managerID): array
{
$temperaturGueltig = (bool) $this->GetValue('TemperaturGueltig');
$temperaturGueltig = (bool) $this->leseZustand('TemperaturGueltig');
$schaltfehler = $this->ReadAttributeString('Schaltfehler');
$legionellenfehler = $this->ReadAttributeString('Legionellenfehler');
$uebertemperatur = $temperaturGueltig
&& (float) $this->GetValue('Boilertemperatur')
> max(
@@ -592,15 +551,15 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
'PrioritaetPV' => $this->ReadPropertyInteger('PrioritaetPV'),
'PrioritaetPeak' => $this->ReadPropertyInteger('PrioritaetPeak'),
'Leistungswerte_W' => $this->leseLeistungsangebot(),
'AenderungMoeglich' => (bool) $this->GetValue('AenderungMoeglich'),
'Verfuegbar' => (bool) $this->GetValue('Verfuegbar'),
'AenderungMoeglich' => (bool) $this->leseZustand('AenderungMoeglich'),
'Verfuegbar' => (bool) $this->leseZustand('Verfuegbar'),
'Istleistung_W' => (float) $this->GetValue('Istleistung'),
'Leistungsquelle' => Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET,
'Zustand' => [
[
'Kennung' => 'Sollleistung_W',
'Art' => 'Sollwert',
'Wert' => (bool) $this->GetValue('SollwertGueltig')
'Wert' => (bool) $this->leseZustand('SollwertGueltig')
? (int) $this->GetValue('Sollleistung')
: null,
'Einheit' => 'W',
@@ -626,13 +585,13 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
[
'Kennung' => 'NachladenAktiv',
'Art' => 'Status',
'Wert' => (bool) $this->GetValue('NachladenAktiv'),
'Wert' => (bool) $this->leseZustand('NachladenAktiv'),
'Einheit' => '',
],
[
'Kennung' => 'LegionellenbetriebAktiv',
'Art' => 'Status',
'Wert' => (bool) $this->GetValue('LegionellenbetriebAktiv'),
'Wert' => (bool) $this->leseZustand('LegionellenbetriebAktiv'),
'Einheit' => '',
],
[
@@ -656,13 +615,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
'Einheit' => '',
'Text' => $schaltfehler,
],
[
'Kennung' => 'Legionellenfehler',
'Art' => 'Stoerung',
'Wert' => $legionellenfehler !== '',
'Einheit' => '',
'Text' => $legionellenfehler,
],
],
];
}
@@ -709,25 +661,23 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
}
foreach ([
'Meldeintervall', 'VorgabeTimeout', 'Interval', 'IdleCounterMax', 'TemperaturMaxAlter',
'ZeitKonstante', 'Boilervolumen', 'LegionellenIntervallTage', 'LegionellenMaximaldauer',
'ZeitKonstante', 'Boilervolumen', 'LegionellenMinimalintervallTage',
'LegionellenMaximalintervallTage',
] as $property) {
if ($this->ReadPropertyInteger($property) <= 0) {
throw new InvalidArgumentException($property . ' muss groesser als 0 sein.');
}
}
if ($this->ReadPropertyInteger('LegionellenHaltezeit') < 0) {
throw new InvalidArgumentException('LegionellenHaltezeit darf nicht negativ sein.');
if ($this->ReadPropertyInteger('LegionellenMinimalintervallTage')
> $this->ReadPropertyInteger('LegionellenMaximalintervallTage')
) {
throw new InvalidArgumentException(
'Das Legionellen-Minimalintervall darf nicht groesser als das Maximalintervall sein.'
);
}
if ($this->ReadPropertyFloat('Hysterese') <= 0) {
throw new InvalidArgumentException('Hysterese muss groesser als 0 sein.');
}
foreach (['NachtstartStunde', 'NachtendeStunde'] as $property) {
$stunde = $this->ReadPropertyInteger($property);
if ($stunde < 0 || $stunde > 23) {
throw new InvalidArgumentException($property . ' muss zwischen 0 und 23 liegen.');
}
}
$minimum = (float) $this->GetValue('Mindesttemperatur');
$maximum = (float) $this->GetValue('Maximaltemperatur');
$legionellen = (float) $this->GetValue('Legionellentemperatur');
@@ -786,8 +736,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->SetValue('Mindesttemperatur', 45.0);
$this->SetValue('Maximaltemperatur', 60.0);
$this->SetValue('Legionellentemperatur', 65.0);
$this->SetValue('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
$this->SetValue('Idle', true);
$this->setzeZustand('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
$this->setzeZustand('Idle', true);
$this->WriteAttributeBoolean('InitialwerteGesetzt', true);
}
@@ -823,11 +773,33 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->regelzyklus(true);
}
private function aktualisiereSichtbarkeit(): void
private function aktualisiereVariablen(): void
{
$diagnose = $this->ReadPropertyBoolean('DiagnosevariablenAnzeigen');
foreach (self::DIAGNOSE_VARIABLEN as $ident) {
IPS_SetHidden($this->GetIDForIdent($ident), !$diagnose);
if ($this->ReadPropertyBoolean('DiagnosevariablenAnzeigen')) {
$this->registriereVerbraucherDiagnose();
$this->RegisterVariableBoolean('TemperaturGueltig', 'Temperatur gueltig', '~Switch', 200);
$this->RegisterVariableBoolean('NachladenAktiv', 'Nachladen aktiv', '~Switch', 210);
$this->RegisterVariableBoolean(
'LegionellenbetriebAktiv',
'Legionellenbetrieb aktiv',
'~Switch',
220
);
$this->RegisterVariableInteger('LegioCounter', 'Zeit seit Legionellenabschluss', '', 230);
$this->RegisterVariableBoolean('Idle', 'Idle', '~Switch', 240);
$this->RegisterVariableInteger('IdleCounter', 'Idle Counter', '', 250);
$this->setzeZustand('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
foreach (array_slice(self::DIAGNOSE_VARIABLEN, 1) as $ident) {
$this->setzeZustand($ident, $this->leseZustand($ident));
}
} else {
foreach (self::DIAGNOSE_VARIABLEN as $ident) {
$variablenID = @IPS_GetObjectIDByIdent($ident, $this->InstanceID);
if (is_int($variablenID) && $variablenID > 0 && IPS_VariableExists($variablenID)) {
$this->UnregisterVariable($ident);
}
}
}
$einstellungen = $this->ReadPropertyBoolean('EinstellungenInVisu');
@@ -841,6 +813,66 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
}
}
/** @param bool|int $wert */
private function setzeZustand(string $ident, $wert): void
{
$booleanAttribute = [
'SollwertGueltig' => 'ZustandSollwertGueltig',
'Verfuegbar' => 'ZustandVerfuegbar',
'AenderungMoeglich' => 'ZustandAenderungMoeglich',
'TemperaturGueltig' => 'ZustandTemperaturGueltig',
'NachladenAktiv' => 'ZustandNachladenAktiv',
'LegionellenbetriebAktiv' => 'ZustandLegionellenbetriebAktiv',
'Idle' => 'ZustandIdle',
];
$integerAttribute = [
'LegioCounter' => 'ZustandLegioCounter',
'IdleCounter' => 'ZustandIdleCounter',
];
if (isset($booleanAttribute[$ident])) {
$wert = (bool) $wert;
$this->WriteAttributeBoolean($booleanAttribute[$ident], $wert);
} elseif (isset($integerAttribute[$ident])) {
$wert = (int) $wert;
$this->WriteAttributeInteger($integerAttribute[$ident], $wert);
} elseif ($ident !== 'Leistungsquelle') {
throw new LogicException('Unbekannter interner Zustand: ' . $ident);
}
$variablenID = @IPS_GetObjectIDByIdent($ident, $this->InstanceID);
if (is_int($variablenID) && $variablenID > 0 && IPS_VariableExists($variablenID)) {
SetValue($variablenID, $wert);
}
}
/** @return bool|int */
private function leseZustand(string $ident)
{
$booleanAttribute = [
'SollwertGueltig' => 'ZustandSollwertGueltig',
'Verfuegbar' => 'ZustandVerfuegbar',
'AenderungMoeglich' => 'ZustandAenderungMoeglich',
'TemperaturGueltig' => 'ZustandTemperaturGueltig',
'NachladenAktiv' => 'ZustandNachladenAktiv',
'LegionellenbetriebAktiv' => 'ZustandLegionellenbetriebAktiv',
'Idle' => 'ZustandIdle',
];
$integerAttribute = [
'LegioCounter' => 'ZustandLegioCounter',
'IdleCounter' => 'ZustandIdleCounter',
];
if (isset($booleanAttribute[$ident])) {
return $this->ReadAttributeBoolean($booleanAttribute[$ident]);
}
if (isset($integerAttribute[$ident])) {
return $this->ReadAttributeInteger($integerAttribute[$ident]);
}
throw new LogicException('Unbekannter interner Zustand: ' . $ident);
}
/** @return list<int> */
private function leseLeistungsangebot(): array
{
@@ -852,37 +884,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
return array_values(array_map('intval', $angebot));
}
private function istNachtstunde(int $stunde): bool
{
$start = $this->ReadPropertyInteger('NachtstartStunde');
$ende = $this->ReadPropertyInteger('NachtendeStunde');
if ($start === $ende) {
return true;
}
if ($start < $ende) {
return $stunde >= $start && $stunde < $ende;
}
return $stunde >= $start || $stunde < $ende;
}
private function protokolliereStatus(bool $erzwingen): void
{
if (!$erzwingen && !$this->ReadPropertyBoolean('LoggingEin')) {
return;
}
$this->SendDebug('Status', json_encode([
'Aktiv' => (bool) $this->GetValue('Aktiv'),
'Boilertemperatur_C' => (float) $this->GetValue('Boilertemperatur'),
'TemperaturGueltig' => (bool) $this->GetValue('TemperaturGueltig'),
'Leistungsangebot_W' => $this->leseLeistungsangebot(),
'Sollleistung_W' => (int) $this->GetValue('Sollleistung'),
'Istleistung_W' => (float) $this->GetValue('Istleistung'),
'AktiveStufe' => (int) $this->GetValue('AktiveStufe'),
'Stoertext' => (string) $this->GetValue('Stoertext'),
], JSON_THROW_ON_ERROR), 0);
}
/** @param mixed $daten */
private function protokolliere(string $bezeichnung, $daten): void
{