pizzalorddex / homebridge-unifi-ap-light

Control the light rings on your UniFi Wireless Access Point(s) with HomeKit
Apache License 2.0
0 stars 0 forks source link

Add Support For UDR LED Control #4

Open pizzalorddex opened 1 month ago

pizzalorddex commented 1 month ago

Describe the solution you'd like: As a user I want to control the blue LED ring of a UDR the same way it is controlled on a WAP.

Additional context: Currently, it doesn't work. The plugin is able to find the UDR, but the light control doesn't do anything.

pizzalorddex commented 1 month ago

Moved from https://github.com/pizzalorddex/homebridge-unifi-ap-light/issues/3#issuecomment-2115931542

Good Evening Pizzalorddex,

you really AMAZING.

Looks better. The plugin start an load an find my two AP the UAP-AC-IW and the Unifi Dream Router and I also get two toggle in HomeKit. The UAP-AC-IW toggle works can turn on and off the Blue LED from the UAP-AC-IW The Unifi Dream Router toggle I can press on and off butt the Blue LED from the Unifi Dream Router do nothing.

But it is already a very good way both toggle appear good work nice 👍

Hier some logs.

[UniFi AP Lights] Finished loading, starting device discovery.

[UniFi AP Lights] Primary authentication method failed, attempting secondary.

[UniFi AP Lights] Authentication with secondary method successful. Requesting URL: /api/s/default/stat/device Endpoint not found: /api/s/default/stat/device, trying next endpoint Requesting URL: /proxy/network/api/s/default/stat/device

[UniFi AP Lights] Adding new accessory: UAP-AC-IW (123456789abcd……..) [UniFi AP Lights] Adding new accessory: Unifi Dream Router (987654321abc……..)

[UniFi AP Lights] Successfully set LED state for Unifi Dream Router to on. (Nothing Happen) [UniFi AP Lights] Successfully set LED state for Unifi Dream Router to off. (Nothing Happen)

[UniFi AP Lights] Successfully set LED state for UAP-AC-IW to on. (Blue LED turn ON) [UniFi AP Lights] Successfully set LED state for UAP-AC-IW to off. (Blue LED turn OFF)

Thanks Again for your Work an Time you a Genius

pizzalorddex commented 1 month ago

Moved from https://github.com/pizzalorddex/homebridge-unifi-ap-light/issues/3#issuecomment-2115948940

Thanks for the feedback. I was hoping it would be simple, but it looks like it isn't so simple. Let me research this a bit more to see if it is possible. I may ask you to run a few commands to gather information about the UDR. I guess it handles its light differently than WAPs.

pizzalorddex commented 1 month ago

Moved from https://github.com/pizzalorddex/homebridge-unifi-ap-light/issues/3#issuecomment-2115973911

Yes of course you can tell me what commands I should run where.

I will take some screenshots later and post it here for you I think I see what is different.

pizzalorddex commented 1 month ago

Moved from https://github.com/pizzalorddex/homebridge-unifi-ap-light/issues/3#issuecomment-2116022215

Here the Picture what I found what is different. Better Picture because I can not explain maybe you would understand me wrong.

1 UAP-AC-IW 2 UDR 3 Console Settings 4 Consol Settings

pizzalorddex commented 1 month ago

Moved from https://github.com/pizzalorddex/homebridge-unifi-ap-light/issues/3#issuecomment-2116097144

Thanks for the additional pictures! That makes it a little more clear for me. It also makes me worried because the app would need to use the API to control the light. If it is not supported in the app it is hard to say if the plugin can support it.

I am sorry, but this will be a long message. If you don't understand anything I will be happy to answer!



To check further there are some commands you can run from a linux machine, like your raspberry pi. Anything in the commands you need to replace with your own information I will put in < >

First we need to log into the API to copy a couple tokens using this command: curl -k -i -X POST "https://<YOUR-HOST>/api/auth/login" -H "Content-Type: application/json" -d '{"username": "<YOUR-USERNAME>", "password": "<YOUR-PASSWORD>"}'

You should see a message like this: HTTP/1.1 200 vary: Origin Set-Cookie: unifises=THE-FIRST-TOKEN; Path=/; HttpOnly Set-Cookie: csrf_token=THE-SECOND-TOKEN; Path=/ X-Frame-Options: DENY Content-Type: application/json;charset=UTF-8 Content-Length: 30 Date: SOME-DAY-AND-TIME GMT

From this message we need both of the sets of random numbers and letters for unifises and csrf_token. Using these we can actually talk to the API.

Next, we can run this command to see what capabilities the udr has: curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: unifises=<YOUR-UNIFISES-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" | jq '.data[] | select(.type == "udm") | {id: ._id, name: .name, type: .type, model: .model, capabilities: (. | with_entries(select(.key | contains("led"))))}'

You should see a message like this: { "id": "AN-ID-NUMBER", "name": "NAME-OF-DEVICE", "type": "udm", "model": "UDR", "capabilities": { "mesh_sta_vap_enabled": false, "led_override_color": "#0000FF", "atf_enabled": false, "dot1x_portctrl_enabled": false, "led_override": "on", "led_override_color_brightness": 100, "vwireEnabled": false }

You can censor the id and name, those are not important. This should be your UDR. For type: it should say udm and for model: it should say UDR.

In this list it is very important that there is something like led_override.

Please send this so I can see what is available on the UDR to play with :)

daywalkeraut commented 1 month ago

It is supported in the App but not on same place like the UAP-AC-IW.

omg you very good you know a lot .

With the first Comand I think I only get the csrf-token. The unifises Token I can not found. I use my only Local User

I get this

HTTP/2 200 server: nginx date: Thu, 16 May 2024 20:27:57 GMT content-type: application/json; charset=utf-8 content-length: 3266 set-cookie: TOKEN=eyJhbGciOi-THE-TOKEN-NzAxIn0.j6rFLLTsvL6GowDCDhZ_PcYKAyY0; path=/; expires=Thu, 16 May 2024 22:27:57 GMT; samesite=none; secure; httponly x-updated-csrf-token: 12345aaa-123a-1234-1a23-aa1aaa1aaaa1 x-token-expire-time: 1415248479109 x-response-time: 834ms access-control-allow-credentials: false access-control-expose-headers: Content-Disposition, Content-Range, Filename, Location, Range, Upload-Length, Upload-Offset, X-Connection-Type, X-Csrf-Token, X-File-Id, X-Token-Expire-Time, X-Updated-Csrf-Token referrer-policy: no-referrer strict-transport-security: max-age=15552000; includeSubDomains x-content-type-options: nosniff x-dns-prefetch-control: off x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block x-csrf-token: 12345aaa-123a-1234-1a23-aa1aaa1aaaa1

EDITED: to remove specifics on the token and any extra device info.

pizzalorddex commented 1 month ago

OH! Ok I didn't know it would return different tokens.

You should still be able to use the command: curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" | jq '.data[] | select(.type == "udm") | {id: ._id, name: .name, type: .type, model: .model, capabilities: (. | with_entries(select(.key | contains("led"))))}'

The token is the really long string of letters and numbers and csrf token is the one that you already saw.

Hopefully with this command you see a shorter list of things that only have to do with "led".

AS INFO: the tokens are only valid for a short period (like 10 minutes) so you may need to run the first command again to generate a new token.

daywalkeraut commented 1 month ago

What token should I use here? -H "Cookie: TOKEN=

I only see the csrf-token.

Did you see the other token?

pizzalorddex commented 1 month ago

It is the very long text after where it says set-cookie: TOKEN=

You only need the long string of letters and numbers. You don't need the ; path=/; expires= blah blah blah that comes after

daywalkeraut commented 1 month ago

Ok thanks I did not see this.

daywalkeraut commented 1 month ago

get this

-bash: jq: command not found % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 8016 0 8016 0 0 82155 0 --:--:-- --:--:-- --:--:-- 82639 curl: (23) Failure writing output to destination

have try it two times

pizzalorddex commented 1 month ago

Ah, I see the problem. Jq is not installed.

Jq will allow us to read certain files from the API.

You can install jq on Debian, raspberryOS, or Ubuntu with the command: sudo apt-get update && sudo apt-get install jq -y

daywalkeraut commented 1 month ago

AMAZING

but the message looks not better .-(

% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 47 100 47 0 0 1432 0 --:--:-- --:--:-- --:--:-- 1468 jq: error (at :0): Cannot iterate over null (null)

pizzalorddex commented 1 month ago

It appears it is not getting any data back from the API which could mean the command is wrong.

I don't really know how exactly the command should be written in your case, but you can try the same command without the jq part to see if you get any data at all.

curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>"

I can look more at this tomorrow to figure out what the command should look like.

daywalkeraut commented 1 month ago

I have try it but it comes so a Big message that I think is not correct.

Please don't stress yourself out about this. It has no urgency at all.

From what time zone you are? Me is from UTC +2

pizzalorddex commented 1 month ago

I am also in UTC+2, Germany :)

A long/big message is great! That means the command worked. That command asks for all information on all devices. Even with one device it can be pretty big.

So it looks like the command failed because it couldn't find any capability on the UDR with "led" in it.

What we can do instead is just ask the UDR to give us all the capabilities it has. The message will probably be quite long with a lot of stuff we don't need, but then we can at least see something. Here we are just looking for something that says "led" or "light" or maybe even something like "status indicator".

To do that this would be the command (after getting the token and csrf_token again): curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" | jq '.data[] | select(.type == "udm") | {id: ._id, name: .name, type: .type, model: .model, capabilities: .}'

If there is any sensitive looking information, like your network names or other settings, you can censor them or remove them from the message before posting it.

daywalkeraut commented 1 month ago

Hahaha, I am from Austria and you are killing me because I have to write in English But it's clear so anyone else can understand it.

The command work. I get a more more longer message. This are 63 Pages in Pages, 9219 Words :-)

This takes long time or the rest of my life for me to find something and remove sensitive information.

daywalkeraut commented 1 month ago

I can find two entries. I have no idea what the context is.

"led_override": "off",

"total_max_power": 40, "led_state": { "pattern": "0", "tempo": 120

pizzalorddex commented 1 month ago

Hahaha, I am from Austria and you are killing me because I have to write in English

Haha! Sorry, wir können auch Deutsch benutzen, but I am not a native speaker. Use whatever you want and I will understand xD

This are 63 Pages in Pages, 9219 Words :-)

OMG WHAT?! I was not expecting it to be so long for one device...

I can find two entries. I have no idea what the context is.

"led_override": "off"

This is exactly what we need! When you ran the command was the light on the UDR off? It should be from the UDR, but we need to make sure this is the UDR and not the UAP-AC-IW.

You can also test turning the light on and off manually with a similar command... To turn on: curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/rest/device/<DEVICE_ID>" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" -d '{"led_override": "on"}'

To turn off: curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/rest/device/<DEVICE_ID>" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" -d '{"led_override": "off"}'

The <DEVICE_ID> should be somewhere at the top of that very long text you got before.

You can also use this command to get a list of all devices which have the "led_override" property (including the UAP-AC-IW): curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" | jq '.data[] | {id: ._id, name: .name, type: .type, model: .model, led_override: .led_override}'

daywalkeraut commented 1 month ago

Yes the Light was off but by both UDR an UAP-AC-IW I turn on the Light at UDR same message "led_override": "off" Turn only UAP-AC-IW light on same message "led_override": "off" Turn both lights on same message "led_override": "off"

with this curl -k -X GET "https:///proxy/network/api/s/default/rest/device/" -H "Content-Type: application/json" -H "Cookie: TOKEN=; csrf_token=" -d '{"led_override": "on"}'

I get this {"meta":{"rc":"error","msg":"api.err.NotFound"},"data":[]}

with this curl -k -X GET "https:///proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: TOKEN=; csrf_token=" | jq '.data[] | {id: ._id, name: .name, type: .type, model: .model, led_override: .led_override}'

I get this

% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 87846 0 87846 0 0 631k 0 --:--:-- --:--:-- --:--:-- 635k { "id": „XXXXXXXX“, "name": "UAP-AC-IW", "type": "uap", "model": "U7IW", "led_override": "on" } { "id": „XXXXXXX“, "name": "USW-Flex-Mini", "type": "usw", "model": "USMINI", "led_override": "off" } { "id": „XXXXXXXXXX“, "name": "Unifi Dream Router", "type": "udm", "model": "UDR", "led_override": "off" THE LIGHT RING IS ON }

I think I would not work Or can it be the problem that I use the Local User?

pizzalorddex commented 1 month ago

This explains why it wasn't working originally. The plugin only tries to change led_override to on or off. However, we have confirmed this is not what the UDR uses to control its own LED light.

Although it is slow we are making progress by eliminating possibilities! ☺️

The next step would be to try and capture the command which is used. To do this we can use a web browser and use the developer tools there. Of course, only if you are willing to do this.

I can help guide you with what to do I only need to know what web browser you will use. I use a Mac with Safari so I know what to do using Safari, but the steps are basically the same for Chrome or Firefox.

Also, if it is easier for you we can either keep communicating here or we can move to a different platform, such as Discord. Whatever is easiest for you 👍

daywalkeraut commented 1 month ago

If you have time, desire and interest Yes Please.

I also Use MacBook Air m2 also with Safari.

How you want we can communicate

pizzalorddex commented 1 month ago

Alright! Let's do this 🤓

  1. Open Safari and go to the menu Safari > Settings > Advanced
  2. Check the box that says "Show features for web developers" at the bottom
  3. Close the Settings window
  4. Open the UniFi Controller website (192.168.1.1 for example) and log in
  5. Go to the part of the website where you can turn the LED on or off
  6. From the top taskbar (Safari, File, Edit, etc.) click on Develop > Show Web Inspector (or the shortcut: option + command + i)
  7. In the Web Inspector window click on "Network"
  8. Toggle the LED on or off and save changes in UniFi
  9. Toggle the LED on or off and save changes in UniFi again
  10. In the Web Inspector window scroll to the bottom, you should see 2 entries that is a series of numbers and letters (it is the device ID). For example: Screenshot 2024-05-17 at 21 21 41
  11. Click on the first one and the response field will open. For example: Screenshot 2024-05-17 at 21 26 00
  12. Switch to the request view from the drop down menu and click the grey { } icon directly to the right of it to format the request nicely. It should look like this if done correctly: Screenshot 2024-05-17 at 22 00 30
  13. Copy the text and paste it into the first field of diffchecker
  14. Repeat steps 11 - 13 for the second request and paste the text into the second field of diffchecker
  15. Click on the green "Find Difference" button on the diffchecker website. This make looking for changes easy and you should see something like this: Screenshot 2024-05-17 at 22 09 01

The field which is highlighted as different should be the thing that the UDR uses to control its light.

After you are done with the steps above and found the difference(s) you can open the menu Safari > Settings > Advanced again and deselect the checkbox "Show features for web developers" to return to normal.

If you made it this far congratulations! You are basically now a developer 💪🤣

daywalkeraut commented 1 month ago

Haha i am not a developer, i am a cheater :-)

Thank you so much for this perfect guide.

Turn on {"ledSettings":{"enabled":true}}

Turn off {"ledSettings":{"enabled":false}}

pizzalorddex commented 1 month ago

AWESOME! This is exactly what we need. I will look into my code now to make the necessary changes

pizzalorddex commented 1 month ago

@daywalkeraut please test with version 1.3.1

For me it is still working with WAPs so I hope your UDR now also works 🙏

daywalkeraut commented 1 month ago

Hello Pizzaloddex,

sorry to say but only the LED from the UAP-AC-IW works. UDR nothing happen. At HomeKit when I push the toggle to on the toggle go instant back off.

some logs for you because I know you like logs :-) i also have try it with port 8443

[UniFi AP Lights] Primary authentication method failed, attempting secondary.

[UniFi AP Lights] Authentication with secondary method successful.

[UniFi AP Lights] Adding new accessory: UAP-AC-IW (XXXXXX) [UniFi AP Lights] Adding new accessory: Unifi Dream Router (XXXXXX)

Endpoint not found: /api/s/default/stat/device, trying next endpoint Endpoint not found: /api/s/default/stat/device, trying next endpoint [UniFi AP Lights] Failed to retrieve LED state for Unifi Dream Router: TypeError: Cannot read properties of undefined (reading 'enabled')

[UniFi AP Lights] Retrieved LED state for UAP-AC-IW

[UniFi AP Lights] Successfully set LED state for UAP-AC-IW to on. [UniFi AP Lights] Retrieved LED state for UAP-AC-IW: on [UniFi AP Lights] Successfully set LED state for UAP-AC-IW to off.

[UniFi AP Lights] Successfully set LED state for Unifi Dream Router to on.

pizzalorddex commented 1 month ago

Thanks for testing it and thanks for the logs 😆

I think I messed up reading the current state of the light on the UDR.

I will try again in the morning 👍

daywalkeraut commented 1 month ago

Me have to Thanks you.

Take your time, enjoy the Weekend.

bg

pizzalorddex commented 1 month ago

Hello again @daywalkeraut. I hope you had a good weekend!

I made a minor change and added new debugging messages to the logs (version 1.3.2) to try to pinpoint the issue.

You can also try to manually set the LED to see if that works. Just as a reminder:

  1. Get your tokens with the command: curl -k -i -X POST "https://<YOUR-HOST>/api/auth/login" -H "Content-Type: application/json" -d '{"username": "<YOUR-USERNAME>", "password": "<YOUR-PASSWORD>"}'
  2. Use the tokens to get the device ID: curl -k -X GET "https://<YOUR-HOST>/proxy/network/api/s/default/stat/device" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" | jq '.data[] | select(.type == "udm") | {id: ._id, name: .name, type: .type}'
  3. Try this command to turn the LED on: curl -k -X PUT "https://<YOUR-HOST>/proxy/network/api/s/default/rest/device/<DEVICE_ID>" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" -d '{"ledSettings":{"enabled":true}}'
  4. Try this command to turn the LED off: curl -k -X PUT "https://<YOUR-HOST>/proxy/network/api/s/default/rest/device/<DEVICE_ID>" -H "Content-Type: application/json" -H "Cookie: TOKEN=<YOUR-TOKEN>; csrf_token=<YOUR-CSRF_TOKEN>" -d '{"ledSettings":{"enabled":false}}'

The command to turn the LED on or off is the same except for turning it on or off. You can just use one or the other to test if it changes.

daywalkeraut commented 1 month ago

Hello sorry I was not at home few days.

I have try the two commands, nothing happens. Not on or not off. Get no message back that any error.

daywalkeraut commented 1 month ago

Could it be that it has something to do with the URL?

To control the light from the UAP-AC-IW I have to go to this URL: https://192.168.1.1/network/default/devices

To control the light from the UDR I have to go to this URL: https://192.168.1.1/console-settings

kloibs commented 3 weeks ago

Hi everyone! I recently purchased a UDR for my studio apartment and I absolutely love it so far! Seeing that I can see it from bed, however, control of the LED/screen would be amazing! I have a Shelly 4 Pro PM and can control the display very easily... it's a shame that it's not quite the simple here.

While I can't say I have any coding experience I would be more than happy to assist in any testing that may be necessary!