TPLinkDeviceManager does not initialise _auth_token unless username and password are provided
The TPLinkDeviceManager class encourages creating it with a username and password, but doing this logs in every time you construct it, which caused me to hit an API rate limit, because I am using TPLinkDeviceManager from a tool that starts and stops frequently.
{
"error_code": -20004,
"msg": "API rate limit exceeded"
}
After reading https://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api/, I realised I could save the token and just pass that to TPLinkDeviceManager instead.
def kasa_login():
device_manager = TPLinkDeviceManager(term_id=CLIENT_TERM_ID)
auth_token = read_token()
if auth_token is not None:
device_manager.set_auth_token(auth_token)
else:
auth_token = device_manager.login(kasa_user, kasa_password)
assert auth_token is not None
write_token(auth_token)
return device_manager
However, this fails because TPLinkDeviceManager does not initialise _auth_token unless username and password are supplied, though it does access it. An abbridged traceback:
File "./tplinkpower2.py", line 43, in kasa_login
device_manager = TPLinkDeviceManager(verbose=False, term_id=CLIENT_TERM_ID)
File "/home/lincolnr/.local/lib/python3.8/site-packages/tplinkcloud/device_manager.py", line 40, in __init__
if prefetch and self._cache_devices and self._auth_token:
AttributeError: 'TPLinkDeviceManager' object has no attribute '_auth_token'
I was able to work around this with a little monkey patching:
from tplinkcloud import TPLinkDeviceManager as TPLinkDeviceManagerBroken
class TPLinkDeviceManager(TPLinkDeviceManagerBroken):
def __init__(self, **kwargs):
self._auth_token = None
return super().__init__(**kwargs)
I am using tplink-cloud-api==3.0.0 (which has the sync API). The issue persists in tplink-cloud-api==4.2.0 (the most recent release, with the async API).