UPDATE 2021/09/23: New YAML for Modbus after change in syntax.
UPDATE 2021/11/30: Fix data types, add energy sensors compatible with long-term stats / energy dashboard
If you live in Western Europa (esp. the DACH region) you might have a Poloplast PoloAir ventilation system in your house, which can be fully integrated into Home Assistant using the existing Modbus integration. Here’s how it is working very well for me with a PoloAir 450+…
Prerequisites / Caveats:
- PoloAir system needs to be part of your network using the ethernet interface, you know the IP address
- The Modbus interface is open, no additional license or config necessary, BUT:
- Note that the Modbus interface on the PoloAir is not secured in any way - meaning you can read and write to it without authentication of any kind. Depending on your network you might want to firewall it and only let your HAss instance communicate to it over the respectice port(s).
- It is also possible to use a serial bus interface - haven’t tried it, should work the same, please refer to the Modbus integration documentation and the manual below.
You can find the whole Modbus config incl. all registers for the PoloAir >>here<<.
If you want to use the energy sensors created below in the HA Energy Dashboard add this to the corresponding parts of your configuration.yaml:
homeassistant:
customize_glob:
sensor.polo_energy*:
last_reset: '1970-01-01T00:00:00+00:00'
device_class: energy
state_class: measurement
I assume that you have a separate Modbus YAML File - if not you have to preface this with modbus:
and indent everything two spaces.
# Sensors for PoloAir 450+
- name: polo
type: tcp
host: 192.168.23.8
port: 502
retry_on_empty: true
retries: 5
sensors:
- name: polo_OnOff
slave: 1
address: 0
lazy_error_count: 2
data_type: uint16
- name: polo_EcoMode
slave: 1
address: 2
lazy_error_count: 2
data_type: uint16
- name: polo_AutoMode
slave: 1
address: 3
lazy_error_count: 2
data_type: uint16
- name: polo_CurrentMode
slave: 1
address: 4
lazy_error_count: 2
data_type: uint16
- name: polo_NextMode
slave: 1
address: 6
lazy_error_count: 2
data_type: uint16
- name: polo_ActiveAlarm
slave: 1
address: 599
lazy_error_count: 2
data_type: uint16
- name: polo_FanAirIn
slave: 1
address: 909
lazy_error_count: 2
data_type: uint16
unit_of_measurement: '%'
- name: polo_FanAirOut
slave: 1
address: 910
lazy_error_count: 2
data_type: uint16
unit_of_measurement: '%'
- name: polo_TempAirOutside
slave: 1
address: 903
lazy_error_count: 2
data_type: int16
unit_of_measurement: °C
device_class: temperature
- name: polo_TempAirIn
slave: 1
address: 901
lazy_error_count: 2
data_type: int16
unit_of_measurement: °C
device_class: temperature
- name: polo_TempAirOut
slave: 1
address: 902
lazy_error_count: 2
data_type: int16
unit_of_measurement: °C
device_class: temperature
- name: polo_FilterImpurity
slave: 1
address: 916
lazy_error_count: 2
data_type: uint16
unit_of_measurement: '%'
- name: polo_Energy
slave: 1
address: 920
lazy_error_count: 2
data_type: uint16
unit_of_measurement: 'W'
- name: polo_Heater
slave: 1
address: 921
lazy_error_count: 2
data_type: uint16
unit_of_measurement: 'W'
- name: polo_HeatexEnergy
slave: 1
address: 922
lazy_error_count: 2
data_type: uint16
unit_of_measurement: 'W'
- name: polo_HeatexEfficiency
slave: 1
address: 923
lazy_error_count: 2
data_type: uint16
unit_of_measurement: '%'
- name: polo_TempPanel
slave: 1
address: 945
lazy_error_count: 2
data_type: int16
unit_of_measurement: °C
device_class: temperature
- name: polo_energy_day
slave: 1
address: 926
lazy_error_count: 2
data_type: uint32
unit_of_measurement: 'kWh'
scale: 0.001
precision: 2
state_class: measurement
- name: polo_energy_month
slave: 1
address: 928
lazy_error_count: 2
data_type: uint32
unit_of_measurement: 'kWh'
scale: 0.001
precision: 2
state_class: measurement
- name: polo_energy_total
slave: 1
address: 930
lazy_error_count: 2
data_type: uint32
unit_of_measurement: 'kWh'
scale: 0.001
precision: 2
state_class: measurement
In your sensors.yaml:
# Transforming sensors from raw data to sensible formats / modes
- platform: template
sensors:
tpolo_currentmode:
friendly_name: "Aktueller Modus"
entity_id: sensor.polo_currentmode
value_template: >-
{% set mapper = {
'0' : 'Standby',
'1' : 'Abwesend',
'2' : 'Normal',
'3' : 'Intensiv',
'4' : 'Boost',
'5' : 'Küche',
'6' : 'Feuer',
'7' : 'Override',
'8' : 'Urlaub',
'9' : 'Luftqualität',
'10' : 'Aus' } %}
{% set state = states.sensor.polo_currentmode.state %}
{{ mapper[state] if state in mapper else 'Unknown' }}
- platform: template
sensors:
tpolo_nextmode:
friendly_name: "Nächster Modus"
entity_id: sensor.polo_nextmode
value_template: >-
{% set mapper = {
'0' : 'Standby',
'1' : 'Abwesend',
'2' : 'Normal',
'3' : 'Intensiv',
'4' : 'Boost',
'5' : 'Küche',
'6' : 'Feuer',
'7' : 'Override',
'8' : 'Urlaub' } %}
{% set state = states.sensor.polo_nextmode.state %}
{{ mapper[state] if state in mapper else 'Unknown' }}
- platform: template
sensors:
tpolo_tempairoutside:
friendly_name: 'Außenlufttemperatur'
device_class: temperature
unit_of_measurement: '°C'
value_template: '{{ states.sensor.polo_tempairoutside.state | float / 10 }}'
tpolo_tempairin:
friendly_name: 'Zulufttemperatur'
device_class: temperature
unit_of_measurement: '°C'
value_template: '{{ states.sensor.polo_tempairin.state | float / 10 }}'
tpolo_tempairout:
friendly_name: 'Ablufttemperatur'
device_class: temperature
unit_of_measurement: '°C'
value_template: '{{ states.sensor.polo_tempairout.state | float / 10 }}'
tpolo_fanairin:
friendly_name: 'Zuluftstrom'
unit_of_measurement: '%'
value_template: '{{ ((states.sensor.polo_fanairin.state | float / 10 )) | round(0) }}'
tpolo_fanairout:
friendly_name: 'Abluftstrom'
unit_of_measurement: '%'
value_template: '{{ ((states.sensor.polo_fanairout.state | float / 10 )) | round(0) }}'
If you need more / different sensors just refer to the documenation linked above and use the register.
Important: Register no. in HAss config = documenation - 1 (don’t know why…)
You can use this service call to change registers (refer to documentation):
- service: modbus.write_register
data:
address: 3 # Register you want to adress
unit: 1
value: 1 # Value you want to write into the register
hub: polo
Some examples for automations.yaml:
# Ventilation
- alias: 'Activate summer mode'
trigger:
- platform: time
at: '06:00:00'
condition:
- condition: numeric_state
entity_id: sensor.weather_today_max_temp
above: 27
action:
- service: modbus.write_register #Active auto mode which is configured in PoloAir
data:
address: 3
unit: 1
value: 1
hub: polo
- delay: 00:00:10
- service: modbus.write_register #Deactivate Eco mode
data:
address: 2
unit: 1
value: 0
hub: polo
- alias: 'Activate normal mode'
trigger:
- platform: time
at: '06:00:10'
condition:
- condition: numeric_state
entity_id: sensor.weather_today_max_temp
below: 27
action:
- service: modbus.write_register
data:
address: 2
unit: 1
value: 0
hub: polo
- delay: 00:00:10
- service: modbus.write_register
data:
address: 3
unit: 1
value: 0
hub: polo
- delay: 00:00:10
- service: modbus.write_register
data:
address: 4
unit: 1
value: 2
hub: polo
- alias: 'Activate Eco Mode when it is hot'
trigger:
platform: numeric_state
entity_id: sensor.polo_tempairoutside
above: 300 # Air sucked in is over 30°C
condition:
- condition: numeric_state
entity_id: sensor.polo_automode
below: 1
- condition: numeric_state
entity_id: sensor.polo_ecomode
below: 1
action:
- service: modbus.write_register
data:
address: 2
unit: 1
value: 1
hub: polo
- alias: 'Deactivate Eco Mode'
trigger:
platform: numeric_state
entity_id: sensor.polo_tempairoutside
below: 280
for: "01:00:00"
condition:
- condition: numeric_state
entity_id: sensor.polo_automode
below: 1
- condition: numeric_state
entity_id: sensor.polo_ecomode
above: 0
action:
- service: modbus.write_register
data:
address: 2
unit: 1
value: 0
hub: polo
Example of standard Lovelace cards to display interesting information and set modes:
cards:
- cards:
- entity: sensor.tpolo_fanairin
max: 100
min: 0
severity:
green: 30
red: 75
yellow: 50
type: gauge
- entity: sensor.polo_currentmode
max: 4
min: 0
name: Modus
severity:
green: 1
red: 3
yellow: 2
type: gauge
- entities:
- entity: sensor.polo_ecomode
hold_action:
action: call-service
service: modbus.write_register
service_data:
address: 2
hub: polo
unit: 1
value: 0
icon: 'mdi:tree-outline'
tap_action:
action: call-service
service: modbus.write_register
service_data:
address: 2
hub: polo
unit: 1
value: 1
- entity: sensor.polo_automode
hold_action:
action: call-service
service: modbus.write_register
service_data:
address: 3
hub: polo
unit: 1
value: 0
icon: 'mdi:clock-outline'
tap_action:
action: call-service
service: modbus.write_register
service_data:
address: 3
hub: polo
unit: 1
value: 1
show_name: false
type: glance
type: horizontal-stack
- cards:
- icon: 'mdi:home-floor-1'
name: Away
tap_action:
action: call-service
service: modbus.write_register
service_data:
address: 4
hub: polo
unit: 1
value: 1
type: button
- icon: 'mdi:home-floor-2'
name: Normal
tap_action:
action: call-service
service: modbus.write_register
service_data:
address: 4
hub: polo
unit: 1
value: 2
type: button
- icon: 'mdi:home-floor-3'
name: Intensive
tap_action:
action: call-service
service: modbus.write_register
service_data:
address: 4
hub: polo
unit: 1
value: 3
type: button
- icon: 'mdi:home-plus'
name: Boost
tap_action:
action: call-service
service: modbus.write_register
service_data:
address: 4
hub: polo
unit: 1
value: 4
type: button
type: horizontal-stack
- entities:
- entity: sensor.tpolo_tempairoutside
- entity: sensor.tpolo_tempairout
- entity: sensor.tpolo_tempairin
- entity: sensor.polo_energy
- entity: sensor.polo_heater
- entity: sensor.polo_heatexenergy
- entity: sensor.polo_heatexefficiency
hours_to_show: 36
refresh_interval: 0
type: history-graph
title: Ventilation
type: vertical-stack
Should look like this:
I’m not an expert on Modbus, but if you have any questions let me know…