This commit is contained in:
@@ -21,6 +21,7 @@ Alle wesentlichen Aenderungen an Enelix EMS werden in dieser Datei dokumentiert.
|
|||||||
- Wartende Easee-Ladestationen erhalten bei positiver Stromvorgabe einmal pro Fahrzeugverbindung einen Startbefehl; Freigabe- und Blockiergruende werden diagnostiziert.
|
- Wartende Easee-Ladestationen erhalten bei positiver Stromvorgabe einmal pro Fahrzeugverbindung einen Startbefehl; Freigabe- und Blockiergruende werden diagnostiziert.
|
||||||
- Fehlende oder veraltete Verbraucher blockieren die Verteilung an aktuelle Verbraucher nicht mehr.
|
- Fehlende oder veraltete Verbraucher blockieren die Verteilung an aktuelle Verbraucher nicht mehr.
|
||||||
- Die Stoerungsueberwachung fordert einen fehlenden Geraetezugang innerhalb ihres Retry-Zyklus automatisch neu an.
|
- Die Stoerungsueberwachung fordert einen fehlenden Geraetezugang innerhalb ihres Retry-Zyklus automatisch neu an.
|
||||||
|
- Der Warmwassererwaermer verwendet konfigurierbare Temperatur-Stoergrenzen von standardmaessig 0 bis 100 Grad C.
|
||||||
- Vollstaendige PHP-, Struktur- und Symcon-Modultests fuer alle Module.
|
- Vollstaendige PHP-, Struktur- und Symcon-Modultests fuer alle Module.
|
||||||
|
|
||||||
### Hinweise
|
### Hinweise
|
||||||
|
|||||||
@@ -130,6 +130,20 @@
|
|||||||
"minimum": 0.1,
|
"minimum": 0.1,
|
||||||
"digits": 1
|
"digits": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "NumberSpinner",
|
||||||
|
"name": "TemperaturUntergrenze",
|
||||||
|
"caption": "Untertemperaturgrenze",
|
||||||
|
"suffix": " °C",
|
||||||
|
"digits": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "NumberSpinner",
|
||||||
|
"name": "TemperaturObergrenze",
|
||||||
|
"caption": "Übertemperaturgrenze",
|
||||||
|
"suffix": " °C",
|
||||||
|
"digits": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "List",
|
"type": "List",
|
||||||
"name": "Zeitplan",
|
"name": "Zeitplan",
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
|||||||
$this->RegisterPropertyString('Zeitplan', '[]');
|
$this->RegisterPropertyString('Zeitplan', '[]');
|
||||||
$this->RegisterPropertyInteger('LastwechselSperrzeit', 5);
|
$this->RegisterPropertyInteger('LastwechselSperrzeit', 5);
|
||||||
$this->RegisterPropertyInteger('TemperaturMaxAlter', 30);
|
$this->RegisterPropertyInteger('TemperaturMaxAlter', 30);
|
||||||
|
$this->RegisterPropertyFloat('TemperaturUntergrenze', 0.0);
|
||||||
|
$this->RegisterPropertyFloat('TemperaturObergrenze', 100.0);
|
||||||
$this->RegisterPropertyFloat('Hysterese', 5.0);
|
$this->RegisterPropertyFloat('Hysterese', 5.0);
|
||||||
$this->RegisterPropertyBoolean('LegionellenfunktionAktiv', true);
|
$this->RegisterPropertyBoolean('LegionellenfunktionAktiv', true);
|
||||||
$this->RegisterPropertyInteger('LegionellenMinimalintervallTage', 4);
|
$this->RegisterPropertyInteger('LegionellenMinimalintervallTage', 4);
|
||||||
@@ -537,6 +539,10 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
|||||||
if (!$temperaturGueltig) {
|
if (!$temperaturGueltig) {
|
||||||
$stoerungen[] = 'Boilertemperatur fehlt oder ist veraltet.';
|
$stoerungen[] = 'Boilertemperatur fehlt oder ist veraltet.';
|
||||||
}
|
}
|
||||||
|
$untertemperatur = $this->istUntertemperatur($temperaturGueltig);
|
||||||
|
if ($untertemperatur) {
|
||||||
|
$stoerungen[] = 'Untertemperatur erkannt.';
|
||||||
|
}
|
||||||
$uebertemperatur = $this->istUebertemperatur($temperaturGueltig);
|
$uebertemperatur = $this->istUebertemperatur($temperaturGueltig);
|
||||||
if ($uebertemperatur) {
|
if ($uebertemperatur) {
|
||||||
$stoerungen[] = 'Uebertemperatur erkannt.';
|
$stoerungen[] = 'Uebertemperatur erkannt.';
|
||||||
@@ -555,19 +561,18 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function istUntertemperatur(bool $temperaturGueltig): bool
|
||||||
|
{
|
||||||
|
return $temperaturGueltig
|
||||||
|
&& (float) $this->GetValue('Boilertemperatur')
|
||||||
|
< $this->ReadPropertyFloat('TemperaturUntergrenze');
|
||||||
|
}
|
||||||
|
|
||||||
private function istUebertemperatur(bool $temperaturGueltig): bool
|
private function istUebertemperatur(bool $temperaturGueltig): bool
|
||||||
{
|
{
|
||||||
if (!$temperaturGueltig) {
|
return $temperaturGueltig
|
||||||
return false;
|
&& (float) $this->GetValue('Boilertemperatur')
|
||||||
}
|
> $this->ReadPropertyFloat('TemperaturObergrenze');
|
||||||
|
|
||||||
$grenze = (float) $this->GetValue('Maximaltemperatur');
|
|
||||||
if ($this->ReadPropertyBoolean('LegionellenfunktionAktiv')) {
|
|
||||||
$grenze = max($grenze, $this->ReadAttributeFloat('ZustandLegionellentemperatur'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (float) $this->GetValue('Boilertemperatur')
|
|
||||||
> $grenze + $this->ReadPropertyFloat('Hysterese');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function sendeVerbraucherdaten(): void
|
private function sendeVerbraucherdaten(): void
|
||||||
@@ -592,6 +597,7 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
|||||||
{
|
{
|
||||||
$temperaturGueltig = (bool) $this->leseZustand('TemperaturGueltig');
|
$temperaturGueltig = (bool) $this->leseZustand('TemperaturGueltig');
|
||||||
$schaltfehler = $this->ReadAttributeString('Schaltfehler');
|
$schaltfehler = $this->ReadAttributeString('Schaltfehler');
|
||||||
|
$untertemperatur = $this->istUntertemperatur($temperaturGueltig);
|
||||||
$uebertemperatur = $this->istUebertemperatur($temperaturGueltig);
|
$uebertemperatur = $this->istUebertemperatur($temperaturGueltig);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@@ -655,6 +661,13 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
|||||||
'Einheit' => '',
|
'Einheit' => '',
|
||||||
'Text' => $temperaturGueltig ? '' : 'Boilertemperatur fehlt oder ist veraltet.',
|
'Text' => $temperaturGueltig ? '' : 'Boilertemperatur fehlt oder ist veraltet.',
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'Kennung' => 'Untertemperatur',
|
||||||
|
'Art' => 'Stoerung',
|
||||||
|
'Wert' => $untertemperatur,
|
||||||
|
'Einheit' => '',
|
||||||
|
'Text' => $untertemperatur ? 'Untertemperatur erkannt.' : '',
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'Kennung' => 'Uebertemperatur',
|
'Kennung' => 'Uebertemperatur',
|
||||||
'Art' => 'Stoerung',
|
'Art' => 'Stoerung',
|
||||||
@@ -745,6 +758,13 @@ class VerbraucherWarmwassererwaermer extends IPSModule implements VerbraucherSch
|
|||||||
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.');
|
||||||
}
|
}
|
||||||
|
if ($this->ReadPropertyFloat('TemperaturUntergrenze')
|
||||||
|
>= $this->ReadPropertyFloat('TemperaturObergrenze')
|
||||||
|
) {
|
||||||
|
throw new InvalidArgumentException(
|
||||||
|
'Die Temperaturuntergrenze muss kleiner als die Temperaturobergrenze sein.'
|
||||||
|
);
|
||||||
|
}
|
||||||
$minimum = (float) $this->GetValue('Mindesttemperatur');
|
$minimum = (float) $this->GetValue('Mindesttemperatur');
|
||||||
$maximum = (float) $this->GetValue('Maximaltemperatur');
|
$maximum = (float) $this->GetValue('Maximaltemperatur');
|
||||||
$legionellen = (float) $this->ReadAttributeFloat('ZustandLegionellentemperatur');
|
$legionellen = (float) $this->ReadAttributeFloat('ZustandLegionellentemperatur');
|
||||||
|
|||||||
@@ -13,9 +13,11 @@
|
|||||||
| `Interval` | entfaellt | Die Regelung wird ereignisbasiert ausgeloest. |
|
| `Interval` | entfaellt | Die Regelung wird ereignisbasiert ausgeloest. |
|
||||||
| `IdleCounterMax` | `LastwechselSperrzeit` | Zykluszaehler wird durch eine Sperrzeit in Sekunden ersetzt; Standard `5`. |
|
| `IdleCounterMax` | `LastwechselSperrzeit` | Zykluszaehler wird durch eine Sperrzeit in Sekunden ersetzt; Standard `5`. |
|
||||||
|
|
||||||
Die neuen Properties `TemperaturMaxAlter`, `Hysterese`, die Parameter der
|
Die neuen Properties `TemperaturMaxAlter`, `TemperaturUntergrenze`,
|
||||||
Legionellenfunktion und `DiagnosevariablenAnzeigen` ersetzen feste Werte und
|
`TemperaturObergrenze`, `Hysterese`, die Parameter der Legionellenfunktion und
|
||||||
nicht pruefbare Annahmen des Altmoduls.
|
`DiagnosevariablenAnzeigen` ersetzen feste Werte und nicht pruefbare Annahmen
|
||||||
|
des Altmoduls. Die Stoergrenzen liegen standardmaessig bei 0 und 100 Grad C und
|
||||||
|
sind von den Regel-Sollwerten `Mindesttemperatur` und `Maximaltemperatur` getrennt.
|
||||||
|
|
||||||
## Variablen
|
## Variablen
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ return static function (TestContext $test): void {
|
|||||||
'LastwechselSperrzeit' => 1,
|
'LastwechselSperrzeit' => 1,
|
||||||
'Hysterese' => 5.0,
|
'Hysterese' => 5.0,
|
||||||
'TemperaturMaxAlter' => 120,
|
'TemperaturMaxAlter' => 120,
|
||||||
|
'TemperaturUntergrenze' => 0.0,
|
||||||
|
'TemperaturObergrenze' => 100.0,
|
||||||
'LegionellenfunktionAktiv' => true,
|
'LegionellenfunktionAktiv' => true,
|
||||||
'LegionellenMinimalintervallTage' => 4,
|
'LegionellenMinimalintervallTage' => 4,
|
||||||
'LegionellenMaximalintervallTage' => 7,
|
'LegionellenMaximalintervallTage' => 7,
|
||||||
@@ -90,6 +92,24 @@ return static function (TestContext $test): void {
|
|||||||
IPS_RequestAction($managerId, 'Regeln', true);
|
IPS_RequestAction($managerId, 'Regeln', true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$test->runCase('Temperaturgrenzen melden Unter- und Uebertemperatur', static function (
|
||||||
|
TestContext $test
|
||||||
|
) use ($verbraucherId, $temperaturSetzen): void {
|
||||||
|
$stoertextId = $test->objectByIdent('Stoertext', $verbraucherId);
|
||||||
|
|
||||||
|
$temperaturSetzen(100.0);
|
||||||
|
$test->assertTrue(!str_contains((string) GetValue($stoertextId), 'Uebertemperatur'));
|
||||||
|
$temperaturSetzen(100.1);
|
||||||
|
$test->assertTrue(str_contains((string) GetValue($stoertextId), 'Uebertemperatur'));
|
||||||
|
|
||||||
|
$temperaturSetzen(0.0);
|
||||||
|
$test->assertTrue(!str_contains((string) GetValue($stoertextId), 'Untertemperatur'));
|
||||||
|
$temperaturSetzen(-0.1);
|
||||||
|
$test->assertTrue(str_contains((string) GetValue($stoertextId), 'Untertemperatur'));
|
||||||
|
|
||||||
|
$temperaturSetzen(52.0);
|
||||||
|
});
|
||||||
|
|
||||||
if ($lizenzcode === '') {
|
if ($lizenzcode === '') {
|
||||||
$test->runCase('Manager bleibt ohne Lizenz sicher gesperrt', static function (
|
$test->runCase('Manager bleibt ohne Lizenz sicher gesperrt', static function (
|
||||||
TestContext $test
|
TestContext $test
|
||||||
|
|||||||
@@ -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 testAlle19PropertiesSindRegistriertUndImFormularDokumentiert(): void
|
public function testAlle21PropertiesSindRegistriertUndImFormularDokumentiert(): 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(19, $properties);
|
self::assertCount(21, $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) {
|
||||||
@@ -136,6 +136,38 @@ final class WarmwassererwaermerModulstrukturTest extends TestCase
|
|||||||
self::assertStringContainsString('Mindesttemperatur < Maximaltemperatur', $inhalt);
|
self::assertStringContainsString('Mindesttemperatur < Maximaltemperatur', $inhalt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTemperaturstoergrenzenSindKonfigurierbarUndVonSollwertenGetrennt(): void
|
||||||
|
{
|
||||||
|
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterPropertyFloat('TemperaturUntergrenze', 0.0)",
|
||||||
|
$inhalt
|
||||||
|
);
|
||||||
|
self::assertStringContainsString(
|
||||||
|
"RegisterPropertyFloat('TemperaturObergrenze', 100.0)",
|
||||||
|
$inhalt
|
||||||
|
);
|
||||||
|
self::assertStringContainsString("ReadPropertyFloat('TemperaturUntergrenze')", $inhalt);
|
||||||
|
self::assertStringContainsString("ReadPropertyFloat('TemperaturObergrenze')", $inhalt);
|
||||||
|
self::assertStringContainsString("'Kennung' => 'Untertemperatur'", $inhalt);
|
||||||
|
self::assertStringContainsString("'Kennung' => 'Uebertemperatur'", $inhalt);
|
||||||
|
|
||||||
|
$formular = json_decode(
|
||||||
|
(string) file_get_contents(self::MODULPFAD . 'form.json'),
|
||||||
|
true,
|
||||||
|
512,
|
||||||
|
JSON_THROW_ON_ERROR
|
||||||
|
);
|
||||||
|
$erweitert = array_values(array_filter(
|
||||||
|
$formular['elements'],
|
||||||
|
static fn (array $element): bool =>
|
||||||
|
$element['caption'] === 'Erweiterte Speichereinstellungen'
|
||||||
|
));
|
||||||
|
self::assertCount(1, $erweitert);
|
||||||
|
self::assertContains('TemperaturUntergrenze', array_column($erweitert[0]['items'], 'name'));
|
||||||
|
self::assertContains('TemperaturObergrenze', array_column($erweitert[0]['items'], 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testSchaltfolgeIstBreakBeforeMake(): void
|
public function testSchaltfolgeIstBreakBeforeMake(): void
|
||||||
{
|
{
|
||||||
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
|
||||||
|
|||||||
Reference in New Issue
Block a user