createVariable(2, 'Netzleistung', 0.0); $einKontaktId = $test->createActionVariable('Kontakt Verbraucher 1-Stufig'); $einStufigId = $test->createInstance( '{15879A4E-D0C2-4495-83DE-46E1E462591E}', 'Verbraucher 1-Stufig', [ 'Nennleistung' => 1000, 'SchaltkontaktVariableID' => $einKontaktId, 'Mindesteinschaltdauer' => 0, 'Mindestausschaltdauer' => 0, 'PrioritaetPV' => 0, 'PrioritaetPeak' => 0, 'DiagnosevariablenAnzeigen' => true, ] ); $temperaturId = $test->createVariable(2, 'Boilertemperatur', 52.0); $warmKontakte = [ $test->createActionVariable('Warmwasser Stufe 1'), $test->createActionVariable('Warmwasser Stufe 2'), ]; $warmStufen = [ ['Stufe' => 1, 'Leistung' => 1000, 'Schaltkontakt_Stufe' => $warmKontakte[0]], ['Stufe' => 2, 'Leistung' => 2000, 'Schaltkontakt_Stufe' => $warmKontakte[1]], ]; $warmwasserId = $test->createInstance( '{B7C54AF4-AD7D-4FE4-B75D-203693906251}', 'Wassererwärmer', [ 'Boilerfuehler_PT1' => $temperaturId, 'LeistungsStufen' => json_encode($warmStufen, JSON_THROW_ON_ERROR), 'LastwechselSperrzeit' => 1, 'LegionellenfunktionAktiv' => false, 'PrioritaetPV' => 1, 'PrioritaetPeak' => 1, 'DiagnosevariablenAnzeigen' => true, ] ); $pufferTemperaturId = $test->createVariable(2, 'Puffertemperatur', 52.0); $aussenTemperaturId = $test->createVariable(2, 'Aussentemperatur', 5.0); $pufferKontakte = [ $test->createActionVariable('Pufferspeicher Stufe 1'), $test->createActionVariable('Pufferspeicher Stufe 2'), ]; $pufferspeicherId = $test->createInstance( '{C92D5EEF-9632-47A5-9659-4B02BF40FBE9}', 'Pufferspeicher', [ 'PufferfuehlerVariableID' => $pufferTemperaturId, 'AussentemperaturVariableID' => $aussenTemperaturId, 'LeistungsStufen' => json_encode([ ['Stufe' => 1, 'Leistung' => 1000, 'Schaltkontakt_Stufe' => $pufferKontakte[0]], ['Stufe' => 2, 'Leistung' => 2000, 'Schaltkontakt_Stufe' => $pufferKontakte[1]], ], JSON_THROW_ON_ERROR), 'LastwechselSperrzeit' => 0, 'PrioritaetPV' => 2, 'PrioritaetPeak' => 2, 'DiagnosevariablenAnzeigen' => true, ] ); $zuordnung = [ ['InstanzID' => $einStufigId, 'Aktiv' => true], ['InstanzID' => $warmwasserId, 'Aktiv' => true], ['InstanzID' => $pufferspeicherId, 'Aktiv' => true], ]; $lizenzcode = trim((string) getenv('ENELIX_TEST_LICENSE_CODE')); $managerId = $test->createInstance( '{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}', 'Manager', [ 'NetzleistungVariableID' => $netzleistungId, 'Lizenzcode' => $lizenzcode, 'AutomatischeSuche' => false, 'VerbraucherZuordnung' => json_encode($zuordnung, JSON_THROW_ON_ERROR), 'KeepAlive' => 30, 'VerbraucherTimeout' => 10, 'Lastspitzenmodus' => 1, 'Lastspitzengrenze' => 0.0, 'SollwertSolarladen' => 0.0, 'Umschaltdifferenz' => 0.0, 'DiagnosevariablenAnzeigen' => true, ] ); $melden = static function () use ($einStufigId, $warmwasserId, $pufferspeicherId): void { foreach ([$einStufigId, $warmwasserId, $pufferspeicherId] as $instanzId) { IPS_RequestAction($instanzId, 'Aktiv', true); IPS_RequestAction($instanzId, 'Melden', true); } }; $regeln = static function (float $netzleistung) use ( $netzleistungId, $managerId, $einStufigId, $warmwasserId, $pufferspeicherId ): void { IPS_RequestAction($einStufigId, 'Melden', true); IPS_RequestAction($warmwasserId, 'Melden', true); IPS_RequestAction($pufferspeicherId, 'Melden', true); SetValue($netzleistungId, $netzleistung); IPS_RequestAction($managerId, 'Regeln', true); }; $kontaktzustand = static fn (): array => [ (bool) GetValue($einKontaktId), (bool) GetValue($warmKontakte[0]), (bool) GetValue($warmKontakte[1]), (bool) GetValue($pufferKontakte[0]), (bool) GetValue($pufferKontakte[1]), ]; $warteAufKontakte = static function (array $erwartet, string $schritt) use ( $test, $kontaktzustand, $managerId ): void { $deadline = microtime(true) + 5.0; do { if ($kontaktzustand() === $erwartet) { return; } IPS_Sleep(50); } while (microtime(true) < $deadline); $test->fail(sprintf( '%s: Kontaktbild %s statt %s; Betriebsart %s; Verteilbudget %.0f W.', $schritt, json_encode($kontaktzustand(), JSON_THROW_ON_ERROR), json_encode($erwartet, JSON_THROW_ON_ERROR), (string) GetValue($test->objectByIdent('Betriebsart', $managerId)), (float) GetValue($test->objectByIdent('Verteilbudget', $managerId)) )); }; $verbraucherstatus = static function () use ($test, $managerId): array { $json = (string) GetValue($test->objectByIdent('Verbraucherstatus', $managerId)); $daten = json_decode($json, true, 512, JSON_THROW_ON_ERROR); return is_array($daten) ? $daten : []; }; $zustandswert = static function (array $daten, int $instanzId, string $kennung) { foreach ($daten['Verbraucher'] ?? [] as $verbraucher) { if (($verbraucher['InstanzID'] ?? 0) !== $instanzId) { continue; } foreach ($verbraucher['Daten']['Zustand'] ?? [] as $zustand) { if (($zustand['Kennung'] ?? '') === $kennung) { return $zustand['Wert'] ?? null; } } } return null; }; if ($lizenzcode === '') { $test->runCase('Manager bleibt ohne Lizenz sicher gesperrt', static function ( TestContext $test ) use ($managerId): void { IPS_RequestAction($managerId, 'Aktiv', true); IPS_RequestAction($managerId, 'Regeln', true); $test->assertInstanceStatus($managerId, 203); $test->assertSame( 'Inaktiv', GetValue($test->objectByIdent('Betriebsart', $managerId)) ); }); return; } $test->runCase('Manager und alle vorhandenen Verbrauchertypen sind verknüpft', static function ( TestContext $test ) use ($managerId, $einStufigId, $warmwasserId, $pufferspeicherId, $melden): void { IPS_RequestAction($managerId, 'Aktiv', true); $melden(); IPS_RequestAction($managerId, 'Regeln', true); foreach ([$managerId, $einStufigId, $warmwasserId, $pufferspeicherId] as $instanzId) { $test->assertInstanceStatus($instanzId); } $test->assertSame( 3, GetValue($test->objectByIdent('VerbraucherAnzahl', $managerId)) ); $test->assertSame( 3, GetValue($test->objectByIdent('VerbraucherVerfuegbar', $managerId)) ); }); $test->runCase('Netzleistung wird in beide Richtungen in PV und Peak geregelt', static function ( TestContext $test ) use ($managerId, $regeln, $warteAufKontakte): void { $regeln(-3000.0); $warteAufKontakte([true, false, true, false, false], 'Netz -3000 W'); $test->assertSame('PV', GetValue($test->objectByIdent('Betriebsart', $managerId))); $regeln(-1000.0); $warteAufKontakte([true, false, true, false, false], 'Netz -1000 W'); $regeln(0.0); $warteAufKontakte([true, false, true, false, false], 'Netz 0 W'); IPS_Sleep(1100); $regeln(1000.0); $warteAufKontakte([false, false, false, false, false], 'Netz +1000 W'); $test->assertSame('Peak', GetValue($test->objectByIdent('Betriebsart', $managerId))); IPS_Sleep(1100); $regeln(3000.0); $warteAufKontakte([false, false, false, false, false], 'Netz +3000 W'); }); $test->runCase('Keep-alive ist aktiv und erneuert unveränderte Sollwerte', static function ( TestContext $test ) use ($managerId, $einStufigId): void { $sollwertId = $test->objectByIdent('Sollleistung', $einStufigId); $vorher = (int) IPS_GetVariable($sollwertId)['VariableUpdated']; IPS_Sleep(1100); IPS_RequestAction($managerId, 'Regeln', true); $test->waitUntil( static fn (): bool => (int) IPS_GetVariable($sollwertId)['VariableUpdated'] > $vorher ); }); $test->runCase('Alle definierten Nachrichtenauslöser aktualisieren den Manager', static function ( TestContext $test ) use ( $managerId, $einStufigId, $warmwasserId, $temperaturId, $melden, $verbraucherstatus, $zustandswert ): void { $melden(); IPS_RequestAction($managerId, 'Regeln', false); $daten = $verbraucherstatus(); $test->assertSame(3, count($daten['Verbraucher'] ?? [])); SetValue($temperaturId, 53.0); $test->waitUntil(static function () use ( $managerId, $warmwasserId, $verbraucherstatus, $zustandswert ): bool { IPS_RequestAction($managerId, 'Regeln', false); $wert = $zustandswert( $verbraucherstatus(), $warmwasserId, 'Wassertemperatur_C' ); return is_numeric($wert) && abs((float) $wert - 53.0) < 0.01; }, 4000, 100); IPS_RequestAction($einStufigId, 'Melden', true); IPS_RequestAction($warmwasserId, 'Melden', true); IPS_RequestAction($managerId, 'Regeln', true); $daten = $verbraucherstatus(); $test->assertTrue( is_bool($zustandswert($daten, $einStufigId, 'Schaltzustand')) ); $test->assertTrue( is_int($zustandswert($daten, $warmwasserId, 'AktiveStufe')) ); $test->assertSame(false, GetValue( $test->objectByIdent('Sammelstoerung', $managerId) )); }); };