Isaksson / node-red-contrib-unifi

MIT License
50 stars 19 forks source link

Let clientdevices command forward mac from payload #97

Closed jokakilla closed 1 year ago

jokakilla commented 1 year ago

The internal getClientDevices method already allows to get information only for a certain device by setting the optional client_mac parameter. Adding the message payload client_mac parameter to the method call allows to get device info just for a single device.

If the msg.payload does not contain client_mac the internal undefined check should handle that by setting an empty string.

jokakilla commented 1 year ago

Hi guys, I use the unifi plugin for some month without any issues for presence detection. Thanks by the way 🙂.

But as the number of devices on my unifi system is constantly rising it would make sense to request only information about the presence relevant device instead of fetching and parsing a huge blob of data.

It would be nice if you could check and integrate my proposal.

pluto202 commented 1 year ago

Hi jokakilla, would you mind to share your current flow to check presence status? I have the same need to get this information out of my UDM. Thanks a lot. Andreas

jokakilla commented 1 year ago

Hi @pluto202, I can't give you the flow right now as I've changed my local implementation with the changes from this pull request. But basically I have an inject node the is triggering every minute the Unifi node with command "ClientDevices" The result is processed by a function node:

var myPhoneMac= "d4:d7:cf:xx:xx:xx";
var myWifesPhoneMac = "b8:3b:cc:xx:xx:xx";

for (var device of msg.payload) {
  if(device.mac == myPhoneMac || device.mac == myWifesPhoneMac) {
      msg.payload = true;
      return msg;
  }
}
msg.payload = false;
return msg;

The unifi node returns an array of devices. When a device leaves the wifi it disappears from the array. With the proposed change I can request the info for every single device and don't have to iterate over an array of 50 devices.

I've tested this by letting my inject node set the payload to {"client_mac": "d4:d7:cf:xx:xx:xx"} When the device is connected an array of size 1 is returned with all the information. If not the payload is only the payload injected to the node. This way I can simply check for presence of the device by: msg.payload.length == 1

PS: Still dreaming of Unifi implementing an event based interface like MQTT for such stuff so I could subscribe to the presence topic of a certain device and instantly get notified about state changes. ;) One more hint: On Android I had to turn off the privacy feature for my Wifi that generates random mac addresses.

Isaksson commented 1 year ago

Hello. Thanks for that. Sure, I will implement this, I need to make some more changes to the documentation and so on but I will do this right now

ozett commented 1 year ago

@jokakilla just out of curiosity: 1) do the phones disappear from wifi in standby mode? (iphone/android different behavior?)

2) instead of waiting for MQTT maybe the log could be parsed for notice of appearance/dissappearence of spedific devices?

Isaksson commented 1 year ago

This is now implemented in version 0.2.12 the command changed to { command: "clientDevices", mac: "device MAC address" }

Isaksson commented 1 year ago

PS: Still dreaming of Unifi implementing an event based interface like MQTT

I am working on solution that will listen for events, but I need to make it solid before I could release it.

jokakilla commented 1 year ago

@ozett on different Android devices (Xiaomi, Realme) with android 9 to 12 it has been working reliable for me in every situation. When leaving the house it sometimes takes a bit. Unfortunately I don't have any apple devices around. I guess many variables can have an impact on reliability:

In first place I expected that the device stays in the array and the disconnect_timestamp field to be updated. My idea was to check if the last_seen timestamp is after the disconnect_timestamp. But it turned out the device completely disappears from the data.

@Isaksson out of curiosity: How are you planing to implement the event solution? I always thought the Unifi API only allows polling.

pluto202 commented 1 year ago

@jokakilla and @ozett seems to be working with Apple devices as well with the code above. Still on Version 0.2.11

ozett commented 1 year ago

i dont really like the idea of 1 minute polling information from the controller . but you encouraged me to take the other road and see if i can catch the same events from the syslog with node-red image

Isaksson commented 1 year ago

@Isaksson out of curiosity: How are you planing to implement the event solution? I always thought the Unifi API only allows polling.

It will be through websocket and listen to events.

Isaksson commented 1 year ago

The only issue with polling 1 time / minute is that in worst case you will miss the event by 59 seconds, there will be no impact on the controller by polling the system.

The is always a delay from Unifi when a client is disconnected, connected is almost always instant. That is how the system works and same result in the GUI.

But it seems like you all need the new feature, so maybe I should speed up the development of that new feature.

ozett commented 1 year ago

love to see doing it with MQTT, (like most other things already on my node-red)

but in a qucik test it works also pretty as push with syslog. filtering on hostapd and dis/association does the job. (random MAC must OFF, as it looks like unify controller allows to name the device even with random-mac, but i dont how how to filter on the name)

syslog
node-red module syslog2

image

[{"id":"9981a256474fb492","type":"syslog-input2","z":"eb151a75.f4dc58","name":"syslog","socktype":"udp","address":"192.168.14.204","port":20514,"topic":"","x":220,"y":290,"wires":[["b6953ed501f637cd"]]},{"id":"b6953ed501f637cd","type":"switch","z":"eb151a75.f4dc58","name":"","property":"payload.msg","propertyType":"msg","rules":[{"t":"nnull"}],"checkall":"true","repair":false,"outputs":1,"x":370,"y":290,"wires":[["12924ecc4052d788","7c23129a64d8831b","d43816d196f86954"]]},{"id":"7c23129a64d8831b","type":"switch","z":"eb151a75.f4dc58","name":"hostapd","property":"payload.msg","propertyType":"msg","rules":[{"t":"cont","v":"hostapd","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":540,"y":360,"wires":[["d3d2ad246a71a69e","1ab3ee5fd3152fc2"]]},{"id":"1ab3ee5fd3152fc2","type":"switch","z":"eb151a75.f4dc58","name":"associated","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"associated","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":720,"y":420,"wires":[["7097022755886567"]]},{"id":"7097022755886567","type":"debug","z":"eb151a75.f4dc58","name":"associated","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload.msg","statusType":"jsonata","x":920,"y":420,"wires":[]}]
Isaksson commented 1 year ago

Well, that's one of the strength with Node-red is that you could fetch data from many different protocol's but handle them the same in your flow. You could fetch a JSON string from MQTT or from Websocket or even HTTP scrape, but in your flows you could just handle them the same, that's very nice. MQTT from Unifi seems unlikely but who knows.

jokakilla commented 1 year ago

I have also strong doubt that Unifi will implement MQTT. But connecting via websocket from an unifi node to the Unifi controller sounds very promising to me. Hope I got the idea right. The unifi node would trigger as soon as certain events from the websocket connection happen?!

@ozett does the syslog solution cause a lot of network traffic between the unifi controller and node-red?

Isaksson commented 1 year ago

I have also strong doubt that Unifi will implement MQTT. But connecting via websocket from an unifi node to the Unifi controller sounds very promising to me. Hope I got the idea right. The unifi node would trigger as soon as certain events from the websocket connection happen?!

Yes, that's correct. It's like a subscription so you subscribe on events and as soon that events happens then the node will output the result.

ozett commented 1 year ago

@ozett does the syslog solution cause a lot of network traffic between the unifi controller and node-red?

dont know how to measure that, but i would say "no". i aggregate lots of appliances into one syslog and its UDP and all data is compressed at the end. no problem. no network load ever recognized, only over the time i have some data collections on the disks.

in case of node red, i would say: if you filter and dont store: no data collection, no real measurable network load. as far as i googled it, nobody seems to be afraid of network overloading.. save to try, i would say

ozett commented 1 year ago

you could try to make presense-detection with athome/away with a trigger node. like HAS is doing it. work like this : if no more lifesign from the reset line, than the trigger times out after 15 minutes of devices wifi is "disassociated".

screenshot

image

jokakilla commented 1 year ago

Thanks once again for quickly integrating the change :) Maybe I'll try the syslog solution or wait for the websocket event based stuff.

But meanwhile simply getting only the relevant devices has reduced cpu load on the RaspberryPi3 that is running the Unifi controller Bildschirmfoto vom 2023-01-07 00-09-51