Conversation
Zigbee IR blasters reached through ZHA had no controller, so a Tuya TS1201
(ZS06 / UFO-R11 family) could not be used as a SmartIR emitter at all.
ZhaController calls zha.issue_zigbee_cluster_command with the code placed in
params.code. The blaster's ZHA quirk builds its own {"key_num":1,...} envelope,
so the code is passed through verbatim; wrapping it here would nest one envelope
inside the other and the blaster then transmits nothing at all -- no error, no
LED, no IR. That failure is silent, hence the comment in the class docstring.
ZHA_COMMANDS_ENCODING accepts Base64 and Raw. Tuya blasters carry FastLZ
compressed microsecond durations as base64, which is neither converted nor
inspected on the way through.
codes/climate/9000.json covers the ACiQ 9K/12K console mini-split (remote
RG10R(M2S)/BGEFU1, a Midea OEM). The frames are synthesised from the protocol
rather than captured one by one, and the generator reproduces all 27 codes
captured from the physical remote bit-for-bit.
Notes on that device file, all measured rather than assumed:
- Keys are Fahrenheit because several Fahrenheit steps collapse onto one
Celsius code on the wire (73F and 74F are both 23C), so 600 lookup paths
resolve to 174 distinct frames.
- The wire carries 17-30C only. The remote displays down to 60F but transmits
17C for 60, 61 and 62, so the bottom of its range is cosmetic.
- AUTO and DRY lock the fan on this unit, so every fan key in those modes maps
to the same frame.
- FAN_ONLY carries no temperature, so every temperature key maps to one frame.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Withdrawing this — we ended up going a different way, and it seems fairer to close it than to leave it sitting in the queue. The device this was written for (an ACiQ mini-split, Midea We also hit two things the command-path model could not express for this unit: swing and turbo are separate command frames rather than fields inside the state frame, and a press is three frames rather than one, with the trailer carrying the exact fan percentage (1–100), a half-degree bit, and the display-unit flag. Omitting that trailer makes the unit revert to a Celsius display, which took us a while to work out. So it now lives as a small standalone integration instead: https://github.com/defl/zha-midea-ir — installable through HACS as a custom repository, for ACiQ / Blueridge / Midea units behind a Tuya TS1201 (ZS06 / UFO-R11) blaster on ZHA. It computes each frame at send time rather than shipping a table. The ZHA controller itself is still worth having here, and shouldn't be lost with this PR. #1178 by @anmar does essentially the same thing and predates this by well over a year — anyone wanting Zigbee IR blasters in SmartIR should look there first. Two small notes from implementing it, in case they help whoever picks it up:
Thanks for SmartIR — the device-file library was genuinely useful for working out what shape our own data needed to be. |
What this adds
A
ZhaController, so Zigbee IR blasters reached through ZHA can be used as SmartIR emitters. Today they cannot be used at all — there is no controller for them.Tested end to end on a Tuya TS1201 (
_TZ3290_j37rooaxrcdcqo5n, the ZS06 / UFO-R11 family) driving an ACiQ 12K console mini-split, on Home Assistant 2026.8.3.This builds on the approach in #1178 (thanks @anmar), with three fixes:
check_encodingvalidates againstESPHOME_COMMANDS_ENCODINGand raises "not supported by the ESPHome controller" — a copy-paste slip. This adds a realZHA_COMMANDS_ENCODING = [ENC_BASE64, ENC_RAW].controller_dataerrors now name every missing key at once, and invalid JSON is reported as such rather than raisingValueErrorfrom insidejson.loads.service_datais copied beforeparamsis added, so the caller's parsed config is not mutated.The one non-obvious detail
The command string is passed to
params.codeverbatim. The blaster's ZHA quirk builds its own{"key_num":1,...,"key_code":…}envelope; wrapping the code here nests one envelope inside the other, and the blaster then transmits nothing at all — no error, no log line, no LED, no IR. It looks exactly like a dead device. That cost me an afternoon, so it is called out in the class docstring.codes/climate/9000.json
ACiQ 9K/12K console mini-split (remote
RG10R(M2S)/BGEFU1, a Midea OEM; the same handset ships on Blueridge XS2A). The 9000 band was unused, and #1178's own docs example uses 9000 for ZHA.The frames are synthesised from the protocol, not captured one at a time: the generator reproduces all 27 codes captured from the physical remote bit-for-bit, which is what makes 600 entries practical to stand behind. Every lookup path SmartIR can request resolves.
Four properties of this device that explain the file's shape, all measured rather than assumed:
Swing is deliberately absent: on this unit swing and turbo are separate command frames rather than part of the state frame, so folding them into the command path would misrepresent the protocol.
Notes
Docs updated in
README.mdandCLIMATE.md. Happy to split the device file into its own PR if you would rather review the controller alone.