Vaskivskyi / asusrouter

API wrapper for communication with ASUSWRT-powered routers using HTTP protocol
Apache License 2.0
51 stars 6 forks source link

AsusData.CLIENTS is not serialiazble when trying to convert to JSON #436

Open jotzet79 opened 7 months ago

jotzet79 commented 7 months ago

Hello @Vaskivskyi, I really like your library, as I want to do some automation with it (specifically switching back 5GHz Channels to DSF >100 if Radar-Detection swaps it with something like 36 / 40 and the like).

However I think I bumped into an error data= loop.run_until_complete(router.async_get_data(AsusData.CLIENTS) if I do the following

json.dumps(data)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/encoder.py", line 200, in encode
    chunks = self.iterencode(o, _one_shot=True)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/encoder.py", line 258, in iterencode
    return _iterencode(o, 0)
           ^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/json/encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type AsusClient is not JSON serializable

Any clues? Did I miss something? Thank you, Joachim

Vaskivskyi commented 7 months ago

Hello,

In order to get json.dumps() to work with custom objects (e.g. classes), you need to provide a default encoder. More details here

data = loop.run_until_complete(router.async_get_data(AsusData.CLIENTS))
print(json.dumps(data, indent=4, default=str))

will result in something like this:

{
    "00:AA:11:BB:22:CC": "AsusClient(state=<ConnectionState.DISCONNECTED: 0>, description=AsusClientDescription(name='XBOX', mac='00:AA:11:BB:22:CC', vendor='MSFT 5.0 XBOX'), connection=AsusClientConnection(type=<ConnectionType.DISCONNECTED: 'disconnected'>, ip_address=None, ip_method=None, internet_state=None, internet_mode=<InternetMode.UNKNOWN: 'unknown'>, node=None, online=False, aimesh=None))"
}

for some random Xbox client as an only member of AsusData.CLIENTS

jotzet79 commented 7 months ago

Hi again,

thanks for the quick reply! But this means that values are not converted like <ConnectionState.DISCONNECTED: 0>, right?

BTW, is there any chance to set the chanspec of a given WLAN (e.g. 5Ghz) programmatically?

Thanks, Joachim

Vaskivskyi commented 7 months ago

json.dumps just returns you a string representation of any object. You would need to work with the original objects and not with JSON data for any useful action

As per the chanspec, it should be possible to control it. Everything that can be done from the Web UI, can be done from the library. The question is only to implement it properly

jotzet79 commented 7 months ago

I was just wondering that other json.dumps operations like data = loop.run_until_complete(router.async_get_data(AsusData.WAN)) succeed, whilst AsusData.CLIENTS does not: That‘s why I asked.

For the second question: Do you have any pointers how to address this, please? Or do you mean, that it would take some time / donation ☕️ to incorporate into your library?

Vaskivskyi commented 7 months ago

Most of the results of async_get_data() are just dictionaries of usual values (strings, numbers) that can be serialized by json by default. That's why you didn't notice this issue before

I would need some time. Still need to finish something else before that, which is in the waiting list for a long time. But in terms of a week or two, this should be possible