Files
Tasmota/tasmota
Benjamin Temple 2418be974f TuyaMCU: pace outgoing frames so the MCU is never written to back-to-back (#25151)
\#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.
2026-10-22 10:40:08 +02:00
..
2026-10-11 13:16:55 +02:00
2026-10-16 11:41:14 +02:00
2026-10-11 18:33:11 +02:00