I’ve recently added my Swegon Casa W3 ventilation unit with heat recovery into Home Assistant using ESPHome and the Modbus integration. I believe the Modbus interface is the same for most Swegon Casa products.
I bought the Swegon Modbus module for my unit and connected that to my ESP8266 with a cheap RS485 module from Aliexpress. Here’s my ESPHome configuration file in case someone’s interested.
# Read data over ModBus from Swegon Casa Ventilation / Heat Recovery device
#
# Not all fields are implemented by all machines.
#
# See reference:
# https://www.swegon.com/siteassets/_product-documents/home-ventilation/control-equipment/_fi/smartmodbusregisterfull.pdf
# https://serviceportal.swegon.com/fi/docs/MB_REG_FI
esphome:
name: swegon-ac-esp8266
esp8266:
board: nodemcuv2
substitutions:
device_name: Swegon W3
# Enable Home Assistant API
api:
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
domain: !secret local_domain
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Swegon Fallback Hotspot"
password: "password"
# Logging is disabled
logger:
level: ERROR
#level: DEBUG
baud_rate: 0
uart:
id: mod_bus
tx_pin: D6
rx_pin: D5
baud_rate: 38400
stop_bits: 1
modbus:
id: modbus1
modbus_controller:
- id: swegon
## the Modbus device address
address: 0x10
modbus_id: modbus1
setup_priority: -10
sensor:
# ENVIRONMENTAL PARAMETERS, 6200-6299
- platform: modbus_controller
modbus_controller_id: swegon
id: fresh_air_temperature
name: "${device_name} Fresh Air Temperature"
address: 6200 # 6201-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: supply_air_before_reheater_temperature
name: "${device_name} Supply Air Before Reheater Temperature"
address: 6201 # 6202-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: supply_air_temperature
name: "${device_name} Supply Air Temperature"
address: 6202 # 6203-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: extract_air_temperature
name: "${device_name} Extract Air Temperature"
address: 6203 # 6204-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: waste_air_temperature
name: "${device_name} Waste Air Temperature"
address: 6204 # 6205-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: room_air_temperature
name: "${device_name} Room Air Temperature"
address: 6205 # 6206-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: user_panel_1_temperature
name: "${device_name} User Panel Temperature"
address: 6206 # 6207-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: user_panel_2_temperature
name: "${device_name} User Panel 2 Temperature"
address: 6207 # 6208-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: water_radiator_temperature
name: "${device_name} Water Radiator Temperature"
address: 6208 # 6209-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: preheater_temperature
name: "${device_name} Pre-heater Temperature"
address: 6209 # 6210-1
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: external_fresh_air_temperature
name: "${device_name} External Fresh Air Temperature"
address: 6210
register_type: read
value_type: U_WORD
unit_of_measurement: "°C"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: co2_unfiltered
name: "${device_name} CO2 Unfiltered"
address: 6211
register_type: read
value_type: U_WORD
unit_of_measurement: "ppm"
- platform: modbus_controller
modbus_controller_id: swegon
id: co2_filtered
name: "${device_name} CO2 Filtered"
address: 6212
register_type: read
value_type: U_WORD
unit_of_measurement: "ppm"
- platform: modbus_controller
modbus_controller_id: swegon
id: relative_humidity
name: "${device_name} Relative Humidity"
address: 6213
register_type: read
value_type: U_WORD
unit_of_measurement: "%"
- platform: modbus_controller
modbus_controller_id: swegon
id: absolute_humidity
name: "${device_name} Absolute Humidity"
address: 6214
register_type: read
value_type: U_WORD
unit_of_measurement: "g/m³"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: absolute_humidity_setpoint
name: "${device_name} Absolute Humidity Setpoint"
address: 6215
register_type: read
value_type: U_WORD
unit_of_measurement: "g/m³"
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: swegon
id: voc
name: "${device_name} VOC"
address: 6216
register_type: read
value_type: U_WORD
unit_of_measurement: "ppm"
# UNIT STATE 6300-6399
- platform: modbus_controller
modbus_controller_id: swegon
id: supply_fan_control
name: "${device_name} Supply Fan Control"
address: 6302
register_type: read
value_type: U_WORD
unit_of_measurement: "%"
- platform: modbus_controller
modbus_controller_id: swegon
id: exhaust_fan_control
name: "${device_name} Exhaust Fan Control"
address: 6303
register_type: read
value_type: U_WORD
unit_of_measurement: "%"
- platform: modbus_controller
modbus_controller_id: swegon
id: supply_fan_rpm
name: "${device_name} Supply Fan RPM"
address: 6304
register_type: read
value_type: U_WORD
unit_of_measurement: "R/min"
filters:
- multiply: 10
- platform: modbus_controller
modbus_controller_id: swegon
id: exhaust_fan_rpm
name: "${device_name} Exhaust Fan RPM"
address: 6305
register_type: read
value_type: U_WORD
unit_of_measurement: "R/min"
filters:
- multiply: 10
- platform: modbus_controller
modbus_controller_id: swegon
id: boost_time_left
name: "${device_name} Boost Time Left"
address: 6307
register_type: read
value_type: U_WORD
unit_of_measurement: "min"
- platform: modbus_controller
modbus_controller_id: swegon
id: hours_to_service
name: "${device_name} Hours to Next Service"
address: 6342
register_type: read
value_type: U_WORD
unit_of_measurement: "h"
binary_sensor:
- platform: modbus_controller
modbus_controller_id: swegon
id: travelling_function_active
name: "${device_name} Travelling Function Active"
register_type: read
address: 6306
bitmask: 0x01 #(bit 1)
- platform: modbus_controller
modbus_controller_id: swegon
id: defrost_active
name: "${device_name} Defrost Active"
register_type: read
address: 6327
lambda: !lambda |-
uint16_t defrost = (data[item->offset] << 8) + data[item->offset+1];
if (defrost > 0) {
return true;
} else {
return false;
}
- platform: modbus_controller
modbus_controller_id: swegon
id: preheater_active
name: "${device_name} Preheater Active"
register_type: read
address: 6332
bitmask: 0x01 #(bit 1)
- platform: modbus_controller
modbus_controller_id: swegon
id: fireplace_function_active
name: "${device_name} Fireplace Function Active"
register_type: read
address: 6334
bitmask: 0x01 #(bit 1)
- platform: modbus_controller
modbus_controller_id: swegon
id: heat_exchanger_bypass
name: "${device_name} Heat Exchanger Bypass"
register_type: read
address: 6340
bitmask: 0x01 #(bit 1)
text_sensor:
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Unit State"
id: unit_state
register_type: read
address: 6300
lambda: !lambda |-
uint16_t int_mode = (data[item->offset] << 8) + data[item->offset+1];
ESP_LOGD("main","Parsed unit state int : %d", int_mode);
std::string mode_str;
switch (int_mode) {
case 0: mode_str = "External stop"; break;
case 1: mode_str = "User stopped"; break;
case 2: mode_str = "Starting"; break;
case 3: mode_str = "Normal"; break;
case 4: mode_str = "Commissioning"; break;
default: mode_str = "Unknown"; break;
}
return mode_str;
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Ventilation Speed State"
id: ventilation_speed_state
register_type: read
address: 6301
lambda: !lambda |-
uint16_t int_mode = (data[item->offset] << 8) + data[item->offset+1];
ESP_LOGD("main","Parsed ventilation speed state int : %d", int_mode);
std::string mode_str;
switch (int_mode) {
case 0: mode_str = "Stopped"; break;
case 1: mode_str = "Away"; break;
case 2: mode_str = "Home"; break;
case 3: mode_str = "Boost"; break;
case 4: mode_str = "Cooling"; break;
default: mode_str = "Unknown"; break;
}
return mode_str;
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Firmware Version"
id: device_firmware_version
register_type: read
address: 6000
response_size: 6
skip_updates: 60
lambda: !lambda |-
uint16_t fw_major = (data[item->offset] << 8) + data[item->offset+1];
uint16_t fw_minor = (data[item->offset+2] << 8) + data[item->offset+3];
uint16_t fw_build = (data[item->offset+4] << 8) + data[item->offset+5];
return (esphome::to_string(fw_major) + "." + esphome::to_string(fw_minor) + "." + esphome::to_string(fw_build));
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Modbus GW Firmware Version"
id: modbus_gw_firmware_version
register_type: read
address: 6005
response_size: 4
skip_updates: 60
lambda: !lambda |-
uint16_t fw_major = (data[item->offset] << 8) + data[item->offset+1];
uint16_t fw_minor = (data[item->offset+2] << 8) + data[item->offset+3];
return (esphome::to_string(fw_major) + "." + esphome::to_string(fw_minor));
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Model Name"
id: model_name
register_type: read
address: 6007
response_size: 16
skip_updates: 60
switch:
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Auto RH Control"
id: auto_rh_control
register_type: holding
address: 5009
bitmask: 1
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Service Reminder"
id: service_reminder
register_type: holding
address: 5140
bitmask: 1
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Fireplace Function"
id: fireplace_function
register_type: holding
address: 5001
bitmask: 1
select:
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Fan Speed Mode"
id: fan_speed_mode
# register_type: holding
address: 5000
optionsmap:
"Away": 1
"Home": 2
"Boost": 3
number:
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Service Reminder Interval"
id: service_reminder_interval
register_type: holding
address: 5141
min_value: 1
max_value: 12
step: 1
mode: slider
- platform: modbus_controller
modbus_controller_id: swegon
name: "${device_name} Temperature Setpoint"
id: temperature_setpoint
register_type: holding
address: 5100
min_value: 16
max_value: 23
step: 1
mode: slider
output:
- platform: modbus_controller
modbus_controller_id: swegon
id: reset_service_reminder
write_lambda: |-
ESP_LOGD("main","Modbus Output reset_service_reminder, value = %f",x);
if (x) {
return 0;
} else {
return 1;
}
address: 5140
register_type: holding
value_type: U_WORD
button:
- platform: output
name: "${device_name} Reset Service Reminder"
output: reset_service_reminder
duration: 1000ms