Status von Zigbee-/Z-Wave-Geräten

Moin,
bei Geräten die direkt am Strom hängen gibt es eigentlich immer eine Variable Status. Problem mit dieser Variable ist das sie nur wirklich richtig ist wenn Strom auch permanent an ist. Schaltet man z.B. mit einem altmodischen Lichschalter eine Zigbee-Birne/-Lampe aus die angeschaltet war behält sie ihren Status an da sie ja nicht wissen kann das sie gleich vom Strom getrennt wird.

Für Zigbee2MQTT und Z-Wave habe ich Scripte geschrieben die eine zusätzliche Power-Variable mit dem Ident RB_Power in den Instanzen anlegen. In dieser Variable steht true wenn das Gerät reagiert und damit Strom bekommt oder false wenn es nicht reagiert. Die Scripte setzen einen 5 Minuten-Timer. Sollte eine schnellere Reaktion benötigt werden einfach den Timer ändern.

Benutzt man einen Bewegungsmelder um Licht zu schalten aber die Lampe ist vom Strom getrennt könnte man Alexa z.B. „Du musst leider den Schalter benutzen“ sagen lasse wenn RB_Power false ist.

Hier das Script für Zigbee2MQTT:

<?php
// Alle Zigbee2MQTT Instanzen in ein Feld einlesen
$InstanzIDsList = IPS_GetInstanceListByModuleID('{E5BB36C6-A70B-EB23-3716-9151A09AC8A2}');  // Zigbee2MQTT

if($_IPS['SENDER'] == "TimerEvent"){
    if (IPS_GetName($_IPS['EVENT']) == 'ScriptTimer'){
// aktuelle Zeit
        $current_time = time();
// alle Z2M Instanzen untersuchen
        foreach ($InstanzIDsList as $InstanzID) {
// Gibt es Status-Variable
            $VarID = @IPS_GetObjectIDByIdent('Z2M_State', $InstanzID);
            if ($VarID > 0) {
// Status abfragen
                $PayloadGet['state'] = '';
                $PayloadJSON = json_encode($PayloadGet, JSON_UNESCAPED_SLASHES);
                Z2M_Command($InstanzID, 'get', $PayloadJSON);
// Power-Variable anlegen wenn nötig
                $PowerID = @IPS_GetObjectIDByIdent('RB_Power', $InstanzID);
                if ($PowerID == false) {
                    $PowerID = IPS_CreateVariable(0);
                    IPS_SetName($PowerID, "Power"); // Variable benennen
                    IPS_SetParent($PowerID, $InstanzID); 
                    IPS_SetIdent($PowerID, "RB_Power"); 
                }
// Änderungszeit der Statusvariable abfragen
                $Variable = IPS_GetVariable($VarID);
// Status wurde länger als 90 Sekunden nicht aktualisiert also muss das Gerät stromlos sein
                if (($current_time - $Variable['VariableUpdated']) > 90){
// wenn Gerät stromlos dann Status und Power auf false setzen
                    if (GetValue($VarID)) SetValue($VarID, false);
                    SetValue($PowerID, false);
                }
// Gerät hat Strom also Power auf true setzen
                else {
                    SetValue($PowerID, true);
                }
            }
        }    
    }
}
// Timer starten
IPS_SetScriptTimer($_IPS['SELF'], 300);
?>

und hier das Script für Z-Wave:

<?php

// Alle Z-Wave Instanzen in ein Feld einlesen

$InstanzIDsList = IPS_GetInstanceListByModuleID('{101352E1-88C7-4F16-998B-E20D50779AF6}');  // Z-Wave

if($_IPS['SENDER'] == "TimerEvent"){

    if (IPS_GetName($_IPS['EVENT']) == 'ScriptTimer'){

// aktuelle Zeit

        $current_time = time();

// alle Z-Wave Instanzen untersuchen

        foreach ($InstanzIDsList as $InstanzID) {

// Gibt es Status-Variable

            $VarID = @IPS_GetObjectIDByIdent('StatusVariable', $InstanzID);

            if ($VarID > 0) {

// Status abfragen

                @ZW_RequestStatus($InstanzID);

// Power-Variable anlegen wenn nötig

                $PowerID = @IPS_GetObjectIDByIdent('RB_Power', $InstanzID);

                if ($PowerID == false) {

                    $PowerID = IPS_CreateVariable(0);

                    IPS_SetName($PowerID, "Power"); // Variable benennen

                    IPS_SetParent($PowerID, $InstanzID); 

                    IPS_SetIdent($PowerID, "RB_Power"); 

                }

// Änderungszeit der Statusvariable abfragen

                $Variable = IPS_GetVariable($VarID);

// Status wurde länger als 90 Sekunden nicht aktualisiert also muss das Gerät stromlos sein

                if (($current_time - $Variable['VariableUpdated']) > 90){

// wenn Gerät stromlos dann Status und Power auf false setzen

                    if (GetValue($VarID)) SetValue($VarID, false);

                    SetValue($PowerID, false);

                }

// Gerät hat Strom also Power auf true setzen

                else {

                    SetValue($PowerID, true);

                }

            }

        }    

    }

}

// Timer starten

IPS_SetScriptTimer($_IPS['SELF'], 300);

?>

Viel Spaß Ralf

Und für jene die z.b. Deconz verwenden.
Hab mir da was gebastelt, das den Configurator ausielst und alle Geräte prüft, die eine InstanzID haben. Somit werden neue Geräte automatisch aufgenommen. Es wird der Instanzenstatus geprüft. Ist dieser Wert über 200, dann liegt ein Fehler vor. Das funktioniert auch. Bei batteriebetriebenen Geräten dauert es halt länger.

//Zigbee Statusupdate
$zigbeedevices=json_decode(IPS_GetConfigurationForm (22672/*ZigBee2Deconz Configurator Instanz*/),true);
$zigbeestatusfehler=false;
$zigbeebatteriewarnung=false;
$zigbeebatteriefehler=false;

$Status_HTML="";
$Status_HTML=$Status_HTML."<table border=\"1\" style=\"width:100%\">";
$Status_HTML = $Status_HTML."<tr>";
$Status_HTML = $Status_HTML."<th><center>Gerät</center></th><th><center>Batterie</center></th>";
$Status_HTML = $Status_HTML."</tr>";
foreach ($zigbeedevices["actions"][0]["values"] as $device)
{
    if ($device["instanceID"]>0)
    {
        $Status_HTML = $Status_HTML."<tr>";
        if (IPS_GetInstance($device["instanceID"])["InstanceStatus"]<200)
        {
            $Farbe="green";
        }
        else
        {
            $Farbe="red";
            $zigbeestatusfehler=true;
        }
        $Status_HTML = $Status_HTML."<td width=\"33%\" style=\"background-color:".$Farbe."\"><center>".$device["name"]."</center></td>";
        $batterievorhanden=false;
        foreach(IPS_GetChildrenIDs($device["instanceID"]) as $variable)
        {
            if (IPS_GetName($variable)=="Batterie")
            {
                $batterie=getvalue($variable);
                switch(true) {
                    case in_array($batterie, range(0,20)):
                        $Farbe="red";
                        $zigbeebatteriefehler=true;
                        break;
                    case in_array($batterie, range(21,60)):
                        $Farbe="orange";
                        $zigbeebatteriewarnung=true;
                        break;
                    case in_array($batterie, range(61,100)):
                        $Farbe="green";
                        break;
                }
                $Status_HTML = $Status_HTML."<td width=\"33%\"style=\"background-color:".$Farbe."\"><center>".$batterie."%</center></td>";
                $batterievorhanden=true;
            }
        }
        if (!$batterievorhanden) $Status_HTML = $Status_HTML."<td width=\"33%\"><center>Dauerstrom</center></td>";
        $Status_HTML = $Status_HTML."</tr>";
    }
}
$Status_HTML=$Status_HTML."</table>";
setvalue(24262/*HTML Variable fürs Webfront*/,$Status_HTML);

Vielen Dank; das ist genau das was ich noch gesucht hatte, um die Problematik von abgeschalteten Ikea Lampen zu erkennen.

Jedoch habe ich folgendes Problem: Ich habe auch noch Aqara Multi-Sensoren. Hier werden mir ja mehrere Instanzen für einen Sensor erstellt (Temperatur, Luftfeuchtigkeit und Luftdruck). Mit diesem Script werden nun für jede dieser Instanzen (obwohl nur ein Device vorhanden ist), die Batterie resp. der Status aufgeführt. Kann man dies irgendwie verhindern?

Bitte gerne.
Dieser Umstand ist mir bewußt, aber mich stört das nicht Du hast mehre Möglichkeiten das zu Ändern. Du könntest im DeconZ Konfigurator die Zusammenfassung aktivieren, dann werden die zusammengehörigen Geräte als eines angezeigt. Du könntest auch den Instanzennamen jener Geräte die du überwachen willst eine bestimmte Zeichenfolge hinzufügen, die du im Skript filterst. Ich habe das bei Gruppen gemacht, die ich in der PhosconApp erstellt habe (Gruppe aus Lichtern und Schaltern). Die müssen nicht überwacht werden. Ich filtere hierbei nach dem Schlüsselwort „Gruppe“. Diese Gruppen kommen auch im Konfigurator an.
Ich hab es zwischenzeitlich komplett umgestellt. Die Daten werden bei mir jetzt in eine MySQL Tabelle geschrieben. Eigentlich nur deshalb, weil ich nach bestimmten Werten sortieren wollte. Also Name, Batteriestand. Ginge in einem Array auch, war mir dann aber zu kompliziert.

Danke für den Input.
Ja, mit dem Zusammenlegen der Instanzen hatte ich schon früher mal gearbeitet. Bin dann aber wieder bewusst davon weggekommen (weiss aber nicht mehr, weshalb … :wink:) . Seit dem habe ich zum Teil nun mehrere Instanzen pro Device.
Mit den Gruppen aus Phoscon/DeConz arbeite ich auch schon. Wäre sicherlich auch eine Möglichkeit.

Im Moment experimentiere ich aber noch mit dem Attribut „DeviceID“ der ZigBee-Instanzen (ich gehe davon aus, dass es sich um die ZigBee-Device-IDs handelt). Ich kann diese dann dadurch automatisch Gruppieren/Zusammenlegen. Dies mal mein aktueller Ansatz; mal schauen.

Die Device ID ist sicher ein guter Ansatz. Die haben am Ende immer „-XXXX“. Der vordere Teil ist immer gleich. Ich hab das Zusammenfassen nicht gemacht, weil ich von manchen Sensoren nicht alle Werte brauche. Und vor der Unlimited Lizenz musste/wollte ich Variablen sparen. Dieses Problem hätte ich jetzt nicht mehr, finde es für mich aber trotzdem übersichtlicher wenn ich getrennte Instanzen habe.

Hi,
ich würde hier mit einer White-List arbeiten da kann man dann gezielt einzelne Instanzen abfragen.

Ralf