Created
November 13, 2020 17:19
-
-
Save SteveDinn/360542f4462ba6073f678a1dd79fa444 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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