\#Description:
TuyaSendCmd() doesn't have any sort of pacing, so two back-to-back
commands can land within milliseconds of eachother.
In my specific devices and likely many other Tuya based devices, this
can cause the MCU to crash. This is compounded by the fact that Tasmota
(unnecessarily) writes the local-time every 60s, and the heartbeat every
11s. So roughly every 660s, they coincide, and then several times a day
the MCU will crash.
The end result is that my lights would randomly turn-off, or in the
case of my 3-way lights, they would even turn on randomly in the middle
of the night.
This patches the Tuya MCU driver to queue outgoing frames and release them from FUNC_LOOP once the following four spacing rules pass:
byte_counter must not be part way through receiving a frame
tx_ack_wait still waiting on a reply, given up after
TUYA_TX_ACK_TIMEOUT_MS
tx_last_ms minimum gap, for commands that don't receive a response
rx_last_ms silence since the last byte in
TUYA_TX_MAX_HOLD_MS limits the ack and quiet wait time.
Behaviour changes for existing users:
- datapoint writes are paced, so a fade or slider drag (might) emit fewer
intermediate values. The queue insertion order is such though that
values are never lost, and this is quite the edge-case.
- a command can be delayed by the minimum gap plus the hold ceiling
- a full queue with nothing collapsible drops its oldest frame
\#Testing:
I wrote a stress test that could crash the MCU at-will by spamming lots
of writes heartbeat writes.
With this applied, the same test does not crash the MCU
I have also been using this for over a month on all of my lights with 0
issues.