diff --git a/ClimacontrolRegulator/form.json b/ClimacontrolRegulator/form.json index 52c1c39..d690049 100644 --- a/ClimacontrolRegulator/form.json +++ b/ClimacontrolRegulator/form.json @@ -6,7 +6,6 @@ "caption": "Address" }, { - "visible": false, "type": "ExpansionPanel", "caption": "Schedule", "expanded": true, @@ -16,94 +15,6 @@ "type": "CheckBox", "caption": "Schedule", "width": "250px" - }, - { - "type": "RowLayout", - "items": [ - { - "name": "ScheduleMinTemp", - "type": "NumberSpinner", - "caption": "lowest temperature", - "digits": 0, - "minimum": 5, - "maximum": 17, - "suffix": " °C", - "width": "250px" - }, - { - "name": "ScheduleMaxTemp", - "type": "NumberSpinner", - "caption": "highest temperature", - "digits": 0, - "minimum": 18, - "maximum": 30, - "suffix": " °C", - "width": "250px" - }, - { - "name": "ScheduleStepsTemp", - "type": "Select", - "caption": "temperature steps", - "options": [ - { - "caption": "0,5 °C", - "value": 1 - }, - { - "caption": "1,0 °C", - "value": 2 - }, - { - "caption": "2 °C", - "value": 4 - }, - { - "caption": "3 °C", - "value": 6 - }, - { - "caption": "4 °C", - "value": 8 - }, - { - "caption": "5 °C", - "value": 10 - }, - { - "caption": "6 °C", - "value": 12 - }, - { - "caption": "7 °C", - "value": 14 - }, - { - "caption": "8 °C", - "value": 16 - } - ], - "width": "250px" - } - ] - }, - { - "type": "RowLayout", - "items": [ - { - "name": "ScheduleMinColor", - "type": "SelectColor", - "caption": "lowest temperature color", - "allowTransparent ": false, - "width": "250px" - }, - { - "name": "ScheduleMaxColor", - "type": "SelectColor", - "caption": "highest temperature color", - "allowTransparent ": false, - "width": "250px" - } - ] } ] }, diff --git a/ClimacontrolRegulator/locale.json b/ClimacontrolRegulator/locale.json index d58ba6b..26e019c 100644 --- a/ClimacontrolRegulator/locale.json +++ b/ClimacontrolRegulator/locale.json @@ -4,6 +4,7 @@ "Address": "Adresse", "Optional status variables": "Optionale Statusvariablen", "Schedule": "Zeitplan", + "Schedule save": "Zeitplan speichern", "Temperature": "Temperatur", "Setpoint temperature": "Solltemperatur", "Operation mode": "Betriebsart", diff --git a/ClimacontrolRegulator/module.php b/ClimacontrolRegulator/module.php index edd40e5..fc69f90 100644 --- a/ClimacontrolRegulator/module.php +++ b/ClimacontrolRegulator/module.php @@ -8,23 +8,26 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ -require_once __DIR__ . '/../libs/HMDeviceBase.php'; // HMBase Klasse +require_once __DIR__ . '/../libs/HMHeatingDevice.php'; // HMBase Klasse /** * HomeMaticClimateControlRegulator - * Erweitert HMDeviceBase. Gerät: HM-CC-TC - * + * Erweitert HMHeatingDevice. Gerät: HM-CC-TC */ -class HomeMaticClimateControlRegulator extends HMDeviceBase +class HomeMaticClimateControlRegulator extends HMHeatingDevice { public const DeviceTyp = \HMExtended\DeviceType::ClimacontrolRegulator; public const ValuesChannel = \HMExtended\Channels::Second; public const ParamChannel = \HMExtended\Channels::Second; + + protected const WeekScheduleIndexTemp = 'TEMPERATUR_%2$s_%1$d'; + protected const WeekScheduleIndexEndTime = 'TIMEOUT_%2$s_%1$d'; + protected const NumberOfTimeSlot = 24; /** * Interne Funktion des SDK. */ @@ -118,7 +121,7 @@ public function RequestAction($Ident, $Value) return; } - protected function SetParamVariable(array $Params) + protected function SetParamVariables(array $Params) { $d = new DateTime(); $d->setTime( @@ -137,14 +140,12 @@ protected function SetParamVariable(array $Params) ); $i = new DateInterval('P' . $Params[\HMExtended\ClimacontrolRegulator::PARTY_END_DAY] . 'D'); $Params[\HMExtended\ClimacontrolRegulator::PARTY_END_TIME] = $d->add($i)->getTimestamp(); - foreach ($Params as $Ident => $Value) { - @$this->SetValue($Ident, $Value); - } + parent::SetParamVariables($Params); } protected function SetVariable(string $Ident, $Value) { - @$this->SetValue($Ident, $Value); + parent::SetVariable($Ident, $Value); switch ($Ident) { case \HMExtended\ClimacontrolRegulator::SETPOINT: IPS_RunScriptText('IPS_RequestAction(' . $this->InstanceID . ',"getParam",0);'); diff --git a/DisplayStatusAnzeige/README.md b/DisplayStatusAnzeige/README.md index f851fac..b6d924e 100644 --- a/DisplayStatusAnzeige/README.md +++ b/DisplayStatusAnzeige/README.md @@ -44,7 +44,7 @@ Dieses Modul ist Bestandteil der [HomeMaticExtended-Library](../). Ebenso ist das Timeout einstellbar, nach wieviel Sekunden wieder auf Seite 1 gesprungen wird. ![Instanzen](../docs/HMExtendedInstanzen.png) - Unter Instanz hinzufügen ist das Gerät 'HomeMatic WM55-Dis' unter dem Hersteller 'HomeMatic' zu finden. + Unter Instanz hinzufügen ist das Gerät 'HomeMatic Dis-WM55' unter dem Hersteller 'HomeMatic' zu finden. Nach dem Anlegen der Instanz sollte als übergeordnetes Gerät schon der HomeMatic Socket ausgewählt sein. Existieren in IPS mehrere Homematic Socket, so ist der auszuwählen, an welcher CCU das Statusdisplay angelernt ist. diff --git a/DisplayStatusAnzeige/module.php b/DisplayStatusAnzeige/module.php index 2fe234b..f88c97c 100644 --- a/DisplayStatusAnzeige/module.php +++ b/DisplayStatusAnzeige/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse diff --git a/ExtendedConfigurator/module.php b/ExtendedConfigurator/module.php index 8bfa85e..efecd94 100644 --- a/ExtendedConfigurator/module.php +++ b/ExtendedConfigurator/module.php @@ -8,22 +8,22 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse require_once __DIR__ . '/../libs/HMTypes.php'; // HMTypes Data + /** * HomeMaticExtendedConfigurator ist die Klasse für das IPS-Modul 'HomeMatic Extended Configurator'. * Erweitert HMBase. - * - * @property array $DeviceNames */ class HomeMaticExtendedConfigurator extends HMBase { private $DeviceData = []; + private $listDevices = []; private $DeviceTyp = ''; /** * Interne Funktion des SDK. @@ -34,7 +34,6 @@ public function Create() $this->RegisterHMPropertys('XXX9999994'); $this->RegisterPropertyBoolean(\HMExtended\Device\Property::EmulateStatus, false); $this->RegisterPropertyInteger('Interval', 0); - //$this->DeviceNames = []; } /** @@ -46,17 +45,6 @@ public function ApplyChanges() } //################# PUBLIC - /** - * IPS-Instanz-Funktion 'HM_ReadRFInterfaces'. - * Liest die Daten der RF-Interfaces und versendet sie an die Children. - * - * @return bool True bei Erfolg, sonst false. - */ - public function Test(string $MethodName, int $Protocol, array $Data) - { - return $this->SendRPC($MethodName, $Protocol, $Data); - } - /** * Interne Funktion des SDK. */ @@ -82,71 +70,10 @@ public function GetConfigurationForm() return json_encode($Form); } - /* - $DevicesIDs = IPS_GetInstanceListByModuleID('{36549B96-FA11-4651-8662-F310EEEC5C7D}'); - $InstanceIDList = []; - foreach ($DevicesIDs as $DeviceID) { - if (IPS_GetInstance($DeviceID)['ConnectionID'] == $ParentId) { - $InstanceIDList[$DeviceID] = IPS_GetProperty($DeviceID, \HMExtended\Device\Property::Address); - } - } - $Liste = []; - $Result = $this->GetInterfaces(); - foreach ($Result as $ProtocolID => $Protocol) { - if (!is_array($Protocol)) { - continue; - } - foreach ($Protocol as $InterfaceIndex => $Interface) { - switch ($ProtocolID) { - case 0: - $Type = 'Funk'; - break; - case 2: - $Type = 'HmIP'; - break; - default: - $Type = 'unknown'; - break; - } - $InstanceID = array_search($Interface['ADDRESS'], $InstanceIDList); - if ($InstanceID !== false) { - $AddValue = [ - 'instanceID' => $InstanceID, - 'name' => IPS_GetName($InstanceID), - 'type' => $Type, - 'address' => $Interface['ADDRESS'], - 'location' => stristr(IPS_GetLocation($InstanceID), IPS_GetName($InstanceID), true) - ]; - unset($InstanceIDList[$InstanceID]); - } else { - $AddValue = [ - 'instanceID' => 0, - 'name' => $Interface['TYPE'], - 'type' => $Type, - 'address' => $Interface['ADDRESS'], - 'location' => '' - ]; - } - $AddValue['create'] = [ - 'moduleID' => '{36549B96-FA11-4651-8662-F310EEEC5C7D}', - 'configuration' => [\HMExtended\Device\Property::Address => $Interface['ADDRESS']] - ]; - $Liste[] = $AddValue; - } - } - foreach ($InstanceIDList as $InstanceID => $Address) { - $AddValue = [ - 'instanceID' => $InstanceID, - 'name' => IPS_GetName($InstanceID), - 'type' => 'unknown', - 'address' => $Address, - 'location' => stristr(IPS_GetLocation($InstanceID), IPS_GetName($InstanceID), true) - ]; - $Liste[] = $AddValue; - } - */ $this->DeviceData = $this->LoadDeviceData(); if (IPS_GetProperty($ParentId, 'RFOpen')) { + //$Form['actions'][0]['values'] = array_merge($Form['actions'][0]['values'], $this->GetConfigRows(0, \HMExtended\GUID::Powermeter)); + //$Form['actions'][0]['values'] = array_merge($Form['actions'][0]['values'], $this->GetConfigRows(0, \HMExtended\GUID::Dis_WM55)); $Form['actions'][0]['values'] = array_merge($Form['actions'][0]['values'], $this->GetConfigRows(0, \HMExtended\GUID::ClimacontrolRegulator)); } if (IPS_GetProperty($ParentId, 'GROpen')) { @@ -199,6 +126,7 @@ private function GetConfigRows(int $Protocol, string $GUID) ]; $Devices = $this->GetDevices($Protocol, \HMExtended\DeviceType::$GuidToType[$GUID]); + $this->SendDebug('Devices', $Devices, 0); $IPSDevices = $this->GetInstanceList($GUID, \HMExtended\Device\Property::Address); foreach ($Devices as &$Device) { $Device = array_change_key_case($Device); @@ -253,17 +181,28 @@ private function GetDeviceData(int $Protocol, array &$Device) } } - private function GetDevices(int $Protocol, string $Type) + private function GetDevices(int $Protocol, array $Types) { - $Result = $this->SendRPC('listDevices', $Protocol, []); - if ($Result === false) { - return []; + if (!array_key_exists($Protocol, $this->listDevices)) { + $Devices = $this->SendRPC('listDevices', $Protocol, []); + if ($Devices === false) { + return []; + } + $this->listDevices[$Protocol] = $Devices; + } else { + $Devices = $this->listDevices[$Protocol]; + } + $Result = []; + foreach ($Types as $Type) { + $this->DeviceTyp = $Type; + $Result = array_merge( + $Result, + array_filter($Devices, function ($Device) + { + return $Device['TYPE'] == $this->DeviceTyp; + }) + ); } - $this->DeviceTyp = $Type; - $Result = array_filter($Result, function ($Device) - { - return $Device['TYPE'] == $this->DeviceTyp; - }); return array_values($Result); } @@ -316,7 +255,7 @@ private function SendRPC(string $MethodName, int $Protocol, array $Data) 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => $Protocol, 'MethodName' => $MethodName, - 'WaitTime' => 5000, + 'WaitTime' => 3, 'Data' => $Data ]; $this->SendDebug('Send', $ParentData, 0); @@ -326,8 +265,8 @@ private function SendRPC(string $MethodName, int $Protocol, array $Data) $this->SendDebug('Error', '', 0); return false; } + $this->SendDebug('Receive', $ResultJSON, 0); $Result = json_decode(utf8_encode($ResultJSON), true); - $this->SendDebug('Receive', $Result, 0); return $Result; } } diff --git a/HeatingGroup/form.json b/HeatingGroup/form.json index d0bc133..c7e0327 100644 --- a/HeatingGroup/form.json +++ b/HeatingGroup/form.json @@ -20,103 +20,12 @@ "width": "250px" }, { - "visible": false, "name": "enable_SCHEDULE", "type": "CheckBox", "caption": "Schedule", "width": "250px" } ] - }, - { - "visible": false, - "type": "RowLayout", - "items": [ - { - "name": "ScheduleMinTemp", - "type": "NumberSpinner", - "caption": "lowest temperature", - "digits": 0, - "minimum": 5, - "maximum": 17, - "suffix": " °C", - "width": "250px" - }, - { - "name": "ScheduleMaxTemp", - "type": "NumberSpinner", - "caption": "highest temperature", - "digits": 0, - "minimum": 18, - "maximum": 30, - "suffix": " °C", - "width": "250px" - }, - { - "name": "ScheduleStepsTemp", - "type": "Select", - "caption": "temperature steps", - "options": [ - { - "caption": "0,5 °C", - "value": 1 - }, - { - "caption": "1,0 °C", - "value": 2 - }, - { - "caption": "2 °C", - "value": 4 - }, - { - "caption": "3 °C", - "value": 6 - }, - { - "caption": "4 °C", - "value": 8 - }, - { - "caption": "5 °C", - "value": 10 - }, - { - "caption": "6 °C", - "value": 12 - }, - { - "caption": "7 °C", - "value": 14 - }, - { - "caption": "8 °C", - "value": 16 - } - ], - "width": "250px" - } - ] - }, - { - "visible": false, - "type": "RowLayout", - "items": [ - { - "name": "ScheduleMinColor", - "type": "SelectColor", - "caption": "lowest temperature color", - "allowTransparent ": false, - "width": "250px" - }, - { - "name": "ScheduleMaxColor", - "type": "SelectColor", - "caption": "highest temperature color", - "allowTransparent ": false, - "width": "250px" - } - ] } ] }, diff --git a/HeatingGroup/locale.json b/HeatingGroup/locale.json index e38eb1b..9c25a6b 100644 --- a/HeatingGroup/locale.json +++ b/HeatingGroup/locale.json @@ -5,6 +5,8 @@ "Optional status variables": "Optionale Statusvariablen", "Control": "Regelung", "Schedule": "Zeitplan", + "Schedule save in profile": "Zeitplan speichern in Profil", + "Schedule save": "Zeitplan speichern", "On": "An", "Off": "Aus", "Start": "Ausführen", diff --git a/HeatingGroup/module.php b/HeatingGroup/module.php index 0953a16..da93e2a 100644 --- a/HeatingGroup/module.php +++ b/HeatingGroup/module.php @@ -8,22 +8,26 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ -require_once __DIR__ . '/../libs/HMDeviceBase.php'; // HMBase Klasse +require_once __DIR__ . '/../libs/HMHeatingDevice.php'; // HMBase Klasse /** * HomeMaticHeatingGroup - * Erweitert HMDeviceBase Virtuelles Gerät: HM-CC-VG-1 + * Erweitert HMHeatingDevice Virtuelles Gerät: HM-CC-VG-1 */ -class HomeMaticHeatingGroup extends HMDeviceBase +class HomeMaticHeatingGroup extends HMHeatingDevice { public const DeviceTyp = \HMExtended\DeviceType::HeatingGroup; public const ValuesChannel = \HMExtended\Channels::First; public const ParamChannel = \HMExtended\Channels::Device; + + protected const NumberOfWeekSchedules = 3; + protected const SelectedWeekScheduleIdent = \HMExtended\HeatingGroup::WEEK_PROGRAM_POINTER; + /** * Interne Funktion des SDK. */ @@ -190,13 +194,16 @@ public function RequestAction($Ident, $Value) if ($this->PutParamSet([$Ident=>$SendValue], true)) { $this->SetValue($Ident, $Value); } + if ($Ident == \HMExtended\HeatingGroup::WEEK_PROGRAM_POINTER) { + $this->RefreshScheduleObject(); + } return; } trigger_error($this->Translate('Invalid Ident.') . ' (' . $Ident . ')', E_USER_NOTICE); return; } - protected function SetParamVariable(array $Params) + protected function SetParamVariables(array $Params) { $d = new DateTime(); $d->setTime( @@ -210,9 +217,7 @@ protected function SetParamVariable(array $Params) $Params[\HMExtended\HeatingGroup::BOOST_TIME_PERIOD] * 5; $Params[\HMExtended\HeatingGroup::WEEK_PROGRAM_POINTER]++; - foreach ($Params as $Ident => $Value) { - @$this->SetValue($Ident, $Value); - } + parent::SetParamVariables($Params); } protected function SetVariable(string $Ident, $Value) @@ -259,7 +264,7 @@ protected function SetVariable(string $Ident, $Value) $Value = 0; break; } - @$this->SetValue($Ident, $Value); + parent::SetVariable($Ident, $Value); } //################# PRIVATE } diff --git a/HeatingGroupHmIP/form.json b/HeatingGroupHmIP/form.json index 0b354cb..de8743e 100644 --- a/HeatingGroupHmIP/form.json +++ b/HeatingGroupHmIP/form.json @@ -20,103 +20,12 @@ "width": "250px" }, { - "visible": false, "name": "enable_SCHEDULE", "type": "CheckBox", "caption": "Schedule", "width": "250px" } ] - }, - { - "visible": false, - "type": "RowLayout", - "items": [ - { - "name": "ScheduleMinTemp", - "type": "NumberSpinner", - "caption": "lowest temperature", - "digits": 0, - "minimum": 5, - "maximum": 17, - "suffix": " °C", - "width": "250px" - }, - { - "name": "ScheduleMaxTemp", - "type": "NumberSpinner", - "caption": "highest temperature", - "digits": 0, - "minimum": 18, - "maximum": 30, - "suffix": " °C", - "width": "250px" - }, - { - "name": "ScheduleStepsTemp", - "type": "Select", - "caption": "temperature steps", - "options": [ - { - "caption": "0,5 °C", - "value": 1 - }, - { - "caption": "1,0 °C", - "value": 2 - }, - { - "caption": "2 °C", - "value": 4 - }, - { - "caption": "3 °C", - "value": 6 - }, - { - "caption": "4 °C", - "value": 8 - }, - { - "caption": "5 °C", - "value": 10 - }, - { - "caption": "6 °C", - "value": 12 - }, - { - "caption": "7 °C", - "value": 14 - }, - { - "caption": "8 °C", - "value": 16 - } - ], - "width": "250px" - } - ] - }, - { - "visible": false, - "type": "RowLayout", - "items": [ - { - "name": "ScheduleMinColor", - "type": "SelectColor", - "caption": "lowest temperature color", - "allowTransparent ": false, - "width": "250px" - }, - { - "name": "ScheduleMaxColor", - "type": "SelectColor", - "caption": "highest temperature color", - "allowTransparent ": false, - "width": "250px" - } - ] } ] }, diff --git a/HeatingGroupHmIP/locale.json b/HeatingGroupHmIP/locale.json index 2d4d5db..6675a2c 100644 --- a/HeatingGroupHmIP/locale.json +++ b/HeatingGroupHmIP/locale.json @@ -5,6 +5,8 @@ "Optional status variables": "Optionale Statusvariablen", "Control": "Regelung", "Schedule": "Zeitplan", + "Schedule save in profile": "Zeitplan speichern in Profil", + "Schedule save": "Zeitplan speichern", "On": "An", "Off": "Aus", "Active profile": "Aktives Zeitprofil", diff --git a/HeatingGroupHmIP/module.php b/HeatingGroupHmIP/module.php index c225b1d..c51430c 100644 --- a/HeatingGroupHmIP/module.php +++ b/HeatingGroupHmIP/module.php @@ -8,22 +8,26 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ -require_once __DIR__ . '/../libs/HMDeviceBase.php'; // HMBase Klasse +require_once __DIR__ . '/../libs/HMHeatingDevice.php'; // HMBase Klasse /** * HomeMaticIPHeatingGroup - * Erweitert HMDeviceBase Virtuelles Gerät: HmIP-HEATING + * Erweitert HMHeatingDevice Virtuelles Gerät: HmIP-HEATING */ -class HomeMaticIPHeatingGroup extends HMDeviceBase +class HomeMaticIPHeatingGroup extends HMHeatingDevice { - public const DeviceTyp = \HMExtended\DeviceType::HeatingGroupHmIP; - public const ValuesChannel = \HMExtended\Channels::First; - public const ParamChannel = \HMExtended\Channels::First; + protected const DeviceTyp = \HMExtended\DeviceType::HeatingGroupHmIP; + protected const ValuesChannel = \HMExtended\Channels::First; + protected const ParamChannel = \HMExtended\Channels::First; + + protected const NumberOfWeekSchedules = 6; + protected const SelectedWeekScheduleIdent = \HMExtended\HeatingGroupHmIP::ACTIVE_PROFILE; + /** * Interne Funktion des SDK. */ @@ -118,7 +122,7 @@ public function RequestAction($Ident, $Value) return; } - protected function SetParamVariable(array $Params) + protected function SetParamVariables(array $Params) { $d = new DateTime(); $d->setTime( @@ -129,28 +133,31 @@ protected function SetParamVariable(array $Params) ); $Params[\HMExtended\HeatingGroupHmIP::DECALCIFICATION_TIME] = $d->getTimestamp(); - foreach ($Params as $Ident => $Value) { - @$this->SetValue($Ident, $Value); - } + parent::SetParamVariables($Params); } protected function SetVariable(string $Ident, $Value) { switch ($Ident) { + case \HMExtended\HeatingGroupHmIP::ACTIVE_PROFILE: + $OldValue = $this->GetValue($Ident); + break; case \HMExtended\HeatingGroupHmIP::PARTY_TIME_START: case \HMExtended\HeatingGroupHmIP::PARTY_TIME_END: if ($Value == '1999_11_30 00:00') { - $TimeStamp = time(); + $Value = time(); } else { $d = DateTime::createFromFormat('Y_m_d H:i', $Value); - $TimeStamp = ($d->getTimestamp() < 7200) ? time() : $d->getTimestamp(); + $Value = ($d->getTimestamp() < 7200) ? time() : $d->getTimestamp(); } - @$this->SetValue($Ident, $TimeStamp); - break; - default: - @$this->SetValue($Ident, $Value); break; } + parent::SetVariable($Ident, $Value); + if ($Ident == \HMExtended\HeatingGroupHmIP::ACTIVE_PROFILE) { + if ($OldValue != $Value) { + $this->RefreshScheduleObject(); + } + } } //################# PRIVATE } diff --git a/HomeMaticScript/module.php b/HomeMaticScript/module.php index f7fc1b4..525e7f4 100644 --- a/HomeMaticScript/module.php +++ b/HomeMaticScript/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; diff --git a/ParaInterface/module.php b/ParaInterface/module.php index ca32b41..f74b313 100644 --- a/ParaInterface/module.php +++ b/ParaInterface/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse @@ -141,8 +141,8 @@ private function GetParamset() 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => $this->ReadPropertyInteger(\HMExtended\Device\Property::Protocol), 'MethodName' => 'getParamset', - 'WaitTime' => 5000, - 'Data' => [$this->ReadPropertyString(\HMExtended\Device\Property::Address), 'MASTER'] + 'WaitTime' => 3, + 'Data' => [$this->ReadPropertyString(\HMExtended\Device\Property::Address), \HMExtended\CCU::MASTER] ]; $this->SendDebug('Send', $ParentData, 0); @@ -174,8 +174,8 @@ private function PutParamSet(array $Parameter) 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => $this->ReadPropertyInteger(\HMExtended\Device\Property::Protocol), 'MethodName' => 'PutParamSet', - 'WaitTime' => ($EmulateStatus ? 1 : 5000), - 'Data' => [$this->ReadPropertyString(\HMExtended\Device\Property::Address), 'MASTER', json_encode($Parameter)] + 'WaitTime' => 3, + 'Data' => [$this->ReadPropertyString(\HMExtended\Device\Property::Address), \HMExtended\CCU::MASTER, json_encode($Parameter)] ]; $this->SendDebug('Send', $ParentData, 0); diff --git a/PowerMeter/module.php b/PowerMeter/module.php index 9d017ea..8db477c 100644 --- a/PowerMeter/module.php +++ b/PowerMeter/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse diff --git a/Programme/module.php b/Programme/module.php index c8ad5f6..1cbbf43 100644 --- a/Programme/module.php +++ b/Programme/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse diff --git a/README.md b/README.md index cdac1c5..4005a43 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![SDK](https://img.shields.io/badge/Symcon-PHPModul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/) -[![Version](https://img.shields.io/badge/Modul%20version-3.50-blue.svg)]() +[![Version](https://img.shields.io/badge/Modul%20version-3.70-blue.svg)]() [![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) [![Version](https://img.shields.io/badge/Symcon%20Version-6.1%20%3E-green.svg)](https://community.symcon.de/t/ip-symcon-6-1-stable-changelog/40276) [![Check Style](https://github.com/Nall-chan/HomematicExtended/workflows/Check%20Style/badge.svg)](https://github.com/Nall-chan/HomematicExtended/actions) [![Run Tests](https://github.com/Nall-chan/HomematicExtended/workflows/Run%20Tests/badge.svg)](https://github.com/Nall-chan/HomematicExtended/actions) @@ -140,6 +140,10 @@ Erweitert IPS um die native Unterstützung von: ### 2. Changelog +Version 3.70: + +* Zeitprofile der Heizgruppen und des HM-CC-TC werden als Wochenplan in IPS dargestellt und können dort bearbeitet werden. + Version 3.60: **Profile vor dem Update löschen:** diff --git a/RFInterface/module.php b/RFInterface/module.php index 54708ff..fa961dd 100644 --- a/RFInterface/module.php +++ b/RFInterface/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse diff --git a/RFInterfaceConfigurator/module.php b/RFInterfaceConfigurator/module.php index 2ecb835..1326ba9 100644 --- a/RFInterfaceConfigurator/module.php +++ b/RFInterfaceConfigurator/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse diff --git a/RFInterfaceSplitter/module.php b/RFInterfaceSplitter/module.php index 659724f..3e00144 100644 --- a/RFInterfaceSplitter/module.php +++ b/RFInterfaceSplitter/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse @@ -178,7 +178,7 @@ private function GetInterfaces() 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => 0, 'MethodName' => 'listBidcosInterfaces', - 'WaitTime' => 5000, + 'WaitTime' => 3, 'Data' => $data ]; $ret = []; diff --git a/Systemvariablen/module.php b/Systemvariablen/module.php index 47479f9..fc05ba8 100644 --- a/Systemvariablen/module.php +++ b/Systemvariablen/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse diff --git a/WRInterface/module.php b/WRInterface/module.php index fbaa5c6..66a4ce4 100644 --- a/WRInterface/module.php +++ b/WRInterface/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse @@ -186,7 +186,7 @@ private function GetInterface() 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => 1, 'MethodName' => 'getLGWStatus', - 'WaitTime' => 5000, + 'WaitTime' => 3, 'Data' => [] ]; $this->SendDebug('Send', $ParentData, 0); diff --git a/actions/setComfortMode.json b/actions/setComfortMode.json deleted file mode 100644 index 440da27..0000000 --- a/actions/setComfortMode.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "{DB9DF59B-0FDC-FD62-5AB7-0B1193598897}", - "caption": "Set mode to COMFORT_MODE", - "form": [], - "restrictions": { - "objectType": [ - 1 - ], - "hasActionStatusVariables": true, - "moduleID": [ - "{EE4A81C6-5C90-4DB7-AD2F-F6BBD521412E}" - ], - "includeEnvironments": [ - "TestCommands", - "Default" - ] - }, - "action": "HM_WriteValueBoolean($_IPS['TARGET'], 'COMFORT_MODE',true);", - "locale": { - "de": { - "Set mode to COMFORT_MODE": "Setze Modus auf COMFORT_MODE" - } - } -} \ No newline at end of file diff --git a/actions/setLoweringMode.json b/actions/setLoweringMode.json deleted file mode 100644 index 7cf57aa..0000000 --- a/actions/setLoweringMode.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "id": "{0313A8A5-3686-293A-6AB5-2AC646D292D3}", - "caption": "Set mode to LOWERING_MODE", - "form": [], - "restrictions": { - "objectType": [ - 1 - ], - "hasActionStatusVariables": true, - "moduleID": [ - "{EE4A81C6-5C90-4DB7-AD2F-F6BBD521412E}" - ], - "includeEnvironments": [ - "TestCommands", - "Default" - ] - }, - "action": "HM_WriteValueBoolean($_IPS['TARGET'], 'LOWERING_MODE',true);", - "locale": { - "de": { - "Set mode to LOWERING_MODE": "Setze Modus auf LOWERING_MODE" - } - } -} \ No newline at end of file diff --git a/actions/setSetControlMode.json b/actions/setSetControlMode.json deleted file mode 100644 index 4db58bb..0000000 --- a/actions/setSetControlMode.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "id": "{0C24AC98-DDB6-A6B8-1012-855087398C60}", - "caption": "Set control mode", - "form": [ - { - "type": "Select", - "caption": "Mode", - "name": "MODE", - "options": [ - { - "value": 0, - "caption": "Auto" - }, - { - "value": 1, - "caption": "Manuel" - }, - { - "value": 2, - "caption": "Boost" - } - ] - } - ], - "restrictions": { - "objectType": [ - 1 - ], - "hasActionStatusVariables": true, - "moduleID": [ - "{EE4A81C6-5C90-4DB7-AD2F-F6BBD521412E}" - ], - "includeEnvironments": [ - "TestCommands", - "Default" - ] - }, - "action": [ - "switch ($_IPS['MODE'])", - "{", - " case 0:", - " HM_WriteValueBoolean($_IPS['TARGET'],'AUTO_MODE',true);", - " break;", - " case 1:", - " HM_WriteValueFloat($_IPS['TARGET'],'MANU_MODE',GetValueFloat(IPS_GetObjectIDByIdent('SET_TEMPERATURE',$_IPS['TARGET'])));", - " break;", - " case 2:", - " HM_WriteValueBoolean($_IPS['TARGET'],'BOOST_MODE',true);", - " break;", - "}" - ], - "locale": { - "de": { - "Set control mode to {MODE, select, 0 {'Auto'} 1 {'Manuel'} 2 {'Boost'}}": "Setze Regelmodus auf {MODE, select, 0 {'Auto'} 1 {'Manuel'} 2 {'Boost'}}", - "Set control mode": "Setze Regelmodus" - } - }, - "format": "Set control mode to {MODE, select, 0 {'Auto'} 1 {'Manuel'} 2 {'Boost'}}" -} \ No newline at end of file diff --git a/ePaperStatusAnzeige/module.php b/ePaperStatusAnzeige/module.php index 28be2ab..583978a 100644 --- a/ePaperStatusAnzeige/module.php +++ b/ePaperStatusAnzeige/module.php @@ -8,10 +8,10 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/../libs/HMBase.php'; // HMBase Klasse @@ -228,7 +228,7 @@ private function SendData($Submit) 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => 0, 'MethodName' => 'setValue', - 'WaitTime' => 5000, + 'WaitTime' => 3, 'Data' => [$this->ReadPropertyString(\HMExtended\Device\Property::Address), 'SUBMIT', '0x02,' . implode(',', $Submit) . ',0x03'] ]; $this->SendDebug('Send', $ParentData, 0); diff --git a/library.json b/library.json index 95409ef..ba54039 100644 --- a/library.json +++ b/library.json @@ -6,7 +6,7 @@ "compatibility": { "version": "6.1" }, - "version": "3.6", - "build": 360, - "date": 1702223362 + "version": "3.7", + "build": 370, + "date": 1702831462 } \ No newline at end of file diff --git a/libs/HMBase.php b/libs/HMBase.php index 99b6d65..67c6a44 100644 --- a/libs/HMBase.php +++ b/libs/HMBase.php @@ -8,9 +8,9 @@ * @package HomematicExtended * @file HMBase.php * @author Michael Tröger - * @copyright 2019 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 - * @version 3.0 + * @version 3.70 */ eval('declare(strict_types=1);namespace HMExtended {?>' . file_get_contents(__DIR__ . '/helper/DebugHelper.php') . '}'); eval('declare(strict_types=1);namespace HMExtended {?>' . file_get_contents(__DIR__ . '/helper/BufferHelper.php') . '}'); @@ -21,7 +21,7 @@ /** * HMBase ist die Basis-Klasse für alle Module welche HMScript verwenden. - * Erweitert ipsmodule. + * Erweitert IPSModule. * * @property int $ParentID Aktueller IO-Parent. * diff --git a/libs/HMDeviceBase.php b/libs/HMHeatingDevice.php similarity index 51% rename from libs/HMDeviceBase.php rename to libs/HMHeatingDevice.php index b19e79a..f76f41c 100644 --- a/libs/HMDeviceBase.php +++ b/libs/HMHeatingDevice.php @@ -8,22 +8,44 @@ * @file module.php * * @author Michael Tröger - * @copyright 2020 Michael Tröger + * @copyright 2023 Michael Tröger * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 * - * @version 3.12 + * @version 3.70 */ require_once __DIR__ . '/HMBase.php'; // HMBase Klasse /** - * HMDeviceBase + * HMHeatingDevice + * + * @property array $WeekSchedules */ -abstract class HMDeviceBase extends HMBase +class HMHeatingDevice extends HMBase { - public const ValuesChannel = ''; - public const ParamChannel = ''; + protected const ValuesChannel = ''; + protected const ParamChannel = ''; protected const DeviceTyp = ''; + protected const WeekScheduleIndexTemp = 'P%3$d_TEMPERATURE_%2$s_%1$d'; + protected const WeekScheduleIndexEndTime = 'P%3$d_ENDTIME_%2$s_%1$d'; + protected const NumberOfWeekSchedules = 1; + protected const NumberOfTimeSlot = 13; + protected const SelectedWeekScheduleIdent = ''; + + protected const EVENT = 'WEEK_PROFIL'; + protected const TIME = 'Time'; + protected const TEMP = 'Temp'; + + protected static $Weekdays = [ + 1 => 'MONDAY', + 2 => 'TUESDAY', + 4 => 'WEDNESDAY', + 8 => 'THURSDAY', + 16 => 'FRIDAY', + 32 => 'SATURDAY', + 64 => 'SUNDAY', + ]; + protected static $VariableTypes = [ 'BOOL' => VARIABLETYPE_BOOLEAN, 'INTEGER' => VARIABLETYPE_INTEGER, @@ -43,12 +65,7 @@ public function Create() $this->RegisterPropertyBoolean('enable_' . $Property, $Value); } $this->RegisterPropertyBoolean('enable_SCHEDULE', false); - $this->RegisterPropertyFloat('ScheduleMinTemp', 5); - $this->RegisterPropertyFloat('ScheduleMaxTemp', 30); - $this->RegisterPropertyInteger('ScheduleStepsTemp', 2); - $this->RegisterPropertyInteger('ScheduleMinColor', 0x0000ff); - $this->RegisterPropertyInteger('ScheduleMaxColor', 0xff0000); - $ScheduleTemps = [ + $ScheduleTempsInit = [ [5, 0x000080], [16, 0x333399], [17, 0x005EC6], @@ -62,7 +79,8 @@ public function Create() [25, 0xE60000], [30, 0xFF0000], ]; - $this->RegisterAttributeString('ScheduleColors', json_encode($ScheduleTemps)); + $this->RegisterAttributeString('ScheduleColors', json_encode($ScheduleTempsInit)); + $this->WeekSchedules = []; } /** @@ -103,67 +121,47 @@ public function ApplyChanges() } } } - - $this->CreateWeekPlan($this->ReadPropertyBoolean('enable_SCHEDULE')); + if ($this->ReadPropertyBoolean('enable_SCHEDULE')) { + $this->CreateWeekPlan(); + $ProfileSubmitPlan = false; + switch (static::SelectedWeekScheduleIdent) { //Nur Speichern Button + case \HMExtended\HeatingGroupHmIP::ACTIVE_PROFILE: + $ProfileSubmitPlan = 'Heating.Control.Profile.HmIP'; + break; + case \HMExtended\HeatingGroup::WEEK_PROGRAM_POINTER: + $ProfileSubmitPlan = 'Heating.Control.Profile.HM'; + break; + } + if ($ProfileSubmitPlan) { + $this->CreateProfile($ProfileSubmitPlan); + $isOld = @$this->GetIDForIdent(\HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM); + $this->RegisterVariableInteger(\HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM, $this->Translate('Schedule save in profile'), $ProfileSubmitPlan); + $this->EnableAction(\HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM); + if (!$isOld) { + $this->SetValue(\HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM, 1); + } + } + $this->CreateProfile('Execute.HM'); + $this->RegisterVariableInteger(\HMExtended\Variables::SUBMIT_WEEK_PROGRAM, $this->Translate('Schedule save'), 'Execute.HM'); + $this->EnableAction(\HMExtended\Variables::SUBMIT_WEEK_PROGRAM); + } else { + $this->UnregisterVariable(\HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM); + $this->UnregisterVariable(\HMExtended\Variables::SUBMIT_WEEK_PROGRAM); + $EventId = @IPS_GetObjectIDByIdent(self::EVENT, $this->InstanceID); + if ($EventId != false) { + IPS_DeleteEvent($EventId); + } + } if (IPS_GetKernelRunlevel() != KR_READY) { return; } if (($Address != '') && ($this->HasActiveParent())) { - $this->createVariablesFromValues(); - $this->getValuesAndSetVariable(); - $this->createVariablesFromParams(); - $this->getParamsAndSetVariable(); - } - } - /* - public function ReadParamset(string $Paramset) - { - $Result = $this->GetParamset($Paramset); - return $Result; - } - - - public function WriteParameterBoolean(string $Parameter, bool $Data) - { - $Result = $this->PutParamSet([$Parameter=> $Data]); - return $Result; - } - - - public function WriteParameterInteger(string $Parameter, int $Data) - { - $Result = $this->PutParamSet([$Parameter=> $Data]); - return $Result; - } - - - public function WriteParameterFloat(string $Parameter, float $Data) - { - $Result = $this->PutParamSet([$Parameter=> $Data]); - return $Result; - } - - - public function WriteParameterString(string $Parameter, string $Data) - { - $Result = $this->PutParamSet([$Parameter=> $Data]); - return $Result; - } - - public function WriteParamset(string $Paramset) - { - $Data = @json_decode($Paramset, true); - if ($Data === false) { - trigger_error('Error in Parameter', E_USER_NOTICE); - return false; + $this->CreateVariablesFromValues(); + $this->GetValuesAndSetVariable(); + $this->CreateVariablesFromParams(); + $this->GetParamsAndSetVariable(); } - $Result = $this->PutParamSet($Data); - return $Result; } - */ - /** - * Interne Funktion des SDK. - */ /** * Interne Funktion des SDK. @@ -175,7 +173,17 @@ public function RequestAction($Ident, $Value) } switch ($Ident) { case 'getParam': - $this->getParamsAndSetVariable(); + $this->GetParamsAndSetVariable(); + return true; + case \HMExtended\Variables::SUBMIT_WEEK_PROGRAM: + if (static::SelectedWeekScheduleIdent) { + $this->SaveSchedule((int) $this->GetValue(\HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM)); + } else { + $this->SaveSchedule(1); + } + return true; + case \HMExtended\Variables::SELECT_NEW_WEEK_PROGRAM: + $this->SetValue($Ident, $Value); return true; } $Property = $Ident; @@ -194,12 +202,35 @@ public function RequestAction($Ident, $Value) return false; } + public function RequestState(string $Ident) + { + if (!array_key_exists($Ident, \HMExtended\ValuesSet::$Variables[static::DeviceTyp])) { + trigger_error($this->Translate('Invalid Ident for VALUE.'), E_USER_NOTICE); + return false; + } + $AddressWithChannel = $this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel; + $Result = $this->SendRPC('getValue', [$AddressWithChannel, $Ident]); + if ($Result === null) { + return false; + } + @$this->SetValue($Ident, $Result); + return true; + } + + public function RequestParams() + { + return $this->GetParamsAndSetVariable(); + } + public function ReceiveData($JSONString) { $Event = json_decode($JSONString, true); - $this->SendDebug('EVENT:' . $Event['VariableName'], $Event['VariableValue'], 0); + //$this->SendDebug('EVENT:' . $Event['VariableName'], $Event['VariableValue'], 0); $this->SetVariable($Event['VariableName'], $Event['VariableValue']); } + + //################# protected + /** * Wird ausgeführt wenn sich der Status vom Parent ändert. */ @@ -207,23 +238,195 @@ protected function IOChangeState($State) { if ($State == IS_ACTIVE) { if (($this->ReadPropertyString(\HMExtended\Device\Property::Address) != '') && ($this->HasActiveParent())) { - $this->getValuesAndSetVariable(); - $this->getParamsAndSetVariable(); + $this->GetValuesAndSetVariable(); + $this->GetParamsAndSetVariable(); + } + } + } + + protected function SetVariable(string $Ident, $Value) + { + @$this->SetValue($Ident, $Value); + } + + protected function SetParamVariables(array $Params) + { + $ScheduleData = []; + $ScheduleTemps = $this->GetTempColorsAttribute(); + $ScheduleActionHasChanged = false; + for ($Plan = 1; $Plan <= static::NumberOfWeekSchedules; $Plan++) { + foreach (static::$Weekdays as $Index => $Day) { + for ($Slot = 1; $Slot <= static::NumberOfTimeSlot; $Slot++) { + $TimeIndex = sprintf(static::WeekScheduleIndexEndTime, $Slot, $Day, $Plan); + $TempIndex = sprintf(static::WeekScheduleIndexTemp, $Slot, $Day, $Plan); + $Time = $Params[$TimeIndex]; + $Temp = $Params[$TempIndex]; + $this->SendDebug($TimeIndex, $Time, 0); + $this->SendDebug($TempIndex, $Temp, 0); + $ScheduleData[$Plan][$Index][$Slot][self::TIME] = $Time; + $ScheduleData[$Plan][$Index][$Slot][self::TEMP] = $Temp; + if (!array_key_exists($Temp, $ScheduleTemps)) { + $Color = $this->GetNextColor($Temp, $ScheduleData); + $ScheduleTemps[$Params[$TempIndex]] = $Color; + $ScheduleActionHasChanged = true; + } + unset($Params[$TimeIndex]); + unset($Params[$TempIndex]); + } + } + } + if ($ScheduleActionHasChanged) { + // todo wenn array zu groß war, Meldung ausgeben. + ksort($ScheduleTemps); + $ScheduleTemps = array_slice($ScheduleTemps, 0, 32, true); + $this->SetTempColorsAttribute($ScheduleTemps); + } + $this->WeekSchedules = $ScheduleData; + foreach ($Params as $Ident => $Value) { + @$this->SetValue($Ident, $Value); + } + $this->RefreshScheduleObject($ScheduleActionHasChanged); + } + + protected function FixValueType($VarType, &$Value) + { + switch ($VarType) { + case VARIABLETYPE_BOOLEAN: + $Value = (bool) $Value; + break; + case VARIABLETYPE_INTEGER: + $Value = (int) $Value; + break; + case VARIABLETYPE_FLOAT: + $Value = (float) $Value; + break; + case VARIABLETYPE_STRING: + $Value = (string) $Value; + break; + } + } + + protected function PutParamSet(array $Parameter, bool $EmulateStatus = false) + { + $Paramset = [$this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ParamChannel, \HMExtended\CCU::MASTER]; + $Result = $this->SendRPC('putParamset', $Paramset, $Parameter, $EmulateStatus); + return ($Result !== null) ? true : false; + } + + protected function PutValueSet($Value, bool $EmulateStatus = false) + { + $Paramset = [$this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel, \HMExtended\CCU::VALUES]; + $Result = $this->SendRPC('putParamset', $Paramset, $Value, $EmulateStatus); + return ($Result !== null) ? true : false; + } + + protected function PutValue(string $ValueName, $Value, bool $EmulateStatus = false) + { + $Paramset = [$this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel, $ValueName]; + $Result = $this->SendRPC('setValue', $Paramset, $Value, $EmulateStatus); + if (($Result !== null) && $EmulateStatus) { + $this->SetVariable($ValueName, $Value); + } + return ($Result !== null) ? true : false; + } + + protected function RefreshScheduleObject(bool $ScheduleActionHasChanged = false) + { + if (!$this->ReadPropertyBoolean('enable_SCHEDULE')) { + return; + } + if (!count($this->WeekSchedules)) { + return; + } + $EventId = @IPS_GetObjectIDByIdent(self::EVENT, $this->InstanceID); + if ($EventId === false) { + return; + } + $Event = IPS_GetEvent($EventId); + foreach ($Event['ScheduleGroups'] as $Group) { + foreach ($Group['Points'] as $Point) { + IPS_SetEventScheduleGroupPoint($EventId, $Group['ID'], $Point['ID'], -1, -1, -1, 0); + } + } + $Actions = $this->UpdateScheduleActions($Event, $ScheduleActionHasChanged); + if (static::SelectedWeekScheduleIdent) { + $ActivePlan = $this->GetValue(static::SelectedWeekScheduleIdent); + } else { + $ActivePlan = 1; + } + $ScheduleData = $this->WeekSchedules[$ActivePlan]; + foreach ($Event['ScheduleGroups'] as $Group) { + $StartHour = 0; + $StartMinute = 0; + foreach ($ScheduleData[$Group['Days']] as $PointId => $Slot) { + $ActionId = array_search($Slot[self::TEMP], $Actions); + IPS_SetEventScheduleGroupPoint($EventId, $Group['ID'], $PointId, $StartHour, $StartMinute, 0, $ActionId); + if ($Slot[self::TIME] == 1440) { + break; + } + $StartHour = intdiv($Slot[self::TIME], 60); + $StartMinute = $Slot[self::TIME] % 60; } } } - //################# PUBLIC + protected function SaveSchedule(int $Plan) + { + $EventId = @IPS_GetObjectIDByIdent(self::EVENT, $this->InstanceID); + if ($EventId === false) { + return; + } + $Event = IPS_GetEvent($EventId); + + $ActionIdToTemp = []; + $Params = []; + $Schedule = []; + foreach ($Event['ScheduleActions'] as $Action) { + $ActionIdToTemp[$Action['ID']] = (float) str_replace(',', '.', $Action['Name']); + } + foreach ($Event['ScheduleGroups'] as $Group) { + $Day = static::$Weekdays[$Group['Days']]; + $Slot = 1; + + for ($i = 1; $i <= count($Group['Points']); $i++) { + $TimeIndex = sprintf(static::WeekScheduleIndexEndTime, $Slot, $Day, $Plan); + $TempIndex = sprintf(static::WeekScheduleIndexTemp, $Slot, $Day, $Plan); + if ($i < count($Group['Points'])) { + $Params[$TimeIndex] = ($Group['Points'][$i]['Start']['Hour'] * 60) + $Group['Points'][$i]['Start']['Minute']; + } else { + $Params[$TimeIndex] = 1440; + } + $Params[$TempIndex] = $ActionIdToTemp[$Group['Points'][$i - 1]['ActionID']]; + $Schedule[$Group['Days']][$Slot] = [ + self::TIME => $Params[$TimeIndex], + self::TEMP => $Params[$TempIndex] + ]; + $Slot++; + } + } + $Schedules = $this->WeekSchedules; + $Schedules[$Plan] = $Schedule; + $this->WeekSchedules = $Schedules; + $this->PutParamSet($Params); + + if (static::SelectedWeekScheduleIdent) { + $ActivePlan = $this->GetValue(static::SelectedWeekScheduleIdent); + } else { + $ActivePlan = 1; + } + if ($ActivePlan != $Plan) { + $this->RefreshScheduleObject(); + } + } + + //################# PRIVATE - protected function createVariablesFromValues() + private function CreateVariablesFromValues() { $AddressWithChannel = $this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel; - $Result = $this->getParamsetDescription('VALUES', $AddressWithChannel); + $Result = $this->GetParamsetDescription(\HMExtended\CCU::VALUES, $AddressWithChannel); foreach ($Result as $Variable) { - //if ($Variable['OPERATIONS'] & 0b101) { $Ident = $Variable['ID']; - //$VarType = self::$VariableTypes[$Variable['TYPE']]; - //$Profile = ''; $Name = $Variable['ID']; $Action = ''; if (!array_key_exists($Ident, \HMExtended\ValuesSet::$Variables[static::DeviceTyp])) { @@ -245,8 +448,6 @@ protected function createVariablesFromValues() $Name = $this->Translate(\HMExtended\ValuesSet::$Variables[static::DeviceTyp][$Ident][3]); } $this->CreateProfile($Profile); - //} - $this->MaintainVariable($Ident, $Name, $VarType, $Profile, 0, true); if ($Action === '') { if ($Variable['OPERATIONS'] & 0b10) { @@ -255,23 +456,26 @@ protected function createVariablesFromValues() } elseif ($Action) { $this->EnableAction($Ident); } - //} } } - protected function getValuesAndSetVariable() + private function GetValuesAndSetVariable(): bool { $AddressWithChannel = $this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel; - $Result = $this->getParamset('VALUES', $AddressWithChannel); - foreach ($Result as $Ident => $Value) { - $this->SetVariable($Ident, $Value); + $Result = $this->GetParamset(\HMExtended\CCU::VALUES, $AddressWithChannel); + if (count($Result) != 0) { + foreach ($Result as $Ident => $Value) { + $this->SetVariable($Ident, $Value); + } + return true; } + return false; } - protected function createVariablesFromParams() + private function CreateVariablesFromParams() { $AddressWithChannel = $this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ParamChannel; - $Result = $this->getParamsetDescription('MASTER', $AddressWithChannel); + $Result = $this->GetParamsetDescription(\HMExtended\CCU::MASTER, $AddressWithChannel); foreach ($Result as $Variable) { $Ident = $Variable['ID']; $Profile = ''; @@ -317,17 +521,18 @@ protected function createVariablesFromParams() } } - protected function getParamsAndSetVariable() + private function GetParamsAndSetVariable(): bool { $AddressWithChannel = $this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ParamChannel; - $Result = $this->getParamset('MASTER', $AddressWithChannel); - $this->SendDebug(__FUNCTION__, $Result, 0); + $Result = $this->GetParamset(\HMExtended\CCU::MASTER, $AddressWithChannel); if (count($Result) != 0) { - $this->SetParamVariable($Result); + $this->SetParamVariables($Result); + return true; } + return false; } - protected function CreateProfile($Profile) + private function CreateProfile($Profile) { if ($Profile) { if (substr($Profile, 0, 1) != '~') { @@ -348,142 +553,29 @@ protected function CreateProfile($Profile) } } - abstract protected function SetVariable(string $Ident, $Value); - abstract protected function SetParamVariable(array $Params); - - protected function CreateWeekPlan(bool $Active) - { - $Event = @IPS_GetObjectIDByIdent('WEEK_PROFIL', $this->InstanceID); - if ($Event === false) { - if (!$Active) { - return false; - } - $Event = IPS_CreateEvent(2); - IPS_SetParent($Event, $this->InstanceID); - IPS_SetIdent($Event, 'WEEK_PROFIL'); - IPS_SetName($Event, $this->Translate('Schedule')); - } else { - if (!$Active) { - IPS_DeleteEvent($Event); - return false; - } - } - /* - $TempMin = $this->ReadPropertyFloat('ScheduleMinTemp'); - $TempMax = $this->ReadPropertyFloat('ScheduleMaxTemp'); - $Steps = $this->ReadPropertyInteger('ScheduleStepsTemp'); - $rgb1 = $this->ReadPropertyInteger('ScheduleMinColor'); - $rgb2 = $this->ReadPropertyInteger('ScheduleMaxColor'); - $r1 = $rgb1 >> 16; - $g1 = ($rgb1 & 0x00FF00) >> 8; - $b1 = $rgb1 & 0x0000FF; - $r2 = $rgb2 >> 16; - $g2 = ($rgb2 & 0x00FF00) >> 8; - $b2 = $rgb2 & 0x0000FF; - $Counts = ($TempMax - $TempMin) / ($Steps / 2) + 1; - $dr = ($r2 - $r1) / $Counts; - $dg = ($g2 - $g1) / $Counts; - $db = ($b2 - $b1) / $Counts; - for ($i = 32; $i > 0; $i--) { - @IPS_SetEventScheduleAction($Event, $i, '', 0, ''); - } - for ($i = 0; $i < $Counts; $i++) { - $rgb = - (round($r1 + $dr * $i) << 16) | - (round($g1 + $dg * $i) << 8) | - (round($b1 + $db * $i)); - - $Temp = ($TempMin + ($i * ($Steps / 2))); - if ($Temp > $TempMax) { - break; - } - IPS_SetEventScheduleAction($Event, $i + 1, sprintf('%0.1f °C', $Temp), $rgb, ''); - if ($i == 31) { - break; - } - } - */ - $ScheduleActionColors = $this->GetColorAttribute(); - $i = 0; - foreach ($ScheduleActionColors as $Temp => $Color) { - $i++; - IPS_SetEventScheduleAction($Event, $i + 1, sprintf('%0.1f °C', $Temp), $Color, ''); - if ($i == 31) { - break; - } - } - for ($i = 0; $i < 7; $i++) { - IPS_SetEventScheduleGroup($Event, $i, (1 << $i)); - } - return $Event; - } - - //################# PRIVATE - protected function FixValueType($VarType, &$Value) - { - switch ($VarType) { - case VARIABLETYPE_BOOLEAN: - $Value = (bool) $Value; - break; - case VARIABLETYPE_INTEGER: - $Value = (int) $Value; - break; - case VARIABLETYPE_FLOAT: - $Value = (float) $Value; - break; - case VARIABLETYPE_STRING: - $Value = (string) $Value; - break; - } - } - - protected function GetParamset(string $Paramset, string $AddressWithChannel) + private function GetParamset(string $Paramset, string $AddressWithChannel) { $Result = $this->SendRPC('getParamset', [$AddressWithChannel, $Paramset]); return is_array($Result) ? $Result : []; } - protected function GetParamsetDescription(string $Paramset, string $AddressWithChannel) + private function GetParamsetDescription(string $Paramset, string $AddressWithChannel) { $Result = $this->SendRPC('getParamsetDescription', [$AddressWithChannel, $Paramset]); return is_array($Result) ? $Result : []; } - protected function PutParamSet(array $Parameter, bool $EmulateStatus = false) - { - $Paramset = [$this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ParamChannel, 'MASTER']; - $Result = $this->SendRPC('putParamset', $Paramset, $Parameter, $EmulateStatus); - return ($Result) ? true : false; - } - - protected function PutValueSet($Value, bool $EmulateStatus = false) - { - $Paramset = [$this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel, 'VALUES']; - $Result = $this->SendRPC('putParamset', $Paramset, $Value, $EmulateStatus); - return ($Result) ? true : false; - } - - protected function PutValue(string $ValueName, $Value, bool $EmulateStatus = false) - { - $Paramset = [$this->ReadPropertyString(\HMExtended\Device\Property::Address) . static::ValuesChannel, $ValueName]; - $Result = $this->SendRPC('setValue', $Paramset, $Value, $EmulateStatus); - if ($Result && $EmulateStatus) { - $this->SetVariable($ValueName, $Value); - } - return ($Result) ? true : false; - } - - protected function SendRPC(string $MethodName, array $Paramset, $Data = null, bool $EmulateStatus = false) + private function SendRPC(string $MethodName, array $Paramset, $Data = null, bool $EmulateStatus = false) { if (!$this->HasActiveParent()) { trigger_error($this->Translate('Instance has no active Parent Instance!'), E_USER_NOTICE); - return false; + return null; } $ParentData = [ 'DataID' => \HMExtended\GUID::SendRpcToIO, 'Protocol' => $this->ReadPropertyInteger(\HMExtended\Device\Property::Protocol), 'MethodName' => $MethodName, - 'WaitTime' => ($EmulateStatus ? 1 : (int) IPS_GetProperty($this->ParentID, 'WaitTimeDevice')), + 'WaitTime' => 3, 'Data' => $Paramset ]; if (is_array($Data)) { @@ -499,18 +591,53 @@ protected function SendRPC(string $MethodName, array $Paramset, $Data = null, bo if ($ResultJSON === false) { trigger_error('Error on ' . $MethodName, E_USER_NOTICE); $this->SendDebug('Error', '', 0); - return false; + return null; } - $this->SendDebug('Receive', $ResultJSON, 0); + $this->SendDebug('Receive JSON', $ResultJSON, 0); if ($ResultJSON === '') { return true; } $Result = json_decode($ResultJSON, true); - $this->SendDebug('Receive', $Result, 0); return $Result; } - private function SetColorAttribute(array $Values) + private function UpdateScheduleActions(array $Event, bool $ScheduleActionHasChanged): array + { + $ScheduleActionColors = $this->GetTempColorsAttribute(); + if ($ScheduleActionHasChanged) { + foreach ($Event['ScheduleActions'] as $Action) { + IPS_SetEventScheduleAction($Event['EventID'], $Action['ID'], '', 0, ''); + } + $i = 0; + foreach ($ScheduleActionColors as $Temp => $Color) { + IPS_SetEventScheduleAction($Event['EventID'], $i++, sprintf('%0.1f °C', $Temp), $Color, 'HM_RequestParams($_IPS[\'TARGET\']);'); + if ($i == 32) { + break; + } + } + } + return array_keys($ScheduleActionColors); + } + + private function CreateWeekPlan() + { + $this->WeekSchedules = []; + $EventId = @IPS_GetObjectIDByIdent(self::EVENT, $this->InstanceID); + if ($EventId === false) { + $EventId = IPS_CreateEvent(2); + IPS_SetParent($EventId, $this->InstanceID); + IPS_SetIdent($EventId, self::EVENT); + IPS_SetName($EventId, $this->Translate('Schedule')); + $Event = IPS_GetEvent($EventId); + $this->UpdateScheduleActions($Event, true); + for ($i = 0; $i < 7; $i++) { + IPS_SetEventScheduleGroup($EventId, $i, (1 << $i)); + } + IPS_SetEventActive($EventId, true); + } + } + + private function SetTempColorsAttribute(array $Values) { ksort($Values); foreach ($Values as $Temp => $Color) { @@ -519,7 +646,7 @@ private function SetColorAttribute(array $Values) $this->WriteAttributeString('ScheduleColors', json_encode($ScheduleTemps)); } - private function GetColorAttribute() + private function GetTempColorsAttribute() { $Values = []; $ScheduleTemps = json_decode($this->ReadAttributeString('ScheduleColors'), true); @@ -529,6 +656,19 @@ private function GetColorAttribute() ksort($Values); return $Values; } + + private function GetNextColor(float $Temp, $Colors) + { + $Found = 0x000080; + foreach ($Colors as $TempColor => $Color) { + if ($TempColor < $Temp) { + $Found = $Color; + } else { + break; + } + } + return $Found; + } } /* @} */ diff --git a/libs/HMTypes.php b/libs/HMTypes.php index 19c0a0b..1e6e8d5 100644 --- a/libs/HMTypes.php +++ b/libs/HMTypes.php @@ -6,8 +6,8 @@ { class GUID { - public const Systemvariablen = '{400F9193-FE79-4086-8D76-958BF9C1B357}'; - public const Powermeter = '{AF50C42B-7183-4992-B04A-FAFB07BB1B90}'; + public const Powermeter = '{400F9193-FE79-4086-8D76-958BF9C1B357}'; + public const Systemvariablen = '{AF50C42B-7183-4992-B04A-FAFB07BB1B90}'; public const Programme = '{A5010577-C443-4A85-ABF2-3F2D6CDD2465}'; public const Dis_WM55 = '{271BCAB1-0658-46D9-A164-985AEB641B48}'; public const Dis_EP_WM55 = '{E64ED916-FA6C-45B2-B8E3-EDC3191BC4C0}'; @@ -30,7 +30,8 @@ class CCU public const BidCos_WR = 'BidCos-Wired'; public const HmIP = 'HmIP-RF'; public const Groups = 'VirtualDevices'; - + public const MASTER = 'MASTER'; + public const VALUES = 'VALUES'; public static $Interfaces = [ self::BidCos_RF, self::BidCos_WR, @@ -41,22 +42,30 @@ class CCU class DeviceType { + public const Powermeter = 'POWERMETER'; // HM-ES-PMSw1-Pl + public const Powermeter_IEC = 'POWERMETER_IEC2'; // HM-ES-TX-WM + public const Dis_WM55 = 'HM-Dis-WM55'; // HM-Dis-WM55 + public const HeatingGroup = 'HM-CC-VG-1'; //'CLIMATECONTROL_RT_TRANSCEIVER'; public const HeatingGroupHmIP = 'HmIP-HEATING'; //'HEATING_CLIMATECONTROL_TRANSCEIVER'; public const ClimacontrolRegulator = 'HM-CC-TC'; //'CLIMATECONTROL_REGULATOR'; public static $GuidToType = [ - /*GUID::Systemvariablen => - GUID::Powermeter => - GUID::Programme => - GUID::Dis_WM55 => - GUID::Dis_EP_WM55 => - GUID::RF_Interface_Splitter => - GUID::RF_Interface_Konfigurator => - GUID::WR_Interface => */ - GUID::HeatingGroup => self::HeatingGroup, - GUID::HeatingGroupHmIP => self::HeatingGroupHmIP, - GUID::ClimacontrolRegulator => self::ClimacontrolRegulator + // Konfigurator muss noch ergänzt werden um: + //GUID::Systemvariablen => + //GUID::Programme => + //GUID::WR_Interface => + // Vorhandener Konfigurator muss noch migriert werden: + //GUID::RF_Interface_Splitter => + //GUID::RF_Interface_Konfigurator => + // Konfigurator 'fertig' => Aber die Instanzen sind noch nicht so weit + GUID::Powermeter => [self::Powermeter, self::Powermeter_IEC], + GUID::Dis_WM55 => [self::Dis_WM55], + //GUID::Dis_EP_WM55 => + // Konfigurator fertig + GUID::HeatingGroup => [self::HeatingGroup], + GUID::HeatingGroupHmIP => [self::HeatingGroupHmIP], + GUID::ClimacontrolRegulator => [self::ClimacontrolRegulator] ]; } @@ -229,6 +238,8 @@ class Property class Variables { public const VARIABLETYPE_NONE = -1; + public const SUBMIT_WEEK_PROGRAM = 'SUBMIT_WEEK_PROGRAM'; + public const SELECT_NEW_WEEK_PROGRAM = 'SELECT_NEW_WEEK_PROGRAM'; public static $Profiles = [ 'Heating.Control.SetPoint.Temperature.HM'=> [