Subflow used to retrieve JSON key value

I am just starting to learn JavaScript & I would really appreciate some guidance. I am trying to create a subflow that will return the value of (2) keys nested within JSON output. (name and last use date)

The "tricky part" is that I only want to return the name & timestamp from the most recent value. (The value that is closest to the "current time".)

For example, based on the JSON output (see below) I would like to return:
"last use date": "2020-12-18T13:53:33", "name": "amazon_dash_button"

{
    "whitelist": {
            "55dd6daa-d54e-4a8d-dd5d-9a9c12ad5283": {
            "last use date": "2020-12-18T13:21:42",
            "create date": "2019-07-26T14:55:07",
            "name": "Hue 3#iPhoneA"
        },
        "d547d0a5-64dc-45d1-a809-66355a6d942a": {
            "last use date": "2020-12-18T04:33:20",
            "create date": "2019-07-26T21:59:18",
            "name": "hue-alexa-smarthome-skill-v1"
        },
        "5e558a27-d071-46c3-851d-c610e9404a8c": {
            "last use date": "2020-07-15T23:55:51",
            "create date": "2019-07-27T00:13:19",
            "name": "Hue 3#iPhoneB"
        },
        "7d08da1d-6cde-4cd5-d14d-21dd6a77d993": {
            "last use date": "2020-10-16T21:48:15",
            "create date": "2019-07-31T21:01:51",
            "name": "Hue 3#iPhoneC"
        },
        "6Xw2Jjha7Y7HNpvqI2OnAodSsxG5LVUod-yVxzvJ": {
            "last use date": "2020-12-18T13:53:33",
            "create date": "2020-01-29T23:02:57",
            "name": "amazon_dash_button"
        },
        "37e85d98-1832-49cd-a508-5747a7716d52": {
            "last use date": "2020-12-18T05:30:11",
            "create date": "2020-06-18T18:25:20",
            "name": "iftttv2"
        }
    }
}

Thanks.

Guidance...
Forget subflow for now & make this work with an inject (to provide the data) --> function node ( to do the js) --> debug node to check the output.

Clues...
Convert the properties in whitelist to an array, then sort, then grab the 1st element.

Read up on Object.keys() & iterating object properties.

Then read up on Array.sort()

Ps, make use of the mdn site. Not only does it explain the things I've mention, it has interactive examples you can tweak and play with right in the browser.


If you sus that out, you will learn a lot.

If you get stuck, ask.

@Steve-Mcl
MDN is a wonderful resource. I am also a huge fan of W3Schools.

However, I am struggling with the fact that each of the top-level properties within the whitelist object are unique hashes.

name and last use date are the two values that I care about. All of the examples that I've found store nested key:value pairs using a for loop. However, I cannot use the same strategy, because the hashes (aka: the parent object) use inconsistent/unique names.

As such, I fail to see how I can store the last use date values into a single array.
Thoughts?

You could use a Jsonata expression in a Change node to create the array
and sort it by "last use date"

Then just pick the first element [0] which should be the max date

Example :

[{"id":"654412d9.ca3e0c","type":"change","z":"284375ad.fa5e3a","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$sort(**[`last use date`], function($l, $r) {\t    $l.`last use date` < $r.`last use date`\t})[0]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":220,"wires":[["6cbadb17.25fd7c"]]},{"id":"6cbadb17.25fd7c","type":"debug","z":"284375ad.fa5e3a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":840,"y":220,"wires":[]},{"id":"5335b63a.5d1fc8","type":"inject","z":"284375ad.fa5e3a","name":"data","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"whitelist\":{\"55dd6daa-d54e-4a8d-dd5d-9a9c12ad5283\":{\"last use date\":\"2020-12-18T13:21:42\",\"create date\":\"2019-07-26T14:55:07\",\"name\":\"Hue 3#iPhoneA\"},\"d547d0a5-64dc-45d1-a809-66355a6d942a\":{\"last use date\":\"2020-12-18T04:33:20\",\"create date\":\"2019-07-26T21:59:18\",\"name\":\"hue-alexa-smarthome-skill-v1\"},\"5e558a27-d071-46c3-851d-c610e9404a8c\":{\"last use date\":\"2020-07-15T23:55:51\",\"create date\":\"2019-07-27T00:13:19\",\"name\":\"Hue 3#iPhoneB\"},\"7d08da1d-6cde-4cd5-d14d-21dd6a77d993\":{\"last use date\":\"2020-10-16T21:48:15\",\"create date\":\"2019-07-31T21:01:51\",\"name\":\"Hue 3#iPhoneC\"},\"6Xw2Jjha7Y7HNpvqI2OnAodSsxG5LVUod-yVxzvJ\":{\"last use date\":\"2020-12-18T13:53:33\",\"create date\":\"2020-01-29T23:02:57\",\"name\":\"amazon_dash_button\"},\"37e85d98-1832-49cd-a508-5747a7716d52\":{\"last use date\":\"2020-12-18T05:30:11\",\"create date\":\"2020-06-18T18:25:20\",\"name\":\"iftttv2\"}}}","payloadType":"json","x":390,"y":220,"wires":[["654412d9.ca3e0c"]]},{"id":"afd8cc8c.d930a","type":"comment","z":"284375ad.fa5e3a","name":"Jsonata expression","info":"","x":590,"y":160,"wires":[]}]
1 Like

@UnborN
Nice! That works :100:%!

I'll def. spend some time reading up on JSONata.

Thoughts,? plenty yes....

I had hoped no one would give you a solution (you don't really learn much when it's put on a plate). I got the impression you wanted to learn JS.

PS, JSONata is handy, but it's not really gonna make you a programmer.

That is why I said read up on iterating object properties." It would have lead you to something like this. I also mentioned Object.keys (which would have lead you to Object.entries(), for-in etc etc).

example...
image


I also said

That should have given you a clue to use the iterating loop to generate an array...


Then I said ...


That would have given you a rather verbose solution - but you would have learned a lot. I would then have shown you a much more concise version using Object.entries and arrow functions...

or a one liner...

4 Likes

I really like @UnborN's K.I.S.S. approach. This solution draws attention to a useful property (JSONata) that exists within the change node.

The (included) example saves me a lot of time & effort. It also provides others with the ability to reproduce (and then evaluate) the Node-RED flow.

@Steve-Mcl Thank you for this detailed explanation. Your "clues" were helpful, but I was thinking on a totally different wavelength. I was trying (unsuccessfully) to use Object.keys() to "capture" the key:value pairs that I cared about. (name and last date used) However, I now realize that this JS function represents a small step, used to create an array containing nothing but the unique hashes.

JSONata is good & all but its not really a transferrable skill. (IMO)

I mistakenly thought you wanted to learn how to program (you asked for "Guidance" and specifically "JavaScript")

Accepting a solution that did not take in to account your requests is not really teaching you much.

As for the "KISS" approach - you probably dont realise the large abount of JavaScript code under the hood of JSONata - the JavaScript I showed you (the longer version) is much more KISS (IMO).

This part confuses me the most. Your for loop (see below) produces the following output:

var keys = Object.keys(object1.whitelist);
 var asArray = [];
 for (let i = 0; i < keys.length; i++) {
     let key = keys[i];
     let item = object1.whitelist[key]; //get item
     asArray.push(object1.whitelist);
 }
 console.log(asArray)


(As written) the loop comes close to producing an array containing the whitelist properties. However, it is currently outputting 6 identical "copies" of the data.

There is a typo (code was untested) (and the 2nd image shows it corrected)

But that is all part of learning.

change asArray.push(object1.whitelist); to asArray.push(item);

Much better. :+1:t3:

Another acceptable solution would be:
asArray.push(object1.whitelist[key])
which is exactly what you used, when you were demonstrating how to sort the array.

Thank you for this learning opportunity. Much appreciated!

@Steve-Mcl can you help me understand the "if" logic (on lines 44 and 45)?
(By default) is the compare() function designed to sort a list of dates oldest --> newest?
If so, is it "ok" to swap the comparison operators (> and <) in order to sort the array newest --> oldest?

Yes. the goal is to return a positive number (e.g. 1), or a negative number (e.g. -1) or 0 (if they match).

If the sort order needs reversing, either swap the -1 and 1 OR swap the comparison operators.

Ok! Here is the final result.

[{"id":"ff0ee1c6.69484","type":"tab","label":"Report Home State","disabled":false,"info":"# Report Home State\n\n## Description\n\nThis flow logs Philips Hue light switch changes.\nPlease follow the instructions to set up this flow to your environment.\n\n## Motivation\n\nI use some rules for my light system and some motion detectors.\nAs I arrive at home, my light switches are automatically triggered by my smartphones WiFi logon.\nSometimes I ask myself, if the lights were really off during the day or always on, caused by a potential misconfiguration.\nSo I set up my Raspberry Pi to create a log file of light changes.\n\nMaybe it's usefull for you as well... ;)\n\n## Setup Instructions\n\n1. Follow the instructions on https://www.developers.meethue.com/documentation/getting-started to get your Philips Hue API URL.\n2. Inject the api url to the global variable `global.settings.hue.url`\n3. Set your desired log file name in the node named `Write to Lights States Log File`\n4. Now you can check when the lights were switched on and off\n \n_\n__Note:__\nThe format of the timestamp is UTC in ISO 8601 compatible format and may not represent your local timezone.\n_"},{"id":"288f64f2.622c9c","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"596ec16a.2048d","type":"subflow","name":"Array Of Booleans to String","info":"","in":[{"x":40,"y":40,"wires":[{"id":"af39cdd0.144f9"}]}],"out":[{"x":440,"y":40,"wires":[{"id":"af39cdd0.144f9","port":0}]}]},{"id":"fdccb947.3480f8","type":"subflow","name":"Get Lights State","info":"","in":[{"x":40,"y":40,"wires":[{"id":"5a751ab7.8f3514"}]}],"out":[{"x":300,"y":40,"wires":[{"id":"5a751ab7.8f3514","port":0}]}]},{"id":"a1719e16.dc588","type":"subflow","name":"Device Responsible for BulbStateChange","info":"","category":"","in":[{"x":20,"y":100,"wires":[{"id":"454db0b1.48969"}]}],"out":[{"x":980,"y":100,"wires":[{"id":"24a93773.36593","port":0}]}],"env":[],"color":"#DDAA99"},{"id":"af39cdd0.144f9","type":"function","z":"596ec16a.2048d","name":"Array Of Booleans to String","func":"let ret = \"\";\n\nfor (const b of msg.payload) {\n    ret += (b === true) ? \"1\" : \"0\";\n}\nmsg.payload = ret;\nreturn msg;","outputs":1,"noerr":0,"x":240,"y":40,"wires":[[]]},{"id":"5a751ab7.8f3514","type":"function","z":"fdccb947.3480f8","name":"Get Lights States","func":"let ret = [];\n\nfor (const light in msg.payload) {\n    ret.push(msg.payload[light].state.on);\n}\n\nmsg.payload = ret;\nreturn msg;\n","outputs":1,"noerr":0,"x":170,"y":40,"wires":[[]]},{"id":"43b7079.0cad1f8","type":"inject","z":"ff0ee1c6.69484","name":"","props":[{"p":"payload","v":"","vt":"date"},{"p":"topic","v":"","vt":"string"}],"repeat":"5","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":180,"wires":[["a646fed9.c4707"]]},{"id":"72f0c35c.c0d9ac","type":"http request","z":"ff0ee1c6.69484","name":"Get Lights","method":"GET","ret":"obj","url":"","tls":"","x":330,"y":380,"wires":[["44540150.c3bd9"]]},{"id":"5a78994b.8884f8","type":"change","z":"ff0ee1c6.69484","name":"Set Lights URL","rules":[{"t":"set","p":"url","pt":"msg","to":"$globalContext(\"settings.hue.url\") & \"/lights\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":160,"y":380,"wires":[["72f0c35c.c0d9ac"]]},{"id":"a9958d2a.8a77e","type":"change","z":"ff0ee1c6.69484","name":"Save Last State","rules":[{"t":"set","p":"lastLightsState","pt":"flow","to":"lightsState","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":160,"y":280,"wires":[["aa099e57.239"]]},{"id":"aa73ebd6.d0e128","type":"change","z":"ff0ee1c6.69484","name":"Set Current State","rules":[{"t":"set","p":"lightsState","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":170,"y":480,"wires":[["1a8479df.871036"]]},{"id":"d7c05f9.56629a","type":"switch","z":"ff0ee1c6.69484","name":"Lights State Changed?","property":"lightsState","propertyType":"flow","rules":[{"t":"else"},{"t":"neq","v":"lastLightsState","vt":"flow"}],"checkall":"true","repair":false,"outputs":2,"x":190,"y":580,"wires":[["4f3ce9e2.673078"],["45d7d2c0.8a203c"]],"outputLabels":["no","yes"]},{"id":"feda1399.e1a9b","type":"debug","z":"ff0ee1c6.69484","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":690,"y":580,"wires":[]},{"id":"5cbc9fd3.489b","type":"change","z":"ff0ee1c6.69484","name":"off text","rules":[{"t":"set","p":"payload","pt":"msg","to":"ALL LIGHTS OFF","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":640,"wires":[["a93d0be5.e98928"]]},{"id":"4f3ce9e2.673078","type":"change","z":"ff0ee1c6.69484","name":"unchanged text","rules":[{"t":"set","p":"payload","pt":"msg","to":"lights unchanged","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":580,"wires":[[]]},{"id":"9053e561.d4eeb8","type":"debug","z":"ff0ee1c6.69484","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":870,"y":420,"wires":[]},{"id":"44540150.c3bd9","type":"subflow:fdccb947.3480f8","z":"ff0ee1c6.69484","x":500,"y":380,"wires":[["f4b1114.a61d6f","a2b2c731.b87918"]]},{"id":"f4b1114.a61d6f","type":"subflow:596ec16a.2048d","z":"ff0ee1c6.69484","name":"Convert to String","x":690,"y":380,"wires":[["9053e561.d4eeb8","6b1950db.6aaa1"]]},{"id":"45d7d2c0.8a203c","type":"switch","z":"ff0ee1c6.69484","name":"Are All Lights Off?","property":"$contains($flowContext(\"lightsState\"), \"1\")","propertyType":"jsonata","rules":[{"t":"false"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":450,"y":640,"wires":[["5cbc9fd3.489b"],["c1112385.476cf"]],"outputLabels":["yes","no"]},{"id":"69162fa8.7249d","type":"change","z":"ff0ee1c6.69484","name":"changed text","rules":[{"t":"set","p":"payload","pt":"msg","to":"\"LIGHTS CHANGED BY: \" & msg.lightChangedBy","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":970,"y":700,"wires":[["a93d0be5.e98928"]]},{"id":"39631a9d.7dbb46","type":"file","z":"ff0ee1c6.69484","name":"Write to Lights States Log File","filename":"/usr/local/bin/PhilipsHue/logs/lightsstates.log","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"utf8","x":1150,"y":640,"wires":[[]]},{"id":"a93d0be5.e98928","type":"change","z":"ff0ee1c6.69484","name":"Prepend Timestamp","rules":[{"t":"set","p":"payload","pt":"msg","to":"$now() & \" - \" & $flowContext(\"lightsState\") & \" - \" & msg.payload","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":860,"y":640,"wires":[["feda1399.e1a9b","39631a9d.7dbb46"]]},{"id":"89aa4dbb.f9aa","type":"comment","z":"ff0ee1c6.69484","name":"Set `global.settings.hue.url` to your Philips Hue api url: https://www.developers.meethue.com/documentation/getting-started","info":"> To get detailed step by step instructions, open the flow description.","x":440,"y":40,"wires":[],"icon":"node-red/alert.png"},{"id":"5315b9cc.738bd8","type":"comment","z":"ff0ee1c6.69484","name":"Check for changes every ... seconds","info":"","x":170,"y":140,"wires":[]},{"id":"9dcf6fef.1b09f","type":"comment","z":"ff0ee1c6.69484","name":"Save previous light state","info":"","x":130,"y":240,"wires":[]},{"id":"47f0a7ce.a5fec8","type":"comment","z":"ff0ee1c6.69484","name":"Get the current light state","info":"","x":130,"y":340,"wires":[]},{"id":"18a4fbe7.e23ea4","type":"comment","z":"ff0ee1c6.69484","name":"Save current light state","info":"","x":120,"y":440,"wires":[]},{"id":"f0dc5ba3.683aa8","type":"comment","z":"ff0ee1c6.69484","name":"Log light state changes","info":"","x":120,"y":540,"wires":[]},{"id":"f5d529a9.469eb8","type":"comment","z":"ff0ee1c6.69484","name":"⬇ SET FILENAME HERE","info":"> To get detailed step by step instructions, open the flow description.","x":1130,"y":600,"wires":[],"icon":"node-red/node-changed.png"},{"id":"9f60f3be.8913e","type":"change","z":"ff0ee1c6.69484","name":"OPEN ME!","rules":[{"t":"set","p":"settings.hue.url","pt":"global","to":"http://ip_address_here/api/api_token_here","tot":"str"},{"t":"set","p":"pi.apiName","pt":"global","to":"Use \"Flow1\" to identify the API name to omit.","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":330,"y":80,"wires":[[]]},{"id":"18d30974.dd7e17","type":"inject","z":"ff0ee1c6.69484","name":"Set Initial Variables","props":[{"p":"payload","v":"","vt":"date"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":80,"wires":[["9f60f3be.8913e"]]},{"id":"4b6ae102.ac9d9","type":"comment","z":"ff0ee1c6.69484","name":"⬅ SET VARIABLES HERE","info":"> To get detailed step by step instructions, open the flow description.","x":530,"y":80,"wires":[],"icon":"node-red/node-changed.png"},{"id":"ca52298c.be1508","type":"link in","z":"ff0ee1c6.69484","name":"Save previous light state","links":["a646fed9.c4707"],"x":55,"y":280,"wires":[["a9958d2a.8a77e"]]},{"id":"ecf7b9a1.4ca168","type":"link in","z":"ff0ee1c6.69484","name":"Get the current light state","links":["aa099e57.239"],"x":55,"y":380,"wires":[["5a78994b.8884f8"]]},{"id":"6e1da50d.f53c4c","type":"link in","z":"ff0ee1c6.69484","name":"Save current light state","links":["6b1950db.6aaa1"],"x":55,"y":480,"wires":[["aa73ebd6.d0e128"]]},{"id":"9a9334da.405dd8","type":"link in","z":"ff0ee1c6.69484","name":"Log light state changes","links":["1a8479df.871036"],"x":55,"y":580,"wires":[["d7c05f9.56629a"]]},{"id":"a646fed9.c4707","type":"link out","z":"ff0ee1c6.69484","name":"","links":["ca52298c.be1508"],"x":235,"y":180,"wires":[]},{"id":"aa099e57.239","type":"link out","z":"ff0ee1c6.69484","name":"","links":["ecf7b9a1.4ca168"],"x":275,"y":280,"wires":[]},{"id":"6b1950db.6aaa1","type":"link out","z":"ff0ee1c6.69484","name":"","links":["6e1da50d.f53c4c"],"x":815,"y":380,"wires":[]},{"id":"1a8479df.871036","type":"link out","z":"ff0ee1c6.69484","name":"","links":["9a9334da.405dd8"],"x":295,"y":480,"wires":[]},{"id":"a2b2c731.b87918","type":"debug","z":"ff0ee1c6.69484","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":670,"y":440,"wires":[]},{"id":"6a688d8c.62eab4","type":"comment","z":"a1719e16.dc588","name":"Capture the Philips Hue config","info":"","x":410,"y":60,"wires":[]},{"id":"f3e9749d.059148","type":"http request","z":"a1719e16.dc588","name":"GetConfig","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":350,"y":100,"wires":[["2a54e795.ae9248"]]},{"id":"454db0b1.48969","type":"change","z":"a1719e16.dc588","name":"Set hueConfig URL","rules":[{"t":"set","p":"url","pt":"msg","to":"$globalContext(\"settings.hue.url\") & \"/config\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":170,"y":100,"wires":[["f3e9749d.059148"]]},{"id":"24a93773.36593","type":"function","z":"a1719e16.dc588","name":"Identify Device Last Used","func":" let hueConfig = msg.payload.whitelist;\n let keys = Object.keys(hueConfig);\n let asArray = [];\n \n //Populates the array using JSON from the hue config\n for (let i = 0; i < keys.length; i++) {\n     let key = keys[i];\n     let item = hueConfig[key]; //get item\n     asArray.push(hueConfig[key]);\n }\n \n //Removes the Raspberry Pi from the array\n let omitFromArray = msg.deviceToOmit;\n for (let i = 0; i < keys.length; i++) {\n    if ( asArray[i].name === omitFromArray) { \n        asArray.splice(i, 1); \n    }\n }\n \n //Sorts the array by \"last use date\"\n //Newest to Oldest\n let sorted = asArray.sort(function compare(a,b) {\n     let aDate = new Date(a[\"last use date\"]), bDate = new Date(b[\"last use date\"]);\n     if (aDate > bDate) return -1;\n     if (aDate < bDate) return 1;\n })\n\nmsg.lightChangedBy = sorted[0].name; //get 1st element\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":810,"y":100,"wires":[[]]},{"id":"c1112385.476cf","type":"subflow:a1719e16.dc588","z":"ff0ee1c6.69484","name":"","x":720,"y":700,"wires":[["69162fa8.7249d"]]},{"id":"2a54e795.ae9248","type":"change","z":"a1719e16.dc588","name":"Identify Device to Omit","rules":[{"t":"set","p":"deviceToOmit","pt":"msg","to":"pi.apiName","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":100,"wires":[["24a93773.36593"]]},{"id":"d72db09f.468d48","type":"http request","z":"288f64f2.622c9c","name":"GetConfig","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":490,"y":140,"wires":[["f5871ca4.7f4048"]]},{"id":"7da858a6.99f3c","type":"change","z":"288f64f2.622c9c","name":"Set hueConfig URL","rules":[{"t":"set","p":"url","pt":"msg","to":"$globalContext(\"settings.hue.url\") & \"/config\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":140,"wires":[["d72db09f.468d48"]]},{"id":"f5871ca4.7f4048","type":"function","z":"288f64f2.622c9c","name":"Identify Device Last Used","func":" let hueConfig = msg.payload.whitelist;\n let keys = Object.keys(hueConfig);\n let asArray = [];\n \n //Populates the array using JSON from the hue config\n for (let i = 0; i < keys.length; i++) {\n    let key = keys[i];\n    let item = hueConfig[key].name; //get item\n    asArray.push(hueConfig[key].name);\n }\n\nmsg.payload = asArray;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":690,"y":140,"wires":[["1a491f1c.8368a1"]]},{"id":"3f64c318.0af854","type":"inject","z":"288f64f2.622c9c","name":"","props":[],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"str","x":130,"y":140,"wires":[["7da858a6.99f3c"]]},{"id":"1a491f1c.8368a1","type":"debug","z":"288f64f2.622c9c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":910,"y":140,"wires":[]},{"id":"630e0608.888b28","type":"comment","z":"288f64f2.622c9c","name":"READ ME!","info":"1) Open the [Debug Sidebar](https://nodered.org/docs/user-guide/editor/sidebar/debug).\n2) Activate the (green) debug node.\n(Click the green box to the right of the node.)\n2) Click the blue \"Inject\" button.\n3) Click on the debug output.\n4) _Copy_ the name used by the raspberry pi.\n5) Go back to the \"Report Home State\" flow.\n6) Double click on the \"OPEN ME\" node.\n7) _Paste_ the name into 2nd global variable. (Called: global.pi.apiName)","x":120,"y":100,"wires":[]},{"id":"baf6f5c2.083cb","type":"comment","z":"288f64f2.622c9c","name":"⬇️ Activate debug node","info":"","x":1050,"y":100,"wires":[]}]

The Philips API does not provide reporting to indicate when lights are turned on/off & by who. This flow achieves just that!

98% of the credit for this flow goes to IOIO72.
Their Node-Red flow pinpointed when the state changes were occurring.
I identified what device issued the state change.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.