Live Events - Ikea Home smart - Dirigera
This flow REQUIRES NodeRED v4+
This uses the fantastic node-red-contrib-dirigera node to get the access-token from the hub. After configuring the websocket-in node with the ip address of the Dirigera hub and adding the access-token as a header the first debug node will return live events from the Dirigera hub.
Unfortunately this doesn't include the name of the device (only an id number) by configuring the function node with the ip address and access-token the hub is then polled and the device name added to the returned data.
If you get an error, double check that you have copied the entire access-token by click-and-drag copying rather than double/triple clicking.
Totally unofficial, not affiliated with IKEA in any way.
[{"id":"99b4841f21ae92b0","type":"tab","label":"Dirigera Live Events","disabled":false,"info":"","env":[]},{"id":"830c76db864c1dbc","type":"group","z":"99b4841f21ae92b0","name":"","style":{"label":true,"color":"#ff0000","stroke":"#ff0000","fill":"#ffffbf"},"nodes":["9022eecc6d4acec2","5a24358440b4cd72","720977a081ba9a82","184b4ea0be0dcb78","7a511ee27b2b3659","23818ce26381a509","8c985f5ef781d5df"],"x":48,"y":181,"w":1438,"h":546},{"id":"8c985f5ef781d5df","type":"group","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["78e3c90b939d8faa","d5522dd28aa0a0c7","ae2cb1d67a0e17d2","53b224f7232f86b0"],"x":74,"y":207,"w":492,"h":494},{"id":"78e3c90b939d8faa","type":"websocket in","z":"99b4841f21ae92b0","g":"8c985f5ef781d5df","name":"wss://{IP ADDRESS}:8443/v1","server":"","client":"f8e4dba3c2372ebe","x":240,"y":440,"wires":[["9022eecc6d4acec2","d5522dd28aa0a0c7"]]},{"id":"23818ce26381a509","type":"debug","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","name":"Info with customName added","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1310,"y":680,"wires":[]},{"id":"7a511ee27b2b3659","type":"function","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","name":"Find customName for device id","func":"//connectedDevices = flow.get(\"connectedDevices\").raw\n\nif (\n msg.type === \"sceneUpdated\"\n)\n{ // if scene updated lists all the ways to update the scene so need to compare time of message to last triggered to find out \n // which method was the trigger\n //Then there is a second websocket message where the time does not equal a trigger time currently ignoring this message \n // this also captures scene edits in the app\n\n //node.warn(\"sceneUpdated\")\n if (msg.data.triggers.some(x => x.triggeredAt === msg.time)) {\n // do something\n // If trigger was app there is no physical device to look up\n msg.data.device = msg.data.triggers.find(x => x.triggeredAt === msg.time).type\n //node.warn(msg.data.device)\n if ( \n\n msg.data.device === \"app\"\n ) {\n\n }\n else {\n \n \n \n msg.data.id = msg.data.triggers.find(x => x.triggeredAt === msg.time).trigger.deviceId;\n msg.data.clickPattern = msg.data.triggers.find(x => x.triggeredAt === msg.time).trigger.clickPattern\n //node.warn(msg.data.id)\n msg.data.customName = msg.devices.raw.find(x => x.id === msg.data.id).attributes.customName;\n }\n return msg;\n }\n else {\n //node.warn(\"Times dont match ignoring \")\n }\n \n\n\n \n}\nelse if (msg.type === \"sceneCreated\" || msg.type === \"sceneDeleted\" ) {\n// nothing to do if secene Created or Deleted so ignore\n}\nelse{\n node.warn(msg.type)\n msg.data.customName = msg.devices.raw.find(x => x.id === msg.data.id).attributes.customName;\n return msg;\n}\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1030,"y":680,"wires":[["23818ce26381a509"]]},{"id":"9022eecc6d4acec2","type":"debug","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","name":"Basic Info - device ID no Name","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1310,"y":440,"wires":[]},{"id":"720977a081ba9a82","type":"http request","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1170,"y":600,"wires":[["184b4ea0be0dcb78"]]},{"id":"184b4ea0be0dcb78","type":"function","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","name":"Sort Device List into Categories","func":"// @ts-nocheck\ndelete msg.dirigeraIP\ndelete msg.dirigeraAccessCode\ndelete msg.url\ndelete msg.rejectUnauthorized\n\nif (msg.statusCode != 200){\nnode.warn (msg.payload.error+\" \"+msg.payload.message)\n node.warn(\"Double check AccessCode is entire length of code\")\n}\nelse {\nconst connectedDevices ={}\nconst raw = msg.payload\n \n for ( var index = 0; index < msg.payload.length; index++)\n {\n var deviceAttributes = {}\n \n var deviceType=msg.payload[index].type\n \n \n if (!connectedDevices.hasOwnProperty(deviceType)) {\n connectedDevices[deviceType]=[]\n }\n \n deviceAttributes.id = msg.payload[index].id\n deviceAttributes.customName = msg.payload[index].attributes.customName\n \n \n connectedDevices[deviceType].push(deviceAttributes);\n }\n\n\n\nmsg.devices = connectedDevices\nmsg.devices.raw = raw\n\ndelete msg.payload\nreturn msg\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":750,"y":680,"wires":[["7a511ee27b2b3659"]]},{"id":"5a24358440b4cd72","type":"function","z":"99b4841f21ae92b0","g":"830c76db864c1dbc","name":"Configures URL to get device list","func":"\ndelete msg._session // deleted as not needed\n\nmsg.url = \"https://\" + msg.dirigeraIP + \":8443/v1/devices\"\n\nmsg.rejectUnauthorized = false // need to stop cert error\n\nmsg.headers = { \"Authorization\": \"Bearer \" + msg.dirigeraAccessCode }\n\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":600,"wires":[["720977a081ba9a82"]]},{"id":"194701ec63851a90","type":"comment","z":"99b4841f21ae92b0","name":"Requires\\n Node-RED v4+ \\n node-red-contrib-dirigera to be configured to get AccessCode ","info":"Requires node-red-contrib-dirigera","x":300,"y":60,"wires":[]},{"id":"d5522dd28aa0a0c7","type":"function","z":"99b4841f21ae92b0","g":"8c985f5ef781d5df","name":"Copy IP and Access code into this function node","func":"\n//ADD IP ADDRESS below\nmsg.dirigeraIP = \"192.168.0.1\"\n\n\n//ADD JUST THE ACCESS CODE below\nmsg.dirigeraAccessCode = \"abd9eG92md;z...\"\n\n//if you get en error make sure you have copied the whole of the access code\n\nif (msg.dirigeraAccessCode ===\"ADD CODE HERE\") {}\nelse {\nreturn msg;}","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":660,"wires":[["5a24358440b4cd72"]]},{"id":"ae2cb1d67a0e17d2","type":"comment","z":"99b4841f21ae92b0","g":"8c985f5ef781d5df","name":"The address for the websocket is\\n wss://{ADD IP ADDRESS OF DIRIGERA HUB HERE}:8443/v1 \\n (ie wss://192.168.1.5:8443/v1)\\n \\n Add a header \\n Authorization = Bearer {dirigeraAccessCode } \\n (ie Authorization = Bearer abd9eG92md;z... ) ","info":"The address for the websocket is\\n\nwss://{ADD IP ADDRESS OF DIRIGERA HUB HERE}:8443/v1 \\n\n(ie wss://192.168.1.5:8443/v1)\\n\n\\n\nAdd a header \\n\nAuthorization = Bearer {dirigeraAccessCode } \\n\n\n\nIf you want details of name of device \\n\n(rather than just the long id number) \\n\n\nAlso add the ip address and dirigeraAccessCode\\n\nto the function node:\\n\n \"Copy IP and Access code into this function node\"\\n\n","x":320,"y":320,"wires":[]},{"id":"53b224f7232f86b0","type":"comment","z":"99b4841f21ae92b0","g":"8c985f5ef781d5df","name":" If you want details of name of device \\n (rather than just the long id number) \\n Also add the ip address and dirigeraAccessCode\\n to the function node:\\n \"Copy IP and Access code into this function node\"","info":" If you want details of name of device \\n (rather than just the long id number) \\n Also add the ip address and dirigeraAccessCode\\n to the function node:\\n \"Copy IP and Access code into this function node\"","x":310,"y":560,"wires":[]},{"id":"478ea1e549b39fb3","type":"dirigera","z":"99b4841f21ae92b0","name":"Configure Node to get Access Code","server":"e1f06c4b53af25e1","choiceType":"specificDevice","choiceTitle":"airPurifier - Hallway - Air purifier 1","choiceId":"934e20b4-cc72-4682-821f-2dc906709e6c_1","choiceIcon":"","outputs":1,"x":230,"y":140,"wires":[[]]},{"id":"f8e4dba3c2372ebe","type":"websocket-client","path":"wss://192.168.0.1:8443/v1","tls":"","wholemsg":"true","hb":"60","subprotocol":"","headers":[{"keyType":"other","keyValue":"authorization","valueType":"other","valueValue":"Bearer abd9eG92md;z..."}]},{"id":"e1f06c4b53af25e1","type":"dirigera-config","name":""}]