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 testPeakBietetUnterMinimumUndBeiAktiverUntererHystereseAlleStufen(): void { $werte = [0, 1000, 2000]; self::assertSame( $werte, WarmwasserRegler::leistungsangebot(true, 44.0, 50.0, 60.0, 5.0, false, $werte) ); self::assertSame( $werte, WarmwasserRegler::leistungsangebot(true, 52.0, 50.0, 60.0, 5.0, true, $werte) ); self::assertSame( [0], WarmwasserRegler::leistungsangebot(true, 52.0, 50.0, 60.0, 5.0, false, $werte) ); } public function testPvErzwingtUnterMinimumMaximumUndBietetSonstZustandsabhaengigAn(): void { $werte = [0, 1000, 2000]; self::assertSame( [2000], WarmwasserRegler::leistungsangebot(false, 44.0, 50.0, 60.0, 5.0, false, $werte) ); self::assertSame( $werte, WarmwasserRegler::leistungsangebot(false, 52.0, 50.0, 60.0, 5.0, false, $werte) ); self::assertSame( $werte, WarmwasserRegler::leistungsangebot(false, 58.0, 50.0, 60.0, 5.0, true, $werte) ); self::assertSame( [0], WarmwasserRegler::leistungsangebot(false, 58.0, 50.0, 60.0, 5.0, false, $werte) ); } 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 testLastwechselRestzeitWirdInSekundenBerechnet(): void { self::assertSame(0, WarmwasserRegler::restzeitBisLastwechsel(0, 100, 5)); self::assertSame(5, WarmwasserRegler::restzeitBisLastwechsel(100, 100, 5)); self::assertSame(2, WarmwasserRegler::restzeitBisLastwechsel(100, 103, 5)); self::assertSame(0, WarmwasserRegler::restzeitBisLastwechsel(100, 105, 5)); } 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']); } 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) ); } }