HowTo: Integrating a Swentibold EuroAir Ventilation with Homeassistant

This article shall describe how to establish a modbus connection to an EuroAir Ventilation System and integrate it into Homeassistant.

I have a EuroAir350 bought in 2024 at my home and the config is tested to work with this modell.

First I bought a Waveshare TCP to Modbus adapter and connected it to the Webcontroller Clamps on the EuroAir Unit (A-A,B-B, GND-GND), as shown in this picture provided to me (via email) by EuroAir.

This video(youtube . com/watch?v=Xuj2YFZ5zME&t=96s&pp=ygUQd2F2ZXNoYXJlIG1vZGJ1cw%3D%3D) goes into detail, on how to configure the Waveshare Modbus adapter, but basically you have to switch on the waveshare modul, and download the configuration software(Vircom)

After that you can configure the following modbus settings in the Vircom software:

9600 baud

8 data bits

No parity

1 stop bit

Integrating it into HomeAssistant

I could not find the correct slaveID anywhere in the documentation, but the company mentioned via Email it’s 10.


modbus:
- name: "lüftung"
  type: tcp
  host: <waveshare ip>
  port: 502
  sensors:
    - name: "Lüftung-Außenluft"
      slave: 10
      address: 4
      input_type: input
      data_type: uint16
      scale: 0.1
      precision: 1
      unit_of_measurement: "°C"
      unique_id: central_lueftung.temp_aussenluft
    - name: "Lüftung-Raumluft"
      slave: 10
      address: 5
      input_type: input
      data_type: uint16
      scale: 0.1
      precision: 1
      unit_of_measurement: "°C"
    - name: "Lüftungstufe"
      address: 42
      input_type: holding
      data_type: uint16
      slave: 10
  switches:
    - name: "Lüftung An/Aus"
      address: 1
      command_on: 1
      command_off: 0
      write_type: holding
      slave: 10
      verify:
          input_type: holding
          address: 1
          state_on: 1
          state_off: 0
    - name: "Lüftung ByPass Offen/Geschlossen"
      address: 31
      command_on: 1
      command_off: 0
      write_type: holding
      slave: 10
      verify:
          input_type: holding
          address: 31
          state_on: 1
          state_off: 0

This Config allows you to e.g. activate the bypass using homeassitant and control the ventilation speed. I will update this post, with a full list of values and maybe even create a custom integration for the EuroAir units.

3 Likes

Here is the download link for vircom: https://www.waveshare.com/wiki/RS485_TO_ETH_(B)#Software_Installation) and a screenshot of the result

1 Like

Hi @ludik0 any progeress on this one?

I got a similar machine. Do you have a full list of Modbus registers? The list i found in the manual seems to be different, because the addresses you used do not match the ones i found in the documentation. https://www.swentibold.com/_files/ugd/cab2d0_dc6cb579ece84272b592bbadf732ffce.pdf (https://www.swentibold.com/wtwtoestellen?lang=de)

Hi @kamil02
I have EuroAir 350,
but I decide to simplify connectivity to device using MAX485 (TTL to RS485 Module) and ESP32, after contacting swentibold, they send me quite old but more correct list of registers together with other modbus important information:

10.02 Swentibold - modbus v1_25_H.pdf

so just contact swentibold regarding your device if those registers didn’t match for you.

esphome relevant configuration that was defined as result of provided documentation that could be useful:

# UART for Modbus
uart:
  id: uart_modbus
  tx_pin: GPIO17 # Connects to DI on MAX485
  rx_pin: GPIO16 # Connects to RO on MAX485
  baud_rate: 9600
  stop_bits: 1
  parity: NONE

# Modbus
modbus:
  id: modbus_hub
  uart_id: uart_modbus
  flow_control_pin: GPIO21 # This single pin MUST be connected to both DE and RE on the MAX485
  send_wait_time: 250ms

# Define the Swentibold ventilation unit as a Modbus controller target
modbus_controller:
  - id: swentibold_wtw
    address: 10            # Slave ID
    modbus_id: modbus_hub
    update_interval: 10s

sensor:
#  # Register 25: Low Speed Hours
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Low Speed Hours"
#    address: 25
#    register_type: holding
#    unit_of_measurement: "h"
#    icon: "mdi:clock-outline"
#  # Register 26: Medium Speed Hours
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Medium Speed Hours"
#    address: 26
#    register_type: holding
#    unit_of_measurement: "h"
#    icon: "mdi:clock-outline"
#  # Register 27: High Speed Hours
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "High Speed Hours"
#    address: 27
#    register_type: holding
#    unit_of_measurement: "h"
#    icon: "mdi:clock-outline"
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Bypass temp test"
#    address: 2
#    register_type: holding
#    unit_of_measurement: "°C"
#    filters:
#      - multiply: 0.1
  # Register 28: Filter Hours
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Filter Hours"
    address: 28
    register_type: holding
    unit_of_measurement: "h"
    icon: "mdi:air-filter"
#  # Register 46: Cooling Percentage
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Cooling Percentage"
#    address: 46
#    register_type: holding
#    unit_of_measurement: "%"
#    icon: "mdi:coolant-temperature"
#  # Register 47: Heating Percentage
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Heating Percentage"
#    address: 47
#    register_type: holding
#    unit_of_measurement: "%"
#    icon: "mdi:radiator"
  # Internal sensor for device type (used by text_sensor below)
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    id: wtw_type_raw
    internal: true
    address: 0 # Register 0: Type
    register_type: holding

text_sensor:
  # Register 0: Device Type
  - platform: template
    name: "Device Type"
    icon: "mdi:information-outline"
    lambda: |-
      auto val = id(wtw_type_raw).state;
      if (isnan(val)) { return {"Unknown"}; }
      switch ((int)val) {
        case 1: return {"Basis"};
        case 2: return {"Bypass"};
        case 3: return {"Comfort"};
        default: return {"Unknown"};
      }

binary_sensor:
  # Register 29: Status (bit-mapped)
  # Bit 1 = Medium vent active
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Medium Ventilation"
    address: 29
    register_type: holding
    bitmask: 0b0000000000000010 # (1 << 1)
    icon: "mdi:fan-speed-2"
  # Bit 2 = High vent active
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "High Ventilation"
    address: 29
    register_type: holding
    bitmask: 0b0000000000000100 # (1 << 2)
    icon: "mdi:fan-speed-3"
  # Register 30: Digin (Digital Inputs, bit-mapped)
  # Bit 2 = Hygrostat
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Hygrostat"
    address: 30
    register_type: holding
    bitmask: 0b0000000000001000 # (1 << 3)
    icon: "mdi:water-percent"
#  # Register 43: Recirculation status
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Recirculation Status"
#    address: 43
#    register_type: holding
#    device_class: opening
#  # Register 44: Cooling status
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Cooling Status"
#    address: 44
#    register_type: holding
#    device_class: running
#  # Register 45: Heating status
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Heating Status"
#    address: 45
#    register_type: holding
#    device_class: heat
#  # Register 40: Error status bits
#  # You can add one for each bit you want to monitor
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Fault E1"
#    address: 40
#    register_type: holding
#    bitmask: 2
#    device_class: problem
#  - platform: modbus_controller
#    modbus_controller_id: swentibold_wtw
#    name: "Fault Ft"
#    address: 40
#    register_type: holding
#    bitmask: 256
#    device_class: problem

select:
  # Register 1: On/Off
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Power"
    address: 1
    optionsmap:
      "Off": 0
      "On": 1
    icon: "mdi:power"
  # Register 8: Filter time reset
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Filter Time Reset"
    address: 8
    optionsmap:
      "No": 0
      "Yes": 1
    icon: "mdi:filter-remove-outline"
  # Register 23: Summer/Winter Time
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Automatic Summer/Winter Time"
    address: 23
    optionsmap:
      "Disabled": 0
      "Enabled": 1
    icon: "mdi:calendar-sync"
  # Register 24: Holiday Mode
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Holiday Mode"
    address: 24
    optionsmap:
      "Disabled": 0
      "Enabled": 1
    icon: "mdi:palm-tree"
  # Register 31: Bypass
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Bypass"
    address: 31
    optionsmap:
      "Closed": 0
      "Open": 1
    icon: "mdi:swap-horizontal"
  # Register 32: Earth cooling
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Earth Cooling"
    address: 32
    optionsmap:
      "Closed": 0
      "Open": 1
    icon: "mdi:earth-arrow-right"
  # Register 42: Ventilation Mode
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Ventilation Mode"
    address: 42
    optionsmap:
      "Auto": 0
      "Low": 1
      "Medium": 2
      "High": 3
    icon: "mdi:fan"

switch:
  - platform: restart
    name: ${device_name} restart

number:
  # Register 2: Bypass Temperature Setpoint
  # Probably FW issue - value * 10 (e.g. 150: 15°C)
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Bypass Temperature Setpoint"
    address: 2
    unit_of_measurement: "°C"
    mode: slider
    step: 10
    min_value: 150
    max_value: 300
    icon: "mdi:thermometer"
  # Register 3: Recirculation temperature
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Recirculation Temperature Setpoint"
    address: 3
    unit_of_measurement: "°C"
    mode: slider
    step: 1
    min_value: -10
    max_value: 30
    icon: "mdi:thermometer"
  # Register 4: Comfort Temperature Setpoint
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Comfort Temperature Setpoint"
    address: 4
    unit_of_measurement: "°C"
    mode: slider
    step: 1
    min_value: 15
    max_value: 30
    icon: "mdi:home-thermometer-outline"
  # Register 5: Hygrostat Switch-On Delay
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Hygrostat Switch-On Delay"
    address: 5
    unit_of_measurement: "m"
    mode: slider
    step: 1
    min_value: 0
    max_value: 120
    icon: "mdi:timer-plus-outline"
  # Register 6: Hygrostat Switch-Off Delay
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Hygrostat Switch-Off Delay"
    address: 6
    unit_of_measurement: "m"
    mode: slider
    step: 1
    min_value: 0
    max_value: 120
    icon: "mdi:timer-minus-outline"
  # Register 7: Filter Change Interval
  - platform: modbus_controller
    modbus_controller_id: swentibold_wtw
    name: "Filter Change Interval"
    address: 7
    unit_of_measurement: "w"
    mode: slider
    step: 1
    min_value: 1
    max_value: 99
    icon: "mdi:calendar-clock"

* some registers are commented just because they have no affect in my case

Hope that will help others to make their ventilation system more smarter :beers: