homebridge-tuya-plus 3.14.0-dev.19 → 3.14.0-dev.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +4 -3
- package/Readme.MD +4 -6
- package/config.schema.json +4 -13
- package/index.js +349 -359
- package/lib/IrrigationSystemAccessory.js +12 -23
- package/lib/SimpleGarageDoorAccessory.js +49 -8
- package/lib/TuyaCloudApi.js +21 -0
- package/lib/TuyaCloudDevice.js +86 -15
- package/lib/TuyaDevice.js +266 -0
- package/package.json +2 -2
- package/test/IrrigationSystemAccessory.test.js +44 -49
- package/test/SimpleGarageDoorAccessory.test.js +59 -7
- package/test/TuyaCloudApi.test.js +17 -0
- package/test/TuyaCloudDevice.test.js +49 -0
- package/test/TuyaDevice.test.js +252 -0
- package/test/index.test.js +141 -0
- package/wiki/Supported-Device-Types.md +5 -4
- package/wiki/Tuya-Cloud-Setup.md +15 -29
package/Changelog.md
CHANGED
|
@@ -4,11 +4,12 @@ All notable changes to this project will be documented in this file. This projec
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
-
* [+] **Tuya Cloud
|
|
7
|
+
* [+] **Tuya Cloud is now a transparent, global fallback for every device.** What started as an experiment to reach battery-powered "sleepy" irrigation timers (which never appear on the LAN) is now a general, optional fallback: add a top-level `cloud` credentials block once and the plugin keeps a single Tuya Cloud/MQTT session alive in the background, falling back to it whenever a device can't be reached on the LAN — a flaky moment, or hardware that's never local. The plugin stays **LAN-first** (local is always tried first and preferred) and cloud remains **strictly opt-in** (nothing runs unless credentials are present).
|
|
8
|
+
* **No per-device configuration.** There is one global session and no per-device cloud settings. Every device automatically uses the LAN first and the cloud as a fallback; a device with no local `key` is reached over the cloud only. Existing LAN configs (numeric data-points) keep working over the cloud — the data-point id↔code map is learned from Tuya's device shadow (`/v2.0/cloud/thing/{id}/shadow/properties`) — and if both transports fail, HomeKit shows "No Response" as before. This mirrors the official Tuya/Smart Life app (LAN when possible, cloud as a backup).
|
|
8
9
|
* Realtime updates arrive over Tuya's **MQTT** message service (via the optional `mqtt` dependency, installed automatically); initial state and control use the Tuya OpenAPI. There is no polling.
|
|
9
10
|
* Works with both **Custom** and **Smart Home** Cloud projects (the latter via app-account login).
|
|
10
|
-
* The
|
|
11
|
-
* See the wiki: **[Tuya Cloud Setup](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Tuya-Cloud-Setup.md)**.
|
|
11
|
+
* The **IrrigationSystem** accessory no longer has any cloud-specific handling — like every other accessory it's transport-agnostic, with the LAN+cloud fallback handled underneath.
|
|
12
|
+
* If your devices sometimes drop off the LAN and show "No Response", adding cloud credentials is an easy way to smooth that over. See the wiki: **[Tuya Cloud Setup](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Tuya-Cloud-Setup.md)**.
|
|
12
13
|
* [*] **Fix realtime (MQTT) cloud updates being silently dropped** — external changes (physical buttons, the Tuya app, the device's own timers) now show up in HomeKit within a second or two. The decryptor was verifying the AES-GCM auth tag (`decipher.final()`), but Tuya's real status frames don't carry a tag that verifies against the documented AAD, so every realtime message was being thrown away. Now decrypts with `update()` only, matching the official `tuya/tuya-homebridge` and `0x5e/homebridge-tuya-platform` implementations.
|
|
13
14
|
* [*] **Fix cloud irrigation valves that could be turned on but not off** — the per-zone write coalescer was dropping any command that matched the last-known `device.state`. Cloud devices never optimistically advance `state` (it only moves once the realtime stream confirms the device), so an "off" issued before the "on" was echoed matched the stale "off" and was discarded — HomeKit showed the zone closed while it kept running. Queued commands are now sent as-is (callers already queue only genuine changes).
|
|
14
15
|
* [*] **IrrigationSystem: remove the rain sensor.** It never reported reliably on these devices, and bundling a sensor (a different HomeKit category) in the same accessory forced the Home app to fragment the sprinkler into "sub-accessories" — blocking control from the main tile and hiding the system master on/off. The accessory is now a single, clean sprinkler tile (IrrigationSystem + valves + optional battery); any leftover Contact/Leak sensor service from a previous build is removed automatically on restart. The `noRainSensor`, `rainSensorType`, `rainInverted`, `dpRain` and `rainOnValue` options are gone.
|
package/Readme.MD
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
A community-maintained Homebridge plugin for controlling Tuya devices locally over LAN. Control your supported Tuya accessories locally in HomeKit.
|
|
17
|
+
A community-maintained Homebridge plugin for controlling Tuya devices locally over LAN. Control your supported Tuya accessories locally in HomeKit, with an optional Tuya Cloud fallback for devices the LAN can't reach.
|
|
18
18
|
|
|
19
19
|
* [Supported Device Types](#supported-device-types)
|
|
20
20
|
* [Supported Tuya Protocol Versions](#supported-tuya-protocol-versions)
|
|
@@ -69,13 +69,11 @@ Protocol **3.5** is currently the newest Tuya LAN protocol in existence: it is t
|
|
|
69
69
|
|
|
70
70
|
This plugin is nevertheless **3.6-ready**: if a device reports a newer protocol version (e.g. `3.6`) in its broadcast, the plugin automatically talks to it using the newest (3.5/GCM) protocol stack while tagging payloads with the device's reported version — the same forward-compatibility strategy used by tinytuya. Should such a device misbehave, you can pin it to a specific protocol with the `forceVersion` device option (e.g. `"forceVersion": "3.5"`), or use `version` to set a protocol for devices that can't be discovered (e.g. on another subnet).
|
|
71
71
|
|
|
72
|
-
## Cloud
|
|
72
|
+
## Cloud fallback (optional)
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
The plugin is LAN-first — everything is controlled locally by default. If you add Tuya Cloud credentials in a top-level `cloud` block, it keeps one cloud session in the background and uses it as a fallback: each device is tried on the LAN first, and only falls back to the cloud when it can't be reached locally — a brief LAN hiccup, or hardware that never appears on the LAN at all (e.g. battery-powered "sleepy" irrigation timers). It's opt-in and local always comes first, and existing configs need no changes — so it's also a handy fix if some devices occasionally show as "No Response".
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
👉 **[Tuya Cloud Setup guide](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Tuya-Cloud-Setup.md)** — how to get credentials and configure a cloud device.
|
|
76
|
+
See the **[Tuya Cloud Setup guide](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Tuya-Cloud-Setup.md)** for credentials and setup.
|
|
79
77
|
|
|
80
78
|
## Installation Instructions
|
|
81
79
|
|
package/config.schema.json
CHANGED
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
},
|
|
22
22
|
"cloud": {
|
|
23
23
|
"type": "object",
|
|
24
|
-
"title": "Tuya Cloud (optional
|
|
25
|
-
"description": "This plugin is LAN-first.
|
|
24
|
+
"title": "Tuya Cloud fallback (optional)",
|
|
25
|
+
"description": "This plugin is LAN-first — every device is controlled locally. Add your Tuya Cloud project credentials here and the plugin keeps one Cloud session running in the background as a transparent fallback for every device: each accessory tries the LAN first, and only falls back to the cloud when it can't be reached locally — a flaky LAN moment, or a battery-powered 'sleepy' device that never appears on the LAN. It's opt-in and local is always preferred. Create a free Cloud project at iot.tuya.com. See the wiki for step-by-step setup.",
|
|
26
26
|
"properties": {
|
|
27
27
|
"accessId": {
|
|
28
28
|
"type": "string",
|
|
@@ -197,16 +197,7 @@
|
|
|
197
197
|
"key": {
|
|
198
198
|
"title": "Tuya Key (local key — required for LAN devices)",
|
|
199
199
|
"type": "string",
|
|
200
|
-
"description": "The device's local key. Required for normal (LAN) devices.
|
|
201
|
-
"condition": {
|
|
202
|
-
"functionBody": "return model.devices && model.devices[arrayIndices].type !== 'null';"
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
"cloud": {
|
|
206
|
-
"type": ["boolean", "object"],
|
|
207
|
-
"title": "Control via Tuya Cloud (instead of the LAN)",
|
|
208
|
-
"default": false,
|
|
209
|
-
"description": "Enable for devices that can't be reached locally (e.g. battery-powered irrigation timers). Uses the platform-level 'cloud' credentials above. Advanced: instead of a checkbox you can set this to an object with per-device { accessId, accessKey, region, … } to use different credentials for this one device.",
|
|
200
|
+
"description": "The device's local key. Required for normal (LAN) devices. A device with no key is treated as cloud-only and is reached through the Tuya Cloud session configured above (e.g. a battery-powered 'sleepy' irrigation timer).",
|
|
210
201
|
"condition": {
|
|
211
202
|
"functionBody": "return model.devices && model.devices[arrayIndices].type !== 'null';"
|
|
212
203
|
}
|
|
@@ -750,7 +741,7 @@
|
|
|
750
741
|
"type": "integer",
|
|
751
742
|
"title": "Number of Valves / Zones",
|
|
752
743
|
"placeholder": 4,
|
|
753
|
-
"description": "How many valves/zones the controller has. They are assumed to be on data-points 1, 2, 3, … (
|
|
744
|
+
"description": "How many valves/zones the controller has. They are assumed to be on data-points 1, 2, 3, … (over the cloud these map to the codes switch_1, switch_2, … automatically). For non-sequential data-points use the 'valves' list instead.",
|
|
754
745
|
"condition": {
|
|
755
746
|
"functionBody": "return model.devices && model.devices[arrayIndices] && ['IrrigationSystem'].includes(model.devices[arrayIndices].type);"
|
|
756
747
|
}
|