From e9b21d982fb27dcdfe68dda59c461930557c6c3f Mon Sep 17 00:00:00 2001 From: "belevo\\dh" Date: Mon, 24 Nov 2025 11:19:07 +0100 Subject: [PATCH] no message --- Shelly_Parser_MQTT/module.php | 119 +++++++++++++++------------------- 1 file changed, 54 insertions(+), 65 deletions(-) diff --git a/Shelly_Parser_MQTT/module.php b/Shelly_Parser_MQTT/module.php index c1584de..ce4d793 100644 --- a/Shelly_Parser_MQTT/module.php +++ b/Shelly_Parser_MQTT/module.php @@ -12,7 +12,7 @@ class Shelly_Parser_MQTT extends IPSModule { parent::Create(); - // MQTT verbinden + // MQTT-Server $this->ConnectParent('{C6D2AEB3-6E1F-4B2E-8E69-3A1A00246850}'); } @@ -20,15 +20,23 @@ class Shelly_Parser_MQTT extends IPSModule { parent::ApplyChanges(); - // Parent verbinden $this->ConnectParent('{C6D2AEB3-6E1F-4B2E-8E69-3A1A00246850}'); - // Niemals im ApplyChanges Publish/Subscribe senden! + // Subscribe wird erst beim ersten Paket ausgeführt $this->Subscribed = false; } /* --------------------------------------------------------- - * SICHER SENDEN + * DEBUG SHORTCUT + * ---------------------------------------------------------*/ + private function Log($title, $msg) + { + $this->SendDebug($title, $msg, 0); + IPS_LogMessage("ShellyMQTT/$title", $msg); + } + + /* --------------------------------------------------------- + * Sicher Senden (Parent OK?) * ---------------------------------------------------------*/ private function SafeSend(array $packet) { @@ -38,24 +46,15 @@ class Shelly_Parser_MQTT extends IPSModule return; } - if (IPS_GetInstance($parent)['InstanceStatus'] !== 102) { // IS_ACTIVE + if (IPS_GetInstance($parent)['InstanceStatus'] !== 102) { return; } - @ $this->SendDataToParent(json_encode($packet)); + @$this->SendDataToParent(json_encode($packet)); } /* --------------------------------------------------------- - * DEBUG - * ---------------------------------------------------------*/ - private function Log($title, $msg) - { - IPS_LogMessage("ShellyMQTT: $title", $msg); - $this->SendDebug($title, $msg, 0); - } - - /* --------------------------------------------------------- - * SUBSCRIBE – nur wenn der Parent sicher aktiv ist! + * Subscribe once * ---------------------------------------------------------*/ private function EnsureSubscribe() { @@ -74,11 +73,11 @@ class Shelly_Parser_MQTT extends IPSModule 'Payload' => '' ]); - $this->Log("Subscribe", "#"); + $this->Log("Subscribe", "Subscribed to #"); } /* --------------------------------------------------------- - * MQTT SEND + * MQTT Publish * ---------------------------------------------------------*/ private function Publish(string $topic, string $payload) { @@ -95,28 +94,28 @@ class Shelly_Parser_MQTT extends IPSModule } /* --------------------------------------------------------- - * REQUEST ACTION + * REQUEST ACTION (Schalten Shelly Output) * ---------------------------------------------------------*/ public function RequestAction($Ident, $Value) { - $this->Log('RequestAction', "$Ident → " . var_export($Value, true)); + $this->Log("RequestAction", "$Ident → " . json_encode($Value)); - // Nur Outputs sind schaltbar if (!str_contains($Ident, '_output_')) { throw new Exception("Unknown Ident: $Ident"); } - // Lokale Variable aktualisieren + // Lokale Variable setzen $varID = $this->FindVariableByIdent($Ident); if ($varID > 0) { SetValue($varID, $Value); } - // deviceID und Index extrahieren + // deviceID / Index extrahieren [$deviceID, $suffix] = explode('_output_', $Ident); $index = intval($suffix); - $topic = $deviceID . '/rpc'; + $topic = "$deviceID/rpc"; + $payload = json_encode([ 'id' => 1, 'src' => 'ips', @@ -135,31 +134,22 @@ class Shelly_Parser_MQTT extends IPSModule * ---------------------------------------------------------*/ public function ReceiveData($JSONString) { - $this->Log('ReceiveData', $JSONString); - - // Erst beim ersten Datenpaket subscriben $this->EnsureSubscribe(); - $data = json_decode($JSONString, true); - if (!is_array($data)) { - return; - } + + if (!is_array($data)) return; $topic = $data['Topic'] ?? ''; $payload = $data['Payload'] ?? ''; - if ($topic === '') { - return; - } + if ($topic === '') return; - $this->Log('ReceiveTopic', "$topic → $payload"); + $this->Log("ReceiveTopic", "$topic → $payload"); $parts = explode('/', $topic); $deviceID = $parts[0] ?? ''; - if ($deviceID === '') { - return; - } + if ($deviceID === '') return; // Online if (($parts[1] ?? '') === 'online') { @@ -167,7 +157,7 @@ class Shelly_Parser_MQTT extends IPSModule return; } - // RPC + // Events RPC if (($parts[1] ?? '') === 'events' && ($parts[2] ?? '') === 'rpc') { $this->HandleRPC($deviceID, $payload); return; @@ -180,83 +170,82 @@ class Shelly_Parser_MQTT extends IPSModule private function HandleOnline(string $deviceID, string $payload) { $value = ($payload === 'true' || $payload === '1'); - - $varID = $this->EnsureBooleanVariable($deviceID, $deviceID . '_online', 'Online'); - SetValue($varID, $value); + $vid = $this->EnsureBooleanVariable($deviceID, $deviceID . '_online', 'Online'); + SetValue($vid, $value); } /* --------------------------------------------------------- - * RPC + * RPC Handler * ---------------------------------------------------------*/ private function HandleRPC(string $deviceID, string $payload) { $json = json_decode($payload, true); - if (!is_array($json)) { - return; - } + if (!is_array($json)) return; $src = $json['src'] ?? ''; - if (!str_starts_with($src, 'shelly')) { - return; - } + if (!str_starts_with($src, 'shelly')) return; // Typ - $type = ShellyParser::ExtractType($src); - $typeID = $this->EnsureStringVariable($deviceID, $deviceID . '_type', 'Typ'); - SetValue($typeID, $type); + $type = ShellyParser::ExtractType($src); + $tid = $this->EnsureStringVariable($deviceID, $deviceID . '_type', 'Typ'); + SetValue($tid, $type); $params = $json['params'] ?? []; $mapped = ShellyParser::MapParams($params); // Outputs foreach ($mapped['outputs'] as $i => $val) { - $vid = $this->EnsureBooleanVariable($deviceID, $deviceID . '_output_' . $i, 'Output ' . $i); + $vid = $this->EnsureBooleanVariable($deviceID, "{$deviceID}_output_$i", "Output $i"); SetValue($vid, $val); } // Inputs foreach ($mapped['inputs'] as $i => $val) { - $vid = $this->EnsureBooleanVariable($deviceID, $deviceID . '_input_' . $i, 'Input ' . $i); + $vid = $this->EnsureBooleanVariable($deviceID, "{$deviceID}_input_$i", "Input $i"); SetValue($vid, $val); } // Temperatur if ($mapped['temperature'] !== null) { - $tid = $this->EnsureFloatVariable($deviceID, $deviceID . '_temperature', 'Temperatur'); - SetValue($tid, $mapped['temperature']); + $f = $this->EnsureFloatVariable($deviceID, "{$deviceID}_temperature", "Temperatur"); + SetValue($f, $mapped['temperature']); } } /* --------------------------------------------------------- - * VARIABLEN ETC. + * VARIABLEN – MIT AUTOMATISCHER REPARATUR * ---------------------------------------------------------*/ private function EnsureBooleanVariable(string $deviceID, string $ident, string $name): int { $folder = $this->GetDeviceFolder($deviceID); - $vid = 0; + $vid = 0; - // Gibt es die Variable schon? foreach (IPS_GetChildrenIDs($folder) as $cid) { $obj = IPS_GetObject($cid); + + // Auto-Repair für alte Versionen ohne Ident + if ($obj['ObjectName'] === $name && $obj['ObjectIdent'] === '') { + IPS_SetIdent($cid, $ident); + $vid = $cid; + break; + } + if ($obj['ObjectIdent'] === $ident) { $vid = $cid; break; } } - // Neu anlegen, falls nicht vorhanden if ($vid === 0) { - $vid = IPS_CreateVariable(0); // 0 = Boolean + $vid = IPS_CreateVariable(0); IPS_SetName($vid, $name); IPS_SetIdent($vid, $ident); IPS_SetParent($vid, $folder); } - // ---- HIER: nur für Outputs Action + Profil setzen ---- + // OUTPUT → Switch-UI + Action if (str_contains($ident, '_output_')) { - // Schaltprofil IPS_SetVariableCustomProfile($vid, '~Switch'); - // Aktion geht direkt an dieses Modul (RequestAction) IPS_SetVariableCustomAction($vid, $this->InstanceID); } @@ -311,7 +300,7 @@ class Shelly_Parser_MQTT extends IPSModule return $fid; } - private function FindVariableByIdent(string $Ident) + private function FindVariableByIdent(string $Ident): int { foreach (IPS_GetChildrenIDs($this->InstanceID) as $folder) { foreach (IPS_GetChildrenIDs($folder) as $cid) {