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": [ "elements": [
{
"type": "Label",
"caption": "Mehrstufiger Warmwassererwaermer nach Enelix-2-Vertrag 3.0"
},
{ {
"type": "ExpansionPanel", "type": "ExpansionPanel",
"caption": "Manager und Zeitverhalten", "caption": "Manager und Zeitverhalten",
@@ -12,13 +8,13 @@
{ {
"type": "NumberSpinner", "type": "NumberSpinner",
"name": "PrioritaetPV", "name": "PrioritaetPV",
"caption": "Prioritaet PV", "caption": "Priorität PV",
"minimum": 0 "minimum": 0
}, },
{ {
"type": "NumberSpinner", "type": "NumberSpinner",
"name": "PrioritaetPeak", "name": "PrioritaetPeak",
"caption": "Prioritaet Peak", "caption": "Priorität Peak",
"minimum": 0 "minimum": 0
}, },
{ {
@@ -52,7 +48,7 @@
}, },
{ {
"type": "ExpansionPanel", "type": "ExpansionPanel",
"caption": "Leistungsstufen", "caption": "Speichereinstellungen",
"expanded": true, "expanded": true,
"items": [ "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", "type": "ExpansionPanel",
"caption": "Temperatur und Speicher", "caption": "Erweiterte Speichereinstellungen",
"expanded": true,
"items": [ "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", "type": "NumberSpinner",
"name": "Boilervolumen", "name": "Boilervolumen",
@@ -141,21 +136,10 @@
"minimum": 0.1, "minimum": 0.1,
"digits": 1 "digits": 1
}, },
{
"type": "CheckBox",
"name": "EinstellungenInVisu",
"caption": "Temperatursollwerte in der Visualisierung anzeigen und bedienen"
}
]
},
{
"type": "ExpansionPanel",
"caption": "Zeitplan",
"items": [
{ {
"type": "List", "type": "List",
"name": "Zeitplan", "name": "Zeitplan",
"caption": "Naechste Solltemperatur vorausberechnen", "caption": "Zeitplan für Solltemperaturen",
"add": true, "add": true,
"delete": true, "delete": true,
"sortable": true, "sortable": true,
@@ -179,7 +163,7 @@
"minimum": 0, "minimum": 0,
"maximum": 100, "maximum": 100,
"digits": 1, "digits": 1,
"suffix": " C" "suffix": " °C"
} }
} }
] ]
@@ -188,60 +172,36 @@
}, },
{ {
"type": "ExpansionPanel", "type": "ExpansionPanel",
"caption": "Legionellenfunktion", "caption": "Erweiterte sonstige Einstellungen",
"items": [ "items": [
{
"type": "NumberSpinner",
"name": "TemperaturMaxAlter",
"caption": "Maximales Messwertalter",
"suffix": " s",
"minimum": 1
},
{ {
"type": "CheckBox", "type": "CheckBox",
"name": "LegionellenfunktionAktiv", "name": "BoilertemperaturGlaetten",
"caption": "Legionellenfunktion aktiv" "caption": "Boilertemperatur mit PT1 glätten"
}, },
{ {
"type": "NumberSpinner", "type": "NumberSpinner",
"name": "LegionellenIntervallTage", "name": "ZeitKonstante",
"caption": "Intervall", "caption": "PT1-Zeitkonstante",
"suffix": " Tage",
"minimum": 1
},
{
"type": "NumberSpinner",
"name": "LegionellenHaltezeit",
"caption": "Haltezeit auf Legionellentemperatur",
"suffix": " s",
"minimum": 0
},
{
"type": "NumberSpinner",
"name": "LegionellenMaximaldauer",
"caption": "Maximaldauer",
"suffix": " s", "suffix": " s",
"minimum": 1 "minimum": 1
}, },
{ {
"type": "NumberSpinner", "type": "CheckBox",
"name": "NachtstartStunde", "name": "EinstellungenInVisu",
"caption": "Nachtbeginn", "caption": "Temperatursollwerte in der Visualisierung anzeigen und bedienen"
"suffix": " Uhr",
"minimum": 0,
"maximum": 23
}, },
{
"type": "NumberSpinner",
"name": "NachtendeStunde",
"caption": "Nachtende",
"suffix": " Uhr",
"minimum": 0,
"maximum": 23
}
]
},
{
"type": "ExpansionPanel",
"caption": "Diagnose",
"items": [
{ {
"type": "CheckBox", "type": "CheckBox",
"name": "DiagnosevariablenAnzeigen", "name": "DiagnosevariablenAnzeigen",
"caption": "Diagnosevariablen anzeigen" "caption": "Diagnosevariablen anlegen"
}, },
{ {
"type": "CheckBox", "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": [ "status": [
{ {
"code": 102, "code": 102,
@@ -277,7 +225,7 @@
{ {
"code": 202, "code": 202,
"icon": "error", "icon": "error",
"caption": "Konfiguration ungueltig" "caption": "Konfiguration ungültig"
}, },
{ {
"code": 203, "code": 203,
+154 -153
View File
@@ -55,11 +55,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->RegisterPropertyInteger('TemperaturMaxAlter', 30); $this->RegisterPropertyInteger('TemperaturMaxAlter', 30);
$this->RegisterPropertyFloat('Hysterese', 5.0); $this->RegisterPropertyFloat('Hysterese', 5.0);
$this->RegisterPropertyBoolean('LegionellenfunktionAktiv', true); $this->RegisterPropertyBoolean('LegionellenfunktionAktiv', true);
$this->RegisterPropertyInteger('LegionellenIntervallTage', 7); $this->RegisterPropertyInteger('LegionellenMinimalintervallTage', 4);
$this->RegisterPropertyInteger('LegionellenHaltezeit', 0); $this->RegisterPropertyInteger('LegionellenMaximalintervallTage', 7);
$this->RegisterPropertyInteger('LegionellenMaximaldauer', 86400);
$this->RegisterPropertyInteger('NachtstartStunde', 22);
$this->RegisterPropertyInteger('NachtendeStunde', 7);
$this->RegisterPropertyBoolean('DiagnosevariablenAnzeigen', false); $this->RegisterPropertyBoolean('DiagnosevariablenAnzeigen', false);
$this->RegisterVariableFloat('Boilertemperatur', 'Boilertemperatur', '~Temperature', 100); $this->RegisterVariableFloat('Boilertemperatur', 'Boilertemperatur', '~Temperature', 100);
@@ -73,31 +70,25 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->EnableAction('Maximaltemperatur'); $this->EnableAction('Maximaltemperatur');
$this->EnableAction('Legionellentemperatur'); $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->RegisterAttributeBoolean('InitialwerteGesetzt', false);
$this->RegisterAttributeInteger('RegistrierteFuehlerID', 0); $this->RegisterAttributeInteger('RegistrierteFuehlerID', 0);
$this->RegisterAttributeInteger('LetzteBerechnung', 0); $this->RegisterAttributeInteger('LetzteBerechnung', 0);
$this->RegisterAttributeInteger('LetzteVorgabeZeit', 0); $this->RegisterAttributeInteger('LetzteVorgabeZeit', 0);
$this->RegisterAttributeInteger('LetzteManagerID', 0); $this->RegisterAttributeInteger('LetzteManagerID', 0);
$this->RegisterAttributeInteger('LetzterLegionellenabschluss', 0); $this->RegisterAttributeInteger('LetzterLegionellenabschluss', 0);
$this->RegisterAttributeInteger('LegionellenStart', 0);
$this->RegisterAttributeInteger('LegionellenSeitZiel', 0);
$this->RegisterAttributeFloat('Glaettungswert', 0.0); $this->RegisterAttributeFloat('Glaettungswert', 0.0);
$this->RegisterAttributeBoolean('GlaettungInitialisiert', false); $this->RegisterAttributeBoolean('GlaettungInitialisiert', false);
$this->RegisterAttributeString('Leistungsangebot', '[]'); $this->RegisterAttributeString('Leistungsangebot', '[]');
$this->RegisterAttributeString('Schaltfehler', ''); $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( $this->RegisterTimer(
'Regelzyklus', 'Regelzyklus',
@@ -121,7 +112,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
parent::ApplyChanges(); parent::ApplyChanges();
$this->initialisiereTemperaturen(); $this->initialisiereTemperaturen();
$this->aktualisiereSichtbarkeit(); $this->aktualisiereVariablen();
try { try {
$this->pruefeKonfiguration(); $this->pruefeKonfiguration();
@@ -129,8 +120,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->SetTimerInterval('Regelzyklus', 0); $this->SetTimerInterval('Regelzyklus', 0);
$this->SetTimerInterval('Meldezyklus', 0); $this->SetTimerInterval('Meldezyklus', 0);
$this->SetTimerInterval('RueckmeldungVerzoegert', 0); $this->SetTimerInterval('RueckmeldungVerzoegert', 0);
$this->SetValue('Verfuegbar', false); $this->setzeZustand('Verfuegbar', false);
$this->SetValue('AenderungMoeglich', false); $this->setzeZustand('AenderungMoeglich', false);
$this->SetStatus(self::STATUS_KONFIGURATION_UNGUELTIG); $this->SetStatus(self::STATUS_KONFIGURATION_UNGUELTIG);
$this->protokolliere('Konfiguration', $fehler->getMessage()); $this->protokolliere('Konfiguration', $fehler->getMessage());
return; return;
@@ -191,9 +182,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->ManagerdatenEmpfangen($daten); $this->ManagerdatenEmpfangen($daten);
return; return;
case 'LogStatus':
$this->protokolliereStatus(true);
return;
} }
throw new InvalidArgumentException('Unbekannte Aktion: ' . $ident); throw new InvalidArgumentException('Unbekannte Aktion: ' . $ident);
@@ -222,7 +210,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->WriteAttributeInteger('LetzteManagerID', $managerID); $this->WriteAttributeInteger('LetzteManagerID', $managerID);
$this->WriteAttributeInteger('LetzteVorgabeZeit', time()); $this->WriteAttributeInteger('LetzteVorgabeZeit', time());
$this->SetValue('Sollleistung', $sollleistung); $this->SetValue('Sollleistung', $sollleistung);
$this->SetValue('SollwertGueltig', true); $this->setzeZustand('SollwertGueltig', true);
$this->regelzyklus(false); $this->regelzyklus(false);
// Verhindert eine synchrone Manager-Verbraucher-Endlosschleife. // Verhindert eine synchrone Manager-Verbraucher-Endlosschleife.
@@ -240,24 +228,24 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
[$angebot, $aenderungMoeglich, $verfuegbar, $zwangsleistung] = [$angebot, $aenderungMoeglich, $verfuegbar, $zwangsleistung] =
$this->bestimmeLeistungsangebot($temperaturGueltig, $jetzt); $this->bestimmeLeistungsangebot($temperaturGueltig, $jetzt);
$this->WriteAttributeString('Leistungsangebot', json_encode($angebot, JSON_THROW_ON_ERROR)); $this->WriteAttributeString('Leistungsangebot', json_encode($angebot, JSON_THROW_ON_ERROR));
$this->SetValue('Verfuegbar', $verfuegbar); $this->setzeZustand('Verfuegbar', $verfuegbar);
$this->SetValue('AenderungMoeglich', $aenderungMoeglich); $this->setzeZustand('AenderungMoeglich', $aenderungMoeglich);
$letzteVorgabe = $this->ReadAttributeInteger('LetzteVorgabeZeit'); $letzteVorgabe = $this->ReadAttributeInteger('LetzteVorgabeZeit');
if ($letzteVorgabe <= 0 if ($letzteVorgabe <= 0
|| $jetzt - $letzteVorgabe > $this->ReadPropertyInteger('VorgabeTimeout') || $jetzt - $letzteVorgabe > $this->ReadPropertyInteger('VorgabeTimeout')
) { ) {
$this->SetValue('SollwertGueltig', false); $this->setzeZustand('SollwertGueltig', false);
} }
$ziel = 0; $ziel = 0;
if ($verfuegbar) { if ($verfuegbar) {
if ($zwangsleistung !== null) { if ($zwangsleistung !== null) {
$ziel = $zwangsleistung; $ziel = $zwangsleistung;
} elseif ((bool) $this->GetValue('SollwertGueltig')) { } elseif ((bool) $this->leseZustand('SollwertGueltig')) {
$ziel = (int) $this->GetValue('Sollleistung'); $ziel = (int) $this->GetValue('Sollleistung');
if (!in_array($ziel, $angebot, true)) { if (!in_array($ziel, $angebot, true)) {
$this->SetValue('SollwertGueltig', false); $this->setzeZustand('SollwertGueltig', false);
$ziel = 0; $ziel = 0;
} }
} }
@@ -271,8 +259,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
} }
} catch (Throwable $fehler) { } catch (Throwable $fehler) {
$this->WriteAttributeString('Schaltfehler', $fehler->getMessage()); $this->WriteAttributeString('Schaltfehler', $fehler->getMessage());
$this->SetValue('Verfuegbar', false); $this->setzeZustand('Verfuegbar', false);
$this->SetValue('AenderungMoeglich', false); $this->setzeZustand('AenderungMoeglich', false);
$this->SetValue('Stoerung', true); $this->SetValue('Stoerung', true);
$this->SetValue('Stoertext', $fehler->getMessage()); $this->SetValue('Stoertext', $fehler->getMessage());
$this->SetStatus(self::STATUS_SCHALTFEHLER); $this->SetStatus(self::STATUS_SCHALTFEHLER);
@@ -284,18 +272,18 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
{ {
$fuehlerID = $this->ReadPropertyInteger('Boilerfuehler_PT1'); $fuehlerID = $this->ReadPropertyInteger('Boilerfuehler_PT1');
if ($fuehlerID <= 0 || !IPS_VariableExists($fuehlerID)) { if ($fuehlerID <= 0 || !IPS_VariableExists($fuehlerID)) {
$this->SetValue('TemperaturGueltig', false); $this->setzeZustand('TemperaturGueltig', false);
return false; return false;
} }
$variable = IPS_GetVariable($fuehlerID); $variable = IPS_GetVariable($fuehlerID);
if (time() - (int) $variable['VariableUpdated'] > $this->ReadPropertyInteger('TemperaturMaxAlter')) { if (time() - (int) $variable['VariableUpdated'] > $this->ReadPropertyInteger('TemperaturMaxAlter')) {
$this->SetValue('TemperaturGueltig', false); $this->setzeZustand('TemperaturGueltig', false);
return false; return false;
} }
$rohwert = GetValue($fuehlerID); $rohwert = GetValue($fuehlerID);
if (!is_int($rohwert) && !is_float($rohwert)) { if (!is_int($rohwert) && !is_float($rohwert)) {
$this->SetValue('TemperaturGueltig', false); $this->setzeZustand('TemperaturGueltig', false);
return false; return false;
} }
@@ -318,7 +306,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
} }
$this->SetValue('Boilertemperatur', $temperatur); $this->SetValue('Boilertemperatur', $temperatur);
$this->SetValue('TemperaturGueltig', true); $this->setzeZustand('TemperaturGueltig', true);
return true; return true;
} }
@@ -330,7 +318,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
{ {
$stufen = WarmwasserRegler::dekodiereLeistungsstufen($this->ReadPropertyString('LeistungsStufen')); $stufen = WarmwasserRegler::dekodiereLeistungsstufen($this->ReadPropertyString('LeistungsStufen'));
if (!(bool) $this->GetValue('Aktiv') || !$temperaturGueltig || $stufen === []) { if (!(bool) $this->GetValue('Aktiv') || !$temperaturGueltig || $stufen === []) {
$this->SetValue('NachladenAktiv', false); $this->setzeZustand('NachladenAktiv', false);
return [[], false, false, 0]; return [[], false, false, 0];
} }
@@ -339,16 +327,25 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$temperatur = (float) $this->GetValue('Boilertemperatur'); $temperatur = (float) $this->GetValue('Boilertemperatur');
$minimum = (float) $this->GetValue('Mindesttemperatur'); $minimum = (float) $this->GetValue('Mindesttemperatur');
$maximum = (float) $this->GetValue('Maximaltemperatur'); $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'); $hysterese = $this->ReadPropertyFloat('Hysterese');
$aktuelleLeistung = (int) round((float) $this->GetValue('Istleistung')); $aktuelleLeistung = (int) round((float) $this->GetValue('Istleistung'));
$nachladen = (bool) $this->GetValue('NachladenAktiv'); $nachladen = (bool) $this->leseZustand('NachladenAktiv');
if ($temperatur < $minimum) { if ($temperatur < $minimum) {
$nachladen = true; $nachladen = true;
} elseif ($temperatur >= $minimum + $hysterese) { } elseif ($temperatur >= $minimum + $hysterese) {
$nachladen = false; $nachladen = false;
} }
$this->SetValue('NachladenAktiv', $nachladen); $this->setzeZustand('NachladenAktiv', $nachladen);
$zeitplanErfordertHeizen = false; $zeitplanErfordertHeizen = false;
$naechster = WarmwasserRegler::naechsterZeitplaneintrag( $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]; return [[$maximalleistung], false, true, $maximalleistung];
} }
if ($temperatur >= $maximum) { if ($temperatur >= $maximum) {
@@ -380,54 +377,21 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
private function aktualisiereLegionellenstatus(bool $temperaturGueltig, int $jetzt): void private function aktualisiereLegionellenstatus(bool $temperaturGueltig, int $jetzt): void
{ {
$aktiviert = $this->ReadPropertyBoolean('LegionellenfunktionAktiv');
$letzterAbschluss = $this->ReadAttributeInteger('LetzterLegionellenabschluss'); $letzterAbschluss = $this->ReadAttributeInteger('LetzterLegionellenabschluss');
$this->SetValue('LegioCounter', max(0, $jetzt - $letzterAbschluss)); $sekundenSeitAbschluss = max(0, $jetzt - $letzterAbschluss);
if (!$this->ReadPropertyBoolean('LegionellenfunktionAktiv')) { if ($aktiviert && $temperaturGueltig
$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
&& (float) $this->GetValue('Boilertemperatur') >= (float) $this->GetValue('Legionellentemperatur') && (float) $this->GetValue('Boilertemperatur') >= (float) $this->GetValue('Legionellentemperatur')
) { ) {
$seitZiel = $this->ReadAttributeInteger('LegionellenSeitZiel'); $this->WriteAttributeInteger('LetzterLegionellenabschluss', $jetzt);
if ($seitZiel <= 0) { $sekundenSeitAbschluss = 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->SetValue('LegionellenbetriebAktiv', $aktiv); $fruehestensFaellig = $aktiviert
&& $sekundenSeitAbschluss >= $this->ReadPropertyInteger('LegionellenMinimalintervallTage') * 86400;
$this->setzeZustand('LegioCounter', $sekundenSeitAbschluss);
$this->setzeZustand('LegionellenbetriebAktiv', $fruehestensFaellig);
} }
private function schalteLeistung(int $zielLeistung): void private function schalteLeistung(int $zielLeistung): void
@@ -468,7 +432,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->WriteAttributeString('Schaltfehler', ''); $this->WriteAttributeString('Schaltfehler', '');
$this->SetValue('Istleistung', (float) $zielLeistung); $this->SetValue('Istleistung', (float) $zielLeistung);
$this->SetValue('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET); $this->setzeZustand('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
$this->SetValue('AktiveStufe', $zielStufe); $this->SetValue('AktiveStufe', $zielStufe);
$this->verarbeiteIdle(true); $this->verarbeiteIdle(true);
$this->protokolliere('Leistungsstufe', ['Leistung_W' => $zielLeistung, 'Stufe' => $zielStufe]); $this->protokolliere('Leistungsstufe', ['Leistung_W' => $zielLeistung, 'Stufe' => $zielStufe]);
@@ -494,14 +458,14 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
private function verarbeiteIdle(bool $geaendert): void private function verarbeiteIdle(bool $geaendert): void
{ {
$counter = (int) $this->GetValue('IdleCounter'); $counter = (int) $this->leseZustand('IdleCounter');
if ($geaendert) { if ($geaendert) {
$counter = $this->ReadPropertyInteger('IdleCounterMax'); $counter = $this->ReadPropertyInteger('IdleCounterMax');
} elseif ($counter > 0) { } elseif ($counter > 0) {
--$counter; --$counter;
} }
$this->SetValue('IdleCounter', $counter); $this->setzeZustand('IdleCounter', $counter);
$this->SetValue('Idle', $counter === 0); $this->setzeZustand('Idle', $counter === 0);
} }
private function aktualisiereEnergie(int $jetzt): void private function aktualisiereEnergie(int $jetzt): void
@@ -537,10 +501,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
if ($this->ReadAttributeString('Schaltfehler') !== '') { if ($this->ReadAttributeString('Schaltfehler') !== '') {
$stoerungen[] = $this->ReadAttributeString('Schaltfehler'); $stoerungen[] = $this->ReadAttributeString('Schaltfehler');
} }
if ($this->ReadAttributeString('Legionellenfehler') !== '') {
$stoerungen[] = $this->ReadAttributeString('Legionellenfehler');
}
$this->SetValue('Stoerung', $stoerungen !== []); $this->SetValue('Stoerung', $stoerungen !== []);
$this->SetValue('Stoertext', implode("\n", array_values(array_unique($stoerungen)))); $this->SetValue('Stoertext', implode("\n", array_values(array_unique($stoerungen))));
if ($this->ReadAttributeString('Schaltfehler') !== '') { if ($this->ReadAttributeString('Schaltfehler') !== '') {
@@ -572,9 +532,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
/** @return array<string, mixed> */ /** @return array<string, mixed> */
private function baueVerbraucherdaten(int $managerID): array private function baueVerbraucherdaten(int $managerID): array
{ {
$temperaturGueltig = (bool) $this->GetValue('TemperaturGueltig'); $temperaturGueltig = (bool) $this->leseZustand('TemperaturGueltig');
$schaltfehler = $this->ReadAttributeString('Schaltfehler'); $schaltfehler = $this->ReadAttributeString('Schaltfehler');
$legionellenfehler = $this->ReadAttributeString('Legionellenfehler');
$uebertemperatur = $temperaturGueltig $uebertemperatur = $temperaturGueltig
&& (float) $this->GetValue('Boilertemperatur') && (float) $this->GetValue('Boilertemperatur')
> max( > max(
@@ -592,15 +551,15 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
'PrioritaetPV' => $this->ReadPropertyInteger('PrioritaetPV'), 'PrioritaetPV' => $this->ReadPropertyInteger('PrioritaetPV'),
'PrioritaetPeak' => $this->ReadPropertyInteger('PrioritaetPeak'), 'PrioritaetPeak' => $this->ReadPropertyInteger('PrioritaetPeak'),
'Leistungswerte_W' => $this->leseLeistungsangebot(), 'Leistungswerte_W' => $this->leseLeistungsangebot(),
'AenderungMoeglich' => (bool) $this->GetValue('AenderungMoeglich'), 'AenderungMoeglich' => (bool) $this->leseZustand('AenderungMoeglich'),
'Verfuegbar' => (bool) $this->GetValue('Verfuegbar'), 'Verfuegbar' => (bool) $this->leseZustand('Verfuegbar'),
'Istleistung_W' => (float) $this->GetValue('Istleistung'), 'Istleistung_W' => (float) $this->GetValue('Istleistung'),
'Leistungsquelle' => Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET, 'Leistungsquelle' => Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET,
'Zustand' => [ 'Zustand' => [
[ [
'Kennung' => 'Sollleistung_W', 'Kennung' => 'Sollleistung_W',
'Art' => 'Sollwert', 'Art' => 'Sollwert',
'Wert' => (bool) $this->GetValue('SollwertGueltig') 'Wert' => (bool) $this->leseZustand('SollwertGueltig')
? (int) $this->GetValue('Sollleistung') ? (int) $this->GetValue('Sollleistung')
: null, : null,
'Einheit' => 'W', 'Einheit' => 'W',
@@ -626,13 +585,13 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
[ [
'Kennung' => 'NachladenAktiv', 'Kennung' => 'NachladenAktiv',
'Art' => 'Status', 'Art' => 'Status',
'Wert' => (bool) $this->GetValue('NachladenAktiv'), 'Wert' => (bool) $this->leseZustand('NachladenAktiv'),
'Einheit' => '', 'Einheit' => '',
], ],
[ [
'Kennung' => 'LegionellenbetriebAktiv', 'Kennung' => 'LegionellenbetriebAktiv',
'Art' => 'Status', 'Art' => 'Status',
'Wert' => (bool) $this->GetValue('LegionellenbetriebAktiv'), 'Wert' => (bool) $this->leseZustand('LegionellenbetriebAktiv'),
'Einheit' => '', 'Einheit' => '',
], ],
[ [
@@ -656,13 +615,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
'Einheit' => '', 'Einheit' => '',
'Text' => $schaltfehler, 'Text' => $schaltfehler,
], ],
[
'Kennung' => 'Legionellenfehler',
'Art' => 'Stoerung',
'Wert' => $legionellenfehler !== '',
'Einheit' => '',
'Text' => $legionellenfehler,
],
], ],
]; ];
} }
@@ -709,25 +661,23 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
} }
foreach ([ foreach ([
'Meldeintervall', 'VorgabeTimeout', 'Interval', 'IdleCounterMax', 'TemperaturMaxAlter', 'Meldeintervall', 'VorgabeTimeout', 'Interval', 'IdleCounterMax', 'TemperaturMaxAlter',
'ZeitKonstante', 'Boilervolumen', 'LegionellenIntervallTage', 'LegionellenMaximaldauer', 'ZeitKonstante', 'Boilervolumen', 'LegionellenMinimalintervallTage',
'LegionellenMaximalintervallTage',
] as $property) { ] as $property) {
if ($this->ReadPropertyInteger($property) <= 0) { if ($this->ReadPropertyInteger($property) <= 0) {
throw new InvalidArgumentException($property . ' muss groesser als 0 sein.'); throw new InvalidArgumentException($property . ' muss groesser als 0 sein.');
} }
} }
if ($this->ReadPropertyInteger('LegionellenHaltezeit') < 0) { if ($this->ReadPropertyInteger('LegionellenMinimalintervallTage')
throw new InvalidArgumentException('LegionellenHaltezeit darf nicht negativ sein.'); > $this->ReadPropertyInteger('LegionellenMaximalintervallTage')
) {
throw new InvalidArgumentException(
'Das Legionellen-Minimalintervall darf nicht groesser als das Maximalintervall sein.'
);
} }
if ($this->ReadPropertyFloat('Hysterese') <= 0) { if ($this->ReadPropertyFloat('Hysterese') <= 0) {
throw new InvalidArgumentException('Hysterese muss groesser als 0 sein.'); 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'); $minimum = (float) $this->GetValue('Mindesttemperatur');
$maximum = (float) $this->GetValue('Maximaltemperatur'); $maximum = (float) $this->GetValue('Maximaltemperatur');
$legionellen = (float) $this->GetValue('Legionellentemperatur'); $legionellen = (float) $this->GetValue('Legionellentemperatur');
@@ -786,8 +736,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->SetValue('Mindesttemperatur', 45.0); $this->SetValue('Mindesttemperatur', 45.0);
$this->SetValue('Maximaltemperatur', 60.0); $this->SetValue('Maximaltemperatur', 60.0);
$this->SetValue('Legionellentemperatur', 65.0); $this->SetValue('Legionellentemperatur', 65.0);
$this->SetValue('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET); $this->setzeZustand('Leistungsquelle', Nachrichtenvertrag::LEISTUNGSQUELLE_BERECHNET);
$this->SetValue('Idle', true); $this->setzeZustand('Idle', true);
$this->WriteAttributeBoolean('InitialwerteGesetzt', true); $this->WriteAttributeBoolean('InitialwerteGesetzt', true);
} }
@@ -823,11 +773,33 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
$this->regelzyklus(true); $this->regelzyklus(true);
} }
private function aktualisiereSichtbarkeit(): void private function aktualisiereVariablen(): void
{ {
$diagnose = $this->ReadPropertyBoolean('DiagnosevariablenAnzeigen'); if ($this->ReadPropertyBoolean('DiagnosevariablenAnzeigen')) {
foreach (self::DIAGNOSE_VARIABLEN as $ident) { $this->registriereVerbraucherDiagnose();
IPS_SetHidden($this->GetIDForIdent($ident), !$diagnose); $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'); $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> */ /** @return list<int> */
private function leseLeistungsangebot(): array private function leseLeistungsangebot(): array
{ {
@@ -852,37 +884,6 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
return array_values(array_map('intval', $angebot)); 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 */ /** @param mixed $daten */
private function protokolliere(string $bezeichnung, $daten): void private function protokolliere(string $bezeichnung, $daten): void
{ {
+10 -13
View File
@@ -25,7 +25,7 @@ Legionellenprogramm koennen die lokale Warmwassersicherheit priorisieren.
## Properties ## Properties
Zu den sechs gemeinsamen Verbraucher-Properties aus Zu den sechs gemeinsamen Verbraucher-Properties aus
[`Schnittstelle.md`](../../Schnittstelle.md) kommen 17 Modul-Properties hinzu. [`Schnittstelle.md`](../../Schnittstelle.md) kommen 14 Modul-Properties hinzu.
| Ident | Typ | Standard | Beschreibung | | Ident | Typ | Standard | Beschreibung |
| --- | --- | ---: | --- | | --- | --- | ---: | --- |
@@ -39,16 +39,12 @@ Zu den sechs gemeinsamen Verbraucher-Properties aus
| `IdleCounterMax` | Integer | `2` | Zyklen bis zum Idle-Status. | | `IdleCounterMax` | Integer | `2` | Zyklen bis zum Idle-Status. |
| `TemperaturMaxAlter` | Integer | `30` | Maximal zulaessiges Messwertalter in Sekunden. | | `TemperaturMaxAlter` | Integer | `30` | Maximal zulaessiges Messwertalter in Sekunden. |
| `Hysterese` | Float | `5.0` | Temperaturhysterese in K. | | `Hysterese` | Float | `5.0` | Temperaturhysterese in K. |
| `LegionellenfunktionAktiv` | Boolean | `true` | Periodische Aufheizung aktiv. | | `LegionellenfunktionAktiv` | Boolean | `true` | Zweistufige periodische Aufheizung aktiv. |
| `LegionellenIntervallTage` | Integer | `7` | Intervall seit erfolgreichem Abschluss. | | `LegionellenMinimalintervallTage` | Integer | `4` | Ab diesem Intervall wird die Legionellentemperatur als Maximaltemperatur angeboten. |
| `LegionellenHaltezeit` | Integer | `0` | Haltezeit auf Zieltemperatur in Sekunden. | | `LegionellenMaximalintervallTage` | Integer | `7` | Ab diesem Intervall wird die Legionellentemperatur zwingend nachgeladen. |
| `LegionellenMaximaldauer` | Integer | `86400` | Abbruchzeit in Sekunden. | | `DiagnosevariablenAnzeigen` | Boolean | `false` | Legt zehn Diagnosevariablen bei Bedarf an. |
| `NachtstartStunde` | Integer | `22` | Fruehester Programmstart. |
| `NachtendeStunde` | Integer | `7` | Ende des Nachtfensters. |
| `DiagnosevariablenAnzeigen` | Boolean | `false` | Blendet zehn Diagnosevariablen ein. |
`LoggingEin` aktiviert laufende Debug-Ausgaben. Der Formular-Knopf schreibt `LoggingEin` aktiviert laufende Debug-Ausgaben.
unabhaengig davon genau einen aktuellen Statusdatensatz ins Debug-Log.
## Variablen ## Variablen
@@ -87,9 +83,10 @@ verzoegert, damit keine synchrone Manager-Verbraucher-Endlosschleife entsteht.
## Tests ## Tests
`WarmwasserReglerTest.php` prueft Leistungsstufen, PT1, Energieberechnung, `WarmwasserReglerTest.php` prueft Leistungsstufen, PT1, Energieberechnung,
Zeitplan und thermische Prognose. `WarmwassererwaermerModulstrukturTest.php` Zeitplan, thermische Prognose und die zweistufigen Legionellengrenzen.
prueft Metadaten, Formular, 23 Properties, Sichtbarkeit, Schnittstellenvertrag `WarmwassererwaermerModulstrukturTest.php` prueft Metadaten, Formular,
und Break-before-make-Schaltung. 20 Properties, bedarfsgesteuerte Diagnosevariablen, Schnittstellenvertrag und
Break-before-make-Schaltung.
## Migration ## Migration
+8 -4
View File
@@ -24,12 +24,16 @@ trait VerbraucherBasisTrait
$this->RegisterVariableBoolean('Aktiv', 'Aktiv', '~Switch', 10); $this->RegisterVariableBoolean('Aktiv', 'Aktiv', '~Switch', 10);
$this->EnableAction('Aktiv'); $this->EnableAction('Aktiv');
$this->RegisterVariableFloat('Istleistung', 'Istleistung', '', 20); $this->RegisterVariableFloat('Istleistung', 'Istleistung', '', 20);
$this->RegisterVariableInteger('Leistungsquelle', 'Leistungsquelle', '', 30);
$this->RegisterVariableInteger('Sollleistung', 'Sollleistung', '', 40); $this->RegisterVariableInteger('Sollleistung', 'Sollleistung', '', 40);
$this->RegisterVariableBoolean('SollwertGueltig', 'Sollwert gueltig', '~Switch', 50);
$this->RegisterVariableBoolean('Verfuegbar', 'Verfuegbar', '~Switch', 60);
$this->RegisterVariableBoolean('AenderungMoeglich', 'Aenderung moeglich', '~Switch', 70);
$this->RegisterVariableBoolean('Stoerung', 'Stoerung', '', 80); $this->RegisterVariableBoolean('Stoerung', 'Stoerung', '', 80);
$this->RegisterVariableString('Stoertext', 'Stoertext', '', 90); $this->RegisterVariableString('Stoertext', 'Stoertext', '', 90);
} }
protected function registriereVerbraucherDiagnose(): void
{
$this->RegisterVariableInteger('Leistungsquelle', 'Leistungsquelle', '', 30);
$this->RegisterVariableBoolean('SollwertGueltig', 'Sollwert gueltig', '~Switch', 50);
$this->RegisterVariableBoolean('Verfuegbar', 'Verfuegbar', '~Switch', 60);
$this->RegisterVariableBoolean('AenderungMoeglich', 'Aenderung moeglich', '~Switch', 70);
}
} }
+26
View File
@@ -138,6 +138,32 @@ final class WarmwasserRegler
return $verfuegbareWaermeJ >= $erforderlicheWaermeJ; return $verfuegbareWaermeJ >= $erforderlicheWaermeJ;
} }
/**
* @return array{0: float, 1: float}
*/
public static function legionellenTemperaturgrenzen(
bool $aktiv,
int $sekundenSeitAbschluss,
int $minimalintervallTage,
int $maximalintervallTage,
float $mindesttemperatur,
float $maximaltemperatur,
float $legionellentemperatur
): array {
if (!$aktiv) {
return [$mindesttemperatur, $maximaltemperatur];
}
if ($sekundenSeitAbschluss >= $minimalintervallTage * 86400) {
$maximaltemperatur = $legionellentemperatur;
}
if ($sekundenSeitAbschluss >= $maximalintervallTage * 86400) {
$mindesttemperatur = $legionellentemperatur;
}
return [$mindesttemperatur, $maximaltemperatur];
}
/** /**
* @return array{Zeitpunkt: int, Solltemperatur: float}|null * @return array{Zeitpunkt: int, Solltemperatur: float}|null
*/ */
+21 -4
View File
@@ -29,17 +29,29 @@ final class VerbraucherBasisTraitTest extends TestCase
[ [
'Aktiv', 'Aktiv',
'Istleistung', 'Istleistung',
'Leistungsquelle',
'Sollleistung', 'Sollleistung',
'SollwertGueltig',
'Verfuegbar',
'AenderungMoeglich',
'Stoerung', 'Stoerung',
'Stoertext', 'Stoertext',
], ],
array_keys($modul->variablen) array_keys($modul->variablen)
); );
self::assertSame(['Aktiv'], $modul->aktionen); self::assertSame(['Aktiv'], $modul->aktionen);
$modul->registriereDiagnose();
self::assertSame(
[
'Aktiv',
'Istleistung',
'Sollleistung',
'Stoerung',
'Stoertext',
'Leistungsquelle',
'SollwertGueltig',
'Verfuegbar',
'AenderungMoeglich',
],
array_keys($modul->variablen)
);
} }
} }
@@ -61,6 +73,11 @@ final class VerbraucherBasisDummy
$this->registriereVerbraucherBasis(); $this->registriereVerbraucherBasis();
} }
public function registriereDiagnose(): void
{
$this->registriereVerbraucherDiagnose();
}
public function RegisterPropertyInteger(string $ident, int $standard): void public function RegisterPropertyInteger(string $ident, int $standard): void
{ {
$this->properties[$ident] = $standard; $this->properties[$ident] = $standard;
+20
View File
@@ -79,4 +79,24 @@ final class WarmwasserReglerTest extends TestCase
); );
self::assertSame(55.0, $eintrag['Solltemperatur']); self::assertSame(55.0, $eintrag['Solltemperatur']);
} }
public function testLegionellenschaltungHebtTemperaturgrenzenZweistufigAn(): void
{
self::assertSame(
[45.0, 60.0],
WarmwasserRegler::legionellenTemperaturgrenzen(true, 3 * 86400, 4, 7, 45.0, 60.0, 65.0)
);
self::assertSame(
[45.0, 65.0],
WarmwasserRegler::legionellenTemperaturgrenzen(true, 4 * 86400, 4, 7, 45.0, 60.0, 65.0)
);
self::assertSame(
[65.0, 65.0],
WarmwasserRegler::legionellenTemperaturgrenzen(true, 7 * 86400, 4, 7, 45.0, 60.0, 65.0)
);
self::assertSame(
[45.0, 60.0],
WarmwasserRegler::legionellenTemperaturgrenzen(false, 8 * 86400, 4, 7, 45.0, 60.0, 65.0)
);
}
} }
+26 -4
View File
@@ -29,14 +29,14 @@ final class WarmwassererwaermerModulstrukturTest extends TestCase
self::assertMatchesRegularExpression('/^\{[0-9A-F-]{36}\}$/', $metadaten['id']); self::assertMatchesRegularExpression('/^\{[0-9A-F-]{36}\}$/', $metadaten['id']);
} }
public function testAlle23PropertiesSindRegistriertUndImFormularDokumentiert(): void public function testAlle20PropertiesSindRegistriertUndImFormularDokumentiert(): void
{ {
$basis = (string) file_get_contents(__DIR__ . '/../libs/VerbraucherBasisTrait.php'); $basis = (string) file_get_contents(__DIR__ . '/../libs/VerbraucherBasisTrait.php');
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php'); $modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
preg_match_all('/RegisterProperty(?:Integer|Float|Boolean|String)\(\'([^\']+)\'/', $basis . $modul, $treffer); preg_match_all('/RegisterProperty(?:Integer|Float|Boolean|String)\(\'([^\']+)\'/', $basis . $modul, $treffer);
$properties = array_values(array_unique($treffer[1])); $properties = array_values(array_unique($treffer[1]));
self::assertCount(23, $properties); self::assertCount(20, $properties);
$formular = (string) file_get_contents(self::MODULPFAD . 'form.json'); $formular = (string) file_get_contents(self::MODULPFAD . 'form.json');
foreach ($properties as $property) { foreach ($properties as $property) {
@@ -55,7 +55,7 @@ final class WarmwassererwaermerModulstrukturTest extends TestCase
self::assertStringNotContainsString("RegisterPropertyInteger('ManagerID'", $inhalt); self::assertStringNotContainsString("RegisterPropertyInteger('ManagerID'", $inhalt);
} }
public function testZehnDiagnosevariablenSindOptionalUndLoggingIstGetrennt(): void public function testZehnDiagnosevariablenWerdenBedarfsgesteuertAngelegtUndGeloescht(): void
{ {
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php'); $inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
preg_match('/private const DIAGNOSE_VARIABLEN = \[(.*?)\];/s', $inhalt, $treffer); preg_match('/private const DIAGNOSE_VARIABLEN = \[(.*?)\];/s', $inhalt, $treffer);
@@ -64,8 +64,30 @@ final class WarmwassererwaermerModulstrukturTest extends TestCase
self::assertCount(10, $variablen[1]); self::assertCount(10, $variablen[1]);
self::assertStringContainsString("ReadPropertyBoolean('DiagnosevariablenAnzeigen')", $inhalt); self::assertStringContainsString("ReadPropertyBoolean('DiagnosevariablenAnzeigen')", $inhalt);
self::assertStringContainsString('registriereVerbraucherDiagnose', $inhalt);
self::assertStringContainsString('UnregisterVariable($ident)', $inhalt);
self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $inhalt); self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $inhalt);
self::assertStringContainsString("case 'LogStatus':", $inhalt); self::assertStringNotContainsString("case 'LogStatus':", $inhalt);
}
public function testFormularIstWieGewuenschtGegliedertUndHatKeineAktionsknoepfe(): void
{
$formular = json_decode(
(string) file_get_contents(self::MODULPFAD . 'form.json'),
true,
512,
JSON_THROW_ON_ERROR
);
self::assertSame(
[
'Manager und Zeitverhalten',
'Speichereinstellungen',
'Erweiterte Speichereinstellungen',
'Erweiterte sonstige Einstellungen',
],
array_column($formular['elements'], 'caption')
);
self::assertArrayNotHasKey('actions', $formular);
} }
public function testTemperatursollwerteSindGeprueftBedienbar(): void public function testTemperatursollwerteSindGeprueftBedienbar(): void