diff --git a/Home Connect Device/module.php b/Home Connect Device/module.php index 2900695..fb01e74 100644 --- a/Home Connect Device/module.php +++ b/Home Connect Device/module.php @@ -56,6 +56,13 @@ public function Create() $this->ConnectParent('{CE76810D-B685-9BE0-CC04-38B204DEAD5E}'); + $parent = IPS_GetInstance($this->InstanceID)['ConnectionID']; + if (IPS_InstanceExists($parent)) { + $this->RegisterMessage($parent, IM_CHANGESTATUS); + } + $this->RegisterMessage($this->InstanceID, FM_CONNECT); + $this->RegisterMessage($this->InstanceID, FM_DISCONNECT); + $this->RegisterPropertyString('HaID', ''); $this->RegisterPropertyString('DeviceType', ''); @@ -122,18 +129,37 @@ public function ApplyChanges() parent::ApplyChanges(); if (IPS_GetKernelRunlevel() === KR_READY) { - if ($this->HasActiveParent() && $this->ReadPropertyString('HaID')) { - $this->SetSummary($this->ReadPropertyString('HaID')); - $this->InitializeDevice(); - $this->SetStatus(IS_ACTIVE); - } else { - $this->SetStatus(IS_INACTIVE); - } + $this->refreshDeviceState(true); } $this->SetReceiveDataFilter('.*' . $this->ReadPropertyString('HaID') . '.*'); } + public function MessageSink($Timestamp, $SenderID, $MessageID, $Data) + { + //Never delete this line! + parent::MessageSink($Timestamp, $SenderID, $MessageID, $Data); + + $parentID = IPS_GetInstance($this->InstanceID)['ConnectionID']; + if ($SenderID == $parentID && $MessageID == IM_CHANGESTATUS) { + $this->refreshDeviceState($Data[0] == IS_ACTIVE); + return; + } + + if ($SenderID == $this->InstanceID) { + switch ($MessageID) { + case FM_CONNECT: + $this->RegisterMessage($Data[0], IM_CHANGESTATUS); + $this->refreshDeviceState(true); + return; + + case FM_DISCONNECT: + $this->SetStatus(IS_INACTIVE); + return; + } + } + } + public function ReceiveData($String) { $this->SendDebug('ReceiveData', $String, 0); @@ -412,6 +438,20 @@ public function RequestDataFromParent(string $endpoint, string $payload = '') return $response; } + private function refreshDeviceState(bool $initializeDevice): void + { + if ($this->HasActiveParent() && $this->ReadPropertyString('HaID')) { + $this->SetSummary($this->ReadPropertyString('HaID')); + if ($initializeDevice) { + $this->InitializeDevice(); + } + $this->SetStatus(IS_ACTIVE); + return; + } + + $this->SetStatus(IS_INACTIVE); + } + private function createPrograms() { $rawPrograms = json_decode($this->RequestDataFromParent('homeappliances/' . $this->ReadPropertyString('HaID') . '/programs'), true); @@ -921,12 +961,12 @@ private function createVariableFromConstraints($profileName, $data, $attribute, switch ($variableType) { case VARIABLETYPE_INTEGER: case VARIABLETYPE_FLOAT: - $constraints = $data['constraints']; + $constraints = isset($data['constraints']) && is_array($data['constraints']) ? $data['constraints'] : []; if (!IPS_VariableProfileExists($profileName)) { //Create profile IPS_CreateVariableProfile($profileName, $variableType); } - IPS_SetVariableProfileText($profileName, '', ' ' . $data['unit']); + IPS_SetVariableProfileText($profileName, '', isset($data['unit']) ? ' ' . $data['unit'] : ''); $min = isset($constraints['min']) ? $constraints['min'] : 0; $max = isset($constraints['max']) ? $constraints['max'] : 86340; IPS_SetVariableProfileValues($profileName, $min, $max, isset($constraints['stepsize']) ? $constraints['stepsize'] : 1); @@ -938,7 +978,7 @@ private function createVariableFromConstraints($profileName, $data, $attribute, break; default: - $constraints = $data['constraints']; + $constraints = isset($data['constraints']) && is_array($data['constraints']) ? $data['constraints'] : []; $variableType = VARIABLETYPE_STRING; if (!IPS_VariableProfileExists($profileName)) { //Create profile @@ -946,9 +986,11 @@ private function createVariableFromConstraints($profileName, $data, $attribute, } //Add potential new options $newAssociations = []; - for ($i = 0, $size = count($constraints['allowedvalues']); $i < $size; $i++) { - $displayName = isset($constraints['displayvalues'][$i]) ? $constraints['displayvalues'][$i] : $this->getLastSnippet($constraints['allowedvalues'][$i]); - $newAssociations[$constraints['allowedvalues'][$i]] = $displayName; + $allowedValues = isset($constraints['allowedvalues']) && is_array($constraints['allowedvalues']) ? $constraints['allowedvalues'] : []; + $displayValues = isset($constraints['displayvalues']) && is_array($constraints['displayvalues']) ? $constraints['displayvalues'] : []; + for ($i = 0, $size = count($allowedValues); $i < $size; $i++) { + $displayName = isset($displayValues[$i]) ? $displayValues[$i] : $this->getLastSnippet($allowedValues[$i]); + $newAssociations[$allowedValues[$i]] = $displayName; } $newAssociations = $this->sortAssociations($data['key'], $newAssociations); diff --git a/tests/HomeConnectOvenTest.php b/tests/HomeConnectOvenTest.php index d331b8a..f292d5a 100644 --- a/tests/HomeConnectOvenTest.php +++ b/tests/HomeConnectOvenTest.php @@ -41,16 +41,18 @@ public function testBaseFunctionality() IPS_SetProperty($oven, 'HaID', 'SIEMENS-HB676G5S6-68A40E2F702D'); IPS_SetProperty($oven, 'DeviceType', 'Oven'); IPS_ApplyChanges($oven); + + $intf = IPS\InstanceManager::getInstanceInterface($oven); + $intf->ReceiveData($this->generateTestData(52)); $initialVar = IPS_GetObjectIDByIdent('CurrentCavityTemperature', $oven); $this->assertEquals(VARIABLETYPE_INTEGER, $this->getValueType($oven)); - $intf = IPS\InstanceManager::getInstanceInterface($oven); $intf->ReceiveData($this->generateTestData(50.99)); $newFloat = IPS_GetObjectIDByIdent('CurrentCavityTemperature', $oven); $this->assertNotEquals($newFloat, $initialVar); $this->assertEquals(VARIABLETYPE_FLOAT, $this->getValueType($oven)); - $intf->ReceiveData($this->generateTestData(52)); + $intf->ReceiveData($this->generateTestData(54)); $this->assertEquals($newFloat, IPS_GetObjectIDByIdent('CurrentCavityTemperature', $oven)); $this->assertEquals(VARIABLETYPE_FLOAT, $this->getValueType($oven)); @@ -59,6 +61,54 @@ public function testBaseFunctionality() $this->assertEquals(VARIABLETYPE_FLOAT, $this->getValueType($oven)); } + public function testReactivatesAfterParentStatusChange() + { + $oven = IPS_CreateInstance('{F29DF312-A62E-9989-1F1A-0D1E1D171AD3}'); + $parent = IPS_GetInstance($oven)['ConnectionID']; + + IPS\InstanceManager::setStatus($parent, IS_INACTIVE); + + IPS_SetProperty($oven, 'HaID', 'SIEMENS-HB676G5S6-68A40E2F702D'); + IPS_SetProperty($oven, 'DeviceType', 'Oven'); + IPS_ApplyChanges($oven); + + $this->assertEquals(IS_INACTIVE, IPS_GetInstance($oven)['InstanceStatus']); + + IPS\InstanceManager::setStatus($parent, IS_ACTIVE); + $intf = IPS\InstanceManager::getInstanceInterface($oven); + $intf->MessageSink(0, $parent, IM_CHANGESTATUS, [IS_ACTIVE]); + + $this->assertEquals(IS_ACTIVE, IPS_GetInstance($oven)['InstanceStatus']); + } + + public function testStringSettingWithoutAllowedValuesDoesNotCrash() + { + $oven = IPS_CreateInstance('{F29DF312-A62E-9989-1F1A-0D1E1D171AD3}'); + $intf = IPS\InstanceManager::getInstanceInterface($oven); + + $method = new ReflectionMethod($intf, 'createVariableFromConstraints'); + $method->setAccessible(true); + $method->invoke( + $intf, + 'HomeConnect.Test.StringSetting', + [ + 'key' => 'Dishcare.Dishwasher.Setting.ProgramInfo', + 'name' => 'Program Info', + 'type' => 'String', + 'constraints' => [ + 'access' => 'readWrite' + ] + ], + 'Setting', + 1 + ); + + $variableID = IPS_GetObjectIDByIdent('ProgramInfo', $oven); + $this->assertNotFalse($variableID); + $this->assertEquals(VARIABLETYPE_STRING, IPS_GetVariable($variableID)['VariableType']); + $this->assertCount(0, IPS_GetVariableProfile('HomeConnect.Test.StringSetting')['Associations']); + } + private function generateTestData($tempValue) { $data = [ @@ -124,4 +174,4 @@ private function getChildrenValues($id) } return $result; } -} \ No newline at end of file +}