no message
This commit is contained in:
@@ -33,34 +33,51 @@ class ShellyParser
|
|||||||
public static function MapParams(array $params): array
|
public static function MapParams(array $params): array
|
||||||
{
|
{
|
||||||
$mapped = [
|
$mapped = [
|
||||||
'input' => null,
|
'outputs' => [], // switch:x → output
|
||||||
'output' => null,
|
'inputs' => [], // input:x → state oder switch:x.input
|
||||||
'temperature' => null
|
'temperature' => null
|
||||||
];
|
];
|
||||||
|
|
||||||
// GEN3 / GEN4 Geräte → switch:0, switch:1, ...
|
|
||||||
foreach ($params as $key => $value) {
|
foreach ($params as $key => $value) {
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// OUTPUTS (switch:0 → output)
|
||||||
|
// -----------------------------
|
||||||
if (str_starts_with($key, 'switch:') && is_array($value)) {
|
if (str_starts_with($key, 'switch:') && is_array($value)) {
|
||||||
|
|
||||||
// Output
|
$index = (int)substr($key, 7);
|
||||||
|
|
||||||
if (isset($value['output'])) {
|
if (isset($value['output'])) {
|
||||||
$mapped['output'] = (bool)$value['output'];
|
$mapped['outputs'][$index] = (bool)$value['output'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input (für Pro / Gen4 Geräte)
|
// Gen4 / Pro Geräte haben input im switch
|
||||||
if (isset($value['input'])) {
|
if (isset($value['input'])) {
|
||||||
$mapped['input'] = (bool)$value['input'];
|
$mapped['inputs'][$index] = (bool)$value['input'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------
|
||||||
|
// 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'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temperatur suchen (beliebig tief)
|
// Temperatur-Suche (verschachtelt)
|
||||||
self::ExtractRecursive($params, $mapped);
|
self::ExtractRecursive($params, $mapped);
|
||||||
|
|
||||||
return array_filter($mapped, fn($v) => $v !== null);
|
return $mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static function ExtractRecursive(array $data, array &$mapped): void
|
private static function ExtractRecursive(array $data, array &$mapped): void
|
||||||
{
|
{
|
||||||
foreach ($data as $key => $value) {
|
foreach ($data as $key => $value) {
|
||||||
|
|||||||
@@ -73,42 +73,29 @@ class Shelly_Parser_MQTT extends IPSModule
|
|||||||
* ---------------------------------------------------------*/
|
* ---------------------------------------------------------*/
|
||||||
public function RequestAction($Ident, $Value)
|
public function RequestAction($Ident, $Value)
|
||||||
{
|
{
|
||||||
// Lokale Variable aktualisieren
|
// Output? z.B. BE_1_3_14_output_0
|
||||||
$varID = @IPS_GetObjectIDByIdent($Ident, $this->InstanceID);
|
if (str_contains($Ident, '_output_')) {
|
||||||
if (!$varID) {
|
|
||||||
// Falls Variable im Ordner liegt:
|
|
||||||
foreach (IPS_GetChildrenIDs($this->InstanceID) as $folder) {
|
|
||||||
foreach (IPS_GetChildrenIDs($folder) as $cid) {
|
|
||||||
if (IPS_GetObject($cid)['ObjectIdent'] === $Ident) {
|
|
||||||
$varID = $cid;
|
|
||||||
break 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($varID) {
|
SetValue(IPS_GetObjectIDByIdent($Ident, $this->FindDeviceFolder($Ident)), $Value);
|
||||||
SetValue($varID, $Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prüfen ob das ein Output ist
|
// Device & Index extrahieren
|
||||||
if (str_ends_with($Ident, '_output')) {
|
$parts = explode('_output_', $Ident);
|
||||||
|
$deviceID = $parts[0];
|
||||||
$deviceID = substr($Ident, 0, -strlen('_output'));
|
$index = (int)$parts[1];
|
||||||
|
|
||||||
$topic = $deviceID . '/rpc/Switch.Set';
|
$topic = $deviceID . '/rpc/Switch.Set';
|
||||||
|
|
||||||
$payload = json_encode([
|
$payload = json_encode([
|
||||||
'id' => 0,
|
'id' => $index,
|
||||||
'on' => (bool)$Value
|
'on' => (bool)$Value
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->Publish($topic, $payload);
|
$this->Publish($topic, $payload);
|
||||||
|
return;
|
||||||
if ($this->ReadPropertyBoolean('Debug')) {
|
|
||||||
IPS_LogMessage("Shelly_Parser_MQTT", "Switching $deviceID -> $Value");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// andere Variablen (falls nötig)
|
||||||
|
throw new Exception("Unknown Ident $Ident");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -157,72 +144,77 @@ class Shelly_Parser_MQTT extends IPSModule
|
|||||||
/* ---------------------------------------------------------
|
/* ---------------------------------------------------------
|
||||||
* ONLINE-STATUS
|
* ONLINE-STATUS
|
||||||
* ---------------------------------------------------------*/
|
* ---------------------------------------------------------*/
|
||||||
private function HandleOnline(string $deviceID, string $payload): void
|
private function HandleOnline(string $deviceID, string $payload): void
|
||||||
{
|
{
|
||||||
$value = ($payload === 'true' || $payload === '1');
|
$value = ($payload === 'true' || $payload === '1');
|
||||||
|
|
||||||
$varID = $this->EnsureBooleanVariable($deviceID, $deviceID . '_online', 'Online');
|
$varID = $this->EnsureBooleanVariable($deviceID, $deviceID . '_online', 'Online');
|
||||||
SetValue($varID, $value);
|
SetValue($varID, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------
|
/* ---------------------------------------------------------
|
||||||
* RPC-EVENTS
|
* RPC-EVENTS
|
||||||
* ---------------------------------------------------------*/
|
* ---------------------------------------------------------*/
|
||||||
private function HandleRPC(string $deviceID, string $payload): void
|
private function HandleRPC(string $deviceID, string $payload): void
|
||||||
{
|
{
|
||||||
$json = json_decode($payload, true);
|
$json = json_decode($payload, true);
|
||||||
if (!is_array($json)) {
|
if (!is_array($json)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shelly prüfen
|
// Gerätetyp setzen
|
||||||
$src = $json['src'] ?? '';
|
$src = $json['src'] ?? '';
|
||||||
if (!is_string($src) || !str_starts_with($src, 'shelly')) {
|
if (!str_starts_with($src, 'shelly')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Typ extrahieren (z.B. "1minig3", "1g4", "plusplugs", ...)
|
|
||||||
$type = ShellyParser::ExtractType($src);
|
$type = ShellyParser::ExtractType($src);
|
||||||
$typeID = $this->EnsureStringVariable($deviceID, $deviceID . '_type', 'Typ');
|
$typeID = $this->EnsureStringVariable($deviceID, $deviceID . '_type', 'Typ');
|
||||||
SetValue($typeID, $type);
|
SetValue($typeID, $type);
|
||||||
|
|
||||||
// Parameter extrahieren
|
// Mappen
|
||||||
$params = $json['params'] ?? [];
|
$params = $json['params'] ?? [];
|
||||||
if (!is_array($params)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mapped = ShellyParser::MapParams($params);
|
$mapped = ShellyParser::MapParams($params);
|
||||||
|
|
||||||
// Output
|
// -----------------------------------
|
||||||
if (array_key_exists('output', $mapped)) {
|
// DYNAMISCHE OUTPUTS
|
||||||
$outID = $this->EnsureBooleanVariable($deviceID, $deviceID . '_output', 'Output');
|
// -----------------------------------
|
||||||
IPS_SetVariableCustomAction($outID, $this->InstanceID);
|
foreach ($mapped['outputs'] as $index => $value) {
|
||||||
SetValue($outID, (bool)$mapped['output']);
|
|
||||||
|
$ident = $deviceID . "_output_" . $index;
|
||||||
|
$name = "Output $index";
|
||||||
|
|
||||||
|
$varID = $this->EnsureBooleanVariable($deviceID, $ident, $name);
|
||||||
|
|
||||||
|
// Aktionsskript aktivieren für Schalten
|
||||||
|
IPS_SetVariableCustomAction($varID, $this->InstanceID);
|
||||||
|
|
||||||
|
SetValue($varID, $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// DYNAMISCHE INPUTS
|
||||||
|
// -----------------------------------
|
||||||
|
foreach ($mapped['inputs'] as $index => $value) {
|
||||||
|
|
||||||
// Input (GEN4 / PRO)
|
$ident = $deviceID . "_input_" . $index;
|
||||||
if (array_key_exists('input', $mapped)) {
|
$name = "Input $index";
|
||||||
$inID = $this->EnsureBooleanVariable(
|
|
||||||
$deviceID,
|
$varID = $this->EnsureBooleanVariable($deviceID, $ident, $name);
|
||||||
$deviceID . '_input',
|
|
||||||
'Input'
|
SetValue($varID, $value);
|
||||||
);
|
|
||||||
SetValue($inID, (bool)$mapped['input']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temperatur (falls gefunden)
|
// -----------------------------------
|
||||||
if (array_key_exists('temperature', $mapped)) {
|
// TEMPERATUR
|
||||||
$tempID = $this->EnsureFloatVariable(
|
// -----------------------------------
|
||||||
$deviceID,
|
if ($mapped['temperature'] !== null) {
|
||||||
$deviceID . '_temperature',
|
$tempID = $this->EnsureFloatVariable($deviceID, $deviceID . '_temperature', 'Temperatur');
|
||||||
'Temperatur'
|
SetValue($tempID, $mapped['temperature']);
|
||||||
);
|
|
||||||
SetValue($tempID, (float)$mapped['temperature']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------
|
/* ---------------------------------------------------------
|
||||||
* Helper für Variablen
|
* Helper für Variablen
|
||||||
* ---------------------------------------------------------*/
|
* ---------------------------------------------------------*/
|
||||||
@@ -303,5 +295,18 @@ class Shelly_Parser_MQTT extends IPSModule
|
|||||||
|
|
||||||
return $folderID;
|
return $folderID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function FindDeviceFolder(string $Ident): int
|
||||||
|
{
|
||||||
|
foreach (IPS_GetChildrenIDs($this->InstanceID) as $folder) {
|
||||||
|
foreach (IPS_GetChildrenIDs($folder) as $cid) {
|
||||||
|
if (IPS_GetObject($cid)['ObjectIdent'] === $Ident) {
|
||||||
|
return $folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|||||||
Reference in New Issue
Block a user