props[$key] ?? 0; } protected function ReadPropertyBoolean($key) { return $this->props[$key] ?? false; } protected function ReadAttributeInteger($key) { return $this->attrs[$key] ?? 0; } protected function ReadAttributeBoolean($key) { return $this->attrs[$key] ?? false; } protected function ReadAttributeString($key) { return $this->attrs[$key] ?? ''; } protected function WriteAttributeInteger($key, $value) { $this->attrs[$key] = $value; } protected function WriteAttributeBoolean($key, $value) { $this->attrs[$key] = $value; } protected function WriteAttributeString($key, $value) { $this->attrs[$key] = $value; } } function IPS_GetObjectIDByIdent($ident, $parent) { return false; } function RequestAction($id, $value) { $GLOBALS['writes'][] = [$id, $value]; return $GLOBALS['accepted']; } require_once __DIR__ . '/../../Batterie/module.php'; $battery = new Batterie(); $battery->InstanceID = 44234; $battery->props = [ 'Batterietyp' => Belevo\EnelixEMS\BatterieRegler::TYP_GOODWE, 'Batteriemanagement' => Belevo\EnelixEMS\BatterieRegler::STEUERUNG_ENELIX, 'ManagementRegisterVariableID' => 1, 'ModusRegisterVariableID' => 2, 'LeistungsRegisterVariableID' => 3, 'Aenderungssperre' => 0, ]; $method = new ReflectionMethod(Batterie::class, 'schreibeRegister'); $accepted = false; $writes = []; try { $method->invoke($battery, 12000, false); throw new LogicException('FALSE was accepted'); } catch (RuntimeException $error) { if (!str_contains($error->getMessage(), 'Registeraktion nicht bestaetigt')) throw $error; } if (($battery->attrs['RegisterInitialisiert'] ?? false) || ($battery->attrs['RegisterSchreiben'] ?? false)) { throw new RuntimeException('Failed action cached or lock not released'); } $accepted = true; $method->invoke($battery, 12000, false); if (($battery->attrs['LetzterSollwert'] ?? 0) !== 12000 || !$battery->attrs['RegisterInitialisiert']) { throw new RuntimeException('Successful retry not cached'); } echo "PASS actual module rejects FALSE register action, releases guard and retries successfully\n";