#--------------------------------------------------------------------------------------------------
# Air conditioning system management
#--------------------------------------------------------------------------------------------------
group:
ac_splits:
name: AC splits
entities:
- climate.kitchen
- climate.library
- climate.parent_bedroom
- climate.kid_bedroom
- climate.gaming_room
- climate.living_room_1
- climate.living_room_2
- climate.office
ac_streamers:
name: Daikin A/C streamers
entities:
- switch.ac_kitchen_streamer
- switch.ac_library_streamer
- switch.ac_parent_bedroom_streamer
- switch.ac_gaming_room_streamer
- switch.ac_living_room_1_streamer
- switch.ac_living_room_2_streamer
- switch.ac_office_streamer
#---- Templated electric consumption monitoring ---------------------------------------------------
template:
- trigger:
- trigger: time_pattern
minutes: /5
sensor:
- name: ac_energy
availability: >
{{ not 'unavailable' in
[
states('sensor.smart_meter_pac_1_electric_consumption_kwh'),
states('sensor.smart_meter_pac_2_electric_consumption_kwh')
] and not 'unknown' in
[
states('sensor.smart_meter_pac_1_electric_consumption_kwh'),
states('sensor.smart_meter_pac_2_electric_consumption_kwh')
]
}}
state: "{{ states('sensor.smart_meter_pac_1_electric_consumption_kwh') | float + states('sensor.heater_energy') | float + states('sensor.smart_meter_pac_2_electric_consumption_kwh') | float }}"
#---- Various utility meters for graphs -----------------------------------------------------------
utility_meter:
daily_ac_energy:
source: sensor.ac_energy
cycle: daily
daily_pac_consumption:
source: sensor.smart_meter_pac_1_electric_consumption_kwh
cycle: daily
daily_pac2_consumption:
source: sensor.smart_meter_pac_2_electric_consumption_kwh
cycle: daily
weekly_ac_energy:
source: sensor.ac_energy
cycle: weekly
weekly_pac_consumption:
source: sensor.smart_meter_pac_1_electric_consumption_kwh
cycle: weekly
weekly_pac2_consumption:
source: sensor.smart_meter_pac_2_electric_consumption_kwh
cycle: weekly
monthly_ac_energy:
source: sensor.ac_energy
cycle: monthly
monthly_pac_consumption:
source: sensor.smart_meter_pac_1_electric_consumption_kwh
cycle: monthly
monthly_pac2_consumption:
source: sensor.smart_meter_pac_2_electric_consumption_kwh
cycle: monthly
#---- AC variables for automations ----------------------------------------------------------------
input_number:
ac_temp_office:
name: temperature in office
min: 12
max: 28
ac_temp_living:
name: temperature in living room
min: 12
max: 28
ac_temp_gaming:
name: temperature in gaming room
min: 12
max: 28
ac_temp_kitchen:
name: temperature in kitchen
min: 12
max: 28
ac_temp_parents:
name: temperature in parents bedroom
min: 12
max: 28
ac_temp_library:
name: temperature in library
min: 12
max: 28
ac_temp_kid:
name: temperature in kid bedroom
min: 12
max: 28
ac_idle_heat_temp:
name: AC heating target temp when not supposed to really act
min: 12
initial: 15
max: 28
ac_idle_cool_temp:
name: AC cooling target temp when not supposed to really act
min: 12
initial: 27
max: 28
office_comfort_heat_temp:
min: 18
initial: 19
max: 20
office_comfort_cool_temp:
min: 21
initial: 23
max: 25
living_comfort_heat_temp:
min: 18
initial: 19
max: 20
living_comfort_cool_temp:
min: 23
initial: 25
max: 26
kid_comfort_heat_temp:
min: 17
initial: 18.5
max: 19
kid_comfort_cool_temp:
min: 22
initial: 24
max: 24
parents_comfort_heat_temp:
min: 18
initial: 18.5
max: 19
parents_comfort_cool_temp:
min: 22
initial: 24
max: 25
gaming_comfort_heat_temp:
min: 17
initial: 18
max: 20
gaming_comfort_cool_temp:
min: 22
initial: 24
max: 25
library_comfort_heat_temp:
min: 18
initial: 20
max: 21
library_comfort_cool_temp:
min: 23
initial: 24
max: 27
kitchen_comfort_heat_temp:
min: 19
initial: 20
max: 21
kitchen_comfort_cool_temp:
min: 22
initial: 24
max: 24
temp_offset:
min: -5
initial: 0
max: 5
ref_temp:
min: -10
initial: 22
max: 50
#---- AC split overrides --------------------------------------------------------------------------
input_text:
gaming_override:
name: Gaming room AC override
living_override:
name: Living room AC override
office_override:
name: Office AC override
kitchen_override:
name: Kitchen AC override
library_override:
name: Library AC override
parents_override:
name: Parents AC override
kid_override:
name: kid AC override
hvac_mode:
name: Global AC mode
hvac_mode_backup:
name: Previous AC mode
#---- AC split disable tag ------------------------------------------------------------------------
input_boolean:
kitchen_ac_disable:
name: Kitchen A/C automation disabling
parents_ac_disable:
name: Parents bedroom A/C automation disabling
library_ac_disable:
name: Library A/C automation disabling
kid_ac_disable:
name: kid bedroom A/C automation disabling
office_ac_disable:
name: Office A/C automation disabling
gaming_ac_disable:
name: Gaming room A/C automation disabling
living_ac_disable:
name: Living room A/C automation disabling
gaming_room_door:
name: Gaming room door dummy sensor
initial: off
office_window:
name: Office window dummy sensor
initial: off
#---- One automation to rule them all -------------------------------------------------------------
automation:
- id: "110001"
alias: Airco - Pilot all A/C mode & temp
description: Set A/C modes, temperature, overrides, disabled & away, per room
triggers:
- trigger: time_pattern
minutes: "/20"
conditions:
- "{{ states('input_boolean.ac_pause') == 'off' }}"
actions:
#----- Global abritrations ----------
- if: "{{ now().minute == 0 and states('switch.faikin_kitchen_powerful') == 'on' }}"
then:
- action: script.ac_powerful
data:
mode: "off"
- action: script.calculate_ac_override
- action: script.calculate_ac_mode
- action: script.calculate_ac_temp
- action: script.detect_conflicts
- action: script.set_fans
- action: script.ac_logs
#----- Mode is set globally ---------
- if: "{{ states('input_text.hvac_mode') != states('input_text.hvac_mode_backup') }}"
then:
- action: climate.set_hvac_mode
data:
hvac_mode: "{{ states('input_text.hvac_mode') }}"
target:
entity_id: group.ac_splits
- action: script.uns
data:
log_facility: airco
message: SET - A/C Mode was {{ states('input_text.hvac_mode_backup') }} and should now be {{ states('input_text.hvac_mode') }}
- delay: "00:00:30"
#----- Temp is set individually -----
- repeat:
for_each:
- hvac: climate.faikin_kitchen_mqtt_hvac
ip: "192.168.0.119"
room: "kitchen"
temp: input_number.ac_temp_kitchen
door: binary_sensor.kitchen_door_sensor_access_control_kitchen
override: input_text.kitchen_override
disabled: input_boolean.kitchen_ac_disable
- hvac: climate.faikin_library_mqtt_hvac
ip: "192.168.0.120"
room: "library"
temp: input_number.ac_temp_library
door: binary_sensor.library_door_sensor_window_door_is_open
override: input_text.library_override
disabled: input_boolean.library_ac_disable
- hvac: climate.faikin_parents_mqtt_hvac
ip: "192.168.0.116"
room: "Parent bedroom"
temp: input_number.ac_temp_parents
door: binary_sensor.parent_bedroom_door_sensor_access_control_window_door_is_open
override: input_text.parents_override
disabled: input_boolean.parents_ac_disable
- hvac: climate.faikin_gaming_mqtt_hvac
ip: "192.168.0.117"
room: "Gaming room"
temp: input_number.ac_temp_gaming
door: input_boolean.gaming_room_door
override: input_text.gaming_override
disabled: input_boolean.gaming_ac_disable
- hvac: climate.faikin_living1_mqtt_hvac
ip: "192.168.0.115"
room: "Living room 1"
temp: input_number.ac_temp_living
door: binary_sensor.living_room_door_sensor_window_door_is_open_3
override: input_text.living_override
disabled: input_boolean.living_ac_disable
- hvac: climate.faikin_living2_mqtt_hvac
ip: "192.168.0.121"
room: "Living room 2"
temp: input_number.ac_temp_living
door: binary_sensor.living_room_door_sensor_window_door_is_open_3
override: input_text.living_override
disabled: input_boolean.living_ac_disable
- hvac: climate.office
ip: "192.168.0.101"
room: "Office"
temp: input_number.ac_temp_office
door: input_boolean.office_window
override: input_text.office_override
disabled: input_boolean.office_ac_disable
sequence:
# If A/C unit isn't disabled or under an override
- if: "{{ states(repeat.item.override) == 'off' and states(repeat.item.disabled) == 'off' }}"
then:
# If A/C unit isn't unavailable
- if: "{{ states(repeat.item.hvac) | lower not in ['none', 'unavailable', 'unknown'] }}"
then:
- action: climate.set_temperature
target:
entity_id: "{{ repeat.item.hvac }}"
data:
temperature: "{{ states(repeat.item.temp) | float }}"
- delay: "00:00:30"
- if: "{{ states(repeat.item.hvac) != states('input_text.hvac_mode') or state_attr(repeat.item.hvac, 'temperature') | float != states(repeat.item.temp) | float }}"
then:
- action: script.ac_recovery
data:
hvac: "{{ repeat.item.hvac }}"
ip: "{{ repeat.item.ip }}"
mode: "{{ states('input_text.hvac_mode') }}"
temperature: "{{ repeat.item.temp }}"
else:
- action: script.uns
data:
log_facility: airco
message: SET - {{ repeat.item.hvac.split('.')[1]
+ ' was ' + states(repeat.item.hvac) + '/' + state_attr(repeat.item.hvac, 'temperature') | string()
+ ' now is ' + states('input_text.hvac_mode') + '/' + states(repeat.item.temp) | string()
+ ', door is ' + iif(states(repeat.item.door) == 'on', 'opened', 'closed') + '.' }}
else:
- action: script.ac_recovery
data:
hvac: "{{ repeat.item.hvac }}"
ip: "{{ repeat.item.ip }}"
mode: "{{ states('input_text.hvac_mode') }}"
temperature: "{{ repeat.item.temp }}"
else:
- if: "{{ states(repeat.item.disabled) == 'off' }}"
then:
- action: script.uns
data:
log_facility: airco
message: WARNING - {{ repeat.item.hvac.split('.')[1] + ' override mode is on, skipping.' }}
else:
- action: script.uns
data:
log_facility: airco
message: WARNING - {{ repeat.item.hvac.split('.')[1] + ' is disabled, skipping.' }}
#---- Scripts supporting AC automation ------------------------------------------------------------
script:
#---- Calculate temperature that needs to be applied in each room -------------------------------
calculate_ac_temp:
sequence:
- action: input_number.set_value
target:
entity_id: input_number.temp_offset
data_template:
value: >
{%- if states('sensor.teleinfo_periode_tarifaire') == 'hpjr' -%}
{{ -1 |float }}
{% elif state_attr('weather.home','temperature') | float(19) < 0 %}
{{ 1.0 |float }}
{% elif (state_attr('weather.home','temperature') | float(19) > 0) and (state_attr('weather.home','temperature') | float(19) < 5) %}
{{ 0.5 |float }}
{%- else %}
{{ 0 |float }}
{%- endif -%}
- if: "{{ is_state('input_boolean.home_away_mode','off') }}"
then:
# Office
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_office
data_template:
value: >
{% if is_state('person.me','not_home') %}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- elif now().hour not in (2,3,4,5,6,7,8) -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.office_comfort_cool_temp')|float, states('input_number.office_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
# Living
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_living
data_template:
value: >
{%- if now().hour not in (0,1,2,3,4,5,6,7,8) and is_state('sensor.tempo_period_isred','False')
and states('binary_sensor.living_room_door_sensor_window_door_is_open_3') == 'off' -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.living_comfort_cool_temp')|float, states('input_number.living_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{% elif is_state('sensor.tempo_period_isred','True') and now().weekday() not in (2,5,6) -%}
{{ 17 | float }}
{% elif is_state('sensor.tempo_period_isred','True') and now().weekday() in (2,5,6) -%}
{{ 18 | float }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
# Kitchen
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_kitchen
data_template:
value: >
{%- if (now().hour in (7,8,12,13,18,19,20,21) or (now().hour in (10,11,14,18,19,22) and now().weekday() in (2,5,6)))
and states('binary_sensor.kitchen_door_sensor_access_control_kitchen') == 'off' -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.kitchen_comfort_cool_temp')|float, states('input_number.kitchen_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
# Parents
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_parents
data_template:
value: >
{%- if now().hour in (23,0,1,2,3,4,5,6,7,8,9,13)
and states('binary_sensor.parent_bedroom_door_sensor_access_control_window_door_is_open') == 'off' -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.parents_comfort_cool_temp')|float, states('input_number.parents_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
# Library
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_library
data_template:
value: >
{%- if (8 < now().hour < 23 and is_state('person.wife','home'))
and states('binary_sensor.library_door_sensor_window_door_is_open') == 'off' -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.library_comfort_cool_temp')|float, states('input_number.library_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
# kid
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_kid
data_template:
value: >
{%- if now().hour in (18,19,20,21,22,23,0,1,2,3,4,5,6,7) or now().weekday() in (2,5,6) %}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.kid_comfort_cool_temp')|float, states('input_number.kid_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
# Gaming
- action: input_number.set_value
target:
entity_id: input_number.ac_temp_gaming
data_template:
value: >
{%- if is_state('sensor.tempo_period_isred', 'False') and (now().hour in (19,20) or (now().weekday() in (2,5,6) and (9 < now().hour < 22))) -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.gaming_comfort_cool_temp')|float, states('input_number.gaming_comfort_heat_temp')|float + states('input_number.temp_offset')|float) }}
{%- else -%}
{{ iif(states('input_text.hvac_mode') == "cool", states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}
{%- endif %}
else:
- action: input_number.set_value
target:
entity_id:
- input_number.ac_temp_gaming
- input_number.ac_temp_kid
- input_number.ac_temp_parents
- input_number.ac_temp_kitchen
- input_number.ac_temp_living
- input_number.ac_temp_library
data:
value: "{{ iif(states('input_text.hvac_mode') == 'cool', states('input_number.ac_idle_cool_temp')|float, states('input_number.ac_idle_heat_temp')|float) }}"
#---- Calculate under which mode each unit should operate ---------------------------------------
calculate_ac_mode:
sequence:
- if: "{{ now().hour in (9,10,11,12,13,14,15,16,17,18,19,20,21,22,23) and now().minute == 0 }}"
then:
- action: input_text.set_value
data_template:
value: "{{states('input_text.hvac_mode')}}"
target:
entity_id:
- input_text.hvac_mode_backup
- action: input_number.set_value
data_template:
value: "{{ ((states('sensor.kitchen_temp_temperature') | float(24) + states('sensor.living_temp_temperature') | float(24) + state_attr('weather.home','temperature') | float(24)) /3) | round(1) }}"
target:
entity_id:
- input_number.ref_temp
- action: input_text.set_value
data_template:
value: >
{% if states('input_number.ref_temp') | float(24) < 23.2 %}
{{ 'heat' }}
{%- else -%}
{{ 'cool' }}
{%- endif %}
target:
entity_id:
- input_text.hvac_mode
- action: system_log.write
data:
logger: "AC"
level: warning
message: "AC-Mode set to {{ states('input_text.hvac_mode') }} because reference temperature is {{ states('input_number.ref_temp') }}"
- if: "{{ states('input_text.hvac_mode') != states('input_text.hvac_mode_backup') }}"
then:
- action: system_log.write
data:
logger: "AC"
level: warning
message: "AC Mode changed from {{states('input_text.hvac_mode_backup')}} to {{states('input_text.hvac_mode')}}"