python-kasa / python-kasa

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

sys_info not None fails assertion #55

Closed lordmundi closed 4 years ago

lordmundi commented 4 years ago

I apologize if this clutters up your issue system, but I couldn't find any better place to ask a question. I'm working under windows and would like to send commands to an HS100 smartplug. I didn't quite see how to install the module under windows (using pip for example), so I just downloaded and put the kasa directory in the same directory as my script and that seems to let the import happen fine.

But, in my code I have:

from kasa import SmartPlug
from pprint import pformat as pf

# Define the connection to the TPLink HS100 smart plug using the kasa module
plug = SmartPlug("192.168.0.99")
#print("Hardware: %s" % pf(plug.hw_info))
#print("Full sysinfo: %s" % pf(plug.get_sysinfo())) # this prints lots of information about the device

print("Alias is", plug.alias)

As soon as I try to do anything with plug, it fails assertion saying:

  File "bla\kasa\smartdevice.py", line 110, in wrapped
    assert self._sys_info is not None

I'm guessing this means the library isn't connecting to the plug. Am I doing anything wrong? Is there anything under windows that might be breaking this?

lordmundi commented 4 years ago

I should also mention that the plug is already provisioned through the Kasa app. Now that it is online though, i've blocked access through the router for it, so it shouldn't be able to get out to the internet (the HS100 I mean). Wanted to mention that in case that has any effect. I can ping the device at the IP though.

rytilahti commented 4 years ago

Hi, no worries about cluttering, I'll modify it to raise a more informative exception instead of just assert failing when not used properly!

The README will be updated as part of #54 to include more examples how to use, but you need to request an update from the device before accessing the information. As this library is using asyncio (see https://realpython.com/async-io-python/), you need to execute all methods in asyncio context.

A simple example (without converting your other code to asyncio) would be:

import asyncio
from kasa import SmartPlug
from pprint import pformat as pf

plug = SmartPlug("192.168.0.99")
asyncio.run(plug.update())
print("Hardware: %s" % pf(plug.hw_info))
print("Full sysinfo: %s" % pf(plug.sys_info))

# turn on the plug
asyncio.run(plug.turn_on())
basnijholt commented 4 years ago

This means that somewhere we are missing the @requires_update decorator because it would have printed the correct warning.

(first indication that having the decorator would work ;)

rytilahti commented 4 years ago

Fair enough! Maybe #51 should then be closed while creating separate PRs for those code cleanups not related to the decorator? Instead of having an assert, we should raise an exception to make it clear if someone tries to use it incorrectly.

The reason why I thought there'd be no need for a decorator is that an update needs to be made no matter which property you are trying to access, making it kind of unnecessary to mark them separately. At the moment there are some methods which are also marked with that decorator even when it's unnecessary, and potentially some properties are missing the mark :-)