Some device calls stalling app depending on `tinytuya`
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?
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
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.
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?
You mean Tuya's LAN protocol, to re-implement tinytuya or something? I have the packet format and checksums documented in #260.
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. :)
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.