$status, 'nrg' => $nrg], JSON_THROW_ON_ERROR); }; $definitionen = [ 'go-e alt' => [ 'Geraetetyp' => 1, 'Geraeteadresse' => '192.0.2.10', 'Testantwort' => $goEAntwort(2, 1100), 'Phasenzahl' => 3, 'BefehlUrlTeil' => 'amp=16', ], 'go-e Gemini' => [ 'Geraetetyp' => 2, 'Geraeteadresse' => '192.0.2.11', 'Testantwort' => $goEAntwort(2, 2300), 'Phasenzahl' => 1, 'BefehlUrlTeil' => 'amp=16', ], 'smart-me Pico' => [ 'Geraetetyp' => 3, 'GeraeteID' => 'pico-id', 'Seriennummer' => 'serial-1', 'Benutzername' => 'api-user', 'Passwort' => $testPasswort, 'Testantwort' => json_encode([ 'State' => 2, 'ActiveChargingPower' => 11.0, 'MaxAllowedChargingCurrent' => 16, ], JSON_THROW_ON_ERROR), 'Phasenzahl' => 3, 'BefehlUrlTeil' => 'current=16000', ], ]; $stationen = []; foreach ($definitionen as $name => $definition) { $properties = array_merge($definition, [ 'MaximalerLadestrom' => 16, 'Ladefreigabe' => true, 'Solarladen' => true, 'EinstellungenInVisu' => true, 'DiagnosevariablenAnzeigen' => true, 'Testmodus' => true, ]); unset($properties['Phasenzahl'], $properties['BefehlUrlTeil']); $stationen[$name] = $test->createInstance( '{0D94913C-0F31-4C29-A685-6EB4AE58E55D}', 'Ladestation ' . $name, $properties ); } $solarPause = $test->createInstance( '{0D94913C-0F31-4C29-A685-6EB4AE58E55D}', 'Ladestation Solarpause', [ 'Geraetetyp' => 1, 'Geraeteadresse' => '192.0.2.12', 'MaximalerLadestrom' => 16, 'Ladefreigabe' => true, 'Solarladen' => true, 'EinstellungenInVisu' => true, 'DiagnosevariablenAnzeigen' => true, 'Testmodus' => true, 'Testantwort' => $goEAntwort(2, 0), ] ); $managerId = $test->createInstance( '{6F771B18-59D4-4C8A-B951-3B2FE9F6A2C4}', 'Hilfsmanager Ladestation', [ 'AutomatischeSuche' => false, 'VerbraucherZuordnung' => json_encode(array_map( static fn (int $id): array => ['InstanzID' => $id, 'Aktiv' => true], array_values($stationen) ), JSON_THROW_ON_ERROR), ] ); $anforderungSenden = static function ( int $stationId, int $leistung, string $betriebsart = 'PV' ) use ($managerId): void { IPS_RequestAction($stationId, 'ManagerdatenEmpfangen', json_encode([ 'Kopf' => [ 'Version' => '4.0', 'AbsenderID' => $managerId, 'EmpfaengerID' => $stationId, 'Zeitpunkt' => time(), ], 'Betriebsart' => $betriebsart, 'Sollleistung_W' => $leistung, ], JSON_THROW_ON_ERROR)); }; $test->runCase('Alle drei Geraetevarianten erkennen Fahrzeug und Phasen', static function ( TestContext $test ) use ($definitionen, $stationen): void { foreach ($stationen as $name => $stationId) { IPS_RequestAction($stationId, 'Aktiv', true); $test->assertSame(true, GetValue($test->objectByIdent('FahrzeugVerbunden', $stationId))); $test->assertSame( $definitionen[$name]['Phasenzahl'], GetValue($test->objectByIdent('Phasenzahl', $stationId)) ); $test->assertSame(false, GetValue($test->objectByIdent('FahrzeugGeladen', $stationId))); IPS_RequestAction($stationId, 'Solarladen', false); $befehl = (string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)); $diagnose = json_encode([ 'Aktiv' => GetValue($test->objectByIdent('Aktiv', $stationId)), 'Ladefreigabe' => GetValue($test->objectByIdent('Ladefreigabe', $stationId)), 'Solarladen' => GetValue($test->objectByIdent('Solarladen', $stationId)), 'FahrzeugGeladen' => GetValue($test->objectByIdent('FahrzeugGeladen', $stationId)), 'Phasenzahl' => GetValue($test->objectByIdent('Phasenzahl', $stationId)), 'Status' => IPS_GetInstance($stationId)['InstanceStatus'], 'Stoertext' => GetValue($test->objectByIdent('Stoertext', $stationId)), ], JSON_THROW_ON_ERROR); $test->assertTrue(str_contains( $befehl, $definitionen[$name]['BefehlUrlTeil'] ), $name . ': Der erwartete 16-A-Geraetebefehl fehlt. Erhalten: ' . $befehl . '; Diagnose: ' . $diagnose); } }); $test->runCase('Solarpause wird nicht als Ladeende erkannt', static function ( TestContext $test ) use ($solarPause): void { IPS_RequestAction($solarPause, 'Solarladen', true); $test->assertSame( false, GetValue($test->objectByIdent('FahrzeugGeladen', $solarPause)) ); $test->assertSame( 2, GetValue($test->objectByIdent('Fahrzeugstatus', $solarPause)) ); }); $test->runCase('ApplyChanges prueft ein gespeichertes Ladeende neu', static function ( TestContext $test ) use ($goEAntwort, $solarPause): void { IPS_RequestAction($solarPause, 'Solarladen', false); IPS_RequestAction($solarPause, 'Statuszyklus', false); $test->assertSame( true, GetValue($test->objectByIdent('FahrzeugGeladen', $solarPause)) ); IPS_SetProperty($solarPause, 'Testantwort', $goEAntwort(2, 2300)); IPS_ApplyChanges($solarPause); $test->assertSame( false, GetValue($test->objectByIdent('FahrzeugGeladen', $solarPause)) ); $test->assertSame( 3, GetValue($test->objectByIdent('Fahrzeugstatus', $solarPause)) ); }); $test->runCase('Solar- und Peakbetrieb liefern die Enelix-1-Angebote', static function ( TestContext $test ) use ($stationen, $anforderungSenden): void { $stationId = $stationen['go-e alt']; IPS_RequestAction($stationId, 'Solarladen', true); $anforderungSenden($stationId, 4150); $befehl = (string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)); $diagnose = json_encode([ 'Sollleistung' => GetValue($test->objectByIdent('Sollleistung', $stationId)), 'SollwertGueltig' => GetValue($test->objectByIdent('SollwertGueltig', $stationId)), 'Status' => IPS_GetInstance($stationId)['InstanceStatus'], 'Stoertext' => GetValue($test->objectByIdent('Stoertext', $stationId)), ], JSON_THROW_ON_ERROR); $test->assertTrue(str_contains( $befehl, 'amp=6' ), 'Solarladen: Der 6-A-Befehl fehlt. Erhalten: ' . $befehl . '; Diagnose: ' . $diagnose); IPS_RequestAction($stationId, 'Solarladen', false); $angebot = (string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId)); $test->assertSame('[11000]', $angebot, 'PV ohne Solarladen muss nur das Maximum anbieten.'); $abgewiesen = false; try { $anforderungSenden($stationId, 4150); } catch (Throwable $fehler) { $abgewiesen = true; } if (!$abgewiesen) { $abgewiesen = GetValue($test->objectByIdent('SollwertGueltig', $stationId)) !== true || GetValue($test->objectByIdent('Sollleistung', $stationId)) !== 4150; } $test->assertSame(true, $abgewiesen, 'Normalbetrieb muss eine Zwischenstufe ablehnen.'); $anforderungSenden($stationId, 4150, 'Peak'); $test->assertSame( '[0,4150,4850,5550,6250,6950,7600,8300,9000,9700,10300,11000]', (string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId)) ); $test->assertTrue(str_contains( (string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)), 'amp=6' ), 'Peak ohne Solarladen muss die Ladestufen annehmen.'); IPS_RequestAction($stationId, 'Solarladen', true); $anforderungSenden($stationId, 0, 'Peak'); $test->assertSame( '[0]', (string) GetValue($test->objectByIdent('LeistungsangebotDiagnose', $stationId)) ); $test->assertTrue(str_contains( (string) GetValue($test->objectByIdent('LetzterGeraetebefehl', $stationId)), 'alw=0' ), 'Peak mit Solarladen muss die Ladestation stoppen.'); }); };