Alle Hue-Lampen gleichzeitig "nativ" per Script auslesen
Verfasst: 01.02.2016, 02:05
Hallo,
da ich recht viele Hue-Lampen habe und die Lampen nicht immer nur über die CCU gesteuert werden, brauchte ich eine zuverlässige Art den Status der Lampen abzufragen.
Es hat sich gezeigt, dass die vorhandenen Wege bei vielen Lampen nicht praktikabel sind und die CCU recht stark belasten wenn man den Status Zeitnah abfragen möchte.
Da sowohl CCU als auch die Hue-Bridge recht träge sind, kann sich die Laufzeit eines Scripts schnell zu einigen Sekunden summieren und im dümmsten Fall „überholen“ sich die aufrufen.
Außerdem ist es nicht besonders elegant für jede Lampe einen Aufruf zu starten, wenn man den Status aller Lampen über eine einzelne Abfrage setzen kann.
Ergebnis ist das Folgende Script (gekürzt auf 5 Lampen). Ich verwende hierbei keines der vorhandenen Scripte, sondern rufe direkt per CURL das komplette Status-JSON der HUE-Lampen ab.
Leider bietet die CCU keinen JSON-Parser o.ä. und man muss die Datenpunkte per rudimentäre String-Operationen aus dem JSON extrahieren.
Die CCU verhält sich hierbei zeitweise recht eigenartig. Verschachteln der einzelnen Operationen mag sie beispielsweise nicht.
Bislang lese ich nur den Dimmwert der Lampen und den ON/OFF Status aus, weil ich meine Lampen in einem einzelnen CUxD-Gerät mit jeweils einem Kanal pro Lampe angelegt habe.
Sobald ich Zeit habe, werde ich die Lampen in separate CuxD-Geräte auftrennen und Farbe und Sättig mit auswerten.
Zu den einzelnen Schritten:
Mit diesem simplen Aufruf laden wir das komplette Array der Lampenstatus in die Variable „v“. Das sieht dann so aus:
Das JSON beginnt für jede Lampe mit der entsprechenden Nummer (1-n) und dem String :{"state": {. Man kann also die einzelnen Lampen anhand des state-Strings separieren. Da im Separator Anführungszeichen sind, musste ich ihn in eine Variable zwischenspeichern.
Mittels StrValueByIndex bekommt mein ein Array, in dem die Informationen pro Lampe getrennt abgespeichert sind und wieder in eine Variable gespeichert werden können.
Die einzelnen Datenpunkte sind nun mit Komma separiert und lassen sich mittels StrValueByIndex einzeln auslesen.
Bei HUE-Lampen ist der Dimmwert in der Bri-Variable auch gespeichert, wenn sie ausgeschaltet sind. In der CCU Logik wäre dieser aber 0 und muss deswegen im OFF-Fall auf 0 gesetzt werden.
OFF-Topic: Aus diesem Grund schaltet sich die Hue-Lampe auch nicht aus, wenn der Dimmwert in der CCU auf 0 gesetzt wird. Mit einer einfachen IF-Abfrage in den bekannten TCL-Scripten kann man das aber beheben.
Der neue aktuelle Dimmwert kann nun mittels SET_STATE gesetzt werden. Ich verwende SET_STATE, weil es nicht gewollt ist das die CCU eine Aktion ausführt (insbesondere wichtig, wenn man nicht die oben erwähnte Änderung des TCL vornimmt). Jedoch wird der neue Wert in der CCU so nicht sichtbar. Mittels anschließendem „leerem“ LEVEL-Befehl, aktualisiert die CCU jedoch den Wert.
Natürlich kann man auch die anderen Werte auslesen. Hier z.B. den Hue (Farb-)Wert:
da ich recht viele Hue-Lampen habe und die Lampen nicht immer nur über die CCU gesteuert werden, brauchte ich eine zuverlässige Art den Status der Lampen abzufragen.
Es hat sich gezeigt, dass die vorhandenen Wege bei vielen Lampen nicht praktikabel sind und die CCU recht stark belasten wenn man den Status Zeitnah abfragen möchte.
Da sowohl CCU als auch die Hue-Bridge recht träge sind, kann sich die Laufzeit eines Scripts schnell zu einigen Sekunden summieren und im dümmsten Fall „überholen“ sich die aufrufen.
Außerdem ist es nicht besonders elegant für jede Lampe einen Aufruf zu starten, wenn man den Status aller Lampen über eine einzelne Abfrage setzen kann.
Ergebnis ist das Folgende Script (gekürzt auf 5 Lampen). Ich verwende hierbei keines der vorhandenen Scripte, sondern rufe direkt per CURL das komplette Status-JSON der HUE-Lampen ab.
Leider bietet die CCU keinen JSON-Parser o.ä. und man muss die Datenpunkte per rudimentäre String-Operationen aus dem JSON extrahieren.
Die CCU verhält sich hierbei zeitweise recht eigenartig. Verschachteln der einzelnen Operationen mag sie beispielsweise nicht.
Bislang lese ich nur den Dimmwert der Lampen und den ON/OFF Status aus, weil ich meine Lampen in einem einzelnen CUxD-Gerät mit jeweils einem Kanal pro Lampe angelegt habe.
Sobald ich Zeit habe, werde ich die Lampen in separate CuxD-Geräte auftrennen und Farbe und Sättig mit auswerten.
Code: Alles auswählen
!XXXXXXXXXXXXXXXXXXXX!
! HUE Status abrufen !
!XXXXXXXXXXXXXXXXXXXX!
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("LD_LIBRARY_PATH=/usr/local/addons/cuxd /usr/local/addons/cuxd/curl -f http://172.31.22.151/api/newdeveloper/lights");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
var v = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
string seperator = ':{\"state\": {';
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Separieren der einzelnen JSON pro Light !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
string Light01 = v.StrValueByIndex(seperator, 01);
string Light02 = v.StrValueByIndex(seperator, 02);
string Light03 = v.StrValueByIndex(seperator, 03);
string Light04 = v.StrValueByIndex(seperator, 04);
string Light05 = v.StrValueByIndex(seperator, 05);
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Dimmlevel der Lampen Bestimmen !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
string BriHelp01 = Light01.StrValueByIndex(",",1); integer Bri01 = BriHelp01.Substr(6, 3); Bri01 = 0 - Bri01.ToInteger();
string BriHelp02 = Light02.StrValueByIndex(",",1); integer Bri02 = BriHelp02.Substr(6, 3); Bri02 = 0 - Bri02.ToInteger();
string BriHelp03 = Light03.StrValueByIndex(",",1); integer Bri03 = BriHelp03.Substr(6, 3); Bri03 = 0 - Bri03.ToInteger();
string BriHelp04 = Light04.StrValueByIndex(",",1); integer Bri04 = BriHelp04.Substr(6, 3); Bri04 = 0 - Bri04.ToInteger();
string BriHelp05 = Light05.StrValueByIndex(",",1); integer Bri05 = BriHelp05.Substr(6, 3); Bri05 = 0 - Bri05.ToInteger();
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Status der Lampe (bei false wird der Bri-Wert auf 0 gesetzt) !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
string StateHelp01 = Light01.StrValueByIndex(",", 0); if (StateHelp01.Substr(16, 5) == false) {Bri01 = -0;}
string StateHelp02 = Light02.StrValueByIndex(",", 0); if (StateHelp02.Substr(16, 5) == false) {Bri02 = -0;}
string StateHelp03 = Light03.StrValueByIndex(",", 0); if (StateHelp03.Substr(16, 5) == false) {Bri03 = -0;}
string StateHelp04 = Light04.StrValueByIndex(",", 0); if (StateHelp04.Substr(16, 5) == false) {Bri04 = -0;}
string StateHelp05 = Light05.StrValueByIndex(",", 0); if (StateHelp05.Substr(16, 5) == false) {Bri05 = -0;}
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Übernehmen der Werte ins HM Frontend !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
dom.GetObject("CUxD.CUX2801002:1.SET_STATE").State(Bri01); dom.GetObject("CUxD.CUX2801002:1.LEVEL").State();
dom.GetObject("CUxD.CUX2801002:2.SET_STATE").State(Bri02); dom.GetObject("CUxD.CUX2801002:2.LEVEL").State();
dom.GetObject("CUxD.CUX2801002:3.SET_STATE").State(Bri03); dom.GetObject("CUxD.CUX2801002:3.LEVEL").State();
dom.GetObject("CUxD.CUX2801002:4.SET_STATE").State(Bri04); dom.GetObject("CUxD.CUX2801002:4.LEVEL").State();
dom.GetObject("CUxD.CUX2801002:5.SET_STATE").State(Bri05); dom.GetObject("CUxD.CUX2801002:5.LEVEL").State();
Zu den einzelnen Schritten:
Code: Alles auswählen
!XXXXXXXXXXXXXXXXXXXX!
! HUE Status abrufen !
!XXXXXXXXXXXXXXXXXXXX!
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("LD_LIBRARY_PATH=/usr/local/addons/cuxd /usr/local/addons/cuxd/curl -f http://172.31.22.151/api/newdeveloper/lights");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
var v = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
string seperator = ':{\"state\": {';
{"1":{"state": {"on":false,"bri":254,"hue":25653,"sat":254,"effect":"none","xy":[0.4084,0.5168],"ct":290,"alert":"none","colormode":"xy","reachable":true}, "type": "Extended color light", "name": "Schlafzimmer", "modelid": "LCT001", "manufacturername": "Philips","uniqueid":"XX:XX:XX:XX:XX:XX:XX:XX-XX", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }},"2":{"state": {"on":true,"bri":40,"hue":5769,"sat":230,"effect":"none","xy":[0.6233,0.3565],"alert":"none","colormode":"hs","reachable":true}, "type": "Color light", "name": "Treppe OG", "modelid": "LST001", "manufacturername": "Philips","uniqueid":"XX:XX:XX:XX:XX:XX:XX:XX-XX", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }},"3":{"state": {"on":true,"bri":254,"alert":"none","reachable":true}, "type": "Dimmable light", "name": "White Diele V", "modelid": "LWB003", "manufacturername": "Philips","uniqueid":"XX:XX:XX:XX:XX:XX:XX:XX-XX", "swversion": "3.0.0.7119", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }}
Das JSON beginnt für jede Lampe mit der entsprechenden Nummer (1-n) und dem String :{"state": {. Man kann also die einzelnen Lampen anhand des state-Strings separieren. Da im Separator Anführungszeichen sind, musste ich ihn in eine Variable zwischenspeichern.
Code: Alles auswählen
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Separieren der einzelnen XML pro Light !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
string Light01 = v.StrValueByIndex(seperator, 01);
{"state": {"on":false,"bri":254,"hue":25653,"sat":254,"effect":"none","xy":[0.4084,0.5168],"ct":290,"alert":"none","colormode":"xy","reachable":true}, "type": "Extended color light", "name": "Schlafzimmer", "modelid": "LCT001", "manufacturername": "Philips","uniqueid":"00:17:88:01:00:b3:3c:3c-0b", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }},"2"
Code: Alles auswählen
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Dimmlevel der Lampen Bestimmen !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
string BriHelp01 = Light01.StrValueByIndex(",",1); integer Bri01 = BriHelp01.Substr(6, 3); Bri01 = 0 - Bri01.ToInteger();
Substr liefert dann den reinen Zahlenwert (aber als String) durch abschneiden der ersten 6 Zeichen ("bri":). Der SET_STATE Befehl von CUxD erwartet einen negativen Integer Wert und errechnet daraus eigenständig den Prozentualen Wert innerhalb des Wertebereichs. Aus diesem Grund ziehen wir den Wert von 0 ab (nicht schön, aber der einige Weg den ich mittel trial and error gefunden habe)."bri":254
Code: Alles auswählen
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Status der Lampe (bei false wird der Bri-Wert auf 0 gesetzt) !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
string StateHelp01 = Light01.StrValueByIndex(",", 0); if (StateHelp01.Substr(16, 5) == false) {Bri01 = -0;}
OFF-Topic: Aus diesem Grund schaltet sich die Hue-Lampe auch nicht aus, wenn der Dimmwert in der CCU auf 0 gesetzt wird. Mit einer einfachen IF-Abfrage in den bekannten TCL-Scripten kann man das aber beheben.
Code: Alles auswählen
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
! Übernehmen der Werte ins HM Frontend !
!XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!
dom.GetObject("CUxD.CUX2801002:1.SET_STATE").State(Bri01); dom.GetObject("CUxD.CUX2801002:1.LEVEL").State();
Natürlich kann man auch die anderen Werte auslesen. Hier z.B. den Hue (Farb-)Wert:
Code: Alles auswählen
string HueHelp08 = Light08.StrValueByIndex(",",2); integer Hue08 = HueHelp08.Substr(6, 6); Hue08 = Hue08.ToInteger();