Mein Blog

Node Red Ikea tradfri 2 Tasten Taster

Node Red Ikea tradfri 2 Tasten Taster

Ikea bietet für 6€ einen günstigen ZigBee-fähigen Dimmer an (https://www.ikea.com/de/de/p/tradfri-kabelloser-dimmer-weiss-70408595/). Diesen habe ich über einen ConBee II (Dresden Elektronik) angebunden. Ich möchte ihn über Node Red steuern können. Dafür nutze ich den Adapter node-red-contrib-deconz 1.1.10 und ioBroker mit dem Tradfri Adapter.

Der Taster liefert 6 verschiedene Statuscodes:

(c) IKEA 2020

Mit den Werten 1002 und 2002 kann man nun einfach über einen switch ein on/off Beispiel bauen.

hier ein Beispiel für den Heizstrahler der nach dem Anschalten maximal. 15min an sein darf. Das kann durch erneutes drücken wiederholt bzw. auf 15min zurück gesetzt werden. “Display Payload” ist ein Subflow der den msg.payload auf Status mit schickt und somit unter dem Element anzeigt. Nachfolgend der Code dafür

[{"id":"9fd20961.36f768","type":"subflow","name":"Display Payload","info":"","category":"","in":[{"x":50,"y":30,"wires":[]}],"out":[{"x":140,"y":100,"wires":[{"id":"9fd20961.36f768","port":0}]}],"env":[],"color":"#DDAA99","status":{"x":160,"y":30,"wires":[{"id":"9fd20961.36f768","port":0}]}}]

Inhaltsverzeichnis

Toggle

Dimm Funktion

Wir wollen nun aber auch das lange drücken mit Auswerten. Dazu nutze ich zusätzlich noch node-red-contrib-simple-gate um ein Element zu haben, was ähnlich einem Tor steuerbar ist und den Inhalt einfach durchleitet.

Beispiel Gate

Die Idee zum dimmen ist nun folgende: Mit dem langen Drücken von I oder O (1001 bzw. 2001) wird das Gate geöffnet und mit 1003 bzw. 2003 (Loslassen von I bzw. O) wird das Gate geschlossen.
Zyklich wird nun ein Inject (einmal pro Sekunde) auf das Gate geschickt. Kommt es durch wird der Helligkeitswert geändert.

Jetzt muss man vorab noch die “Richtung”, also hoch zählen oder runter zählen definieren. Dazu werten wir auch den Start des langen Drückens mit aus und setzen intern den Wert für die Zählrichtung.

Kommt nun ein Wert durch das Gate wird der aktuelle Wert plus gerechnet mit dem Produkt aus dem Wert wie stark es sich ändern soll und der Richtung (1 für hoch und -1 für runter) also wenn der Wert 50 ist und die Stufenbreite 10 wäre das beim Runter zählen: 50 + (10 * -1) = 40.
Geht der Wert über die Grenze von 1-100 hinaus wird er zurück gesetzt auf den Grenzwert.

var brightness = parseInt(flow.get('Brightness')) || 1;
var step = parseInt(env.get('StepBrightness')) || 10;
var direction = parseInt(msg.payload) || 1;

var newBrightness = brightness + (step *  direction);
if (newBrightness > 100) newBrightness = 100;
if (newBrightness < 1) newBrightness = 1;

flow.set('Brightness', newBrightness); // save new value

msg.payload = newBrightness;
return msg;

Anschließend wird der neue Helligkeitswert aus gegeben.

Doppelklick

Auch einen Doppelklick kann man realisieren. In der Ereignisgetriebenen Entwicklung kennen wir aber nicht die Dimension Zeit. Das heißt wir wissen nicht was man vorher geklickt hat, wie lange das her ist oder wie oft. Daher werden wir vorher ein Subflow bauen, welcher speichert wie oft ein Ereignis in einer bestimmten Zeit kam. Das geht ganz einfach, indem wir den Zeitstempel (Eintreffen eines Events) in ein Array legen und im Flow speichern. Danach werden alle Einträge entfernen, welche älter sind als unser Messzeitraum. Und am Ende zählen wir die Elemente und geben die Zahl aus.

Das sieht erstmal recht unspektakulär aus:

var now = Math.floor(Date.now() / 1000 ) || 0; 

function RemoveOld(ts){
    var diff = env.get('TimeRangeInSeconds') || 5;
    var now = Math.floor(Date.now() / 1000 ) || 0;
    var now2 = now - diff; 
    
  return Math.floor(ts) > now2;
}

var data = flow.get('data') || "[]";

data = JSON.parse(data);
data.push(now);
data=data.filter(RemoveOld);

msg.payload = data.length;
flow.set('data', JSON.stringify(data));

return msg;

Über Umgebungsvariablen wird hier die Zeit übergeben. Wird der Wert nicht gesetzt wird 5 als Standard angenommen.

Mit diesem Subflow können wir nun den Wert 1002 zählen lassen. Ist dieser größer/gleich 2 können wir ein Doppelklick-Ereignis ausführen. Ich will hier eine definierte Helligkeit setzen.

Der ganze Subflow gibt natürlich auch noch einen Status aus, weswegen die Linien etwas kreuz und quer gehen. Aber hier jetzt endlich der Überblick:

Im oberen Teil ist die simple on/off-Logik, in der Mitte das Dimmen und dadrunter der Doppelklick. Die Initialisierung der Helligkeit findet ganz unten statt wo der Wert einmalig in die Flow-Variable geschrieben wird.

Hier der Code für den gesamten Subflow:

[{"id":"549c3f58.ff0c9","type":"subflow","name":"Event per Time","info":"","category":"","in":[{"x":80,"y":180,"wires":[{"id":"8cd4f008.190f"}]}],"out":[{"x":520,"y":180,"wires":[{"id":"8cd4f008.190f","port":0}]}],"env":[{"name":"TimeRangeInSeconds","type":"num","value":"5"}],"color":"#DDAA99","status":{"x":520,"y":120,"wires":[{"id":"8cd4f008.190f","port":0}]}},{"id":"8cd4f008.190f","type":"function","z":"549c3f58.ff0c9","name":"count","func":"var now = Math.floor(Date.now() / 1000 ) || 0; \n\nfunction RemoveOld(ts){\n    var diff = env.get('TimeRangeInSeconds') || 5;\n    var now = Math.floor(Date.now() / 1000 ) || 0;\n    var now2 = now - diff; \n    \n  return Math.floor(ts) > now2;\n}\n\nvar data = flow.get('data') || \"[]\";\n\ndata = JSON.parse(data);\ndata.push(now);\ndata=data.filter(RemoveOld);\n\nmsg.payload = data.length;\nflow.set('data', JSON.stringify(data));\n\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":180,"wires":[[]]},{"id":"4bf947ab.211498","type":"subflow","name":"Ikea Dimmer","info":"","category":"","in":[{"x":40,"y":300,"wires":[{"id":"7b4c9956.acfc58"}]}],"out":[{"x":1120,"y":340,"wires":[{"id":"32889690.fc46ea","port":0},{"id":"584679a5.c1bed8","port":0},{"id":"62117ea.1e7368","port":0}]},{"x":1320,"y":140,"wires":[{"id":"4a660c11.3eef94","port":0},{"id":"fac64923.bc6848","port":0}]}],"env":[{"name":"StartBrightness","type":"num","value":"50"},{"name":"StepBrightness","type":"num","value":"10"},{"name":"DoubleClickBrithness","type":"str","value":"1"}],"color":"#C0DEED","inputLabels":["Button Event"],"outputLabels":["Brightness","State"],"icon":"node-red-contrib-polymer/ui_radio.png","status":{"x":1420,"y":360,"wires":[{"id":"a5af8864.f47fe8","port":0},{"id":"4a660c11.3eef94","port":0},{"id":"fac64923.bc6848","port":0},{"id":"62117ea.1e7368","port":0}]}},{"id":"be8924a5.85ce88","type":"switch","z":"4bf947ab.211498","name":"Switch an / aus","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1002","vt":"num"},{"t":"eq","v":"2002","vt":"str"}],"checkall":"true","repair":true,"outputs":2,"x":460,"y":140,"wires":[["32889690.fc46ea","4a660c11.3eef94"],["fac64923.bc6848"]]},{"id":"32889690.fc46ea","type":"change","z":"4bf947ab.211498","name":"Brightness","rules":[{"t":"set","p":"payload","pt":"msg","to":"Brightness","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":80,"wires":[[]]},{"id":"4a660c11.3eef94","type":"change","z":"4bf947ab.211498","name":"true","rules":[{"t":"set","p":"payload","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1090,"y":140,"wires":[[]]},{"id":"fac64923.bc6848","type":"change","z":"4bf947ab.211498","name":"false","rules":[{"t":"set","p":"payload","pt":"msg","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":750,"y":260,"wires":[[]]},{"id":"51a608f0.19e558","type":"gate","z":"4bf947ab.211498","name":"","controlTopic":"control","defaultState":"closed","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","defaultCmd":"default","persist":false,"x":670,"y":420,"wires":[["584679a5.c1bed8"]]},{"id":"152bae03.a8beb2","type":"change","z":"4bf947ab.211498","name":"Open","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"open","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":420,"wires":[["51a608f0.19e558"]]},{"id":"f05a97bf.f288b8","type":"change","z":"4bf947ab.211498","name":"close","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"close","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":360,"wires":[["51a608f0.19e558"]]},{"id":"7b4c9956.acfc58","type":"switch","z":"4bf947ab.211498","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1001","vt":"num"},{"t":"eq","v":"1002","vt":"str"},{"t":"eq","v":"1003","vt":"str"},{"t":"eq","v":"2001","vt":"str"},{"t":"eq","v":"2002","vt":"str"},{"t":"eq","v":"2003","vt":"str"}],"checkall":"false","repair":true,"outputs":6,"x":150,"y":300,"wires":[["152bae03.a8beb2","8669e2f1.85e18"],["be8924a5.85ce88","f86a943.76f5a68"],["f05a97bf.f288b8"],["152bae03.a8beb2","c9fa3fd7.398fa"],["be8924a5.85ce88"],["f05a97bf.f288b8"]]},{"id":"b610e1da.630f1","type":"inject","z":"4bf947ab.211498","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":110,"y":740,"wires":[["435751f4.1dc28"]]},{"id":"435751f4.1dc28","type":"function","z":"4bf947ab.211498","name":"set brightness","func":"flow.set('Brightness', env.get('StartBrightness'));\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":740,"wires":[[]]},{"id":"8669e2f1.85e18","type":"change","z":"4bf947ab.211498","name":"1","rules":[{"t":"set","p":"richtung","pt":"flow","to":"1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":500,"wires":[[]]},{"id":"c9fa3fd7.398fa","type":"change","z":"4bf947ab.211498","name":"-1","rules":[{"t":"set","p":"richtung","pt":"flow","to":"-1","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":540,"wires":[[]]},{"id":"f02ae375.ce76d","type":"inject","z":"4bf947ab.211498","name":"","topic":"","payload":"richtung","payloadType":"flow","repeat":"1","crontab":"","once":false,"onceDelay":0.1,"x":500,"y":480,"wires":[["51a608f0.19e558"]]},{"id":"584679a5.c1bed8","type":"function","z":"4bf947ab.211498","name":"calc Brightness","func":"var brightness = parseInt(flow.get('Brightness')) || 1;\nvar step = parseInt(env.get('StepBrightness')) || 10;\nvar direction = parseInt(msg.payload) || 1;\n\nvar newBrightness = brightness + (step *  direction);\nif (newBrightness > 100) newBrightness=100;\nif (newBrightness < 1) newBrightness = 1;\n\nflow.set('Brightness', newBrightness);\n\nmsg.payload = newBrightness;\nreturn msg;","outputs":1,"noerr":0,"x":860,"y":420,"wires":[["a5af8864.f47fe8","4a660c11.3eef94"]]},{"id":"a5af8864.f47fe8","type":"function","z":"4bf947ab.211498","name":"Status Text","func":"msg.payload = \"Brightness \" + msg.payload;\nreturn msg;","outputs":1,"noerr":0,"x":1150,"y":420,"wires":[[]]},{"id":"f86a943.76f5a68","type":"subflow:549c3f58.ff0c9","z":"4bf947ab.211498","name":"","env":[{"name":"TimeRangeInSeconds","value":"2","type":"num"}],"x":540,"y":580,"wires":[["72e4c98e.d8c378"]]},{"id":"72e4c98e.d8c378","type":"switch","z":"4bf947ab.211498","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"1","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":750,"y":580,"wires":[["4a660c11.3eef94","62117ea.1e7368"]]},{"id":"62117ea.1e7368","type":"change","z":"4bf947ab.211498","name":"Brightness","rules":[{"t":"set","p":"payload","pt":"msg","to":"DoubleClickBrithness","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":580,"wires":[[]]},{"id":"cec0708c.4d36b","type":"comment","z":"4bf947ab.211498","name":"Double Click","info":"","x":550,"y":540,"wires":[]},{"id":"24357078.86ba6","type":"comment","z":"4bf947ab.211498","name":"dimming function","info":"","x":700,"y":380,"wires":[]},{"id":"710c80ee.7da92","type":"comment","z":"4bf947ab.211498","name":"direct Switch","info":"","x":470,"y":100,"wires":[]},{"id":"7b10ac7.5b7b554","type":"comment","z":"4bf947ab.211498","name":"Init Brightness","info":"","x":110,"y":700,"wires":[]}]

Wie ihr seht, hat der Subflow 2 Ausgänge. Der 1. Ausgang steuert die Helligkeit und der 2. den Status an/aus. Diese müssen dann noch verbunden werden. Als Eingang dienst der Ikea-Taster mit seinen 6 Statuscodes.

Die mobile Version verlassen