diff --git a/Shelly_Parser_MQTT/libs/ShellyParser.php b/Shelly_Parser_MQTT/libs/ShellyParser.php index f3039ee..fef133e 100644 --- a/Shelly_Parser_MQTT/libs/ShellyParser.php +++ b/Shelly_Parser_MQTT/libs/ShellyParser.php @@ -31,51 +31,52 @@ class ShellyParser * - temperature (float, inkl. tC) */ public static function MapParams(array $params): array - { - $mapped = [ - 'outputs' => [], // switch:x → output - 'inputs' => [], // input:x → state oder switch:x.input - 'temperature' => null - ]; +{ + $mapped = [ + 'outputs' => [], // switch:x → output + 'inputs' => [], // input:x → state oder switch:x.input + 'temperature' => null + ]; - foreach ($params as $key => $value) { + foreach ($params as $key => $value) { - // ----------------------------- - // OUTPUTS (switch:0 → output) - // ----------------------------- - if (str_starts_with($key, 'switch:') && is_array($value)) { + // ----------------------------- + // OUTPUTS (switch:0 → output) + // ----------------------------- + if (str_starts_with($key, 'switch:') && is_array($value)) { - $index = (int)substr($key, 7); + $index = (int)substr($key, 7); - if (isset($value['output'])) { - $mapped['outputs'][$index] = (bool)$value['output']; - } - - // Gen4 / Pro Geräte haben input im switch - if (isset($value['input'])) { - $mapped['inputs'][$index] = (bool)$value['input']; - } + if (isset($value['output'])) { + $mapped['outputs'][$index] = (bool)$value['output']; } - // ----------------------------- - // INPUTS (input:0 → state) - // ----------------------------- - if (str_starts_with($key, 'input:') && is_array($value)) { - - $index = (int)substr($key, 6); - - if (isset($value['state'])) { - $mapped['inputs'][$index] = (bool)$value['state']; - } + // Gen4 Input in switch + if (isset($value['input'])) { + $mapped['inputs'][$index] = (bool)$value['input']; } } - // Temperatur-Suche (verschachtelt) - self::ExtractRecursive($params, $mapped); + // ----------------------------- + // INPUTS (input:0 → state) + // ----------------------------- + if (str_starts_with($key, 'input:') && is_array($value)) { - return $mapped; + $index = (int)substr($key, 6); + + if (isset($value['state'])) { + $mapped['inputs'][$index] = (bool)$value['state']; + } + } } + // Temperatur (verschachtelt) + self::ExtractRecursive($params, $mapped); + + return $mapped; +} + + private static function ExtractRecursive(array $data, array &$mapped): void diff --git a/Shelly_Parser_MQTT/module.php b/Shelly_Parser_MQTT/module.php index d6da48d..339bc49 100644 --- a/Shelly_Parser_MQTT/module.php +++ b/Shelly_Parser_MQTT/module.php @@ -73,39 +73,46 @@ class Shelly_Parser_MQTT extends IPSModule * ---------------------------------------------------------*/ public function RequestAction($Ident, $Value) { + IPS_LogMessage("ShellyDebug", "RequestAction($Ident → $Value)"); + + // Dynamischer Output? z.B. BE_1_3_14_output_0 if (str_contains($Ident, '_output_')) { - // Lokale Variable setzen + // 1) Variable im Geräte-Ordner finden & setzen $varID = $this->FindVariableByIdent($Ident); if ($varID) { SetValue($varID, $Value); } - // device + index ermitteln + // 2) Device + Switch-Index extrahieren $parts = explode('_output_', $Ident); $deviceID = $parts[0]; - $index = (int)$parts[1]; + $index = intval($parts[1]); - // GEN3 / GEN4 / PRO → Switch.Set muss im rpc-Root gesendet werden + // 3) Shelly-konformes Topic $topic = $deviceID . '/rpc'; + // 4) Shelly-konformes Payload gemäß API-Dokumentation $payload = json_encode([ - "id" => 1, - "src" => "ips", - "method" => "Switch.Set", - "params" => [ + "id" => 1, + "src" => "ips", + "method" => "Switch.Set", + "params" => [ "id" => $index, "on" => (bool)$Value ] ]); + IPS_LogMessage("ShellyDebug", "SEND → $topic : $payload"); + + // 5) Absenden $this->Publish($topic, $payload); - IPS_LogMessage("Shelly_Parser_MQTT", "SEND → $topic : $payload"); return; } - } + throw new Exception("Unknown Ident: " . $Ident); + } /* --------------------------------------------------------- @@ -190,29 +197,29 @@ class Shelly_Parser_MQTT extends IPSModule // ----------------------------------- foreach ($mapped['outputs'] as $index => $value) { - $ident = $deviceID . "_output_" . $index; - $name = "Output $index"; + $ident = $deviceID . "_output_" . $index; + $name = "Output $index"; - $varID = $this->EnsureBooleanVariable($deviceID, $ident, $name); + $varID = $this->EnsureBooleanVariable($deviceID, $ident, $name); - // Aktionsskript aktivieren für Schalten - IPS_SetVariableCustomAction($varID, $this->InstanceID); + // Für Schalten in RequestAction + IPS_SetVariableCustomAction($varID, $this->InstanceID); - SetValue($varID, $value); - } + SetValue($varID, $value); + } // ----------------------------------- // DYNAMISCHE INPUTS // ----------------------------------- - foreach ($mapped['inputs'] as $index => $value) { + foreach ($mapped['inputs'] as $index => $value) { - $ident = $deviceID . "_input_" . $index; - $name = "Input $index"; + $ident = $deviceID . "_input_" . $index; + $name = "Input $index"; - $varID = $this->EnsureBooleanVariable($deviceID, $ident, $name); + $varID = $this->EnsureBooleanVariable($deviceID, $ident, $name); - SetValue($varID, $value); - } + SetValue($varID, $value); + } // ----------------------------------- // TEMPERATUR @@ -317,5 +324,17 @@ class Shelly_Parser_MQTT extends IPSModule return 0; } + private function FindVariableByIdent(string $Ident) + { + foreach (IPS_GetChildrenIDs($this->InstanceID) as $folder) { + foreach (IPS_GetChildrenIDs($folder) as $cid) { + if (IPS_GetObject($cid)['ObjectIdent'] === $Ident) { + return $cid; + } + } + } + return 0; + } + } ?>