[tuya] Improve handling of battery devices - #20760
Conversation
Signed-off-by: Mike Jagdis <mjagdis@eris-associates.co.uk>
There was a problem hiding this comment.
Pull request overview
Improves the Tuya binding's local TCP handling, primarily to better support battery-powered devices that are only briefly online. The handler now connects more aggressively, delays the initial query, recycles long-lived connections, and detects "dead" connections via a dedicated response-timeout handler. The query/refresh/set APIs of TuyaDevice were simplified so the device builds its all-DP query/control payloads once, and connectionStatus() now carries an initialDelay hint. The DP_QUERY_NOT_SUPPORTED synthetic command is removed in favor of always sending DP_QUERY+CONTROL pairs.
Changes:
- New connection-lifecycle constants/timeouts and a
MaxLifetimeHandlerplus aResponseTimeoutHandlernetty pipeline component; smarter heartbeat behavior for battery devices. TuyaDeviceprecomputes the all-DP query/control/refresh messages, takes the DP id list in the constructor, simplifies set/refresh/requestStatus, and adds initial-refusal reconnect throttling.- Handler-side cleanup:
connectionStatuspropagates an initial delay before requesting status, removes the DP_QUERY-not-supported fallback path, and updates poll scheduling.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| TuyaBindingConstants.java | New/retuned TCP lifetime, response, retry and initial-delay constants. |
| local/TuyaDevice.java | New pipeline handlers, simplified message APIs, reconnect throttling and dispose synchronization. |
| local/CommandType.java | Removes the internal DP_QUERY_NOT_SUPPORTED enum value. |
| local/DeviceStatusListener.java | connectionStatus gains an initialDelay parameter. |
| local/handlers/TuyaDecoder.java | Drops DP_QUERY_NOT_SUPPORTED synthesis; treats data format error like json obj data unvalid and improves JSON-parse logging (contains an operator-precedence bug). |
| local/handlers/TuyaMessageHandler.java | Removes DP_QUERY_NOT_SUPPORTED handling; passes 0 initial delay after session key negotiation. |
| handler/TuyaDeviceHandler.java | Removes setQueryUsesControl fallback, schedules initial query with delay, switches refresh/requestStatus to no-arg variants, passes DP id list to TuyaDevice. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Mike Jagdis <mjagdis@eris-associates.co.uk>
|
As the timings have changed substantially i wonder if we need to test this in different setups before this is merged. |
|
I've tested with protocol 3.3, 3.4 and 3.5 mains and battery devices, including power switches, temp/humidity sensors and door/window sensors. It would be kind of nice to test with a whole load of other things if anyone cares. |
lsiepel
left a comment
There was a problem hiding this comment.
Thansk, LGTM
Thanks, the tests seem good enough for now. It is a well used binding, so if there will be any issue, it surfaces quickly.
* [tuya] Improve handling of battery devices Signed-off-by: Mike Jagdis <mjagdis@eris-associates.co.uk>
* [tuya] Improve handling of battery devices Signed-off-by: Mike Jagdis <mjagdis@eris-associates.co.uk>
* [tuya] Improve handling of battery devices Signed-off-by: Mike Jagdis <mjagdis@eris-associates.co.uk> Signed-off-by: olemr <olemr@olemr.com>
* [tuya] Improve handling of battery devices Signed-off-by: Mike Jagdis <mjagdis@eris-associates.co.uk> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
Battery powered devices only occasionally power up periodically and/or when there is a status change to report. They only stay powered up for a few seconds after their last status change report. So we have a race to connect while they are powered up. Plus we have to connect early enough after they have powered up to catch the initial status because it might change again before we see it (e.g. a contact sensor when a door opens and closes). On top of that some devices appear to initialize their stack in the wrong order and accept TCP connections before the API layer is plugged in leading to "not supported" responses, a situation that doesn't clear without a reconnect. And when the device powers down again it does not close or reset connections, just leaves them hanging.
So... we have to be fairly aggressive about trying to connect - without hammering the device as it's trying to boot up. We have to delay the initial query for some devices. We have to be fairly proactive in figuring out when devices have "gone away".
This also includes a maximum connection lifetime timeout. This isn't really related to battery devices and I don't think it helps with issues I have with some smart plugs. But recycling connections now and again seems a sensible idea and it's simple enough to do.