A small Zigbee IR blaster turns dumb appliances into things Home Assistant can control — TVs, fans, air conditioners. The integration is simple on paper:
Home Assistant → mqtt.publish → Zigbee2MQTT → IR blaster → appliance
The interesting part is the protocol. IR has no feedback and no handshake, and air conditioner remotes do not send commands — they send full state.
Codes are states, not buttons
A TV remote sends "volume up". An air conditioner remote sends the complete state every time: power, mode, target temperature and fan speed together. There is no "make it one degree warmer"; there is only "Cool, 26 °C, fan auto".
That means one learned code per state you want to use, and automation logic that picks a state instead of pressing buttons.
Learning codes
In the Zigbee2MQTT device page, expose and enable Learn IR code, point the
physical remote at the blaster, and press the button you want to capture. The
code lands in a sensor like sensor.<device>_learned_ir_code as a long base64
string — often over a thousand characters.
A practical set for an air conditioner:
AutoCool 25Cool 26Off
Sending codes
From Home Assistant the reliable path is mqtt.publish:
action: mqtt.publish
data:
topic: zigbee2mqtt/<friendly_name>/set
payload: '{"ir_code_to_send": "<BASE64>"}'
Three things that cost time before they are understood:
- The topic needs the Zigbee2MQTT friendly name, which may be different from the name Home Assistant shows for the device.
base_topicis needed when publishing from Home Assistant ormosquitto_pub, but not in the Zigbee2MQTT Dev Console — the console is already inside that topic namespace. Adding the prefix there produces "Entity 'zigbee2mqtt' unknown".- Do not use
text.set_valueon the exposed IR-code text entity. It is limited to 255 characters while the codes are much longer, and the send fails with a generic "Unknown error".
Automation design
Because every code is a complete state, keep the state set small and let the automation choose:
- room temperature above 28 °C → send
Cool 26 - nobody home for 30 minutes → send
Off
Store the long base64 strings in secrets.yaml and reference them, so the
automations stay readable and the codes can be updated in one place.
Debug checklist
- Entity unknown → the topic or the friendly name is wrong.
- "Entity 'zigbee2mqtt' unknown" → remove the
base_topicprefix in the Dev Console. - "Unknown error" → the code is too long for the text entity; use
mqtt.publishinstead.
IR stays a one-way protocol, so Home Assistant never knows whether the appliance received the command. Design for the states you can send, and keep the automation logic simple enough to reason about from the codes alone.