tinytuya icon indicating copy to clipboard operation
tinytuya copied to clipboard

Some device calls stalling app depending on `tinytuya`

Open lmcd opened this issue 11 months ago • 6 comments

Hey,

I'm using tinytuya from a Swift codebase (via PythonKit) to interact with a set of Tuya devices via a native macOS app. Works really well 🎉

However, sometimes the app completely stalls waiting on a network request when a device is no longer discoverable on the network. For example, I'm seeing this in BulbDevice.heartbeat, even with nowait: true. It's not always reproducible, but often I come back to the app after it's been running for a few hours and have switched network, and the main thread is completely stuck inside heartbeat. Sometimes, if I switch back to the Tuya wifi network, the app will spring back to life, presumably because the devices are now discoverable.

Any idea how I can have these methods more gracefully fail if a device is not detected, rather than hanging indefinitely?

lmcd avatar Jan 28 '25 15:01 lmcd

Also, I'm noticing the various timeout parameters when initialising BulbDevice, but could these methods not be designed non-blocking with zero penalty if nowait: true

lmcd avatar Jan 28 '25 15:01 lmcd

Unfortunately there really isn't a good way to make it non-blocking. v3.4 and v3.5 devices require a 3-way handshake before any commands can be sent, and the library just isn't written to be non-blocking. It can be done (I do it for both the scanner and my half-finished multiserver) but it's pretty hack-y.

nowait just tells it to not wait for a reply to a command, making a connection and (for v3.4 and v3.5 devices) the 3-way handshake always block.

The most common way I've seen to reduce the impact of offline devices is to turn off retrying and setting a really low connection timeout with connection_retry_limit=1 and connection_timeout=0.5.

uzlonewolf avatar Jan 29 '25 02:01 uzlonewolf

Got it, thanks for the information!

I might spend some time implementing a simple swift-nio port - as this is specifically designed for any kind of non-blocking use case.

The tinytuya code seems quite straightforward to understand, but is there any protocol documentation floating around that could ease an implementation?

lmcd avatar Jan 29 '25 02:01 lmcd

You mean Tuya's LAN protocol, to re-implement tinytuya or something? I have the packet format and checksums documented in #260.

uzlonewolf avatar Jan 29 '25 03:01 uzlonewolf

I would love to see us move the library to a more elegant non-blocking asyncio friendly approach. Of course, if that were easy, it would have been done by now. :)

jasonacox avatar Jan 29 '25 04:01 jasonacox

I have a really nice Swift proof of concept version of TinyTuya now working 🎉 Fully async with Swift Concurrency. Was able to bootstrap fairly quickly by having Claude Pro help me figure out the protocol/encryption based on tinytuya code.

Doesn't support receiving messages - only sending, no scanning on anything like that, and only supports v3.3 devices without the handshake, but I can't see why all this can't be added fairly trivially.

Will post the repo when it's stable.

lmcd avatar Jan 30 '25 01:01 lmcd