There are many ways to add a Daikin HVAC into HA but there are also even more varieties of Daikin/Airzone out there that may not work with integrations or prefabricated products out there. My unit happened to not work in any of the pre made integrations from HACS or HA proper so I went down the road of connecting via modbus/MQTT/RPI to my unit.
If you are looking to integrate your HVAC try the integrations already available.
DKN Cloud for HASS
Daikin AC
Go DAIKIN
Also check out these prefabricated products:
Faikin
Faikout
Additionally, I think a simple RS485 to Wi-Fi gateway device would work with the built-in HA Modbus integration with minimal effort. These can run about $60 and make this project a lot easier.
I had some spare parts on hand and old RPI (overkill) that needed a home somewhere.
My Goal was to create a simple way to integrate my Daikin HVAC into Home Assistant without cloud dependencies.
My Equipment:
- Airzone AZWSDAI0630 (required as it is the Modbus hub but any Airzone controller should work not this specific model number)
- Indoor ducted air handler FDMQ24WVJU9 (Airzone is mounted on this device)
Parts list:
- RPi zero 2 (any RPi with Wi-Fi or w/adapter will work) (An ESP32 device would work as well but your code would need to be updated. Use AI to code quickly!)
- USB to RS485 module ($16 on * amazon). Buy one with FTDI based or SP485EEN chip for best experience. Also note do not try to use uart(GPIO pins) to rs485 as they DO NOT WORK in my experience, for this project.
- micro usb to usb A (female) wire (connect rs485 module to rpi zero 2.) ***You may not need this based on your RPi of choice but most likely will need a short USB extension cord
- power brick and usb cable
- Wires for connecting RS485 module to the Airwave device. Twisted pairs is preferred such as ethernet cable. I used doorbell wire laying around and twisted it with a drill.
- One 4-pin 3.81 pitch phoenix screw terminal block connector. (on * amazon) (only needed if your HVAC techs didn’t leave the terminal block in the Airzone)
- SD card that fits your RPi (8gb or larger should be sufficient)
The build:
Pretty simple but connect the RS485 module to an available USB on your RPI (ensure you use the data OTG usb socket rather than the PWR socket if using the RPi Zero) Connect the RS485 device to the Airzone device using two wires of your choosing. The USB device clearly indicates A+ and B- Terminals while the Airzone device provides less than desired indicators on the physical terminals. I believe all Airzone modules use the same terminals but double check your airzone modbus documentation to be sure. Otherwise connect to the terminals as shown in the photo below. The RS485 A+ terminal to the A/BMS+ (blue) terminal and RS485 Terminal B- to the B/BMS- (green) terminal. If they are reversed there will be no issues or damage done it just won’t communicate. **If you don’t get communication on the first try swap the wires.
When you are done testing make sure to print or buy an enclosure for your RPi.
Programming RPI:
Start by using Rpi Imager to flash the appropriate version of RPi OS Lite on your device. (64 or 32 bit is fine) Enable SSH, set Wi-Fi SSID and password, and all the other initial setup info then start the program writing to your SD card. When RPi Imager is done put that SD right into your RPi and fire it up. Now head back to your PC and SSH into the RPI using Putty or your preferred program.
Update your RPi software:
sudo apt update
sudo apt upgrade -y
Install, create and activate python environment:
sudo apt install python3-venv -y
python3 -m venv ~/airzone-env
source ~/airzone-env/bin/activate
Install MQTT:
pip install pyserial paho-mqtt
ID your rs485 adapter:
ls /dev/serial/by-id/
expected out put (similiar): usb-FTDI_FT232R_USB_UART_BG01PRL4-if00-port0
Copy down full path for use later example:
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_BG01PRL4-if00-port0
Create python MQTT Modbus script:
sudo nano airzone_bridge.py
paste the snippet below into your new file: update password and IP first!
Remember the password as you will use it when creating a user in MQTT in HA later.
Update the IP address to your HA instance or wherever your mosquito broker is.
#!/home/pi/airzone-env/bin/python
import serial
import time
import struct
import json
import paho.mqtt.client as mqtt
# =========================================================
# CONFIG
# =========================================================
MQTT_BROKER = "192.168.1.31"
MQTT_PORT = 1883
MQTT_USER = "airzone"
MQTT_PASS = "create_your_password"
PORT = "/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_BG01PRL4-if00-port0"
SLAVE_ID = 1
DEVICE_NAME = "Daikin Mini Split"
DEVICE_ID = "daikin_mini_split"
# =========================================================
# SERIAL
# =========================================================
ser = serial.Serial(
port=PORT,
baudrate=19200,
bytesize=8,
parity=serial.PARITY_EVEN,
stopbits=1,
timeout=2
)
# =========================================================
# MQTT
# =========================================================
client = mqtt.Client(
callback_api_version=mqtt.CallbackAPIVersion.VERSION2
)
client.username_pw_set(MQTT_USER, MQTT_PASS)
# =========================================================
# MODBUS CRC
# =========================================================
def modbus_crc(data):
crc = 0xFFFF
for pos in data:
crc ^= pos
for _ in range(8):
if crc & 1:
crc >>= 1
crc ^= 0xA001
else:
crc >>= 1
return struct.pack('<H', crc)
# =========================================================
# READ REGISTER
# =========================================================
def read_register(register):
request = bytes([
SLAVE_ID,
0x03,
(register >> 8) & 0xFF,
register & 0xFF,
0x00,
0x01
])
request += modbus_crc(request)
ser.write(request)
time.sleep(0.2)
response = ser.read(100)
if len(response) >= 5:
value = response[3] << 8 | response[4]
return value
return None
# =========================================================
# WRITE REGISTER
# =========================================================
def write_register(register, value):
request = bytes([
SLAVE_ID,
0x06,
(register >> 8) & 0xFF,
register & 0xFF,
(value >> 8) & 0xFF,
value & 0xFF
])
request += modbus_crc(request)
print(f"Writing register {register} value {value}")
ser.write(request)
time.sleep(0.2)
response = ser.read(100)
if response:
print(f"Write response: {response.hex()}")
return True
print("No write response")
return False
# =========================================================
# MQTT DISCOVERY
# =========================================================
def publish_discovery():
discovery_topic = (
f"homeassistant/climate/{DEVICE_ID}/config"
)
payload = {
"name": DEVICE_NAME,
"unique_id": DEVICE_ID,
# -------------------------------------------------
# HVAC MODES
# -------------------------------------------------
"mode_state_topic":
"airzone/mode/state",
"mode_command_topic":
"airzone/mode/set",
"modes": [
"off",
"auto",
"cool",
"heat",
"fan_only",
"dry"
],
# -------------------------------------------------
# TEMPERATURES
# -------------------------------------------------
"temperature_state_topic":
"airzone/setpoint/state",
"temperature_command_topic":
"airzone/setpoint/set",
"current_temperature_topic":
"airzone/roomtemp/state",
"temp_step": 1,
"min_temp": 60,
"max_temp": 86,
"precision": 1.0,
# -------------------------------------------------
# FAN MODES
# -------------------------------------------------
"fan_mode_state_topic":
"airzone/fan/state",
"fan_mode_command_topic":
"airzone/fan/set",
"fan_modes": [
"auto",
"1",
"2",
"3"
],
# -------------------------------------------------
# DEVICE INFO
# -------------------------------------------------
"device": {
"identifiers": [DEVICE_ID],
"name": DEVICE_NAME,
"manufacturer": "Daikin/Airzone",
"model": "Airzone Aidoo",
"sw_version": "1.0"
}
}
client.publish(
discovery_topic,
json.dumps(payload),
retain=True
)
print("Published MQTT discovery")
# =========================================================
# MQTT CALLBACK
# =========================================================
def on_message(client, userdata, msg):
topic = msg.topic
payload = msg.payload.decode()
print(f"MQTT command received:")
print(f"Topic: {topic}")
print(f"Payload: {payload}")
try:
# -------------------------------------------------
# SETPOINT
# -------------------------------------------------
if topic == "airzone/setpoint/set":
temp = int(float(payload) * 10)
success = write_register(1, temp)
print(f"Setpoint write success: {success}")
# -------------------------------------------------
# HVAC MODES
# -------------------------------------------------
elif topic == "airzone/mode/set":
# OFF
if payload == "off":
success = write_register(0, 0)
print(f"Power OFF success: {success}")
else:
# Ensure power ON
write_register(0, 1)
modes = {
"auto": 1,
"cool": 2,
"heat": 3,
"fan_only": 4,
"dry": 5
}
if payload in modes:
success = write_register(
3,
modes[payload]
)
print(f"Mode write success: {success}")
# -------------------------------------------------
# FAN SPEED
# -------------------------------------------------
elif topic == "airzone/fan/set":
fan_modes = {
"auto": 0,
"1": 1,
"2": 2,
"3": 3
}
if payload in fan_modes:
success = write_register(
54,
fan_modes[payload]
)
print(f"Fan write success: {success}")
except Exception as e:
print(f"MQTT write error: {e}")
# =========================================================
# MQTT CONNECT
# =========================================================
print("Connecting to MQTT broker...")
client.on_message = on_message
client.connect(
MQTT_BROKER,
MQTT_PORT,
60
)
print("Connected to MQTT broker")
client.subscribe("airzone/setpoint/set")
client.subscribe("airzone/mode/set")
client.subscribe("airzone/fan/set")
print("MQTT subscriptions active")
client.loop_start()
publish_discovery()
# =========================================================
# MAIN LOOP
# =========================================================
while True:
try:
power = read_register(0)
setpoint = read_register(1)
room_temp = read_register(2)
mode = read_register(3)
fan = read_register(54)
# -------------------------------------------------
# SETPOINT
# -------------------------------------------------
if setpoint is not None:
client.publish(
"airzone/setpoint/state",
setpoint / 10,
retain=True
)
# -------------------------------------------------
# ROOM TEMP
# -------------------------------------------------
if room_temp is not None:
client.publish(
"airzone/roomtemp/state",
room_temp / 10,
retain=True
)
# -------------------------------------------------
# POWER
# -------------------------------------------------
if power is not None:
client.publish(
"airzone/power/state",
power,
retain=True
)
# -------------------------------------------------
# HVAC MODE
# -------------------------------------------------
if power == 0:
client.publish(
"airzone/mode/state",
"off",
retain=True
)
elif mode is not None:
mode_map = {
1: "auto",
2: "cool",
3: "heat",
4: "fan_only",
5: "dry"
}
client.publish(
"airzone/mode/state",
mode_map.get(mode, "unknown"),
retain=True
)
# -------------------------------------------------
# FAN MODE
# -------------------------------------------------
if fan is not None:
fan_map = {
0: "auto",
1: "1",
2: "2",
3: "3"
}
client.publish(
"airzone/fan/state",
fan_map.get(fan, "auto"),
retain=True
)
# -------------------------------------------------
# STATUS OUTPUT
# -------------------------------------------------
room_display = "?"
setpoint_display = "?"
mode_display = "?"
fan_display = "?"
if room_temp is not None:
room_display = room_temp / 10
if setpoint is not None:
setpoint_display = setpoint / 10
if mode is not None:
mode_display = mode
if fan is not None:
fan_display = fan
print(
f"Room: {room_display}F | "
f"Setpoint: {setpoint_display}F | "
f"Mode: {mode_display} | "
f"Fan: {fan_display}"
)
time.sleep(5)
except Exception as e:
print(f"Main loop error: {e}")
time.sleep(5)
Make script executable:
chmod +x ~/airzone_bridge.py
Create systemd service:
sudo nano airzone-bridge.service
Then paste the below into the new file
[Unit]
Description=Airzone MQTT Modbus Bridge
After=network.target
[Service]
ExecStart=/home/pi/airzone-env/bin/python /home/pi/airzone_bridge.py
WorkingDirectory=/home/pi
StandardOutput=inherit
StandardError=inherit
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
Enable autostart:
sudo systemctl daemon-reload
sudo systemctl enable airzone-bridge
sudo systemctl start airzone-bridge
Log out of your RPi, pat your self on the back and open Home Assistant.
Home assistant Config:
Install MQTT broker, in the apps section of HA, if you don’t already have it. Link here. Then go into the configuration and create a new username and password. This is from your python script above. Username: airzone password: create_your_own. Once complete make sure you save out of the dialog box AND save out of the config section!
Install the MQTT integration if you don’t already have it. Open the integration and it should auto discover your new Daikin mini split system. May have to reload or restart HA to get the auto discovery to see the data.
Create a cool lovelace card:
Install Mushroom card from HACS click here
Then open your dashboard and create new card using the manual card option (select manual when adding new card) paste the yaml below into your new manual card;
type: vertical-stack
cards:
- type: custom:mushroom-title-card
title: Daikin Mini Split
subtitle: Airzone Modbus HVAC
- type: thermostat
entity: climate.daikin_mini_split
features:
- type: climate-hvac-modes
hvac_modes:
- "off"
- auto
- cool
- heat
- fan_only
- dry
- type: horizontal-stack
cards:
- type: button
entity: climate.daikin_mini_split
name: "OFF"
tap_action:
action: call-service
service: climate.set_hvac_mode
target:
entity_id: climate.daikin_mini_split
data:
hvac_mode: "off"
- type: button
entity: climate.daikin_mini_split
name: AUTO
tap_action:
action: call-service
service: climate.set_hvac_mode
target:
entity_id: climate.daikin_mini_split
data:
hvac_mode: auto
- type: button
entity: climate.daikin_mini_split
name: COOL
tap_action:
action: call-service
service: climate.set_hvac_mode
target:
entity_id: climate.daikin_mini_split
data:
hvac_mode: cool
- type: button
entity: climate.daikin_mini_split
name: HEAT
tap_action:
action: call-service
service: climate.set_hvac_mode
target:
entity_id: climate.daikin_mini_split
data:
hvac_mode: heat
- type: horizontal-stack
cards:
- type: button
name: FAN
tap_action:
action: call-service
service: climate.set_hvac_mode
target:
entity_id: climate.daikin_mini_split
data:
hvac_mode: fan_only
- type: button
name: DRY
tap_action:
action: call-service
service: climate.set_hvac_mode
target:
entity_id: climate.daikin_mini_split
data:
hvac_mode: dry
- type: entities
title: Fan Speed
entities:
- entity: climate.daikin_mini_split
name: Fan Mode
- type: custom:mini-climate
entity: climate.daikin_mini_split
name: Daikin HVAC
icon: mdi:air-conditioner
That should just about do it for this guide. Let me know if i skipped on any details you find useful.

