diff --git a/VGT_Sub/module.json b/VGT_Sub/module.json index d6f045f..8b39024 100644 --- a/VGT_Sub/module.json +++ b/VGT_Sub/module.json @@ -8,10 +8,10 @@ ], "prefix": "VGT", "parentRequirements": [ - "{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}" + "{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}" ], "childRequirements": [], "implemented": [ - "{018EF6B5-AB94-40C6-AA53-46943E824ACF}" + "{7F7632D9-FA40-4F38-8DEA-C83CD4325A32}" ] } diff --git a/VGT_Sub/module.php b/VGT_Sub/module.php index d5c5d63..86a62e0 100644 --- a/VGT_Sub/module.php +++ b/VGT_Sub/module.php @@ -8,148 +8,159 @@ class VGT_Sub extends IPSModule { parent::Create(); - // Konfig - $this->RegisterPropertyString("DeviceID", ""); + // Konfiguration + $this->RegisterPropertyString('DeviceID', ''); - // Editable Variablen (werden in feedback-response gesendet) - $this->RegisterVariableFloat("PowerProduction", "Power Production", "", 10); - $this->EnableAction("PowerProduction"); + // Eigene Status-Variablen (schreibbar) + $this->RegisterVariableFloat('PowerProduction', 'Power Production', '', 10); + $this->EnableAction('PowerProduction'); - $this->RegisterVariableFloat("StateOfCharge", "State of Charge", "", 20); - $this->EnableAction("StateOfCharge"); + $this->RegisterVariableFloat('StateOfCharge', 'State of Charge', '', 11); + $this->EnableAction('StateOfCharge'); - $this->RegisterVariableBoolean("IsRunning", "Is Running", "", 30); - $this->EnableAction("IsRunning"); + $this->RegisterVariableBoolean('IsRunning', 'Is Running', '', 12); + $this->EnableAction('IsRunning'); - $this->RegisterVariableBoolean("IsReady", "Is Ready", "", 40); - $this->EnableAction("IsReady"); + $this->RegisterVariableBoolean('IsReady', 'Is Ready', '', 13); + $this->EnableAction('IsReady'); - $this->RegisterVariableInteger("MinSOC", "Min SOC", "", 50); - $this->EnableAction("MinSOC"); + $this->RegisterVariableFloat('MinSoc', 'Min SoC', '', 14); + $this->EnableAction('MinSoc'); - $this->RegisterVariableInteger("MaxSOC", "Max SOC", "", 60); - $this->EnableAction("MaxSOC"); + $this->RegisterVariableFloat('MaxSoc', 'Max SoC', '', 15); + $this->EnableAction('MaxSoc'); - // Remote-Control Input Variablen (nur lesen) - $this->RegisterVariableFloat("RC_PowerSetpoint", "RC Power Setpoint", "", 70); - $this->RegisterVariableString("RC_Strategy", "RC Strategy", "", 80); + // Eingehende remote-control commands + $this->RegisterVariableInteger('PowerSetpoint', 'Power Setpoint', '', 30); + IPS_SetVariableCustomAction($this->GetIDForIdent('PowerSetpoint'), 0); // readonly - // Parent verbinden - $this->ConnectParent('{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}'); + $this->RegisterVariableString('Strategy', 'Strategy', '', 31); + IPS_SetVariableCustomAction($this->GetIDForIdent('Strategy'), 0); // readonly } - public function ApplyChanges() { parent::ApplyChanges(); - - // Sicherstellen, dass Parent gesetzt ist $this->ConnectParent('{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}'); + + $this->SubscribeTopics(); } + private function SubscribeTopics() + { + $device = $this->ReadPropertyString('DeviceID'); + if ($device == '') { + return; + } + + $topics = [ + "feedback-request/$device", + "remote-control-request/$device" + ]; + + foreach ($topics as $topic) { + $this->SendDebug("Subscribe", $topic, 0); + $this->SendDataToParent(json_encode([ + 'DataID' => '{7F7632D9-FA40-4F38-8DEA-C83CD4325A32}', + 'Topic' => $topic, + 'Payload' => '', + 'Retain' => false + ])); + } + } + + public function ReceiveData($JSONString) + { + $data = json_decode($JSONString, true); + + if (!isset($data['Topic'])) { + return; + } + + $topic = $data['Topic']; + $payload = $data['Payload']; + + $this->SendDebug("RX Topic", $topic, 0); + $this->SendDebug("RX Payload", $payload, 0); + + $device = $this->ReadPropertyString('DeviceID'); + + // ----------------------------------------------------- + // 1) FEEDBACK REQUEST → send FEEDBACK RESPONSE + // ----------------------------------------------------- + if ($topic === "feedback-request/$device") { + $this->HandleFeedbackRequest($device); + return; + } + + // ----------------------------------------------------- + // 2) REMOTE CONTROL REQUEST → write values + respond + // ----------------------------------------------------- + if ($topic === "remote-control-request/$device") { + $this->HandleRemoteControlRequest($device, $payload); + return; + } + } + + private function HandleFeedbackRequest($device) + { + $response = [ + "power_production" => GetValueFloat($this->GetIDForIdent('PowerProduction')), + "state_of_charge" => GetValueFloat($this->GetIDForIdent('StateOfCharge')), + "is_running" => GetValueBoolean($this->GetIDForIdent('IsRunning')), + "is_ready" => GetValueBoolean($this->GetIDForIdent('IsReady')), + "min_soc" => GetValueFloat($this->GetIDForIdent('MinSoc')), + "max_soc" => GetValueFloat($this->GetIDForIdent('MaxSoc')) + ]; + + $json = json_encode($response); + + $topic = "feedback-response/$device"; + + $this->SendDebug("TX Feedback", "$topic => $json", 0); + + $this->SendDataToParent(json_encode([ + 'DataID' => '{7F7632D9-FA40-4F38-8DEA-C83CD4325A32}', + 'Topic' => $topic, + 'Payload' => $json, + 'Retain' => false + ])); + } + + private function HandleRemoteControlRequest($device, $payload) + { + $json = @json_decode($payload, true); + if (!is_array($json)) { + $this->SendDebug("Error", "Ungültiges JSON", 0); + return; + } + + // Werte aus JSON übernehmen + if (isset($json['power_setpoint'])) { + SetValue($this->GetIDForIdent('PowerSetpoint'), (int)$json['power_setpoint']); + } + + if (isset($json['strategy'])) { + SetValueString($this->GetIDForIdent('Strategy'), (string)$json['strategy']); + } + + // Antwort identisch zurücksenden + $topic = "remote-control-response/$device"; + + $this->SendDataToParent(json_encode([ + 'DataID' => '{7F7632D9-FA40-4F38-8DEA-C83CD4325A32}', + 'Topic' => $topic, + 'Payload' => json_encode($json), + 'Retain' => false + ])); + + $this->SendDebug("TX RemoteControl", "$topic => " . json_encode($json), 0); + } public function RequestAction($Ident, $Value) { SetValue($this->GetIDForIdent($Ident), $Value); } - - - // Eingehende Daten vom MQTT-Client - public function ReceiveData($JSONString) - { - $data = json_decode($JSONString); - - // Format wird vom MQTT-Client-Splitter geliefert: - // { "Topic": "...", "Payload": "..." } - if (!isset($data->Topic) || !isset($data->Payload)) { - return; - } - - $topic = $data->Topic; - $payload = $data->Payload; - - $device = $this->ReadPropertyString("DeviceID"); - - // Feedback-Request - if ($topic === "feedback-request/" . $device) { - $this->HandleFeedbackRequest(); - } - - // Remote-Control Request - if ($topic === "remote-control-request/" . $device) { - $this->HandleRemoteControlRequest($payload); - } - } - - - private function HandleFeedbackRequest() - { - $response = [ - "power_production" => GetValue($this->GetIDForIdent("PowerProduction")), - "state_of_charge" => GetValue($this->GetIDForIdent("StateOfCharge")), - "is_running" => GetValue($this->GetIDForIdent("IsRunning")), - "is_ready" => GetValue($this->GetIDForIdent("IsReady")), - "min_soc" => GetValue($this->GetIDForIdent("MinSOC")), - "max_soc" => GetValue($this->GetIDForIdent("MaxSOC")) - ]; - - $this->SendToMQTT( - "feedback-response/" . $this->ReadPropertyString("DeviceID"), - json_encode($response) - ); - } - - - private function HandleRemoteControlRequest(string $payload) - { - $data = json_decode($payload, true); - if (!is_array($data)) { - return; - } - - // Werte setzen - if (isset($data["power_setpoint"])) { - SetValue($this->GetIDForIdent("RC_PowerSetpoint"), $data["power_setpoint"]); - } - - if (isset($data["strategy"])) { - SetValue($this->GetIDForIdent("RC_Strategy"), $data["strategy"]); - } - - // Antwort zurück - $this->SendToMQTT( - "remote-control-response/" . $this->ReadPropertyString("DeviceID"), - json_encode($data) - ); - } - - - // MQTT Publish (korrektes Format für deinen MQTT-Client-Splitter) - private function SendToMQTT(string $topic, string $payload) - { - $this->SendDataToParent(json_encode([ - "DataID" => "{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}", - "PacketType" => 3, // Publish - "QualityOfService" => 0, - "Retain" => false, - "Topic" => $topic, - "Payload" => $payload - ])); - } - - - public function GetConfigurationForm() - { - return json_encode([ - "elements" => [ - [ - "type" => "ValidationTextBox", - "name" => "DeviceID", - "caption" => "Device ID" - ] - ] - ]); - } } ?>