codetheweb / tuyapi

🌧 An easy-to-use API for devices that use Tuya's cloud services. Documentation: https://codetheweb.github.io/tuyapi.
MIT License
2.05k stars 337 forks source link

Device sometimes returns an encrypted payload instead of JSON #32

Closed codetheweb closed 6 years ago

codetheweb commented 6 years ago

Ideally we'd decrypt the payload if it's not JSON, but as a short-term fix we may be able to just wrap get() in a retry.operation().

clach04 commented 6 years ago

See https://github.com/clach04/python-tuya/blob/master/pytuya/__init__.py#L264 for technique that appears to work reliably.

codetheweb commented 6 years ago

That looks like it could work, but isn't there usually stuff after the data payload that your code doesn't remove?

clach04 commented 6 years ago

I've not seen any packets like that and there haven't been any user reports yet.... doesn't mean there won't be some though :-)

There are at least two Home Assistant users so they would have reported if they had seen a packet like that. HA will hammer away on devices for status updates a few times every minute. Most users are switch users (and maybe a bulb user) so it may depend on the device?

That being said, my current code could benefit from adding some protection code to dump out packets under error conditions for postmortem debugging - I'm not sure I'm going to get around to that though :(

clach04 commented 6 years ago

Forgot to add, that code is about 4 months old - so its been out in the wild for a while. https://github.com/clach04/python-tuya/commit/8d70404fb38cf2144c60329678b8f6bb84a8720d

codetheweb commented 6 years ago

Do you happen to have any examples of encrypted data packets being returned (when setting the status)? My device returns packets like this: 000055aa00000000000000080000008b00000000332e3164316439613931613733356239373937594b69334b424c686f2b452b5958546d7550594b6e536974354c6f4741334d6746594e6169434174687330366c68334135494c555375344541627848585342506f79302b314d6a5a6c54475279304f796f44325a647677706e54544c3237773064526d774a7a5a334f7a6b3dd72badbe0000aa55

EDIT: Github won't correctly format the bytes that have no ASCII representation, you'll have to go here to convert the above hex string.

clach04 commented 6 years ago

@codetheweb that looks exactly like what I had to handle. I do not have an example payload, that's the point I was trying to make above about adding logging on error for postmortem, its also a weakness in the test suite I have sigh.

I recall setting timers and then hammering the device to induce this . If I had a log I'd email it privately as one could in theory derive the key ;) - but I don't (not near a device at the moment). I did post a tool somewhere for decrypting arbitrary packets let me see where I posted that....

clach04 commented 6 years ago

decrypting arbitrary packets posted to https://github.com/codetheweb/tuyapi/issues/5#issuecomment-348803506 - not used this in ages as not seen any packets I couldn't parse.

codetheweb commented 6 years ago

Oh, my bad; I didn't see line 233 🙄. I couldn't figure out how you managed to successfully decrypt the above payload without remove the prefix and suffix. Never mind.

BillSobel commented 6 years ago

@clach04 FYI on at least my test plug devices pressing the physical button on them to change their state results in.an encrypted message. The content is the same as a normal status response but also includes a time stamp and one other field that isn’t needed. So status poll non encrypted, user actions are. Also I found at startup the devices will send one packets stating the json object is invalid (including a cute misspelling of unvalid) on the second status poll this goes away. Only found it unplugging/replugging devices to test my reconnection code.

codetheweb commented 6 years ago

Fixed in 2fb33c0e5939547c152e280b71e6b5d66672ec45.