From 6094694809306853057d6d68d358b0cbecbb0edd Mon Sep 17 00:00:00 2001 From: DanielHaefliger Date: Tue, 10 Feb 2026 13:59:34 +0100 Subject: [PATCH] no message --- VGT_Sub/form.json | 30 +++++++++- VGT_Sub/module.json | 6 +- VGT_Sub/module.php | 132 +++++++++++++++++++++++++++++++------------- 3 files changed, 127 insertions(+), 41 deletions(-) diff --git a/VGT_Sub/form.json b/VGT_Sub/form.json index 3ecbe31..f115aaf 100644 --- a/VGT_Sub/form.json +++ b/VGT_Sub/form.json @@ -2,7 +2,35 @@ "elements": [ { "type": "Label", - "caption": "MQTT Konfiguration" + "caption": "MQTT Verbindungseinstellungen" + }, + { + "type": "ValidationTextBox", + "name": "MQTTClientID", + "caption": "Client ID" + }, + { + "type": "ValidationTextBox", + "name": "MQTTUser", + "caption": "Benutzername" + }, + { + "type": "PasswordTextBox", + "name": "MQTTPassword", + "caption": "Passwort" + }, + { + "type": "CheckBox", + "name": "UpdateGatewayConfig", + "caption": "Diese Einstellungen auf das Gateway anwenden (Überschreiben)" + }, + { + "type": "Label", + "caption": "--------------------------------------------------------" + }, + { + "type": "Label", + "caption": "MQTT Topic Konfiguration" }, { "type": "ValidationTextBox", diff --git a/VGT_Sub/module.json b/VGT_Sub/module.json index 41f4ade..7283293 100644 --- a/VGT_Sub/module.json +++ b/VGT_Sub/module.json @@ -6,7 +6,9 @@ "aliases": [ "VGT MQTT Device" ], - "parentRequirements": ["{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}"], + "parentRequirements": ["{F66ADE63-8834-4178-8CA5-AE4465D2E252}"], + "childRequirements": [], + "implemented": ["{018EF6B5-AB94-40C6-AA53-46943E824ACF}"], "prefix": "VGT", - "version": "1.3" + "version": "1.5" } \ No newline at end of file diff --git a/VGT_Sub/module.php b/VGT_Sub/module.php index 76c8e4a..fded11b 100644 --- a/VGT_Sub/module.php +++ b/VGT_Sub/module.php @@ -8,9 +8,18 @@ class VGT_Sub extends IPSModule { parent::Create(); - // --- Eigenschaften --- + // --------------------------------------------------------------------- + // 1. MQTT Verbindungsdaten (werden an das Gateway durchgereicht) + // --------------------------------------------------------------------- $this->RegisterPropertyString('MQTTBaseTopic', 'Test VGT_Steuerung/Komm'); + $this->RegisterPropertyString('MQTTClientID', 'symcon_vgt_client'); + $this->RegisterPropertyString('MQTTUser', ''); + $this->RegisterPropertyString('MQTTPassword', ''); + $this->RegisterPropertyBoolean('UpdateGatewayConfig', true); // Schalter: Sollen wir das Gateway überschreiben? + // --------------------------------------------------------------------- + // 2. Hardware Verknüpfungen + // --------------------------------------------------------------------- $this->RegisterPropertyInteger('SourceSoC', 0); $this->RegisterPropertyInteger('SourcePowerProd', 0); $this->RegisterPropertyInteger('SourceIsReady', 0); @@ -19,7 +28,9 @@ class VGT_Sub extends IPSModule $this->RegisterPropertyInteger('SourceMaxSoC', 0); $this->RegisterPropertyInteger('TargetControlVar', 0); - // --- Variablen --- + // --------------------------------------------------------------------- + // 3. Interne Variablen + // --------------------------------------------------------------------- $this->RegisterVariableString('Strategy', 'Strategy', '', 10); $this->RegisterVariableInteger('PowerSetpoint', 'Power Setpoint', '', 20); @@ -36,15 +47,26 @@ class VGT_Sub extends IPSModule { parent::ApplyChanges(); - // --- MQTT Filter setzen --- - // Wir abonnieren alles, was mit dem BaseTopic beginnt + // --------------------------------------------------------------------- + // A. Filter setzen (Automatisches Subscribe) + // --------------------------------------------------------------------- $topic = $this->ReadPropertyString('MQTTBaseTopic'); - $cleanTopic = preg_quote($topic, '/'); - - // Filterformat für MQTT Splitter - $this->SetReceiveDataFilter(".*\"Topic\":\"" . $cleanTopic . "/.*\".*"); + if($topic !== "") { + $cleanTopic = preg_quote($topic, '/'); + // Wir abonnieren ALLES unterhalb des BaseTopics + $this->SetReceiveDataFilter(".*\"Topic\":\"" . $cleanTopic . "/.*\".*"); + } - // --- Events registrieren --- + // --------------------------------------------------------------------- + // B. Gateway (IO) Konfiguration aktualisieren + // --------------------------------------------------------------------- + if ($this->ReadPropertyBoolean('UpdateGatewayConfig')) { + $this->ConfigureGateway(); + } + + // --------------------------------------------------------------------- + // C. Events registrieren + // --------------------------------------------------------------------- $socID = $this->ReadPropertyInteger('SourceSoC'); if (IPS_VariableExists($socID)) { $this->RegisterMessage($socID, VM_UPDATE); @@ -53,21 +75,66 @@ class VGT_Sub extends IPSModule $this->RegisterMessage($this->GetIDForIdent('PowerSetpoint'), VM_UPDATE); } - // --- DATEN EMPFANGEN (Vom MQTT Splitter) --- + /** + * Diese Funktion sucht die IO-Instanz (MQTT Client) und setzt User/Passwort + */ + private function ConfigureGateway() + { + // 1. Suche Parent (MQTT Splitter) + $instance = IPS_GetInstance($this->InstanceID); + $splitterID = $instance['ConnectionID']; + + if ($splitterID > 0) { + // 2. Suche Grandparent (MQTT Client / IO) + $splitter = IPS_GetInstance($splitterID); + $ioID = $splitter['ConnectionID']; + + if ($ioID > 0) { + // Prüfen, ob es ein MQTT Client ist (GUID prüfen oder einfach Eigenschaften setzen) + // Wir setzen die Eigenschaften, wenn sie existieren. + + $user = $this->ReadPropertyString('MQTTUser'); + $pass = $this->ReadPropertyString('MQTTPassword'); + $client = $this->ReadPropertyString('MQTTClientID'); + + $hasChanged = false; + + // ClientID (Achtung: Symcon MQTT Splitter nutzt ClientID meist im Splitter, nicht IO) + // Wir prüfen, wo die Property existiert. + + // Versuch 1: IO Konfigurieren (User/Pass) + if (@IPS_GetProperty($ioID, 'Username') !== false) { + if (IPS_GetProperty($ioID, 'Username') != $user) { IPS_SetProperty($ioID, 'Username', $user); $hasChanged = true; } + if (IPS_GetProperty($ioID, 'Password') != $pass) { IPS_SetProperty($ioID, 'Password', $pass); $hasChanged = true; } + } + + // Versuch 2: ClientID wird oft im Splitter (dem direkten Parent) konfiguriert + if (@IPS_GetProperty($splitterID, 'ClientID') !== false) { + if (IPS_GetProperty($splitterID, 'ClientID') != $client) { IPS_SetProperty($splitterID, 'ClientID', $client); $hasChanged = true; } // Splitter neu laden + if ($hasChanged) IPS_ApplyChanges($splitterID); + } + + // Änderungen am IO übernehmen + if ($hasChanged) { + IPS_ApplyChanges($ioID); + } + } + } + } + + // ------------------------------------------------------------------------- + // MQTT Logik (unverändert) + // ------------------------------------------------------------------------- public function ReceiveData($JSONString) { $data = json_decode($JSONString); - - // Der Splitter liefert 'Topic' und 'Payload' (Payload ist meist UTF-8) $payload = utf8_decode($data->Payload); $topic = $data->Topic; - $baseTopic = $this->ReadPropertyString('MQTTBaseTopic'); - // Debugging (optional, schreibt ins Meldungsfenster) - // $this->SendDebug('MQTT In', "Topic: $topic | Payload: $payload", 0); + // Debug + $this->SendDebug('MQTT Received', "Topic: $topic | Payload: $payload", 0); - // Routing if ($topic === $baseTopic . '/Writebefehl') { $this->ProcessWriteCommand($payload); } @@ -76,7 +143,6 @@ class VGT_Sub extends IPSModule } } - // --- LOGIK --- public function MessageSink($TimeStamp, $SenderID, $Message, $Data) { if ($Message == VM_UPDATE) { @@ -111,26 +177,23 @@ class VGT_Sub extends IPSModule elseif ($val < -6000) $val = -6000; $this->SetValue('PowerSetpoint', $val); } - if (isset($data['strategy'])) { $this->SetValue('Strategy', $data['strategy']); } $this->ExecuteControlLogic(); - // Antwort Senden $output = [ 'power_setpoint' => $this->GetValue('PowerSetpoint'), 'strategy' => $this->GetValue('Strategy') ]; - + // Antwort senden $this->SendMQTT($this->ReadPropertyString('MQTTBaseTopic') . '/Writebefehl Antwort', json_encode($output)); } private function ProcessReadCommand() { $data = $this->GatherHardwareData(); - $this->SetValue('Visu_Production', $data['raw_prod']); $this->SetValue('Visu_IsReady', $data['is_ready']); @@ -142,7 +205,7 @@ class VGT_Sub extends IPSModule 'min_soc' => $data['min_soc'], 'max_soc' => $data['max_soc'] ]; - + // Antwort senden $this->SendMQTT($this->ReadPropertyString('MQTTBaseTopic') . '/Lesebefehl Antwort', json_encode($mqttData)); } @@ -153,7 +216,6 @@ class VGT_Sub extends IPSModule $strategy = $this->GetValue('Strategy'); $setpoint = $this->GetValue('PowerSetpoint'); - $socID = $this->ReadPropertyInteger('SourceSoC'); $soc = IPS_VariableExists($socID) ? GetValue($socID) : 0; @@ -178,7 +240,6 @@ class VGT_Sub extends IPSModule $id = $this->ReadPropertyInteger($propName); return IPS_VariableExists($id) ? GetValue($id) : 0; }; - return [ 'raw_prod' => $safeGet('SourcePowerProd'), 'is_ready' => (bool)$safeGet('SourceIsReady'), @@ -189,22 +250,17 @@ class VGT_Sub extends IPSModule ]; } -// Hilfsfunktion: MQTT Senden protected function SendMQTT($Topic, $Payload) { - // DataID für MQTT Publish (TX) an den Splitter - $Data['DataID'] = '{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}'; - - $Data['PacketType'] = 3; // 3 = MQTT Publish - $Data['QualityOfService'] = 0; - $Data['Retain'] = false; - $Data['Topic'] = $Topic; - $Data['Payload'] = $Payload; - - $JSON = json_encode($Data); - - // Senden an Parent (MQTT Splitter) - $this->SendDataToParent($JSON); + // Standard DataID für MQTT Publish an Splitter + $Data['DataID'] = '{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}'; + $Data['PacketType'] = 3; + $Data['QualityOfService'] = 0; + $Data['Retain'] = false; + $Data['Topic'] = $Topic; + $Data['Payload'] = $Payload; + $JSON = json_encode($Data); + $this->SendDataToParent($JSON); } } ?> \ No newline at end of file