diff --git a/VGT_Sub/module.json b/VGT_Sub/module.json index ef50d59..44f1cab 100644 --- a/VGT_Sub/module.json +++ b/VGT_Sub/module.json @@ -7,11 +7,11 @@ "VGT MQTT Device" ], "parentRequirements": [ - "{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}", - "{F66ADE63-8834-4178-8CA5-AE4465D2E252}" + "{F66ADE63-8834-4178-8CA5-AE4465D2E252}", + "{F7A0DD2E-7684-95C0-64C2-D2A9DC47577B}" ], "childRequirements": [], "implemented": ["{018EF6B5-AB94-40C6-AA53-46943E824ACF}"], "prefix": "VGT", - "version": "2.1" + "version": "3.0" } \ No newline at end of file diff --git a/VGT_Sub/module.php b/VGT_Sub/module.php index 7ef4f7e..7fe9e6e 100644 --- a/VGT_Sub/module.php +++ b/VGT_Sub/module.php @@ -4,6 +4,10 @@ declare(strict_types=1); class VGT_Sub extends IPSModule { + // GUIDs für den offiziellen IP-Symcon Datenfluss (MQTT) + const MQTT_TX_GUID = '{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}'; // Wir senden das an den Splitter + const MQTT_RX_GUID = '{018EF6B5-AB94-40C6-AA53-46943E824ACF}'; // Wir empfangen das (implemented) + public function Create() { parent::Create(); @@ -11,7 +15,7 @@ class VGT_Sub extends IPSModule // --- Konfiguration --- $this->RegisterPropertyString('MQTTBaseTopic', 'Test VGT_Steuerung/Komm'); - // --- Optionale Gateway-Konfig (Nur für IO/Socket relevant) --- + // Gateway-Konfig (Optional für Komfort) $this->RegisterPropertyString('MQTTUser', ''); $this->RegisterPropertyString('MQTTPassword', ''); $this->RegisterPropertyBoolean('UpdateGatewayConfig', false); @@ -37,36 +41,49 @@ class VGT_Sub extends IPSModule { parent::ApplyChanges(); - // 1. Filter setzen (Abonnieren) + // --------------------------------------------------------------------- + // DATENFLUSS: Filter setzen + // --------------------------------------------------------------------- + // Wir teilen dem Splitter mit: "Schick mir nur Daten für mein Topic" + // Das entlastet das System massiv. $topic = $this->ReadPropertyString('MQTTBaseTopic'); if($topic !== "") { $cleanTopic = preg_quote($topic, '/'); - // Dieser Filter funktioniert für beide Splitter-Varianten + // Regex Filter auf das Feld "Topic" im JSON Datensatz $this->SetReceiveDataFilter(".*\"Topic\":\"" . $cleanTopic . "/.*\".*"); } - // 2. Gateway Config (Optional) + // --------------------------------------------------------------------- + // Komfort: Gateway Konfiguration durchreichen + // --------------------------------------------------------------------- if ($this->ReadPropertyBoolean('UpdateGatewayConfig')) { $this->ConfigureGateway(); } - // 3. Events registrieren + // --------------------------------------------------------------------- + // Events + // --------------------------------------------------------------------- $socID = $this->ReadPropertyInteger('SourceSoC'); if (IPS_VariableExists($socID)) $this->RegisterMessage($socID, VM_UPDATE); $this->RegisterMessage($this->GetIDForIdent('Strategy'), VM_UPDATE); $this->RegisterMessage($this->GetIDForIdent('PowerSetpoint'), VM_UPDATE); } + // ------------------------------------------------------------------------- + // DATENFLUSS: Empfang (ReceiveData) + // ------------------------------------------------------------------------- + // Wird automatisch aufgerufen, wenn der Splitter Daten hat, die zum Filter passen. public function ReceiveData($JSONString) { $data = json_decode($JSONString); - // Payload Dekodierung + // Daten aus dem JSON extrahieren (Standard Symcon Format) $payload = utf8_decode($data->Payload); $topic = $data->Topic; $baseTopic = $this->ReadPropertyString('MQTTBaseTopic'); + // Routing if ($topic === $baseTopic . '/Writebefehl') { $this->ProcessWriteCommand($payload); } @@ -75,6 +92,28 @@ class VGT_Sub extends IPSModule } } + // ------------------------------------------------------------------------- + // DATENFLUSS: Senden (SendDataToParent) + // ------------------------------------------------------------------------- + protected function SendMQTT($Topic, $Payload) + { + // Wir bauen das JSON Paket exakt so, wie der MQTT Splitter es erwartet + $Data = [ + 'DataID' => self::MQTT_TX_GUID, // Die ID für "MQTT Publish" + 'PacketType' => 3, // 3 = Publish + 'QualityOfService' => 0, + 'Retain' => false, + 'Topic' => $Topic, + 'Payload' => $Payload + ]; + + // Ab an den Parent (Splitter) + $this->SendDataToParent(json_encode($Data)); + } + + // ------------------------------------------------------------------------- + // Interne Logik + // ------------------------------------------------------------------------- private function ProcessWriteCommand($jsonInput) { $data = json_decode($jsonInput, true); @@ -130,33 +169,18 @@ class VGT_Sub extends IPSModule else RequestAction($targetID, -2500); } } - - protected function SendMQTT($Topic, $Payload) - { - // Standard DataID für MQTT. Funktioniert meistens auch mit dem 77B-Modul. - $Data['DataID'] = '{043EA491-0325-4ADD-8FC2-A30C8EEB4D3F}'; - $Data['PacketType'] = 3; - $Data['QualityOfService'] = 0; - $Data['Retain'] = false; - $Data['Topic'] = $Topic; - $Data['Payload'] = $Payload; - $this->SendDataToParent(json_encode($Data)); - } - // Automatische Konfiguration des Parents (falls aktiviert) + // Hilfsfunktion: IO Konfigurieren private function ConfigureGateway() { $instance = IPS_GetInstance($this->InstanceID); - $parentId = $instance['ConnectionID']; // Das ist dein 77B Modul oder der native Splitter + $parentId = $instance['ConnectionID']; if ($parentId > 0) { - // Wir versuchen, User/Pass auf dem Parent zu setzen (manche Module haben das direkt) - // Oder wir suchen den IO darunter. - $user = $this->ReadPropertyString('MQTTUser'); $pass = $this->ReadPropertyString('MQTTPassword'); - // Check: Hat der Parent direkt Username/Password? (Schnittcher Modul hat das oft) + // Versuch 1: Parent ist direkt konfigurierbar (z.B. Schnittcher Splitter) if (@IPS_GetProperty($parentId, 'Username') !== false) { IPS_SetProperty($parentId, 'Username', $user); IPS_SetProperty($parentId, 'Password', $pass); @@ -164,7 +188,8 @@ class VGT_Sub extends IPSModule return; } - // Wenn nicht, suchen wir den IO darunter (Native Symcon Logik) + // Versuch 2: Standard Symcon Weg (Device -> Splitter -> IO) + // Wir müssen den IO unter dem Splitter finden $parentInfo = IPS_GetInstance($parentId); $ioID = $parentInfo['ConnectionID']; if ($ioID > 0) {