As mentioned I want it linked to HA entities which is easiest to do with customizations, so there’s some stuffing about because of that. I use Node Red, so this is my prototype:
This loads all of the “lastseen” values against the relevant entities. Then I use the following template to show those that haven’t been seen recently. Unfortunately by this stage “lastseen” is a string, so (like you), I’m doing a string comparison which just feels wrong, but never mind.
{% set then = utcnow() - timedelta(hours=8) %}
{% set test = then.strftime("%Y-%m-%dT%H:%M:%SZ") %}
{{ states.sensor
| selectattr('attributes.deconz_lastseen_utc', 'defined')
| selectattr('attributes.deconz_lastseen_utc', 'lt', test)
| map(attribute='entity_id')
| list
}}
This could then be extended to have a “ignore_lastseen” customization, and exclude them.
If you end up looking at the code below, there are a couple of things to note.
- It uses a global to get the path to the deCONZ API.
- The purple MQTT-out node is sending that data to an MQTT sensor. I’m not using it, but just wanted the data available.
- I’m using a stand-alone Node Red, so my path to HA is different to if it was the addon.
[{"id":"a372aaa5e0f3f8ae","type":"group","z":"2f4619ac.4996b6","name":"Load deCONZ sensor data into HA","style":{"label":true,"fill":"#e3f3d3"},"nodes":["9ef0f958b6acbe59","b0a01888b41f747c","ec0d42c8bca597f7","536ab81ab10b33d9","b3f5f2bcedeadca7","e61cbaa74de159a6","74a14541d5d550b2","94a9cd8e0729cd28","d7765b1309a403ba","7135d0356fe127ba","2e7fd2467720e272","21a7cccfe2d61e6a","3c5982a9d69bbe1d","c91b4d4c6cdbd1dd","8f505bd3204082b5","3dfdc85b0af10de0","3b3994b26e07ea3f","7f03dda64ef75ee2","0b2d1d5ef3cbd462","8abb5cc9347809df","c3965558a3df1ae4"],"x":14,"y":5239,"w":1372,"h":262},{"id":"9ef0f958b6acbe59","type":"http request","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"deCONZ sensors","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":470,"y":5340,"wires":[["e61cbaa74de159a6"]]},{"id":"b0a01888b41f747c","type":"cronplus","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"4h","outputField":"payload","timeZone":"","storeName":"","commandResponseMsgOutput":"output1","defaultLocation":"","defaultLocationType":"default","outputs":1,"options":[{"name":"schedule1","topic":"topic1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 0 */4 * * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":110,"y":5280,"wires":[["7f03dda64ef75ee2"]]},{"id":"ec0d42c8bca597f7","type":"mqtt out","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"","topic":"mb/nr/sensor/deconz_sensors","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"2a3b12ee.85570e","x":1150,"y":5400,"wires":[]},{"id":"536ab81ab10b33d9","type":"file in","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"HA entities","filename":"/ha/config/.storage/core.entity_registry","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":450,"y":5400,"wires":[["b3f5f2bcedeadca7"]]},{"id":"b3f5f2bcedeadca7","type":"json","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"","property":"payload","action":"","pretty":false,"x":610,"y":5400,"wires":[["e61cbaa74de159a6"]]},{"id":"e61cbaa74de159a6","type":"join","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Join","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":770,"y":5340,"wires":[["d7765b1309a403ba"]]},{"id":"74a14541d5d550b2","type":"change","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Topic","rules":[{"t":"set","p":"topic","pt":"msg","to":"deconz","tot":"str"},{"t":"set","p":"url","pt":"msg","to":"$globalContext('deconz_api') &\t\"sensors\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":5340,"wires":[["9ef0f958b6acbe59"]]},{"id":"94a9cd8e0729cd28","type":"change","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Topic","rules":[{"t":"set","p":"topic","pt":"msg","to":"registry","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":290,"y":5400,"wires":[["536ab81ab10b33d9"]]},{"id":"d7765b1309a403ba","type":"function","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Merge","func":"var ha_entities = msg.payload.registry.data.entities;\nvar deconz = msg.payload.deconz;\n\nmsg.payload = {\n devices: Object.entries(deconz).map(([k, v]) => {\n const id = deconz[k].uniqueid;\n return { \n deconz: {\n key: k,\n value: v\n },\n ha_entities: ha_entities\n .filter((e) => e.disabled_by == null)\n .filter((e) => e.unique_id.startsWith(id))\n .map((e) => e.entity_id)\n }\n })\n}\nmsg.payload.state = msg.payload.devices.length;\nglobal.set('deconz', msg.payload);\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":910,"y":5340,"wires":[["ec0d42c8bca597f7","3b3994b26e07ea3f"]]},{"id":"7135d0356fe127ba","type":"api-call-service","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Update","server":"5c211963.f91a88","version":5,"debugenabled":false,"domain":"homeassistant","service":"update_entity","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1080,"y":5460,"wires":[["0b2d1d5ef3cbd462"]]},{"id":"2e7fd2467720e272","type":"change","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Payload","rules":[{"t":"set","p":"deconz","pt":"msg","to":"deconz","tot":"global"},{"t":"set","p":"payload","pt":"msg","to":"(\t deconz.devices.ha_entities\t ~> $distinct()\t ~> $sort()\t ~> $map(function($entity_id) {(\t $deconz := $$.deconz.devices[$entity_id in ha_entities].deconz.value;\t {\t $entity_id: {\t \"deconz_lastseen_utc\": $deconz.lastseen,\t \"deconz_lastseen\": $moment($deconz.lastseen).format('D MMM YY')\t }\t }\t )})\t ~> $merge()\t)","tot":"jsonata"},{"t":"set","p":"refresh","pt":"msg","to":"{\t \"target\": {\t \"entity_id\": $keys(payload)\t }\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":5460,"wires":[["21a7cccfe2d61e6a"]]},{"id":"21a7cccfe2d61e6a","type":"yaml","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","property":"payload","name":"","x":450,"y":5460,"wires":[["3c5982a9d69bbe1d"]]},{"id":"3c5982a9d69bbe1d","type":"file","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Save","filename":"/ha/config/customize_deconz.yaml","filenameType":"str","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":590,"y":5460,"wires":[["c91b4d4c6cdbd1dd"]]},{"id":"c91b4d4c6cdbd1dd","type":"api-call-service","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Reload","server":"5c211963.f91a88","version":5,"debugenabled":false,"domain":"homeassistant","service":"reload_core_config","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":740,"y":5460,"wires":[["8f505bd3204082b5"]]},{"id":"8f505bd3204082b5","type":"change","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Payload","rules":[{"t":"move","p":"refresh","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":5460,"wires":[["7135d0356fe127ba"]]},{"id":"3dfdc85b0af10de0","type":"link in","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"deCONZ sensor","links":[],"x":120,"y":5340,"wires":[["74a14541d5d550b2","94a9cd8e0729cd28"]],"l":true},{"id":"3b3994b26e07ea3f","type":"link out","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Create sensor return","mode":"return","links":[],"x":1120,"y":5340,"wires":[],"l":true},{"id":"7f03dda64ef75ee2","type":"link call","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"","links":["3dfdc85b0af10de0"],"linkType":"static","timeout":"30","x":320,"y":5280,"wires":[["c3965558a3df1ae4"]]},{"id":"0b2d1d5ef3cbd462","type":"link out","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"Create cust return","mode":"return","links":[],"x":1270,"y":5460,"wires":[],"l":true},{"id":"8abb5cc9347809df","type":"link in","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"deCONZ cust","links":[],"x":110,"y":5460,"wires":[["2e7fd2467720e272"]],"l":true},{"id":"c3965558a3df1ae4","type":"link call","z":"2f4619ac.4996b6","g":"a372aaa5e0f3f8ae","name":"","links":["8abb5cc9347809df"],"linkType":"static","timeout":"30","x":520,"y":5280,"wires":[[]]},{"id":"2a3b12ee.85570e","type":"mqtt-broker","name":"Home","broker":"mqtt.blight.duckdns.org","port":"1883","clientid":"nr_docker","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"5c211963.f91a88","type":"server","name":"Home Assistant","version":5,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]```