Giter Club home page Giter Club logo

tplink-omada-api's People

Contributors

d-j-see avatar fabaff avatar guillempages avatar markgodwin avatar mheath avatar milothomas avatar odouville avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

tplink-omada-api's Issues

Dynamically modify ssl_verify

Running on homeassistant with the omada integration, it appears my existing integration stopped working with an SSL verify error. Looks like home-assistant upgraded a newer version of python.

My fix - Implement a feature for the tplink-omada-api package to allow for dynamic modification of the SSL_verify flag, then allow the user to call that method from homeassistant.

Controller v5.12 new openapi endpoints

In version 5.12 they now have released a more documented API with support for oauth and client tokens.

https://community.tp-link.com/en/business/forum/topic/619304?sortDir=ASC&page=1

Open API: Omada Controller now supports Open API integration. You can access it through Global view > Settings > Platform Integration, which allows you to utilize the REST API of most Controller services. This feature enables you to develop custom applications, embed APIs, or combine your own applications. Refer to the Online API Document for guidance on usage, and view more by toggling the drop-down menu in the upper left corner.

The main difference in the urls is the /openapi/v1 endpoint, and some of the parameters are changes currentPage -> page

There is even API docs now hosted on the controller itself
(however, the page is terribly slow on my oc200, i don't think its powerful enough for whatever they are doing to generate them)

Does this repo have any intention on supporting this new "openapi" they have? I think it would be very useful for applications like home assistant to be able to use the new client tokens instead of username/password.

feature request: write/read dhcp reservations

GM,
it would be great if we could read/write dhcp reservations.
something like

1**. omada dhcp set-reservation** $MAC $IP $NAME [$NETMASK] [$GATEWAY] [$DNS] ...
2. omada dhcp get-reservation $MAC | $IP | $NAME # display all the details on a specific clients reservation based on either NAME, IP, MAC
3. omada dhcp reservations # display a list of the clients reservations main attributes (MAC, IP, NAME)

suggestion populate omada client names from reverse dns

  • first of all thank you for this library it is a huge time saver!
  • I wrote a very basic shell script to leverage your "omada clients" output and "omada set-client-name" to populate hostnames automatically based on reverse dns. H
  • Here is the code if you want to add it to your library or maybe provide it as an add-in for people interested (I also posted to tplink in case they want to add something similar in SDN directly):
#!/usr/bin/bash
HELP="
dns2omada.sh is the most simplistic script ever meant to paliate one of dumbest laziest lack of feature of the tp-link OMADA SDN software....
it simply populate the OMADA client's name based on DNS name... 
using a python omada api...
Assumptions: 
- you already have a local DNS server able to perform reverse DNS resolution per IP.
- you already have omada SDN setup on the network
- you should create an OMADA admin account dedicated to this process using a very long random password string without any special character 
- my subnet is simply from 192.168.0.1 to 192.168.0.256 so I have a simple loop, you might have to modify the script if your subnet is class B 
with an outer loop etc...
usage: 
    1) install python: sudo apt install python3-pip
    2) install the omada python api: pip install tplink-omada-client
    3) update the parameters CHANGE_ME values in the scipt below
    4) run the script manually or in cron... 
"

# these should be self-explanatory
omada_username="CHANGEME_mrpotatoe"
omada_password="CHANGEME_lfdaruiRWGFD335qw324z"
omada_site="CHANGEME_homesweethome"
omada_url="https://CHANGEME_omada.mylocaldomain" 
subnet=CHANGEME_192.168.0
dns_server=CHANGEME_192.168.0.1
omadabin=/CHANGEME/bin/omada   # the absolute path to the omada binarie whch gets installed with the client.




if [[ $# -gt 0 ]]
then
    echo $HELP
    exit 3
fi

if fgrep -v grep $0 | fgrep CHANGEME  >/dev/null
then
    echo "ERROR: you forgot to change these varialbes from $0:"
    fgrep -v grep $0 | fgrep CHANGEME 
    echo "$HELP"
    exit 4
fi
$omadabin -t myomada target --url $omada_url --user $omada_username --password $omada_password --site $omada_site --set-default

omadaclients=/tmp/omadaclients.$$.txt

$omadabin clients  > $omadaclients
clientname=""
let ip4thfield=1
while [[ $ip4thfield -lt 256 ]]
do 
    clientname=""
    clientmac=""
    clientname=$(nslookup ${subnet}.$ip4thfield $dns_server 2>/dev/null | fgrep "=" |cut -f2 -d"=" |cut -f1 -d"."|tail -1)
    if [[ $clientname != "" ]]
    then        
        clientmac=$(fgrep " ${subnet}.$ip4thfield " $omadaclients| cut -f1 -d" "|tail -1)
        if [[ $clientmac != "" ]]
        then
            echo "setting hostname for ${subnet}.$ip4thfield to $clientname for mac $clientmac "        
            $omadabin set-client-name $clientmac $clientname            
        else
            echo "skipping ${subnet}.$ip4thfield  because omada does not see any client MAC for it"
        fi
    else
        echo "skipping ${subnet}.$ip4thfield  because I cant resolve it"
    fi
    let ip4thfield=ip4thfield+1 
done
rm -f $omadaclients

Werid issue with clients endpoint

Hey there

I came across a werid bug trying to get the connected clients.

This is the code i am using

import asyncio

from tplink_omada_client.omadaclient import OmadaClient

async def hello():
    async with OmadaClient(url=URL, username=USERNAME, password=PASSWORD) as client:
        sites = await client.get_sites()
        site = next((s for s in sites if s.name == SITE), None)

        site_client = await client.get_site_client(site)

        connected_clients = site_client.get_connected_clients()

        async for client in connected_clients:
            print(client.name)

asyncio.run(hello())

And this is the traceback

Traceback (most recent call last):
  File "/Users/daniel/tplink-omada-api/run.py", line 42, in <module>
    asyncio.run(hello())
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/Users/daniel/tplink-omada-api/run.py", line 38, in hello
    async for client in connected_clients:
  File "/Users/daniel/tplink-omada-api/venv/lib/python3.11/site-packages/tplink_omada_client/omadasiteclient.py", line 125, in get_connected_clients
    async for client in self._api.iterate_pages(self._api.format_url("clients", self._site_id)):
  File "/Users/daniel/tplink-omada-api/venv/lib/python3.11/site-packages/tplink_omada_client/omadaapiconnection.py", line 158, in iterate_pages
    response = await self.request("get", url, request_params)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/daniel/tplink-omada-api/venv/lib/python3.11/site-packages/tplink_omada_client/omadaapiconnection.py", line 176, in request
    return await self._do_request(method, url, params=params, payload=payload)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/daniel/tplink-omada-api/venv/lib/python3.11/site-packages/tplink_omada_client/omadaapiconnection.py", line 215, in _do_request
    self._check_application_errors(content)
  File "/Users/daniel/tplink-omada-api/venv/lib/python3.11/site-packages/tplink_omada_client/omadaapiconnection.py", line 238, in _check_application_errors
    raise RequestFailed(response["errorCode"], response["msg"])
tplink_omada_client.exceptions.RequestFailed: Omada controller responded 'General error.' (-1)

I used Developer tools in Firefox and saw the web requests to get clients was
/clients?currentPage=1&currentPageSize=10&filters.active=true&_=1700282586424

The only difference I could see between this and firefox the filters.active and _ params. I replayed the request using curl and tested removing the params and when I removed filters.active I got the same error of

{"errorCode":-1,"msg":"General error."}%                                                                                                                                         

I found a solution (although not very clean), adding this in _do_request function before it does the request in OmadaApiConnection class seems to fix it

if "clients" in url:
    params["filters.active"] = "true"

Tag the source

It would be very helpful if you could tag releases as well. This would enable distributions who want to run your tests to fetch the package from GitHub instead of PyPI.

Thanks

suggestion extract VLANs and LAG?

anyway to identify VLANs settings when setup by ports?
(or is this what the Type and Profile refer to?)

example:

Port: 4 - Port4
Type: 1
Profile: All - ☐
Enabled: ☑
Status: ☑
PoE: ☑ 0.0W
Link Speed: SPEED_100_MBPS (Max: SPEED_1_GBPS)
Transmitted: 1.3GB
Received: 95.0MB
Operation: switching
Limit Mode: OFF
Port: 5 - Port5
Type: 1
Profile: All - ☐
Enabled: ☑
Status: ☐
PoE: ☑ 0.0W
Link Speed: SPEED_10_MBPS (Max: SPEED_1_GBPS)
Transmitted: 0.0MB
Received: 0.0MB
Operation: switching
Limit Mode: OFF

Ability to set client name

It would be useful if there was a method to set the name/username for a device. Then we can use either a static list, or arp (!), to push human-readable names into the controller.

KeyError: 'uplinkMac' when calling `OmadaLink.mac`

I just noticed this bug that comes up when running $ omada switch .... The fix is simple. I'll be pushing up a PR shortly. Here's the full stacktrace.

Traceback (most recent call last):
  File "/home/vscode/.local/bin/omada", line 8, in <module>
    sys.exit(main())
  File "/workspaces/tplink-omada-api/src/tplink_omada_client/cli/__init__.py", line 64, in main
    return asyncio.run(args.func(vars(args)))
  File "/usr/local/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "/workspaces/tplink-omada-api/src/tplink_omada_client/cli/command_switch.py", line 33, in command_switch
    print(f"- {downlink.mac} {downlink.name}")
  File "/workspaces/tplink-omada-api/src/tplink_omada_client/devices.py", line 146, in mac
    return self._data.get("mac", self._data["uplinkMac"])
KeyError: 'uplinkMac'

KeyError on OmadaListDevice.need_upgrade and OmadaListDevice.fw_download

(Seen on version 1.2.4)

When retrieving status on devices, I sometimes get the error KeyError: 'needUpgrade' or KeyError: 'fwDownload' (see tracebacks below).
It happens when, for example, the device is disconnected (seen on a spare AP that I keep in a closet).

The following code is used:

    for device in (await site_client.get_devices()):
        print(device.raw_data)
        print(f'Device {device.name}: Firmware downloading: {device.fw_download}')

(same code with need_upgrade instead of fw_download can be used as well)

Traceback for need_upgrade:

Traceback (most recent call last):
  File "C:\Users\***\PycharmProjects\OmadaClient\main.py", line 54, in <module>
    asyncio.run(test_omada())
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Users\***\PycharmProjects\OmadaClient\main.py", line 35, in test_omada
    print(f'Device {device.name}: Need upgrade: {device.need_upgrade}')
                                                 ^^^^^^^^^^^^^^^^^^
  File "C:\Users\***\PycharmProjects\OmadaClient\venv\Lib\site-packages\tplink_omada_client\devices.py", line 112, in need_upgrade
    return self._data["needUpgrade"]
           ~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'needUpgrade'

Traceback for fw_download:

Traceback (most recent call last):
  File "C:\Users\***\PycharmProjects\OmadaClient\main.py", line 54, in <module>
    asyncio.run(test_omada())
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Users\***\PycharmProjects\OmadaClient\main.py", line 35, in test_omada
    print(f'Device {device.name}: Firmware downloading: {device.fw_download}')
                                                 ^^^^^^^^^^^^^^^^^^
  File "C:\Users\***\PycharmProjects\OmadaClient\venv\Lib\site-packages\tplink_omada_client\devices.py", line 112, in fw_download
    return self._data["fwDownload"]
           ~~~~~~~~~~^^^^^^^^^^^^^^
KeyError: 'fwDownload'

issue: omada access-point incompatible with EAP245 ?

just an FYI, that there is an error when trying to execute omada access-point against an older access point EAP245(US) v3.0:
it works find with EAP773(US) v1.0

notes:

  • there are no VLAN configured in this case,
  • the eap245 uses the same site-wide-default configuration as the other access points.
  • other commands seem to work fine with the EAP245...
ff@hal:~/naxdev/logs$ omada access-point wee_wifi
Name: wee_wifi
Address: AA-BB-CC-DD-EE-FF (192.168.0.212)
Status: CONNECTED (CONNECTED)
LAN Ports: 1
Traceback (most recent call last):
  File "/home/ff/.local/bin/omada", line 8, in <module>
    sys.exit(main())
  File "/home/ff/.local/lib/python3.10/site-packages/tplink_omada_client/cli/__init__.py", line 74, in main
    return asyncio.run(args.func(vars(args)))
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/home/ff/.local/lib/python3.10/site-packages/tplink_omada_client/cli/command_access_point.py", line 22, in command_access_point
    print(f"   Port {p.port_name}  PoE Supported: {get_checkbox_char(p.supports_poe)} {get_power_char(p.poe_enable)}  Vlan: {get_checkbox_char(p.supports_vlan and p.local_vlan_enable)} {p.local_vlan_id}")
  File "/home/ff/.local/lib/python3.10/site-packages/tplink_omada_client/devices.py", line 371, in local_vlan_id
    return self._data["localVlanId"]
KeyError: 'localVlanId'

Feature: Rename clients

I'd love to see the wrapper to be able to rename (change the username) of a client device. Right now most of my client names are just MAC addresses which is not useful. Not sure the API supports a rename operation, but if it does, it would be super useful.

Fails with self-signed certs -

I have a Omada controller install with self-signed certs. Connecting both via IP and FQDN fail.

Cannot connect to host omada.xzy.com:8043 ssl:True [SSLCertVerificationError: (1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:997)')]

I'd like to see an override switch to not fail on self-signed cert.

Certificate installation and renewal

As a long time C/C++ programmer I know just enough about Python to be extremely dangerous. In-spite of that handicap, I have gotten the sample_client.py working to list all of my site devices, but I don't see any clues as to how to install or renew a TLS Certificate.

Has that part of the API been coded yet?

minor bug; fix order ssid,device to device,ssid for omada client output for Access point

would it be possible to make the order consistent between switches and access points in the output of the "omada clients"?
the output of omada client seems to be:
for physical switches: MAC, IP, Name, device, port
for AccessPoints: MAC, IP, Name, SSID, device

  1. Could you please fix it such that it is consistent:
    for both: MAC, IP, Name, SSID/Port, device

  2. As a rule of thumb, it might make sense to add a title header row with column names. This would make it easier to identify such issues and force standardization.

  3. make the change backward compatible by versioning formated output and allow users to specific which version of output they want to use. In other words, running "omada clients" or "omada clients --version=1" will keep providing the same format as today. however running "omada clients --version=2" would return the fixed format with the headers row.
    This provides also more flexibility to adapt the library in case tp-link introduces new formats later as well...

Invalid value for OmadaPortStatus.link_status

(Seen on version 1.2.4)

When retrieving port status on my switch, I get the error "ValueError: 1 is not a valid LinkStatus" (see traceback below) on the first port whose link is up (tested on several switches, each raising the error on the first UP link).

The following code is used :

    for port in switch.ports:
        print(f'Port {port.port}: name={port.name}, link={port.port_status.link_status.name}')

Accessing the property port.port_status.link_status without trying to get its name causes the same error.

I'll try to submit a pull request myself (could take some time as this is my first participation on github) as I know how to correct that.
However I am wondering if this is a matter of API version or something else ? Still not sure if modifying the LinkStatus enum is the correct fix to this issue, or if several versions of the Omada API should be managed.
For information, here is my api/info content :

{
   "errorCode":0,
   "msg":"Success.",
   "result":{
      "controllerVer":"5.9.31",
      "apiVer":"3",
      "configured":true,
      "type":1,
      "supportApp":true,
      "omadacId":"***********",
      "registeredRoot":true
   }
}

Traceback :

Traceback (most recent call last):
  File "C:\Users\***\PycharmProjects\OmadaClient\main.py", line 51, in <module>
    asyncio.run(connect_omada())
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\***\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 650, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Users\***\PycharmProjects\OmadaClient\main.py", line 36, in connect_omada
    print(f'Port {port.port}: name={port.name}, link={port.port_status.link_status.name}')
                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\***\PycharmProjects\OmadaClient\venv\Lib\site-packages\tplink_omada_client\devices.py", line 159, in link_status
    return LinkStatus(self._data["linkStatus"])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Olivier\AppData\Local\Programs\Python\Python311\Lib\enum.py", line 695, in __call__
    return cls.__new__(cls, value)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Olivier\AppData\Local\Programs\Python\Python311\Lib\enum.py", line 1111, in __new__
    raise ve_exc
ValueError: 1 is not a valid LinkStatus

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.