I feel that it is important that I describe my setup, what works, how it works, and what I’m trying to do now before I get into the configuration.
I have a nest thermostat on the first floor and a Z-Wave multisensor on the second floor. As of now, I have a handful of automations that allow me to manipulate the nest thermostat to keep the second floor at a constant temperature. This works great and has for years.
How this works…When I select Home Assistant to do temperature control off of the second floor, it will artificially bump up the target temperature of the nest by the difference between the first floor and the second floor until the second floor hits the desired temperature.
Example:
- Mode: Heat
- Second Floor Target Temp = 72
- Nest Target Temp = 72
- Second Floor Current Temp = 70
- First Floor Current Temp = 72
Action: Increase Nest Target Temp to 74 and stay there until Second Floor Current Temp = 72. Once this is completed, Set Nest Target Temp back to 72.
Once again, this works great! I will share my current solution at the end as others might want to use this.
But now onto the problem!
I am trying to convert these automations into a generic thermostat and a switch. This will allow me to use the lovelace thermostat card and make it look more “real”.
The current idea is to use 2 generic thermostats (heat/cool) and 2 switches (heat/cool). I’m sure I’ll be able to refine this to 1 switch in the future but for simplicity, I’m avoiding that for now.
What happens… The generic thermostats seem to trigger the turn_on state about 80% of the time. I’m assuming things are getting into weird states and that is why it isn’t 100%. The real problem seems to be involved with the turn_off state within the switches and I’m at a loss as to why they don’t get triggered. Maybe I’m using the value_template field of the switches incorrectly or some of my assumptions are incorrect.
Here is the code for the important pieces. I have not included some smaller pieces as I don’t think they’re important and I’m pretty confident they work. I will post them if others think it will help.
Old Code (Automation Method):
- alias: Local Temperature Control Mode
initial_state: on
trigger:
platform: state
entity_id: input_select.temperature_control_mode
to: 'Main Floor'
action:
- service: input_number.set_value
data_template:
entity_id: input_number.previous_remote_temp
value: '{{ states.input_number.target_temperature.state }}'
- service: input_number.set_value
data_template:
entity_id: input_number.target_temperature
value: '{{ states.input_number.previous_local_temp.state }}'
- service: automation.turn_off
entity_id: automation.reach_desired_remote_temperature
- service: automation.turn_on
entity_id: automation.set_main_floor_target_temperature
- service: automation.turn_on
entity_id: automation.set_nest_target_temperature
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: '{{ states.input_number.target_temperature.state }}'
- alias: Remote Temperature Control Mode
initial_state: on
trigger:
platform: state
entity_id: input_select.temperature_control_mode
to: 'Second Floor'
action:
- service: input_number.set_value
data_template:
entity_id: input_number.previous_local_temp
value: '{{ states.input_number.target_temperature.state }}'
- service: input_number.set_value
data_template:
entity_id: input_number.target_temperature
value: '{{ states.input_number.previous_remote_temp.state }}'
- service: automation.turn_off
entity_id: automation.set_main_floor_target_temperature
- service: automation.turn_off
entity_id: automation.set_nest_target_temperature
- service: automation.turn_on
entity_id: automation.reach_desired_remote_temperature
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: '{{ states.input_number.target_temperature.state }}'
- alias: Reach Desired Remote Temperature
initial_state: off
trigger:
platform: state
entity_id: sensor.baby_room_temperature
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.temperature_control_mode
state: 'Second Floor'
- condition: template
value_template: '{{ states.sensor.dining_room_thermostat_hvac_state.state == "off" }}'
- condition: template
value_template: >
{% if states.sensor.dining_room_thermostat_operation_mode.state == 'heat' %}
{{ (states.sensor.baby_room_temperature.state | float + 2) <= (states.input_number.target_temperature.state | float)}}
{% elif states.sensor.dining_room_thermostat_operation_mode.state == 'cool' %}
{{ (states.sensor.baby_room_temperature.state | float - 2) >= (states.input_number.target_temperature.state | float)}}
{% else %}
False
{% endif %}
action:
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: >
{% if float(states.sensor.baby_room_temperature.state) > float(states.sensor.dining_room_thermostat_temperature.state) %}
{{ float(states.sensor.dining_room_thermostat_temperature.state) - ((float(states.sensor.baby_room_temperature.state) - float(states.sensor.dining_room_thermostat_temperature.state)) | abs) }}
{% elif float(states.sensor.baby_room_temperature.state) < float(states.sensor.dining_room_thermostat_temperature.state) %}
{{ float(states.sensor.dining_room_thermostat_temperature.state) + ((float(states.sensor.baby_room_temperature.state) - float(states.sensor.dining_room_thermostat_temperature.state)) | abs) }}
{% endif %}
- service: homeassistant.turn_on
entity_id: automation.desired_remote_temperature_achieved
- service: homeassistant.turn_off
entity_id: automation.reach_desired_remote_temperature
- alias: Desired Remote Temperature Achieved
initial_state: off
trigger:
platform: state
entity_id: sensor.baby_room_temperature
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.temperature_control_mode
state: 'Second Floor'
- condition: template
value_template: '{{ states.sensor.dining_room_thermostat_hvac_state.state != "off" }}'
- condition: template
value_template: >
{% if states.sensor.dining_room_thermostat_operation_mode.state == 'heat' %}
{{ (states.sensor.baby_room_temperature.state | float) >= (states.input_number.target_temperature.state | float) }}
{% elif states.sensor.dining_room_thermostat_operation_mode.state == 'cool' %}
{{ (states.sensor.baby_room_temperature.state | float) <= (states.input_number.target_temperature.state | float) }}
{% else %}
False
{% endif %}
action:
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: '{{ states.input_number.previous_local_temp.state }}'
- service: homeassistant.turn_on
entity_id: automation.reach_desired_remote_temperature
- service: homeassistant.turn_off
entity_id: automation.desired_remote_temperature_achieved
- alias: Set Nest Target Temperature
initial_state: on
trigger:
platform: state
entity_id: input_number.target_temperature
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.temperature_control_mode
state: 'Main Floor'
- condition: template
value_template: '{{ states.sensor.dining_room_thermostat_target.state != states.input_number.target_temperature.state }}'
action:
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: '{{ states.input_number.target_temperature.state }}'
- alias: Set Main Floor Target Temperature
initial_state: on
trigger:
platform: state
entity_id: sensor.dining_room_thermostat_target
condition:
condition: and
conditions:
- condition: state
entity_id: input_select.temperature_control_mode
state: 'Main Floor'
- condition: template
value_template: '{{ states.sensor.dining_room_thermostat_target.state != states.input_number.target_temperature.state }}'
action:
- service: input_number.set_value
data_template:
entity_id: input_number.target_temperature
value: '{{ states.sensor.dining_room_thermostat_target.state }}'
- alias: Smart Temperature Control
initial_state: on
trigger:
platform: state
entity_id: device_tracker.baby_camera
action:
- service: input_select.select_option
data_template:
entity_id: input_select.temperature_control_mode
option: >
{% if states.device_tracker.baby_camera.state == 'not_home' %}
Main Floor
{% elif states.device_tracker.baby_camera.state == 'home' %}
Second Floor
{% else %}
Main Floor
{% endif %}
Now the new method…(Once again, only showing the relevant big pieces. I can show more if needed)
climate:
- platform: generic_thermostat
name: Upstairs Heat
initial_operation_mode: "off"
heater: switch.upstairs_heat
ac_mode: false
target_sensor: sensor.baby_room_temperature
target_temp: 71
cold_tolerance: 2
precision: 0.1
max_temp: 90
min_temp: 40
- platform: generic_thermostat
name: Upstairs Cool
initial_operation_mode: "off"
heater: switch.upstairs_cool
ac_mode: true
target_sensor: sensor.baby_room_temperature
target_temp: 74
hot_tolerance: 2
precision: 0.1
max_temp: 90
min_temp: 40
- platform: template
switches:
upstairs_heat:
friendly_name: "Upstairs Heat"
value_template: "{{ (float(states.climate.upstairs_heat.attributes.current_temperature) <= float(states.climate.upstairs_heat.attributes.temperature - 2) and is_state ('climate.upstairs_heat', 'idle')) or (float(states.climate.upstairs_heat.attributes.current_temperature) <= float(states.climate.upstairs_heat.attributes.temperature) and is_state ('climate.upstairs_heat', 'heat')) }}"
turn_on:
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: >
{{ float(states.climate.dining_room.attributes.current_temperature) + ((float(states.climate.upstairs_heat.attributes.current_temperature) - float(states.climate.dining_room.attributes.current_temperature)) | abs) }}
turn_off:
service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: '{{ states.input_number.previous_local_temp_heat.state }}'
- platform: template
switches:
upstairs_cool:
friendly_name: "Upstairs Cool"
value_template: "{{ (float(states.climate.upstairs_cool.attributes.current_temperature) >= float(states.climate.upstairs_cool.attributes.temperature + 2) and is_state ('climate.upstairs_cool', 'idle')) or (float(states.climate.upstairs_cool.attributes.current_temperature) >= float(states.climate.upstairs_cool.attributes.temperature) and is_state ('climate.upstairs_cool', 'cool')) }}"
turn_on:
- service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: >
{{ float(states.climate.dining_room.attributes.current_temperature) - ((float(states.climate.upstairs_heat.attributes.current_temperature) - float(states.climate.dining_room.attributes.current_temperature)) | abs) }}
turn_off:
service: climate.set_temperature
data_template:
entity_id: climate.dining_room
temperature: '{{ states.input_number.previous_local_temp_cool.state }}'
Hopefully this is an obvious fix and I’ve just been staring at this problem for too long.
Thanks in advance for any help solving this! It should be pretty slick once I’m done.