ventilation-watcher/ventilation.yaml

683 lines
20 KiB
YAML

esphome:
name: ventilation
esp32:
board: nodemcu-32s
framework:
type: arduino
# Enable logging
logger:
level: INFO
# Enable Home Assistant API
api:
password: !secret device_password
reboot_timeout: 0s
ota:
password: !secret device_password
wifi:
ssid: "kh-iot"
password: !secret wifi_password
manual_ip:
static_ip: 192.168.5.39
gateway: 192.168.5.1
subnet: 255.255.255.0
fast_connect: true
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Ventilation Fallback Hotspot"
password: !secret hotspot_password
captive_portal:
web_server:
port: 80
uart:
id: mod_bus
tx_pin: 17
rx_pin: 18
baud_rate: 9600
parity: EVEN
stop_bits: 1
modbus:
send_wait_time: 200ms
id: modbus1
modbus_controller:
- id: ventilation_device
## the Modbus device addr
address: 0x1
modbus_id: modbus1
setup_priority: -10
update_interval: 10s
http_request:
useragent: ventilation watcher
timeout: 10s
interval:
- interval: 30s
then:
- http_request.post:
url: "http://192.168.5.2:88/influxdb/write?db=kanthaus"
headers:
Content-Type: text/plain
Authorization: Basic a2FudGhhdXMtd3JpdGVyOmdDTkxKMDlMdlV0blM4a2dQSFA0
body: !lambda |-
return ((std::string) "ventilation outdoor_air_temperature="+str_sprintf("%0.1f", id(outdoor_air_temperature).state)+
",extract_air_temperature="+str_sprintf("%0.1f", id(extract_air_temperature).state)+
",supply_air_temperature="+str_sprintf("%0.1f", id(supply_air_temperature).state)+
",supply_air_temperature_target="+str_sprintf("%0.1f", id(supply_air_temperature_target).state)+
",relative_humidity_exhaust="+str_sprintf("%0.1f", id(relative_humidity_of_exhaust_air).state)+
",supply_air_fan_speed="+str_sprintf("%0.1f", id(supply_air_fan_speed).state)+
",exhaust_air_fan_speed="+str_sprintf("%0.1f", id(exhaust_air_fan_speed).state)+
",heat_exchanger_ao="+str_sprintf("%0.1f", id(heat_exchanger_ao).state)+
",relative_humidity_setpoint="+str_sprintf("%0.1f", id(demand_control_rh_setpoint).state)
).c_str();
# Additional defrosting logic
- interval: 15min
then:
- lambda: |-
static int defrosting = 0;
if (defrosting == 1) {
id(user_mode_request).make_call().set_option("Auto").perform();
}
if (defrosting > 0) {
defrosting += 1;
if (defrosting >= 4) {
defrosting = 0;
}
return;
}
if (
defrosting == 0 &&
id(outdoor_air_temperature).state < -1 &&
id(supply_air_fan_speed).state > 500 &&
id(exhaust_air_fan_speed).state > 500 &&
id(recovery_efficiency).state < 80 &&
id(extract_air_temperature).state > 5
) {
defrosting = 1;
id(user_mode_request).make_call().set_option("Away").perform();
}
sensor:
- platform: uptime
name: "Uptime"
update_interval: 60s
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Air temperature - outdoor
id: outdoor_air_temperature
register_type: holding
address: 12101 # REG_SENSOR_OAT, 12102 according to the documentation, so 12101
unit_of_measurement: "°C"
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand control - calculated RH setpoint
# register_type: holding
# address: 12101
# unit_of_measurement: "%"
# value_type: S_WORD
# accuracy_decimals: 1
# filters:
# - multiply: 0.1
# - heartbeat: 5min
# - sliding_window_moving_average:
# window_size: 288
# - clamp:
# min_value: -10
# max_value: 10
# ignore_out_of_range: true
# - lambda: return 50 + (x+10)*(70-50)/(10+10);
# - round: 0
# on_value:
# then:
# - lambda: |-
# ESP_LOGI("demand_control_setpoint", "new RH setpoint calculated: %0.1f", x);
# auto previous = id(demand_control_rh_setpoint).state;
# if (abs(x - previous) < 2) return;
# if (id(demand_control_rh_setpoint_winter).state == id(demand_control_rh_setpoint_summer).state) {
# if (id(demand_control_season).state == "Winter") {
# id(demand_control_rh_setpoint_winter).make_call().set_value(x).perform();
# }
# else {
# id(demand_control_rh_setpoint_summer).make_call().set_value(x).perform();
# }
# }
# else if (id(demand_control_rh_setpoint_winter).state == previous) {
# ESP_LOGI("demand_control_setpoint", "selected winter setpoint");
# id(demand_control_rh_setpoint_winter).make_call().set_value(x).perform();
# }
# else if (id(demand_control_rh_setpoint_summer).state == previous) {
# ESP_LOGI("demand_control_setpoint", "selected summer setpoint");
# id(demand_control_rh_setpoint_summer).make_call().set_value(x).perform();
# }
# id(ventilation_device).update();
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Air temperature - supply
id: supply_air_temperature
register_type: holding
address: 12102 # REG_SENSOR_SAT, 12103 according to the documentation, so 12102
unit_of_measurement: "°C"
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Air temperature - extract
id: extract_air_temperature
register_type: holding
address: 12543 # REG_SENSOR_EAT, 12544 according to the documentation, so 12543
unit_of_measurement: "°C"
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Air temperature target - supply
id: supply_air_temperature_target
register_type: holding
address: 2000 # REG_TC_SP, 2001 according to the documentation, so 2000
unit_of_measurement: "°C"
value_type: S_WORD
accuracy_decimals: 1
filters:
- multiply: 0.1
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: "Relative humidity of exhaust air"
id: relative_humidity_of_exhaust_air
register_type: holding
address: 12135 # REG_SENSOR_RHS_PDM
unit_of_measurement: "%H"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed supply
id: supply_air_fan_speed
register_type: read
address: 12400 # REG_SENSOR_RPM_SAF, 12401 according to the documentation, so 12400
unit_of_measurement: "RPM"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed exhaust
id: exhaust_air_fan_speed
register_type: read
address: 12401 # REG_SENSOR_RPM_EAF, 12402 according to the documentation, so 12401
unit_of_measurement: "RPM"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: "Heat exchanger AO"
id: heat_exchanger_ao
register_type: read
address: 14102 # REG_OUTPUT_Y2_ANALOG, 14103 according to the documentation, minus 1
unit_of_measurement: "V"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Demand Control - RH setpoint
id: demand_control_rh_setpoint
register_type: read
address: 1010 # REG_DEMC_RH_PI_SP
unit_of_measurement: "%H"
value_type: U_WORD
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Demand Control - RH Sensor value
register_type: read
address: 1011 # REG_DEMC_RH_PI_FEEDBACK
unit_of_measurement: "%H"
value_type: U_WORD
on_value:
then:
- lambda: id(calculated_setpoint).publish_state(x);
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode remaining time
register_type: read
address: 1110 # REG_USERMODE_REMAINING_TIME_L and REG_USERMODE_REMAINING_TIME_H
register_count: 2
unit_of_measurement: "s"
value_type: U_DWORD_R
- platform: template
name: Recovery efficiency (temperature based)
id: recovery_efficiency
update_interval: 10s
unit_of_measurement: "%"
lambda: return (id(supply_air_temperature).state - id(outdoor_air_temperature).state) / (id(extract_air_temperature).state - id(outdoor_air_temperature).state);
filters:
- lambda: |-
if (id(supply_air_fan_speed).state < 500 || id(exhaust_air_fan_speed).state < 500) {
return {};
}
return x;
- throttle_average: 120s
- multiply: 100
- platform: template
name: Demand Control - Calculated setpoint
id: calculated_setpoint
unit_of_measurement: "%H"
filters:
- heartbeat: 1min
- median:
window_size: 120
send_every: 30
send_first_at: 15
- lambda: return x + 1.5;
- round: 0
on_value:
then:
- lambda: |-
ESP_LOGI("demand_control_setpoint", "new RH setpoint calculated: %0.1f", x);
auto previous = id(demand_control_rh_setpoint).state;
if (abs(x - previous) < 2) return;
if (id(demand_control_rh_setpoint_winter).state == id(demand_control_rh_setpoint_summer).state) {
if (id(demand_control_season).state == "Winter") {
id(demand_control_rh_setpoint_winter).make_call().set_value(x).perform();
}
else {
id(demand_control_rh_setpoint_summer).make_call().set_value(x).perform();
}
}
else if (id(demand_control_rh_setpoint_winter).state == previous) {
ESP_LOGI("demand_control_setpoint", "selected winter setpoint");
id(demand_control_rh_setpoint_winter).make_call().set_value(x).perform();
}
else if (id(demand_control_rh_setpoint_summer).state == previous) {
ESP_LOGI("demand_control_setpoint", "selected summer setpoint");
id(demand_control_rh_setpoint_summer).make_call().set_value(x).perform();
}
text_sensor:
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Demand Control Season
id: demand_control_season
register_type: read
address: 1038 # REG_SUMMER_WINTER, 1039 according to the documentation, minus 1
raw_encode: HEXBYTES
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
switch (value) {
case 0: return {"Summer"};
case 1: return {"Winter"};
default: return {"Unknown"};
}
return x;
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode active
register_type: holding
address: 1160 # REG_USERMODE_MODE 1161
raw_encode: HEXBYTES
lambda: |-
uint16_t value = modbus_controller::word_from_hex_str(x, 0);
switch (value) {
case 0: return {"Auto"};
case 1: return {"Manual"};
case 2: return {"Crowded"};
case 3: return {"Refresh"};
case 4: return {"Fireplace"};
case 5: return {"Away"};
case 6: return {"Holiday"};
case 7: return {"Cooker Hood"};
case 8: return {"Vacuum Cleaner"};
case 9: return {"CDI1"};
case 10: return {"CDI2"};
case 11: return {"CDI3"};
case 12: return {"PressureGuard"};
default: return {"Unknown"};
}
return x;
select:
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode - Request
id: user_mode_request
address: 1161 # REG_USERMODE_HMI_CHANGE_REQUEST 1162
value_type: U_WORD
optimistic: true
optionsmap:
"None": 0
"Auto": 1
"Manual": 2
"Crowded": 3
"Refresh": 4
"Fireplace": 5
"Away": 6
"Holiday": 7
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Crowded - Supply Fan Speed
address: 1134
value_type: U_WORD
optimistic: true
optionsmap:
"Normal": 3
"High": 4
"Maximum": 5
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Crowded - Extract Fan Speed
address: 1135
value_type: U_WORD
optimistic: true
optionsmap:
"Normal": 3
"High": 4
"Maximum": 5
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Refresh - Supply Fan Speed
address: 1136
value_type: U_WORD
optimistic: true
optionsmap:
"Normal": 3
"High": 4
"Maximum": 5
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Refresh - Extract Fan Speed
address: 1137
value_type: U_WORD
optimistic: true
optionsmap:
"Normal": 3
"High": 4
"Maximum": 5
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Away - Supply Fan Speed
address: 1140
value_type: U_WORD
optimistic: true
optionsmap:
"Off": 0
"Minimum": 1
"Low": 2
"Normal": 3
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Away - Extract Fan Speed
address: 1141
value_type: U_WORD
optimistic: true
optionsmap:
"Off": 0
"Minimum": 1
"Low": 2
"Normal": 3
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Holiday - Supply Fan Speed
address: 1142
value_type: U_WORD
optimistic: true
optionsmap:
"Off": 0
"Minimum": 1
"Low": 2
"Normal": 3
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Holiday - Extract Fan Speed
address: 1143
value_type: U_WORD
optimistic: true
optionsmap:
"Off": 0
"Minimum": 1
"Low": 2
"Normal": 3
number:
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Holiday - Time delay setting (days)
address: 1100
unit_of_measurement: "days"
value_type: U_WORD
min_value: 1
max_value: 365
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Away - Time delay setting (hours)
address: 1101
unit_of_measurement: "min"
value_type: U_WORD
min_value: 1
max_value: 72
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Crowded - Time delay setting (hours)
address: 1104 #REG_USERMODE_CROWDED_TIME 1105
unit_of_measurement: "h"
value_type: U_WORD
min_value: 1
max_value: 8
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: User Mode Refresh - Time delay setting (minutes)
address: 1103
unit_of_measurement: "min"
value_type: U_WORD
min_value: 1
max_value: 240
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed Low - SAF speed value
address: 1402
unit_of_measurement: "%"
value_type: U_WORD
min_value: 16
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed Low - EAF speed value
address: 1403
unit_of_measurement: "%"
value_type: U_WORD
min_value: 16
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed Normal - SAF speed value
address: 1404
unit_of_measurement: "%"
value_type: U_WORD
min_value: 16
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed Normal - EAF speed value
address: 1405
unit_of_measurement: "%"
value_type: U_WORD
min_value: 16
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed High - SAF speed value
address: 1406
unit_of_measurement: "%"
value_type: U_WORD
min_value: 16
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Fan speed High - EAF speed value
address: 1407
unit_of_measurement: "%"
value_type: U_WORD
min_value: 16
max_value: 100
step: 1
mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - CO2 Pband
# address: 1040
# unit_of_measurement: "ppm"
# value_type: U_WORD
# min_value: 50
# max_value: 2000
# step: 1
# mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - CO2 set point
# address: 1042
# unit_of_measurement: "ppm"
# value_type: U_WORD
# min_value: 100
# max_value: 2000
# step: 1
# mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - CO2 sensor value
# address: 12114
# unit_of_measurement: "ppm"
# value_type: U_WORD
# min_value: 0
# max_value: 2000
# step: 1
# mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - CO2 sensor value UI1
# address: 12150
# unit_of_measurement: "ppm"
# value_type: U_WORD
# min_value: 0
# max_value: 2000
# step: 1
# mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - RH sensor value
# address: 12108
# unit_of_measurement: "%"
# value_type: U_WORD
# min_value: 0
# max_value: 100
# step: 1
# mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - CO2 allowed flag
# address: 1043
# unit_of_measurement: ""
# value_type: U_WORD
# min_value: 0
# max_value: 1
# step: 1
# mode: box
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - RH allowed flag
# address: 1034
# unit_of_measurement: ""
# value_type: U_WORD
# min_value: 0
# max_value: 1
# step: 1
# mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Demand Control - RH set point winter
id: demand_control_rh_setpoint_winter
address: 1032
unit_of_measurement: "%"
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: Demand Control - RH set point summer
id: demand_control_rh_setpoint_summer
address: 1033
unit_of_measurement: "%"
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: SAF Override Enabled
address: 13600
value_type: U_WORD
min_value: 0
max_value: 1
step: 1
mode: box
- platform: modbus_controller
modbus_controller_id: ventilation_device
name: SAF Override Speed
address: 13800
unit_of_measurement: "%"
value_type: U_WORD
min_value: 0
max_value: 100
step: 1
mode: box
# switch:
# NOTE: cannot be used because it sends command 05 instead 06
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - CO2 allowed flag
# address: 1043
# register_type: holding
# - platform: modbus_controller
# modbus_controller_id: ventilation_device
# name: Demand Control - RH allowed flag
# address: 1034
# register_type: holding