No worries, no rush!
For me, the PR2 - protocol 3.5 is therefore working fine. I haven’t tested it on my production environment, but I can if needed.
Thanks @GBoulvin ,
I’ve updated the Docker image, which now also supports 3.4: it’s now routed to the fork @demirdeniz/tuyapi-newgen (the same one that handles 3.5), and a 3.4 version parser has been added to the local UDP scan between the 3.1 and 3.5 parsers. You can retest whenever you want with the new image.
If possible, also test the UDP scan (independently) to ensure everything works. Thanks in advance
On my side, normally no need: the changes add routing strictly triggered by protocolVersion === '3.4' or '3.5'. Devices 3.1 and 3.3 continue to use the legacy tuyapi library without any modification to the call path — so no risk of regression on what already worked.
That said, if you want to take the opportunity to validate on your production environment, it’s ideal: your 3.4 devices (which didn’t work) should now be functional, and your 3.1/3.3/3.5 devices should remain the same as before. No obligation, it’s just a bonus if you have 5 minutes.
EDIT :
For info @pierre-gilles , I renamed the PR by explicitly naming the 3.4 addition in addition to 3.5, both using the same library. The PR is a bit larger, but we’re still under 600 lines of changes, it’s mainly the tests that are significant (represent half of the added lines)
Dumb question maybe, but is the image still on the same tag (pr1)?
Yes, always ^^ Better to ask ^^
Hello!
I tested the available version and protocol 3.4 is detected and works directly. Local IP address detection also works (for 3.4, yes, but not for 3.5. I had already noticed, but my network setup isn’t the best for testing this, so it’s hard to confirm it’s due to the protocol).
All good for me then! Thanks!!
The following 2 PRs are awaiting review:
Adding support for protocols 3.4 and 3.5:
master ← Terdious:tuya-local-protocol-3.5
ouvert 02:40AM - 21 Feb 26 UTC
### Pull Request check-list
To ensure your Pull Request can be accepted as fa… st as possible, make sure to review and check all of these items:
- [x] If your changes affect the code, did you write the tests?
- [x] Are tests passing? (`npm test` on both front/server)
- [x] Is the linter passing? (`npm run eslint` on both front/server)
- [x] Did you run prettier? (`npm run prettier` on both front/server)
- [x] If you are adding a new feature/service, did you run the integration comparator? (`npm run compare-translations` on front)
- [x] Did you test this pull request in real life? With real devices? If this development is a big feature or a new service, we recommend that you provide a Docker image to the community ([forum](https://community.gladysassistant.com/)) for testing before merging.
- [ ] If your changes modify the API (REST or Node.js), did you modify the API documentation? (Documentation is based on comments in code)
- [ ] If you are adding a new features/services which needs explanation, did you modify the user documentation? See [the GitHub repo](https://github.com/GladysAssistant/v4-website) and the [website](https://gladysassistant.com).
- [ ] Did you add fake requests data for the demo mode (`front/src/config/demo.js`) so that the demo website is working without a backend? (if needed) See [https://demo.gladysassistant.com](https://demo.gladysassistant.com).
NOTE: these things are not required to open a PR and can be done afterwards / while the PR is open.
### Description of change
## Summary
Adds support for **Tuya local protocols 3.4 and 3.5** to the Tuya integration. Stacks on top of [PR #2434](https://github.com/GladysAssistant/Gladys/pull/2434) which is now merged into `master`.
The official `tuyapi@7.2.0` only supports protocols 3.1 and 3.3 — it has **no cipher or parser** for 3.4 (the "3.4" dropdown option was pointing to a non-functional path) and obviously none for 3.5. A second client (`@demirdeniz/tuyapi-newgen`) is added and used **only** when `protocolVersion === '3.4'` or `'3.5'`. Protocols 3.1 and 3.3 keep using the original `tuyapi` client and are not impacted.
## Details
**Protocol routing**
- `tuya.localPoll.js` and `tuya.setValue.js` pick the local API class based on an `isNewGenProtocol` flag (`isProtocol34 || isProtocol35`).
- For 3.5 only: `keepAlive` is disabled and `socketTimeout` is floored at 5 s because the 3.5 handshake takes longer than the others.
- For 3.5 only: a small fallback chain (`{schema:true}` → `{schema:true, dps:[1]}` → `{}`) because some firmwares reject a bare schema get on first contact. 3.4 uses a single schema attempt.
- Protocol 3.4 reuses the existing `tuyapi-newgen` `_decrypt34` cipher and `0x6699/0x9966` UDP framing.
**UDP local scan**
- `tuya.localScan.js` now parses incoming packets with three `MessageParser` instances in order `[3.1, 3.4, 3.5]` and keeps the first one that succeeds.
- `localScan(input)` accepts either a number or an object so existing callers passing `{ timeoutSeconds: N }` still work.
- `timeoutSeconds` is sanitized into `[1, 30] s`.
**Robustness improvements (touched along the way)**
- `localPoll.timeoutMs` is sanitized into `[500, 30000] ms` to prevent immediate timeouts or pathologically long hangs.
- `setValue` now throws `BadParameters` when the external_id has no command instead of silently falling back to the cloud.
**Front (`TuyaDeviceBox.jsx`)**
- Protocol 3.5 is enabled in the dropdown (3.4 was already listed but non-functional before this PR).
- `pollLocal()` adds 3.5 to the fallback list and captures `currentDevice` once at the start of the async loop to avoid stale `this.state.device` reads across protocol attempts.
- Obsolete i18n keys `protocol35OptionUnsupported` and `protocolVersionRequired` removed (en/fr/de).
**Dependency**
- `@demirdeniz/tuyapi-newgen` is **pinned** to exact version `8.1.5` (no caret), since it is a single-maintainer scoped fork. License MIT, integrity hash present in lockfile.
## Scope
Computed against `master` (PR #2434 already merged).
- **server (prod)** : ~150 lines (3 files: `tuya.localPoll.js`, `tuya.localScan.js`, `tuya.setValue.js`)
- **server (tests)** : ~325 lines (3 files: `tuya.localPoll.test.js`, `tuya.localScan.test.js`, `tuya.setValue.test.js`)
- **front (prod)** : ~29 lines (`TuyaDeviceBox.jsx`)
- **translations** : ~18 lines (`en.json`, `fr.json`, `de.json`)
- **packages / lockfiles** : ~75 lines (`package.json`, `package-lock.json`)
Total : ~597 lines across 12 files.
## Validation
- `npm run test-service --service=tuya` → **159 passing, 0 failing**
- `eslint server/services/tuya server/test/services/tuya` → clean
- `eslint front/src/routes/integration/all/tuya` → clean
## Summary by CodeRabbit
* **New Features**
* Local device polling with multi-protocol fallback, UDP local discovery, connection status, manual disconnect, reconnect logic, and cloud/local mode controls.
* **UI**
* Richer Tuya setup UI with new credential fields and connection states; device view shows masked IP, product/device identifiers, protocol/IP controls, local-poll actions, GitHub issue shortcut, and improved discovery ordering/status.
* **Localization**
* Expanded DE/EN/FR translations for setup, discovery, devices, statuses, errors, and guidance.
* **Tests**
* Extensive new and updated tests for local poll/scan, discovery, config, status, setValue, and lifecycle.
Adding the first cloud/local mapping bricks and notably local UDP discovery:
master ← Terdious:tuya-local-mapping-core
ouvert 12:04PM - 27 Feb 26 UTC
### Pull Request check-list
To ensure your Pull Request can be accepted as fa… st as possible, make sure to review and check all of these items:
- [x] If your changes affect the code, did you write the tests?
- [x] Are tests passing? (`npm test` on both front/server)
- [x] Is the linter passing? (`npm run eslint` on both front/server)
- [x] Did you run prettier? (`npm run prettier` on both front/server)
- [x] If you are adding a new feature/service, did you run the integration comparator? (`npm run compare-translations` on front)
- [x] Did you test this pull request in real life? With real devices? If this development is a big feature or a new service, we recommend that you provide a Docker image to the community ([forum](https://community.gladysassistant.com/)) for testing before merging.
- [ ] If your changes modify the API (REST or Node.js), did you modify the API documentation? (Documentation is based on comments in code)
- [ ] If you are adding a new features/services which needs explanation, did you modify the user documentation? See [the GitHub repo](https://github.com/GladysAssistant/v4-website) and the [website](https://gladysassistant.com).
- [ ] Did you add fake requests data for the demo mode (`front/src/config/demo.js`) so that the demo website is working without a backend? (if needed) See [https://demo.gladysassistant.com](https://demo.gladysassistant.com).
NOTE: these things are not required to open a PR and can be done afterwards / while the PR is open.
### Description of change
This PR introduces a mapping core for Tuya devices to make local/cloud handling more consistent and future device integrations easier.
## Summary
Brings PR3 in sync with master + PR1/PR2 review fixes (PR1 was squash-merged
in `bf8bbff1`; PR2 carries the master merge and its own review-feedback
batch). PR3's own contribution — Tuya mapping core, `convertDevice` /
`convertFeature` refactor, `tuya.deviceMapping` / `tuya.localMapping`,
poll hardening, and Smart Socket reference implementation — is preserved
on top of the aligned base.
## Details
Merge of `tuya-local-protocol-3.5` (PR2) into PR3 brings forward:
- master alignment via PR2's merge commit (`0c457670`): Gladys 4.73.0,
Matter.js 0.16.11, Airplay sender rewrite, energy/i18n updates
- PR1 review fixes baked-in via the master squash (single
`/configuration` endpoint, reconnect prototype refactor moved to
`lib/tuya.reconnect.js` with proper wiring in `lib/index.js`,
`stopReconnect()` call in `lib/tuya.disconnect.js`, `addSelector`
in `convertDevice` / `convertFeature`, `MarkupText` invalid-paragraph
fix in `SetupTab.jsx`, `discoverDevices` JSDoc fix, `bridge minimal`
`services/tuya/index.js`)
- PR2 review feedback (`6b760790`): exact `@demirdeniz/tuyapi-newgen`
pin to `8.1.5`, `socketTimeout`/`keepAlive` documented for protocol
3.5, DPS fallback chain documented, dropped redundant `localKey`
guard in `updateDiscoveredDeviceAfterLocalPoll`, dropped redundant
double-disconnect in `localPoll` outer catch
- PR2 protocol 3.4 newgen routing (`2679dba6`): `localScan` ordered
parsers `[3.1, 3.4, 3.5]`, `localPoll` / `setValue` route 3.4 via
`isNewGenProtocol`
Conflict resolutions (manual, then validated via tests + lint):
- `tuya.localPoll.js`: PR2 base (proto 3.4 routing + comments) +
PR3 add-on reposed (`logDps`, `addFallbackBinaryFeature`, `dps` passing)
- `tuya.poll.js`: PR3 refactor kept; obsolete PR2 baseline snippet dropped
- `tuya.convertFeature.js`: PR3 imports + PR1 `addSelector` combined
- `SetupTab.jsx` and `i18n/fr.json`: PR3 pre-PR1-fix workarounds dropped
- `tuya.poll.test.js`: PR3 tests kept (cover PR2 baseline by equivalence)
- `tuya.localScan.test.js`: PR2 added test
`should instantiate parsers for protocols 3.1, 3.4 and 3.5` kept
- `tuya.convertFeature.test.js`: selector expectation harmonised to
the slugified form (consistent with the rest of the file)
Validation:
- `npm run test-service --service=tuya`: **209 passing**
- `npx nyc --include='services/tuya/**'`: **99.59% lines / 99.60% stmts /
99.39% functions / 88.94% branches**
- `eslint server/services/tuya server/test/services/tuya`: clean
- `eslint front/src/routes/integration/all/tuya`: clean
## Scope
Scope vs the immediate parent branch in the stack
(`tuya-local-protocol-3.5`, PR #2438):
| Area | Insertions | Deletions |
|---|---:|---:|
| `server/services/tuya` (prod) | +987 | -178 |
| `server/test/services/tuya` (tests) | +1313 | -26 |
| `front/src/routes/integration/all/tuya` (prod) | +13 | -8 |
| **Total** | **+2313** | **-212** |
No translation, package or lockfile changes (the `localModeLimitInfo`
restoration in commit `865e2cc3` was a fix for a key dropped during the
merge of PR2, with zero net delta vs PR2).
27 files changed, 0 leak outside the Tuya scope.
## Summary by CodeRabbit
* **New Features**
* Local UDP discovery and local polling for Tuya devices; cloud/local mode toggle, manual cloud disconnect, and explicit Save → Connect flow.
* Real-time connection status and disconnect controls with improved reconnect handling.
* **Improvements**
* Updated setup copy and field labels (Client ID/Client Secret, App UID, App Username) with validation and user-friendly error messages.
* Device panel shows identifiers, IP/protocol, product info, local-poll controls/progress, success/error indicators and clearer "unknown" value labels.
@GBoulvin , if you want to test PR3, I created a new image terdious/gladys:tuya-PR3, specifically:
starting with your database from the last test,
then performing an auto UDP local scan
then deleting the already registered devices, logging out, then logging back in and running another auto UDP local scan, to make sure everything is properly found.
Thanks in advance.