Skip to content

Instantly share code, notes, and snippets.

@i8beef
Last active March 20, 2023 03:28
Show Gist options
  • Save i8beef/ab6386f1bb8f25c154e51df9a465eb05 to your computer and use it in GitHub Desktop.
Save i8beef/ab6386f1bb8f25c154e51df9a465eb05 to your computer and use it in GitHub Desktop.

Ubiquiti UniFi Presence Detection

Uses a UniFi node to monitor a UniFi management instance for named devices and their "Last Seen" values to determine device presence on the network.

Usage

  1. Install the node-red-contrib-unifi package.
  2. Past into a new or existing flow.
  3. Modify the UniFi node settings.
  4. Change the list of devices in the "Determine device presence" node. It maps the final MQTT topic that will be used to announce presence to the device name setup in UniFi for a client. Could be easily changed to be based on MAC address, etc., but if you name the devices in UniFi you can then later change those names without changing this flow.
[{"id":"a79a3412.95bbc8","type":"comment","z":"198805b3.d752aa","name":"Presence","info":"","x":100,"y":1420,"wires":[]},{"id":"356d290f.2adc76","type":"inject","z":"198805b3.d752aa","name":"Every 5 seconds","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":false,"x":130,"y":1460,"wires":[["2fe17f39.cb2e2"]]},{"id":"2fe17f39.cb2e2","type":"Unifi","z":"198805b3.d752aa","name":"","ip":"","port":8443,"site":"default","command":"20","x":310,"y":1460,"wires":[["9c4ebd18.14827"]]},{"id":"9c4ebd18.14827","type":"function","z":"198805b3.d752aa","name":"Determine device presence","func":"const lastSeenSeconds = 20;\nlet presenceCutoff = (Math.abs(new Date()) - (lastSeenSeconds * 1000)) / 1000; \nconst people = {\n \"presence/person1\": \"Identifier1\",\n \"presence/person2\": \"Identifier2\"\n};\n\nreturn Object.keys(people).map(function(topic) {\n let devices = msg.payload.filter(device => device.name === people[topic] && device.last_seen > presenceCutoff);\n return {\n topic: topic,\n retain: true,\n payload: devices.length > 0\n };\n});","outputs":"2","noerr":0,"x":520,"y":1460,"wires":[["1d706e57.f39ea2"],["84981.f0fe567f"]],"outputLabels":["michael presence","meredith presence"]},{"id":"1d706e57.f39ea2","type":"rbe","z":"198805b3.d752aa","name":"","func":"rbe","gap":"","start":"","inout":"out","x":750,"y":1440,"wires":[["e52f02f3.7cd59"]]},{"id":"84981.f0fe567f","type":"rbe","z":"198805b3.d752aa","name":"","func":"rbe","gap":"","start":"","inout":"out","x":750,"y":1480,"wires":[["e52f02f3.7cd59"]]}]
@quadhammer
Copy link

I'm not at my computer to check, but from memory the array thing had to be expanded, and perhaps you need to use a complete message object debug note, rather than just the message.payload one. Apologies if this is obvious, and you have already tried it.

@i8beef
Copy link
Author

i8beef commented Jan 23, 2021

Sorry, no idea off hand. If the message payload coming out of that is empty it sounds like theres something not right in your node setup, or something. might want to ask on the UniFi node's Github or something and see if they know.

@quadhammer
Copy link

The node-red-contrib-unifi package has stopped working for me too, so it's probably the culprit here.

@groenerik
Copy link

Thank you very much for this code!

To get it working here with Unifi Application: Network 7.2.97 and node-red v3.0.2 I needed to make two changes.

To remove a code verification error I changed the second line to :
let presenceCutoff = (Date.now() - (lastSeenSeconds * 1000)) / 1000;
new Date() appears to return an object in stead of a number.

Then during executing I got an error message and no results.
"TypeError: msg.payload[0].filter is not a function"

I could resolve it bij removing the [0] index from msg.payload[0].filter.
let devices = msg.payload.filter(device => device.name === people[topic]);

Apparently the structure of the Unifi output has changed over time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment