nickovs / unificontrol

A high-level Python interface to the Unifi controller software
Apache License 2.0
96 stars 41 forks source link

Unable to connect to a UDM Pro with this library #12

Open richardellwood opened 3 years ago

richardellwood commented 3 years ago

Attempting to connect to my UDM Pro with the program


from unificontrol import UnifiClient
import ssl

cert = ssl.get_server_certificate(("10.1.0.1", 443))

router = UnifiClient(host = "10.1.0.1", port = "443", username = "admin", password = "[password]", cert = cert)

I get the following error

Traceback (most recent call last):
  File "test.py", line 8, in <module>
    clients = router.list_sites()
  File "/home/sysop/.local/lib/python3.5/site-packages/unificontrol/metaprogram.py", line 123, in wrapper
    return instance(client, *a, **kw)
  File "/home/sysop/.local/lib/python3.5/site-packages/unificontrol/metaprogram.py", line 101, in __call__
    return client._execute(url, self._method, rest_dict, need_login=self._need_login)
  File "/home/sysop/.local/lib/python3.5/site-packages/unificontrol/unifi.py", line 110, in _execute
    response = resp.json()
  File "/home/sysop/.local/lib/python3.5/site-packages/requests/models.py", line 898, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

Any advice is appreciated. Richard

nickovs commented 3 years ago

Historically by default the Unifi controller is on port 8443, not port 443. If you are running a CloudKey or similar then there is a UI on 443, but it redirects you to port 8443 for the Unifi Network interface and port 7443 for the Unifi Protect interface. Try the using port 8443 and see if that fixes it (or just don't specify the port argument, since it defaults to the right port).

That said, even if that fixes it the error message is unhelpful; I'll put in some more informative error handling when I have some time.

richardellwood commented 3 years ago

Thank you, Nickovs. 8443 isn't working for me either. I'm going to try digging into your code and see if I can figure out what's going on. If I find a solution, I'll certainly contribute.

nickovs commented 3 years ago

Based on the stack backtrace, it looks like the crash is happening because whatever the server is sending back can not be decoded as a JSON payload even though the HTTP request returned an OK result. This is happening at line 110 in unifi.py. This suggests to me that the endpoint that you are hitting is not the Unifi controller endpoint but something else (hence my suggestion that you check the port).

If you are up for trying to debug this yourself then you probably want to start by printing r.text just before the code tries to extract the reply body as JSON, to see what is actually getting returned.

avleen commented 3 years ago

I've been running into this issue too, on the latest 1.8.5 firmware.

When I do the print, the output is:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1"><link href="/2.css" rel="stylesheet"></head>
<body>
<div id="root"></div>
<script type="text/javascript" src="/vendor.0306759b.chunk.js"></script><script type="text/javascript" src="/main.d8e6c715.js"></script></body>
</html>

I had to edit metaprogram.py and on L77 change:

return "https://{host}:{port}/api/s/{site}/{endpoint}{path}".format(

to:

return "https://{host}:{port}/proxy/network/api/s/{site}/{endpoint}{path}".format(
avleen commented 3 years ago

Likewise, in unifi.py, L142 needs to change to:

"auth/login"

and L161 needs to change to:

"auth/logout"
avleen commented 3 years ago

Also in unifi.py, L114, there is on response['data'] object any more. I'm not sure what it used to look like before, but now response is just a hash full of lots of info. I assume that might be what we're looking for? Sorry about the flood of comments, I don't know how you'd want to update the library to support the new firmware with all these changes and still be backwards compatible so I'm dumping this knowledge here :)

avleen commented 3 years ago

Ok, hopefully last update, this is a diff of what worked in the end, for both login and various other things. Happy to send a pull request if you want it as is, but it will break people on older firmware for sure: https://github.com/avleen/unificontrol/commit/0c9fcfaa19fe9671e12ac68de054f1e4b47d8e31

nickovs commented 3 years ago

@avleen Thanks for all of these details. Can you confirm that you are also using a UDM Pro? What version of the server code are you running? I don't currently have access to a UDM Pro but if we can find a way to tell the difference and you are up for some testing then maybe we can build a version of this library that works with the UDM, the CloudKey and the stand-alone Java version.

avleen commented 3 years ago

Hi Nicko!

I have the UDM (non-pro) device, which has the built-in cloud key. I'm happy to do testing :)

On Thu, Jan 14, 2021 at 4:28 PM Nicko van Someren notifications@github.com wrote:

@avleen https://github.com/avleen Thanks for all of these details. Can you confirm that you are also using a UDM Pro? What version of the server code are you running? I don't currently have access to a UDM Pro but if we can find a way to tell the difference and you are up for some testing then maybe we can build a version of this library that works with the UDM, the CloudKey and the stand-alone Java version.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nickovs/unificontrol/issues/12#issuecomment-760307578, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEDXBKQ7ZGEQBDU2GWEO4DSZ4LS7ANCNFSM4TP6Y2HQ .

thundergreen commented 3 years ago

Hello i am running in the same issue . i installed this library with pip install git+git://github.com/avleen/unificontrol.git@0c9fcfaa19fe9671e12ac68de054f1e4b47d8e31 but still getting same error :(

avleen commented 3 years ago

Hello i am running in the same issue . i installed this library with pip install git+git://github.com/avleen/unificontrol.git@0c9fcfaa19fe9671e12ac68de054f1e4b47d8e31 but still getting same error :(

What device and firmware version do you have @thundergreen ?

5bomen commented 3 years ago

I am running a UDM Pro with firmware 1.8.5 - and willing to test. Though my python skills are very limited. The UDM Pro hosts multiple functions. Apart from the Network Controller there is also Protect, Access and Talk. Which is why the Network API endpoints are at /proxy/network/api/s and the authentication endpoints at /api/auth.

SinisterStairs commented 3 years ago

FYI, I'm also getting the same error with a UDM Base. The Network Controller is 6.0.43, UDM firmware is 1.8.5.

I"m not sure if this helps you detect UDM*, but uname -a (from the UniFi OS shell) gives me: Linux ubnt 4.1.37-v1.8.5.2964-30c04be #1 SMP Tue Dec 29 05:40:16 MST 2020 aarch64 GNU/Linux

Quite a few defaults seem to be different: I believe hostname is always unifi (and default domain is .localdomain), default port is 443, default administrator is root.

The root web application (https://unifi) lets you choose between the Network Controller (URI /network), or managing the UDM itself (/settings).

The latest API, via curl, is here: https://dl.ui.com/unifi/6.0.45-564eef1dda/unifi_sh_api

nickovs commented 3 years ago

It would be helpful if someone (or even several people) with UDMs, CloudKeys and locally installed Java controllers could run:

import requests
print(requests.get("https://<unifi IP address>:8443/status", verify=False).text)
print(requests.get("https://<unifi IP address>:443/status", verify=False).text)

and send me the output.

To save clogging this discussion up, maybe paste the output into a Gist and just post the link here. I'm guessing that this might be enough to let me auto-detect what sort of controller the client is trying to talk to.

avleen commented 3 years ago

Hey Nicko,

At least on the 1.8.5 firmware on the UDM (non-pro), that URL doesn't work any more:

  1. Port 8443 isn't used any more
  2. /status isn't a valid URL any more, it returns this: https://gist.github.com/avleen/b57408d4da00751baa2b6c6ef1e373f0

On Mon, Jan 25, 2021 at 10:28 PM Nicko van Someren notifications@github.com wrote:

It would be helpful if someone (or even several people) with UDMs, CloudKeys and locally installed Java controllers could run:

import requestsprint(requests.get("https://:8443/status", verify=False).text)print(requests.get("https://:443/status", verify=False).text)

and send me the output.

To save clogging this discussion up, maybe paste the output into a Gist https://gist.github.com and just post the link here. I'm guessing that this might be enough to let me auto-detect what sort of controller the client is trying to talk to.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nickovs/unificontrol/issues/12#issuecomment-767154850, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEDXBPZGZOKTJFDE6YCGKLS3XV7HANCNFSM4TP6Y2HQ .

nickovs commented 3 years ago

Can you try https://<unifi IP address>:443/proxy/network/status?

avleen commented 3 years ago

Unauthenticated this doesn't work. Authenticated I get back:


{"meta":{"rc":"ok","uuid":"<uuid_stripped>"},"data":[]}

On Mon, Jan 25, 2021 at 10:50 PM Nicko van Someren notifications@github.com wrote:

Can you try https://:443/proxy/network/status?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/nickovs/unificontrol/issues/12#issuecomment-767163159, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEDXBJGPVOQSCMU7TW7HYLS3XYUBANCNFSM4TP6Y2HQ .

nickovs commented 3 years ago

Thanks. When you say "doesn't work", do you get a 401 result? If so, do you get something akin to:

{"meta":{"rc":"error","msg":"api.err.LoginRequired"},"data":[]}

in the body that is returned. Thanks.

SinisterStairs commented 3 years ago

Yes, unauthenticated, the UDM's /proxy/network/status endpoint returns a 401. Response body is simply Unauthorized.

As verification of the response body, the response header contains:

Content-Length: 12
Content-Type:  text/plain; charset=utf-8

...so, not JSON with useful information, just plain text.

nickovs commented 3 years ago

@SinisterStairs Thanks for that, although it's not what I had hoped. What do you get if you try https://<unifi IP address>:443/api/auth/login or https://<unifi IP address>:443/api/auth/login?username=xxxx&password=xxxx ? Do you get a similarly unhelpful response body or do you get JSON with error details?

SinisterStairs commented 3 years ago

Interestingly enough, I typo'd the auth login URL (I used /auth/login instead of /api/auth/login, and got a 200 using basic authentication (response text/html). I get hung up trying to pass in the username/password as query strings to /auth/login.

Using /api/auth/login gives me a JSON 401 when using basic authentication, and hangs trying to pass authentication via query strings. EDIT: This was user error, with how I constructed my curl command.

UPDATE: Need sleep, getting sloppy. I lost of track when I used GET or POST, and when I used basic authentication or query strings. By "hung up" I mean no immediate response to curl, and I hit ctrl-c before timing out.

nickovs commented 3 years ago

I have pushed a branch which hopefully will allow support for the Dream Machine as well as the "classic" controller. It's available in the udm-support branch. There is a new server_type argument to the client constructor; if you pass unificontrol.UNIFI_SERVER_UDM then hopefully it should work with the UDM; it defaults to support the classic controller so as not to break existing code.

It would be a big help if some of you could give this a try and tell me if it works. I don't have a UDM so it's basically based on the code @avleen posted. If I manage to lay my hands on a UDM I'll also try to write some reliable auto-detection code but for the moment you'll need to tell it which you're using.

SinisterStairs commented 3 years ago

Thanks so much. I'm getting a unificontrol.exception.UnifiTransportError: 404: Not Found due to invalid credentials.

I tried my UDM's local account, my Unifi Cloud account, and the root SSH password. https://gist.github.com/SinisterStairs/ab2ebbc208b5bcf34f15a3872811467a

EDIT: Will play around some more in a bit; just wanted to provide some quick feedback. EDIT2: With curl I get a 405 using /api/auth/login and 200 using /auth/login. Changing unifi.py to use /auth/login didn't make a difference, however. WIth curl, I'm passing in username and password through basic authentication, not as query string parameters. EDIT3: This was errors with my curl command.

nickovs commented 3 years ago

@SinisterStairs Thanks for trying it out. In the mean time I will see if I can find access to a UDM myself.

SinisterStairs commented 3 years ago

I tried to create a read-only user for you on my NC that could call the API w/o editing; but I don't think that's possible. If you're unable to find access to a UDM, maybe we could do a screen share sometime (e.g. Zoom). I'm on US Eastern time.

EDIT: I also wanted to thank you for your persistence, supporting a device you don't even own!

nickovs commented 3 years ago

@SinisterStairs Can you try running the following code before you import unificontrol or attempt to connect to your controller and post what log output you get?

import logging
logging.basicConfig(level=logging.DEBUG)
SinisterStairs commented 3 years ago

I edited both the gist's code and comment with the latest. https://gist.github.com/SinisterStairs/939d6a33521aed0e4e6ab36239e584f7

EDIT: To update my previous comments: Authenticating with /api/auth/login is working via curl; previous errors I reported were due to how I constructed the curl command or invoked the endpoint. My functioning curl command is in the comments within the gist above.

nickovs commented 3 years ago

Thanks for the debug output. Can you try adding a call to client.login() before your call to list_clients()? Since the client uses a pooled HTTP/1.1 connection it's possible that the Unifi proxy somehow marks connection as having failed after the first 401 error thus doesn't accept the login retry.

SinisterStairs commented 3 years ago

I updated the gist with the code including client.login(), and added the output as a new comment. https://gist.github.com/SinisterStairs/939d6a33521aed0e4e6ab36239e584f7

nickovs commented 3 years ago

Thanks. It looks like there are several issues here:

  1. There seems to be some redirection going on (the code tried to request /api/auth/login but the debug message suggests that it got a 200 reply from /auth/login).
  2. It seems that the reply from a successful login on the UDM is in a different format to the reply from all the other API calls
  3. It looks like the proxy might return 404 on all subsequent requests if the first request on an HTTP/1.1 connection returns a 401 error.

The login and logout methods have always been a little anomalous compared to all of the other calls so I think that I will just need to have special case code to deal with these quirks. I will see what I can do.

SinisterStairs commented 3 years ago

FWIW, using curl to /api/auth/login and /auth/login give me different responses. The /api endpoint gives me the JSON already in the gist, while the /auth endpoint gives me HTML. I'll update the gist with the latter.

nickovs commented 3 years ago

Did you edit the code at all before running the tests? Your last comment on the gist has a debug entry saying that it's sending POST /auth/login HTTP/1.1 but the source code in my latest branch says /api/auth/login.

SinisterStairs commented 3 years ago

Good catch...at some point I edited unifi.py to see if it made any difference to try /api/auth/login vs /auth/login. I'll revert and re-run everything again.

EDIT: Gist Revision 2 results updated in the gist (and invalid one deleted).

nickovs commented 3 years ago

Great. So that deals with issue (1) in my comment above. Issue (3) is a fairly easy fix. This still leaves the fact that the result returned by the UDM's authentication is different. It would be helpful if you could re-try the CURL authentication request and send me the complete JSON output (or at least all the keys, feel free to redact the values where it looks like private information). I can then try to write a new login() method that supports both old and new styles.

SinisterStairs commented 3 years ago

EDIT: I deleted the old curl results from the comments, then added up-to-date ones as comments. https://gist.github.com/SinisterStairs/939d6a33521aed0e4e6ab36239e584f7

Also note, I am using my local NC account to authenticate (both python and curl), not Unifi Cloud account.

nickovs commented 3 years ago

OK. I've pushed some fixes that might work for you. Please give them a try when you can.

SinisterStairs commented 3 years ago

Cheers! I raise my glass to you:

jMacPro15:~/src$ ./test.py 
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): unifi.local:443
DEBUG:urllib3.connectionpool:https://unifi.local:443 "POST /api/auth/login HTTP/1.1" 200 4836
DEBUG:urllib3.connectionpool:https://unifi.local:443 "GET /proxy/network/api/s/default/stat/sta HTTP/1.1" 200 None
[{'site_id': 'SUID', 'assoc_time': 1612175493, 'latest_assoc_time': 1612211103, 'oui': 'Espressi', 'user_id': 'UUID', '_id': 'UID', 'mac': '00:00:00:FF:00:FF', ...

(The JSON was simply produced by print(str(clients)), which is why there's a leading bracket. FYI, I left the client.login() line still in the script, as shown in the gist's rev 2.)

nickovs commented 3 years ago

Excellent! I'm glad you got it going.

When you have a moment if you could test a few bits it would be a big help so that I can clean this up and push a new version.

  1. Can you please confirm if the auto-login works (i.e. calling an API call without first calling client.login())?
  2. Please can you try the client.stat_status() call? It has a different, non-API path on the classic controller so I've no idea if the path is going to be the same on the UDM.
  3. If you check that client.logout() works too then that would be good.

I'll then fix up the documentation and push a new master branch and PyPI package.

SinisterStairs commented 3 years ago
  1. Failed, with client.login() commented out https://gist.github.com/SinisterStairs/939d6a33521aed0e4e6ab36239e584f7#gistcomment-3616078
  2. Failed, trying client.stat_status(). If I get time, I'll try and see if /api/status, or some derivative, works https://gist.github.com/SinisterStairs/939d6a33521aed0e4e6ab36239e584f7#gistcomment-3616086
  3. Failed, trying client.logout(). 405 Method Not Allowed, so it probably needs to be a POST instead of GET https://gist.github.com/SinisterStairs/939d6a33521aed0e4e6ab36239e584f7#gistcomment-3616093
nickovs commented 3 years ago

Thanks. I thought those might fail! I think that I'm going to need to lay my hands on a UDM in order to debug this properly.

If you're willing to take a peek under the hood, one thing you can do is fire up the Developer Mode on your web browser and look at the network resources that are accessed. In there you should be able see if there is a "status" path that gets accessed and spot what method gets used on the login and logout calls.

SinisterStairs commented 3 years ago

Interesting, logout is indeed POST https://unifi.local/api/auth/logout:

Request Header ``` POST /api/auth/logout HTTP/1.1 Host: unifi User-Agent: [UA] Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://unifi/network/site/default/v2/settings/wifi x-csrf-token: [TOKEN] Origin: https://unifi DNT: 1 Connection: keep-alive Cookie: _delighted_web={[URL_ENCODED_HASH]:{%22_delighted_fst%22:{%22t%22:%22[TIME_MS]%22}}}; _ga=GA1.1.[DONT.KNOW]; TOKEN=[LONG HASH, SESSIONID?] Pragma: no-cache Cache-Control: no-cache Content-Length: 0 ```
Response Header ``` HTTP/1.1 200 OK Vary: Origin Access-Control-Allow-Origin: https://unifi X-DNS-Prefetch-Control: off X-Frame-Options: SAMEORIGIN Strict-Transport-Security: max-age=15552000; includeSubDomains X-Download-Options: noopen X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Accept-Ranges: bytes Content-Type: application/json; charset=utf-8 Content-Length: 21 X-Response-Time: 5ms Set-Cookie: TOKEN=[TOKEN]; path=/; secure; httponly Date: Tue, 02 Feb 2021 04:19:26 GMT Connection: keep-alive ```
Response Body (application/json) ```json {"success":true} ```
SinisterStairs commented 3 years ago

Logging into Unifi OS (https://unifi):

Login screen Screen Shot 2021-02-01 at 23 36 37 PM
XHR & websockets after submitting login ![Screen Shot 2021-02-01 at 23 30 49 PM](https://user-images.githubusercontent.com/1282348/106552747-e0fe9080-64e5-11eb-8034-0800b92bcc71.png)
Screen after logging in; I don't know what this is called Screen Shot 2021-02-01 at 23 40 14 PM

Clicking on Network goes to the the Network Controller, Settings goes to UDM's UniFi Settings.

nickovs commented 3 years ago

In order to sort this out I bought one of the stand-alone Dream Machine units and, after upgrading to the version 6 controller, I can now test this myself. As a result I have pushed a new version of code to the udm-support branch. This properly supports the automatic login, so as long as you pass server_type=UnifiServerType.UDM to the client constructor you should just be able to point it at the server and go.

Having said that, it appears that there are quite a few API endpoints that are very different in the new version of the controller. It's possible that I'll need to split out support for the UDM into a new client class so I've not merged this branch onto the master yet. If people with UDMs feel like testing various API calls and reporting their success or failure it would be a big help.

stevehoek commented 3 years ago

Hi... following this issue. I've been playing around with the udm-support branch and using Sinister's test script have been able to login and get client info.

Am happy to help you debug more of the library so that you can release the UDM support to master. Not super experienced with Python, but am with many other languages.

nickovs commented 3 years ago

@stevehoek Many thanks for the offer of help. At this stage what I need most is for people to (a) test all the various calls that are there at the moment to see if they work correctly on the UDM and (b) identify any functionality in the newest UDM console that is not currently covered by the unificontrol client.

stevehoek commented 3 years ago

@nickovs perfect, I will do that. Similar to what Sinister noted, the client.logout is not working even though your latest udm-support branch seems to be doing a POST /api/auth/logout

Here is what I get from my app I'm trying to integration your library in:

File "./pialert.py", line 513, in query_unifi_api unifi.logout() File "/home/pi/pialert/back/src/unificontrol/unificontrol/metaprogram.py", line 157, in wrapper return instance(client, *a, **kw) File "/home/pi/pialert/back/src/unificontrol/unificontrol/metaprogram.py", line 130, in call reply_format=self._reply_format) File "/home/pi/pialert/back/src/unificontrol/unificontrol/unifi.py", line 129, in _execute raise UnifiTransportError("{}: {}".format(resp.status_code, resp.reason)) unificontrol.exceptions.UnifiTransportError: 404: Not Found

mjhcdk commented 3 years ago

sorry to ask - but how to clone the udm-branch version from GitHub

nickovs commented 3 years ago

Hi @mjhcdk. Actually that's a perfectly reasonable question.

If you just want to install the test branch directly into a Python environment (regular or virtual) then you can run:

pip install git+https://github.com/nickovs/unificontrol.git@udm-support#egg=unificontrol

If you want to play with the source code as well then you should do something like:

git clone https://github.com/nickovs/unificontrol.git
cd unificontrol
git checkout udm-support
pip install --editable .

If you've previously installed the package and you now want to switch to using a local, editable copy you might need to change that last line to read:

pip install --force-reinstall --editable .
mjhcdk commented 3 years ago

Thanks for clarification. At least for time being I will just go with install option.
However, at this time not sure what is causing the failure when running script...

EDIT: Tried with another function , and now I get successful feedback - Great

router = UnifiClient(host = "10.0.1.1", port = "443", username = UNIFI_USERNAME, password = UNIFI_PASSWORD,site='default',server_type=UnifiServerType.UDM)
clients = router.list_clients()
print (clients)

DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): 10.0.1.1:443
DEBUG:urllib3.connectionpool:https://10.0.1.1:443 "GET /proxy/network/api/s/default/stat/sta HTTP/1.1" 401 12
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): 10.0.1.1:443
DEBUG:urllib3.connectionpool:https://10.0.1.1:443 "POST /api/auth/login HTTP/1.1" 200 1451
DEBUG:urllib3.connectionpool:https://10.0.1.1:443 "GET /proxy/network/api/s/default/stat/sta HTTP/1.1" 200 None
[{'site_id': '5e53b368f5399c04f8bb2ef1', 'assoc_time': 1612162028, 'latest_assoc_time': 1612663336, 'oui': 'Sonos', 'user_id': '5e53b8ddf5399c0538275953', '_id': '5e53b8ddf5399c0538275953', 'mac': '00:0e:58:f4:d0:fa', 'is_guest': False, 'first_seen': 1582545117, 'last_s

Original.


# Unifi.py 
import sys
from unificontrol               import UnifiClient
from unificontrol.constants     import UnifiServerType
import requests
import json
import re
import logging
logging.basicConfig(level=logging.DEBUG)
UNIFI_USERNAME="xxx"
UNIFI_PASSWORD="xxx"

router = UnifiClient(host = "10.0.1.1", port = "443", username = UNIFI_USERNAME, password = UNIFI_PASSWORD,site='default',server_type=UnifiServerType.UDM)
guests = router.list_guests(within=24)
print (guests)
## end
Michaels-Mac:~ michael$ python3 unifi.py 
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): 10.0.1.1:443
DEBUG:urllib3.connectionpool:https://10.0.1.1:443 "POST /proxy/network/api/s/default/stat/guest HTTP/1.1" 401 12
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): 10.0.1.1:443
DEBUG:urllib3.connectionpool:https://10.0.1.1:443 "POST /api/auth/login HTTP/1.1" 200 1451
DEBUG:urllib3.connectionpool:https://10.0.1.1:443 "POST /proxy/network/api/s/default/stat/guest HTTP/1.1" 404 9
Traceback (most recent call last):
  File "/Users/michael/unifi.py", line 17, in <module>
    guests = router.list_guests(within=24)
  File "/usr/local/lib/python3.9/site-packages/unificontrol/metaprogram.py", line 157, in wrapper
    return instance(client, *a, **kw)
  File "/usr/local/lib/python3.9/site-packages/unificontrol/metaprogram.py", line 128, in __call__
    return client._execute(url, method, rest_dict,
  File "/usr/local/lib/python3.9/site-packages/unificontrol/unifi.py", line 129, in _execute
    raise UnifiTransportError("{}: {}".format(resp.status_code, resp.reason))
unificontrol.exceptions.UnifiTransportError: 404: Not Found
Michaels-Mac:~ michael$ 
nickovs commented 3 years ago

Thanks for the update. Finding these differences is exactly why I need people to test this!