Verbraucher Warmwassererwaermer implementieren
Tests / test (push) Canceled after 0s

This commit is contained in:
dh
2026-09-16 05:18:01 +00:00
parent 0a3ece3a81
commit 7a3c436039
14 changed files with 1751 additions and 69 deletions
+17 -9
View File
@@ -8,18 +8,17 @@ use PHPUnit\Framework\TestCase;
final class DokumentationsstrukturTest extends TestCase
{
/** @return list<string> */
/** @return list<array{string}> */
public function modulReadmes(): array
{
return [
'Batterie',
'Wassererwaermer',
'Pufferspeicher',
'Verbraucher-1-Stufig',
'Waermepumpe',
'Ladestation-Stand-Alone',
'Ladestation-Gateway',
'Easee-Gateway',
['Batterie'],
['Pufferspeicher'],
['Verbraucher-1-Stufig'],
['Waermepumpe'],
['Ladestation-Stand-Alone'],
['Ladestation-Gateway'],
['Easee-Gateway'],
];
}
@@ -49,4 +48,13 @@ final class DokumentationsstrukturTest extends TestCase
self::assertStringContainsString('Status: Implementiert', $inhalt);
self::assertStringContainsString('Verteilalgorithmus', $inhalt);
}
public function testWarmwassererwaermerDokumentiertDenImplementiertenStand(): void
{
$inhalt = file_get_contents(__DIR__ . '/../docs/module/Wassererwaermer/README.md');
self::assertNotFalse($inhalt);
self::assertStringContainsString('Status: implementiert', $inhalt);
self::assertStringContainsString('Properties', $inhalt);
self::assertStringContainsString('Managerkommunikation', $inhalt);
}
}
+1 -1
View File
@@ -88,7 +88,7 @@ final class ManagerReglerTest extends TestCase
public function testNichtAenderbarerVerbraucherReserviertSeineIstleistung(): void
{
$fest = $this->verbraucher(10, 0, [0, 3000], 3000, false);
$steuerbar = $this->verbraucher(20, 1, [0, ['Von_W' => 0, 'Bis_W' => 4000]], 0);
$steuerbar = $this->verbraucher(20, 1, [0, ['Von_W' => 1, 'Bis_W' => 4000]], 0);
$ergebnis = ManagerRegler::verteile(3000.0, 5000.0, [$fest, $steuerbar], 'PrioritaetPV');
+82
View File
@@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace Belevo\EnelixEMS\Tests;
use Belevo\EnelixEMS\WarmwasserRegler;
use DateTimeImmutable;
use DateTimeZone;
use InvalidArgumentException;
use PHPUnit\Framework\TestCase;
final class WarmwasserReglerTest extends TestCase
{
public function testLeistungsstufenWerdenValidiertUndAufsteigendSortiert(): void
{
$stufen = WarmwasserRegler::dekodiereLeistungsstufen(json_encode([
['Stufe' => 2, 'Leistung' => 6000, 'Schaltkontakt_Stufe' => 102],
['Stufe' => 1, 'Leistung' => 3000, 'Schaltkontakt_Stufe' => 101],
], JSON_THROW_ON_ERROR));
self::assertSame(
[
['Stufe' => 1, 'Leistung_W' => 3000, 'KontaktID' => 101],
['Stufe' => 2, 'Leistung_W' => 6000, 'KontaktID' => 102],
],
$stufen
);
self::assertSame([0, 3000, 6000], WarmwasserRegler::leistungswerte($stufen));
self::assertSame(2, WarmwasserRegler::stufeFuerLeistung($stufen, 6000));
self::assertSame(0, WarmwasserRegler::stufeFuerLeistung($stufen, 0));
}
public function testDoppelteKontakteWerdenAbgewiesen(): void
{
$this->expectException(InvalidArgumentException::class);
WarmwasserRegler::dekodiereLeistungsstufen(json_encode([
['Stufe' => 1, 'Leistung' => 3000, 'Schaltkontakt_Stufe' => 101],
['Stufe' => 2, 'Leistung' => 6000, 'Schaltkontakt_Stufe' => 101],
], JSON_THROW_ON_ERROR));
}
public function testNichtKonfigurierteSollleistungWirdAbgewiesen(): void
{
$this->expectException(InvalidArgumentException::class);
WarmwasserRegler::stufeFuerLeistung([
['Stufe' => 1, 'Leistung_W' => 3000, 'KontaktID' => 101],
], 1500);
}
public function testPt1VerwendetRegelintervallUndZeitkonstante(): void
{
self::assertEqualsWithDelta(20.4, WarmwasserRegler::pt1(20.0, 30.0, 5, 120), 0.001);
}
public function testEnergieWirdInKWhBerechnet(): void
{
self::assertEqualsWithDelta(3.0, WarmwasserRegler::energieKWh(3000.0, 3600), 0.000001);
}
public function testThermischePrognose(): void
{
self::assertTrue(WarmwasserRegler::kannZielErreichen(300.0, 50.0, 60.0, 7200, 3000));
self::assertFalse(WarmwasserRegler::kannZielErreichen(300.0, 20.0, 60.0, 3600, 3000));
}
public function testNaechsterZeitplaneintragIstHeuteOderMorgen(): void
{
$jetzt = new DateTimeImmutable('2026-09-16 10:00:00', new DateTimeZone('Europe/Zurich'));
$eintrag = WarmwasserRegler::naechsterZeitplaneintrag(json_encode([
['Uhrzeit' => '08:00', 'Solltemperatur' => 50],
['Uhrzeit' => '11:00', 'Solltemperatur' => 55],
], JSON_THROW_ON_ERROR), $jetzt);
self::assertNotNull($eintrag);
self::assertSame(
(new DateTimeImmutable('2026-09-16 11:00:00', new DateTimeZone('Europe/Zurich')))->getTimestamp(),
$eintrag['Zeitpunkt']
);
self::assertSame(55.0, $eintrag['Solltemperatur']);
}
}
@@ -0,0 +1,89 @@
<?php
declare(strict_types=1);
namespace Belevo\EnelixEMS\Tests;
use PHPUnit\Framework\TestCase;
final class WarmwassererwaermerModulstrukturTest extends TestCase
{
private const MODULPFAD = __DIR__ . '/../Warmwassererwaermer/';
public function testModulIstVollstaendigUndMetadatenSindGueltig(): void
{
foreach (['module.json', 'form.json', 'module.php'] as $datei) {
self::assertFileExists(self::MODULPFAD . $datei);
}
$metadaten = json_decode(
(string) file_get_contents(self::MODULPFAD . 'module.json'),
true,
512,
JSON_THROW_ON_ERROR
);
self::assertSame('VerbraucherWarmwassererwaermer', $metadaten['name']);
self::assertSame(3, $metadaten['type']);
self::assertMatchesRegularExpression('/^\{[0-9A-F-]{36}\}$/', $metadaten['id']);
}
public function testAlle23PropertiesSindRegistriertUndImFormularDokumentiert(): void
{
$basis = (string) file_get_contents(__DIR__ . '/../libs/VerbraucherBasisTrait.php');
$modul = (string) file_get_contents(self::MODULPFAD . 'module.php');
preg_match_all('/RegisterProperty(?:Integer|Float|Boolean|String)\(\'([^\']+)\'/', $basis . $modul, $treffer);
$properties = array_values(array_unique($treffer[1]));
self::assertCount(23, $properties);
$formular = (string) file_get_contents(self::MODULPFAD . 'form.json');
foreach ($properties as $property) {
self::assertStringContainsString('"name": "' . $property . '"', $formular, $property);
}
}
public function testModulVerwendetAusschliesslichDenVertrag30(): void
{
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
self::assertStringContainsString('implements VerbraucherSchnittstelle', $inhalt);
self::assertStringContainsString('ManagerdatenEmpfangen(array $daten)', $inhalt);
self::assertStringContainsString('Nachrichtenvertrag::pruefeManagerdaten', $inhalt);
self::assertStringContainsString('Nachrichtenvertrag::pruefeVerbraucherdaten', $inhalt);
self::assertStringNotContainsString("RegisterVariableString('PowerSteps'", $inhalt);
self::assertStringNotContainsString("RegisterPropertyInteger('ManagerID'", $inhalt);
}
public function testZehnDiagnosevariablenSindOptionalUndLoggingIstGetrennt(): void
{
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
preg_match('/private const DIAGNOSE_VARIABLEN = \[(.*?)\];/s', $inhalt, $treffer);
self::assertArrayHasKey(1, $treffer);
preg_match_all('/\'([^\']+)\'/', $treffer[1], $variablen);
self::assertCount(10, $variablen[1]);
self::assertStringContainsString("ReadPropertyBoolean('DiagnosevariablenAnzeigen')", $inhalt);
self::assertStringContainsString("ReadPropertyBoolean('LoggingEin')", $inhalt);
self::assertStringContainsString("case 'LogStatus':", $inhalt);
}
public function testTemperatursollwerteSindGeprueftBedienbar(): void
{
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
foreach (['Mindesttemperatur', 'Maximaltemperatur', 'Legionellentemperatur'] as $ident) {
self::assertStringContainsString("EnableAction('" . $ident . "')", $inhalt);
}
self::assertStringContainsString('setzeTemperaturSollwert', $inhalt);
self::assertStringContainsString('Mindesttemperatur < Maximaltemperatur', $inhalt);
}
public function testSchaltfolgeIstBreakBeforeMake(): void
{
$inhalt = (string) file_get_contents(self::MODULPFAD . 'module.php');
$aus = strpos($inhalt, "RequestAction(\$stufe['KontaktID'], false)");
$ein = strpos($inhalt, "RequestAction(\$stufe['KontaktID'], true)");
self::assertIsInt($aus);
self::assertIsInt($ein);
self::assertLessThan($ein, $aus);
}
}