python-kasa / python-kasa

🏠🤖 Python API for TP-Link smarthome products
https://python-kasa.readthedocs.io/en/stable/
Other
1.2k stars 194 forks source link

Issue printing device in on_discovered: pydantic.error_wrappers.ValidationError: 3 validation errors for SmartBulbPreset #439

Closed jimboca closed 1 year ago

jimboca commented 1 year ago

My code is printing a device in the method called by on_discovered: await Discover.discover(target=broadcast_address,on_discovered=self.discover_new_add_device)

Which fails with:

Traceback (most recent call last):
  File "/var/polyglot/pg3/ns/000db952c414_2/nodes/Controller.py", line 157, in discover_new_add_device
    LOGGER.debug(f'enter: mac={smac} dev={dev}')
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartdevice.py", line 706, in __repr__
    return f"<{self._device_type} model {self.model} at {self.host} ({self.alias}), is_on: {self.is_on} - dev specific: {self.state_information}>"
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartdevice.py", line 88, in wrapped
    return f(*args, **kwargs)
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartlightstrip.py", line 82, in state_information
    info = super().state_information
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartdevice.py", line 88, in wrapped
    return f(*args, **kwargs)
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartbulb.py", line 468, in state_information
    info["Presets"] = self.presets
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartdevice.py", line 88, in wrapped
    return f(*args, **kwargs)
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartbulb.py", line 512, in presets
    return [SmartBulbPreset(**vals) for vals in self.sys_info["preferred_state"]]
  File "/var/polyglot/.local/lib/python3.9/site-packages/kasa/smartbulb.py", line 512, in <listcomp>
    return [SmartBulbPreset(**vals) for vals in self.sys_info["preferred_state"]]
  File "/var/polyglot/.local/lib/python3.9/site-packages/pydantic/main.py", line 342, in __init__
    raise validation_error
pydantic.error_wrappers.ValidationError: 3 validation errors for SmartBulbPreset
hue
  field required (type=value_error.missing)
saturation
  field required (type=value_error.missing)
color_temp
  field required (type=value_error.missing)
rytilahti commented 1 year ago

Could you enable debug logging and retry to see what are the contents for the presets (keyed preferred_state)? The preset parsing was created using my color test bulb and I suppose yours doesn't support colors, so we need to adjust those fields.

Which device is that btw? Would you mind adding a fixture to https://github.com/python-kasa/python-kasa/tree/master/kasa/tests/fixtures as all currently known devices do have those fields? You can find the dump_devinfo.py script inside devtools directory that will create the file.

jimboca commented 1 year ago

I will do that tonight when I am back home.

jimboca commented 1 year ago

I've not been able to get debug info out, will look into that more, but this is one of the devices causing an issue: dev=<DeviceType.Plug model HS100(US) at 192.168.86.11 (Home Development Env HS100), is_on: True - dev specific: {'LED state': True, 'On since': datetime.datetime(2023, 3, 15, 4, 37, 52)}> Never mind, still looking...

jimboca commented 1 year ago

I'm trying to run pytest on the device but it doesn't work as documented?


(python-kasa-py3.9) [admin@polisy-dev ~/dev/pg3/python-kasa]$ pytest --ip  192.168.86.177
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --ip
  inifile: /usr/home/admin/dev/pg3/python-kasa/pyproject.toml
  rootdir: /usr/home/admin/dev/pg3/python-kasa
``
I've never used poetry before so probably something I did wrong?
rytilahti commented 1 year ago

Could you please try the dump_devinfo.py script I mentioned in my previous comment? That will perform some queries on the device and create a JSON file containing the responses (sensitive information is redacted from the output).

I haven't run the test suite against a real device for a while, as it's not usually that useful, but pytest kasa --ip=192.168.86.177 should run the tests against the a device. Running those tests against a real device is not recommended though, as they will perform state changes on the device (turning off and on, changing their settings, etc).

But there's something odd going on, as a HS100 plug as shown by your output should not really try to access bulb-specific presets... I don't currently have any bulbs but the on_discovered seems to be working fine on other devices:

import asyncio
from kasa import Discover

broadcast_address = "xx.xx.xx.255"

async def discovered(dev):
    print(f"discovered {dev}")

async def main():
    await Discover.discover(target=broadcast_address, on_discovered=discovered)

if __name__ == "__main__":
    asyncio.run(main())
discovered <DeviceType.Plug model KP115(EU) at xx.xx.xx.xx (TP-LINK_Smart Plug_2FBC), is_on: True - dev specific: {'LED state': False, 'On since': datetime.datetime(2023, 3, 3, 14, 39, 15)}>
discovered <DeviceType.Plug model HS110(EU) at xx.xx.xx.xx (Bedroom), is_on: True - dev specific: {'LED state': False, 'On since': datetime.datetime(2023, 3, 3, 14, 49, 15)}>
discovered <DeviceType.Strip model KP303(UK) at xx.xx.xx.xx (kp303), is_on: False - dev specific: {'LED state': False, 'Childs count': 0, 'On since': None}>
discovered <DeviceType.Plug model KP115(EU) at xx.xx.xx.xx (livingroom), is_on: True - dev specific: {'LED state': False, 'On since': datetime.datetime(2023, 3, 3, 14, 40, 44)}>
discovered <DeviceType.Plug model HS110(EU) at xx.xx.xx.xx (new alias), is_on: False - dev specific: {'LED state': False, 'On since': None}>
jimboca commented 1 year ago

Looks like it's an issue with my KL430, I'll add the device info file, but here's the log:

Testing Call(module='system', method='get_sysinfo')..OK
Testing Call(module='emeter', method='get_realtime')..FAIL module not support
Testing Call(module='smartlife.iot.dimmer', method='get_dimmer_parameters')..FAIL module not support
Testing Call(module='smartlife.iot.common.emeter', method='get_realtime')..OK
Testing Call(module='smartlife.iot.smartbulb.lightingservice', method='get_light_state')..FAIL module not support
Testing Call(module='smartlife.iot.LAS', method='get_config')..FAIL module not support
Testing Call(module='smartlife.iot.PIR', method='get_config')..FAIL module not support
Got 2 successes
## device info file ##
jimboca commented 1 year ago

Hi @rytilahti are you able to debug & fix with my PR #441 ?

rytilahti commented 1 year ago

Hey @jimboca, that helps indeed! Looks like the presets that activate an effect have different contents. I just updated the PR accordingly, feel free to test and report back if you wish :-)

jimboca commented 1 year ago

I'm running with your change, no errors seen, will check again tonight to make sure it's all working properly.

rytilahti commented 1 year ago

Great, there should be no issues while reading and I'll add some tests later to make sure the save_preset functionality does not break either.

jimboca commented 1 year ago

No issues after running with it for a couple days now.