Skip to content

Instantly share code, notes, and snippets.

@SteveDinn
Created November 13, 2020 17:19
Show Gist options
  • Select an option

  • Save SteveDinn/360542f4462ba6073f678a1dd79fa444 to your computer and use it in GitHub Desktop.

Select an option

Save SteveDinn/360542f4462ba6073f678a1dd79fa444 to your computer and use it in GitHub Desktop.
# This file is the common stuff that both the recroom heatpump and the livingroom heatpump
# can use.
# This defines the climate mode for the whole house. Since I have a mini-split heat pump,
# the two indoor units don't like it if one is set to cooling and the other to heating.
input_select:
climate_mode:
name: Climate mode
options:
- "Off"
- "Manual"
- "Heat"
- "Cool"
climate_mode_previous:
name: Climate mode (previous)
options:
- "Off"
- "Manual"
- "Heat"
- "Cool"
automation:
- alias: climate_mode_change
mode: queued
max: 25
trigger:
- platform: state
entity_id:
- input_select.climate_mode
variables:
climateMode: >
{{ states('input_select.climate_mode') | lower }}
action:
- service: input_select.select_option
data:
entity_id: input_select.climate_mode_previous
option: >
{{ states('input_select.climate_mode_previous')
if is_state('input_select.climate_mode', 'Off')
else states('input_select.climate_mode') }}
- condition: template
value_template: >
{{ climateMode != 'manual' }}
- service: input_select.select_option
data_template:
entity_id:
- input_select.livingroom_heatpump_mode
- input_select.recroom_heatpump_mode
option: >
{{ climateMode
if (climateMode in state_attr('climate.livingroom', 'hvac_modes'))
else 'off' }}
- alias: climate_status
description: Sends an MQTT command so the climate component can update.
mode: queued
max: 25
trigger:
- platform: event
event_type: climate_status
action:
- service: mqtt.publish
data_template:
topic: >
{%- set area = trigger.event.data.area | lower -%}
climate/{{ area }}/stat
retain: true
payload: >
{%- set area = trigger.event.data.area | lower -%}
{%- set mode = states('input_select.' + area + '_heatpump_mode') -%}
{%- set action = 'idle' -%}
{%- if (mode == 'off') -%}
{%- set action = 'off' -%}
{%- elif (states('input_text.' + area + '_heatpump_command') | from_json).mode == mode -%}
{%- set action = mode + 'ing' -%}
{%- endif -%}
{{
{
'mode': mode,
'action': action,
'temp': states('input_number.' + area + '_heatpump_temp'),
'fan': states('input_select.' + area + '_heatpump_fanspeed'),
} | to_json
}}
- alias: heatpump_command
mode: queued
max: 25
description: Writes the command to set the heatpump to what the area's fields dictate
trigger:
# Triggers for things that would be changed manually
- platform: state
entity_id:
- input_number.livingroom_heatpump_temp
- input_select.livingroom_heatpump_mode
- input_select.livingroom_heatpump_fanspeed
- input_number.livingroom_temperature_range_high
- input_number.livingroom_temperature_range_low
- input_number.recroom_heatpump_temp
- input_select.recroom_heatpump_mode
- input_select.recroom_heatpump_fanspeed
- input_number.recroom_temperature_range_high
- input_number.recroom_temperature_range_low
# triggers for sensor state changes that happen automatically
- platform: state
entity_id:
- binary_sensor.livingroom_temperature_diff_high
- binary_sensor.livingroom_temperature_diff_low
- binary_sensor.recroom_temperature_diff_high
- binary_sensor.recroom_temperature_diff_low
from: "on"
to: "off"
for: "00:05:00"
- platform: state
entity_id:
- binary_sensor.livingroom_temperature_diff_high
- binary_sensor.livingroom_temperature_diff_low
- binary_sensor.recroom_temperature_diff_high
- binary_sensor.recroom_temperature_diff_low
from: "off"
to: "on"
for: "00:05:00"
condition:
- condition: template
value_template: >
{%- set parts = trigger.entity_id.split('.') -%}
{%- if (parts[0] != 'binary_sensor') -%}
true
{%- else -%}
{%- set parts = parts[1].split('_') -%}
{%- set room = parts[0] -%}
{%- set high = 'binary_sensor.' + room + '_temperature_diff_high' -%}
{%- set low = 'binary_sensor.' + room + '_temperature_diff_low' -%}
{{ 'true' if (is_state(high, 'on') or is_state(low, 'on')) else 'false' }}
{%- endif -%}
action:
########################################################################################
# Note: Do NOT use the template sensors in these calculations becuase they update too
# slowly. These include
# - sensor.[livingroom, recroom]_temperature_diff
# - binary_sensor.[livingroom, recroom]_temperature_diff_[high, low]
# We will recalculate those values in this template.
########################################################################################
- service: input_text.set_value
data_template:
entity_id: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
input_text.{{ area }}_heatpump_command_next
value: >
{# Set area #}
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
{# Get sensor and input states #}
{%- set temperature = states('sensor.' + area + '_temperature') | float -%}
{%- set mode = states('input_select.' + area + '_heatpump_mode') | lower -%}
{%- set setpoint = states('input_number.' + area + '_heatpump_temp') | float -%}
{%- set fanspeed = states('input_select.' + area + '_heatpump_fanspeed') | lower -%}
{%- set range_high = states('input_number.' + area + '_temperature_range_high') | float -%}
{%- set range_low = (states('input_number.' + area + '_temperature_range_low') | float) * -1 -%}
{# Calculate temperature ranges #}
{%- set delta = temperature - setpoint -%}
{%- set delta_multiplier = 1 if (mode == 'heat') else (-1 if (mode == 'cool') else 0) -%}
{%- set diff = delta * delta_multiplier -%}
{%- set diff_high = diff > range_high -%}
{%- set diff_low = diff < range_low -%}
{%- set power = 'off' if (mode == 'off') else 'on' -%}
{%- set heatpumpTemp = setpoint | round(0) | int -%}
{%- if (mode in ['heat', 'cool']) -%}
{# if we're heating, raise the heatpump setpoint. If we're cooling, drop it. #}
{# 2.4 will make it so that when we round it, it'll be 2 degrees higher or lower #}
{%- set heatpumpTemp =
(setpoint + 2.4) if (mode == 'heat') else
((setpoint - 2.4) if (mode == 'cool') else
(setpoint + 0.4)) -%}
{# Make sure that heatpump is between min_temp and max_temp #}
{%- set entity = 'climate.' + area -%}
{%- set max_temp = state_attr(entity, 'max_temp') | float | round(0) -%}
{%- set min_temp = state_attr(entity, 'min_temp') | float | round(0) -%}
{%- set heatpumpTemp = [max_temp, ([min_temp, heatpumpTemp | round(0)] | max)] | min | int -%}
{%- if diff_high -%}
{%- set power = 'off' -%}
{%- set mode = 'off' -%}
{%- endif -%}
{%- endif -%}
{%- set fanspeeds = {
'auto': 'auto',
'low': 'min',
'medium': 'medium',
'high': 'max'
} -%}
{{
{
'vendor': 'midea',
'power': power,
'mode': mode,
'temp': heatpumpTemp,
'fanspeed': fanspeeds[fanspeed]
} | to_json
}}
- service: mqtt.publish
data_template:
topic: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
climate/{{ area }}/debug/heatpump_command
payload: >
1 - {%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
{{ {
'trigger': trigger.entity_id,
'from': trigger.from_state.state,
'to': trigger.to_state.state,
'area': area,
'command': states('input_text.' + area + '_heatpump_command'),
'command_next': states('input_text.' + area + '_heatpump_command_next')
} | to_json }}
- event: climate_status
event_data_template:
area: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] -%}
{{ area }}
- condition: template
value_template: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
{%- set current = states('input_text.' + area + '_heatpump_command') -%}
{%- set next = states('input_text.' + area + '_heatpump_command_next') -%}
{{ current != next }}
- service: input_text.set_value
data_template:
entity_id: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
input_text.{{ area }}_heatpump_command
value: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
{{ states('input_text.' + area + '_heatpump_command_next') }}
- service: mqtt.publish
data_template:
topic: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
climate/{{ area }}/debug/heatpump_command
payload: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
2 - {{ {
'trigger': trigger.entity_id,
'from': trigger.from_state.state,
'to': trigger.to_state.state,
'area': area,
'command': 'Committing ' + states('input_text.' + area + '_heatpump_command')
} | to_json }}
- event: climate_status
event_data_template:
area: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
{{ area }}
- alias: heatpump_status_changed
mode: queued
max: 25
description: Updates the status and starts the timer when the command changes
trigger:
- platform: state
entity_id: input_text.livingroom_heatpump_command
- platform: state
entity_id: input_text.recroom_heatpump_command
condition:
- condition: template
value_template: >
{{ trigger.from_state.state
and (trigger.from_state.state not in ['', 'unknown', 'undefined'])
and (trigger.from_state.state != trigger.to_state.state) }}
action:
- service: mqtt.publish
data_template:
topic: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
climate/{{ area }}/debug/heatpump_status_changed
payload: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] | lower -%}
1 - {{ {
'trigger': trigger.entity_id,
'from': trigger.from_state.state,
'to': trigger.to_state.state,
'area': area
} | to_json }}
- service: timer.cancel
data_template:
entity_id: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] -%}
timer.{{ area }}_heatpump_command
- service: timer.start
data_template:
entity_id: >
{%- set area = trigger.entity_id.split('.')[1].split('_')[0] -%}
timer.{{ area }}_heatpump_command
- alias: heatpump_status_stable
description: Issues the command when it has not changed for 1 second
mode: queued
max: 25
trigger:
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.livingroom_heatpump_command
- platform: event
event_type: timer.finished
event_data:
entity_id: timer.recroom_heatpump_command
condition:
- condition: template
value_template: >
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] -%}
{{ not is_state('input_text.' + area + '_heatpump_command', '') }}
#- condition: template
# value_template: >
# {%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] -%}
# {{ now().timestamp() - as_timestamp(states.input_text[area + '_heatpump_command'].last_changed) >= 1 }}
action:
- service: mqtt.publish
data_template:
topic: >
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] | lower -%}
climate/{{ area }}/debug/heatpump_status_stable
payload: >
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] | lower -%}
{%- set command = states('input_text.' + area + '_heatpump_command') -%}
1 - {{ {
'trigger': trigger.event.data.entity_id,
'room': area,
'command': command
} | to_json
}}
- service: mqtt.publish
data_template:
topic: >
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] | lower -%}
climate/{{ area }}/debug/heatpump_status_stable
payload: >
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] | lower -%}
{%- set command = states('input_text.' + area + '_heatpump_command') -%}
2 - {{ {
'trigger': trigger.event.data.entity_id,
'room': area,
'command': command
} | to_json
}}
- service: mqtt.publish
data_template:
topic: >
{%- set areas = {
'livingroom': 'LivingRoomIR',
'recroom': 'RecroomIR'
}
-%}
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] | lower -%}
cmnd/{{ areas[area] }}/IRhvac
payload: >
{%- set area = trigger.event.data.entity_id.split('.')[1].split('_')[0] | lower -%}
{{ states('input_text.' + area + '_heatpump_command') }}
#######################################################
# MQTT listening automations
#######################################################
- alias: heatpump_mode_mqtt
mode: queued
max: 25
trigger:
- platform: mqtt
topic: "climate/livingroom/MODE"
- platform: mqtt
topic: "climate/recroom/MODE"
action:
- service: input_select.select_option
data_template:
entity_id: >
{%- set area = trigger.topic.split('/')[1] | lower -%}
input_select.{{ area }}_heatpump_mode
option: >
{{ trigger.payload | lower }}
- alias: heatpump_fanspeed_mqtt
mode: queued
max: 25
trigger:
- platform: mqtt
topic: "climate/livingroom/FAN"
- platform: mqtt
topic: "climate/recroom/FAN"
action:
- service: input_select.select_option
data_template:
entity_id: >
{%- set area = trigger.topic.split('/')[1] | lower -%}
input_select.{{ area }}_heatpump_fanspeed
option: >
{{ trigger.payload | lower }}
- alias: heatpump_temp_mqtt
mode: queued
max: 25
trigger:
- platform: mqtt
topic: "climate/livingroom/TEMP"
- platform: mqtt
topic: "climate/recroom/TEMP"
action:
- service: input_number.set_value
data_template:
entity_id: >
{%- set area = trigger.topic.split('/')[1] | lower -%}
input_number.{{ area }}_heatpump_temp
value: >
{{ trigger.payload | float | round(1) }}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment