diff --git a/blueprints/automations/bzo_climate.yaml b/blueprints/automations/bzo_climate.yaml index ab7787a..f62016c 100644 --- a/blueprints/automations/bzo_climate.yaml +++ b/blueprints/automations/bzo_climate.yaml @@ -1,331 +1,347 @@ -blueprint: - name: BZO's Smart Climate Controller - description: > - Automatically control a climate device based on indoor/outdoor temperatures, - using one command per update. Sends HVAC mode, temperature, and fan settings - only if different from current state. Supports external temp threshold for heat/cool switching, - presence, schedule, optional override, optional away mode, logging level, and optional window detection. - domain: automation - input: - climate_entity: - name: Climate Device - description: 'Selet the unit or units that will be controled.' - selector: - entity: - domain: climate + blueprint: + name: BZO's Smart Climate Controller + description: > + Automatically control a climate device based on indoor/outdoor temperatures, + using one command per update. Sends HVAC mode, temperature, and fan settings + only if different from current state. Supports external temp threshold for heat/cool switching, + presence, schedule, optional override, optional away mode, logging level, and optional window detection. + domain: automation + input: + climate_entity: + name: Climate Device + description: 'Selet the unit or units that will be controled.' + selector: + entity: + domain: climate - room_temp_sensor: - name: Room Temperature Sensor - description: 'Sensor or group of sensors used to calculate thermostat values.' - selector: - entity: - domain: sensor - device_class: temperature + room_temp_sensor: + name: Room Temperature Sensor + description: 'Sensor or group of sensors used to calculate thermostat values.' + selector: + entity: + domain: sensor + device_class: temperature - outdoor_temp_sensor: - name: Outdoor Temperature Sensor - description: 'Used to determine HVAC mode ( cool or heat ).' - selector: - entity: - domain: sensor - device_class: temperature + outdoor_temp_sensor: + name: Outdoor Temperature Sensor + description: 'Used to determine HVAC mode ( cool or heat ).' + selector: + entity: + domain: sensor + device_class: temperature - presence_entity: - name: Presence Sensor or Group - description: 'Used to tun off the units if house is empty.' - selector: - entity: - domain: person + presence_entity: + name: Presence Sensor or Group + description: 'Used to tun off the units if house is empty.' + selector: + entity: + domain: person - schedule_entity: - name: Schedule Helper - description: 'Schedule for the unit to run.' - selector: - entity: - domain: schedule + schedule_entity: + name: Schedule Helper + description: 'Schedule for the unit to run.' + selector: + entity: + domain: schedule - override_switch: - name: (Optional) Manual Override Switch - description: 'Override presence and schedule and turn on the unit.' - default: '' - selector: - entity: - domain: input_boolean + override_switch: + name: (Optional) Manual Override Switch + description: 'Override presence and schedule and turn on the unit.' + default: '' + selector: + entity: + domain: input_boolean - away_mode_helper: - name: (Optional) Away Mode Helper (turns off A/C) - default: '' - selector: - entity: - domain: input_boolean + away_mode_helper: + name: (Optional) Away Mode Helper (turns off A/C) + default: '' + selector: + entity: + domain: input_boolean - window_sensor: - name: (Optional) Window Sensor - default: '' - selector: - entity: - domain: binary_sensor + window_sensor: + name: (Optional) Window Sensor + default: '' + selector: + entity: + domain: binary_sensor - delta_fan_low: - name: Temperature Delta for Mid Fan - default: 2 - selector: - number: - min: 1 - max: 5 - step: 0.5 - unit_of_measurement: °C + delta_fan_low: + name: Temperature Delta for Mid Fan + default: 2 + selector: + number: + min: 1 + max: 5 + step: 0.5 + unit_of_measurement: °C - delta_fan_high: - name: Temperature Delta for High Fan - default: 3 - selector: - number: - min: 2 - max: 10 - step: 0.5 - unit_of_measurement: °C + delta_fan_high: + name: Temperature Delta for High Fan + default: 3 + selector: + number: + min: 2 + max: 10 + step: 0.5 + unit_of_measurement: °C - external_temp_threshold: - name: External Temperature Heat/Cool Switch Threshold - default: 18 - selector: - number: - min: -10 - max: 35 - step: 1 - unit_of_measurement: °C + external_temp_threshold: + name: External Temperature Heat/Cool Switch Threshold + default: 18 + selector: + number: + min: -10 + max: 35 + step: 1 + unit_of_measurement: °C - target_temp_helper: - name: Target Temperature Helper - description: ' - Control your comfort temperature via automations or the UI, you can - specify an *[input_number](https://www.home-assistant.io/integrations/input_number/)* - entity here. + target_temp_helper: + name: Target Temperature Helper + description: ' + Control your comfort temperature via automations or the UI, you can + specify an *[input_number](https://www.home-assistant.io/integrations/input_number/)* + entity here. - Create your helper [here](https://my.home-assistant.io/redirect/helpers/). ' - selector: - entity: - domain: input_number + Create your helper [here](https://my.home-assistant.io/redirect/helpers/). ' + selector: + entity: + domain: input_number - temp_adjust_threshold: - name: Temperature Delta Adjustment Threshold - description: 'The Delta value, representing the difference between the desired and actual temperature, will adjust the thermostat.' - default: 4 - selector: - number: - min: 0 - max: 10 - step: 0.5 - unit_of_measurement: °C + temp_adjust_threshold: + name: Temperature Delta Adjustment Threshold + description: 'The Delta value, representing the difference between the desired and actual temperature, will adjust the thermostat.' + default: 4 + selector: + number: + min: 0 + max: 10 + step: 0.5 + unit_of_measurement: °C - temp_adjust_amount: - name: Temperature Adjustment Amount - description: 'How many degrees to add or subtract if the difference between the desired temp and actual temp is higher than Delta.' - default: 1 - selector: - number: - min: 0 - max: 5 - step: 0.5 - unit_of_measurement: °C + temp_adjust_amount: + name: Temperature Adjustment Amount + description: 'How many degrees to add or subtract if the difference between the desired temp and actual temp is higher than Delta.' + default: 1 + selector: + number: + min: 0 + max: 5 + step: 0.5 + unit_of_measurement: °C - fan_mode_profile: - name: Fan Mode Profile - description: 'Fan mode: Standard for Auto, High, mid, low and numerif for Auto, 1, 2, etc.' - default: standard - selector: - select: - options: - - standard - - numeric + fan_mode_profile: + name: Fan Mode Profile + description: 'Fan mode: Standard for Auto, High, mid, low and numerif for Auto, 1, 2, etc.' + default: standard + selector: + select: + options: + - standard + - numeric - log_level: - name: Logging Level - default: info - selector: - select: - options: - - info - - debug + log_level: + name: Logging Level + default: info + selector: + select: + options: + - info + - debug -mode: restart -max_exceeded: silent -trigger_variables: - override_switch: !input override_switch + mode: restart + max_exceeded: silent + trigger_variables: + override_switch: !input override_switch -trigger: - - platform: time_pattern - minutes: "/5" - - platform: state - entity_id: !input schedule_entity - to: "on" - - platform: state - entity_id: !input target_temp_helper + trigger: + - platform: time_pattern + minutes: "/5" + - platform: state + entity_id: !input schedule_entity + to: "on" + - platform: state + entity_id: !input target_temp_helper -condition: - - condition: template - value_template: > - {{ override_switch == '' or is_state( override_switch, 'off') }} - - condition: state - entity_id: !input schedule_entity - state: "on" - - condition: state - entity_id: !input presence_entity - state: "home" - # - condition: template - # value_template: > - # {% set window = window_sensor %} - # {{ window == '' or is_state(window, 'off') }} + condition: + - condition: template + value_template: > + {{ override_switch == '' or is_state( override_switch, 'off') }} + - condition: state + entity_id: !input schedule_entity + state: "on" + - condition: state + entity_id: !input presence_entity + state: "home" + # - condition: template + # value_template: > + # {% set window = window_sensor %} + # {{ window == '' or is_state(window, 'off') }} -action: - - variables: - climate: !input climate_entity - room_sensor: !input room_temp_sensor - outside_sensor: !input outdoor_temp_sensor - target_temp_entity: !input target_temp_helper - fan_profile: !input fan_mode_profile - away: !input away_mode_helper - adjust_threshold: !input temp_adjust_threshold - adjust_amount: !input temp_adjust_amount - delta_low: !input delta_fan_low - delta_high: !input delta_fan_high - threshold: !input external_temp_threshold - override_switch: !input override_switch + action: + - variables: + climate: !input climate_entity + room_sensor: !input room_temp_sensor + outside_sensor: !input outdoor_temp_sensor + target_temp_entity: !input target_temp_helper + fan_profile: !input fan_mode_profile + away: !input away_mode_helper + adjust_threshold: !input temp_adjust_threshold + adjust_amount: !input temp_adjust_amount + delta_low: !input delta_fan_low + delta_high: !input delta_fan_high + threshold: !input external_temp_threshold + override_switch: !input override_switch + presence_entity: !input presence_entity - room_temp: > - {% set r = states(room_sensor) %} - {{ r | float(0) if r not in ['unknown', 'unavailable'] else 0 }} + room_temp: > + {% set r = states(room_sensor) %} + {{ r | float(0) if r not in ['unknown', 'unavailable'] else 0 }} - outside_temp: > - {% set o = states(outside_sensor) %} - {{ o | float(999) if o not in ['unknown', 'unavailable'] else 999 }} + outside_temp: > + {% set o = states(outside_sensor) %} + {{ o | float(999) if o not in ['unknown', 'unavailable'] else 999 }} - desired_temp: > - {% set t = states(target_temp_entity) %} - {{ t | float(22) if t not in ['unknown', 'unavailable'] else 22 }} + desired_temp: > + {% set t = states(target_temp_entity) %} + {{ t | float(22) if t not in ['unknown', 'unavailable'] else 22 }} - adjusted_temp: > - {% set delta = (room_temp - desired_temp) | abs %} - {% if delta >= adjust_threshold %} - {% if room_temp > desired_temp %} - {{ desired_temp - adjust_amount }} + adjusted_temp: > + {% set delta = (room_temp - desired_temp) | abs %} + {% if delta >= adjust_threshold %} + {% if room_temp > desired_temp %} + {{ desired_temp - adjust_amount }} + {% else %} + {{ desired_temp + adjust_amount }} + {% endif %} {% else %} - {{ desired_temp + adjust_amount }} + {{ desired_temp }} {% endif %} - {% else %} - {{ desired_temp }} - {% endif %} - hvac_mode: > - {% if outside_temp < threshold %} heat - {% elif outside_temp < 999 %} cool - {% else %} auto {% endif %} - - delta: "{{ room_temp - desired_temp }}" - - fan_mode: > - {% if fan_profile == 'standard' %} - {% if delta | abs >= delta_high %} high - {% elif delta | abs >= delta_low %} mid + hvac_mode: > + {% if outside_temp < threshold %} heat + {% elif outside_temp < 999 %} cool {% else %} auto {% endif %} - {% else %} - {% if delta | abs >= delta_high %} "5" - {% elif delta | abs >= delta_low %} "3" - {% else %} "1" {% endif %} - {% endif %} - - choose: - - conditions: - - condition: state - entity_id: !input schedule_entity - state: "off" - sequence: - - service: climate.turn_off - target: - entity_id: !input climate_entity - - service: logbook.log - data: - name: "Smart Climate" - message: "A/C turned off because schedule is OFF" - entity_id: !input climate_entity + delta: "{{ room_temp - desired_temp }}" - - choose: - - conditions: - - condition: template - value_template: > - {{ away != '' and is_state(away, 'on') }} - sequence: - - service: climate.turn_off - target: - entity_id: !input climate_entity - - service: logbook.log - data: - name: "Smart Climate" - message: "A/C turned off due to Away Mode" - entity_id: !input climate_entity + fan_mode: > + {% if fan_profile == 'standard' %} + {% if delta | abs >= delta_high %} high + {% elif delta | abs >= delta_low %} mid + {% else %} auto {% endif %} + {% else %} + {% if delta | abs >= delta_high %} "5" + {% elif delta | abs >= delta_low %} "3" + {% else %} "1" {% endif %} + {% endif %} - - condition: template - value_template: > - {{ away == '' or is_state(away, 'off') }} + - choose: + - conditions: + - condition: state + entity_id: !input schedule_entity + state: "off" + sequence: + - service: climate.turn_off + target: + entity_id: !input climate_entity + - service: logbook.log + data: + name: "Smart Climate" + message: "A/C turned off because schedule is OFF" + entity_id: !input climate_entity - - choose: - - conditions: - - condition: template - value_template: "{{ log_level == 'debug' }}" - sequence: - - service: logbook.log - data: - name: "Smart Climate" - message: > - External temp = {{ outside_temp }}°C, Threshold = {{ threshold }}°C → Mode = {{ hvac_mode }} - entity_id: !input climate_entity + - choose: + - conditions: + - condition: template + value_template: > + {{ is_state(presence_entity, 'not_home') }} + sequence: + - service: climate.turn_off + target: + entity_id: !input climate_entity + - service: logbook.log + data: + name: "Smart Climate" + message: "A/C turned off because no one is home" + entity_id: !input climate_entity - - service: logbook.log - data: - name: "Smart Climate DEBUG" - message: > - Current state = {{ states(climate) }}, HVAC = {{ state_attr(climate, 'hvac_modes') or 'unknown' }}, - Temp = {{ state_attr(climate, 'temperature') }}, Fan = {{ state_attr(climate, 'fan_mode') or 'unknown' }}; - Target: HVAC = {{ hvac_mode }}, Temp = {{ adjusted_temp }}, Fan = {{ fan_mode }} - entity_id: !input climate_entity - - conditions: - - condition: template - value_template: "{{ log_level == 'info' }}" - sequence: - - service: logbook.log - data: - name: "Smart Climate" - message: "Automation triggered (log level: info)" - entity_id: !input climate_entity + - choose: + - conditions: + - condition: template + value_template: > + {{ away != '' and is_state(away, 'on') }} + sequence: + - service: climate.turn_off + target: + entity_id: !input climate_entity + - service: logbook.log + data: + name: "Smart Climate" + message: "A/C turned off due to Away Mode" + entity_id: !input climate_entity - - condition: or - conditions: - - condition: template - value_template: > - {{ states(climate) in ['off', 'unavailable', 'unknown'] }} - - condition: template - value_template: > - {% set state = states(climate) %} - {% set fan = (state_attr(climate, 'fan_mode') or 'unknown') | string %} - {% set temp = state_attr(climate, 'temperature') | float(999) %} - {{ state != hvac_mode or fan != fan_mode or (temp | round(1)) != (adjusted_temp | round(1)) }} + - condition: template + value_template: > + {{ away == '' or is_state(away, 'off') }} - - service: climate.set_temperature - target: - entity_id: !input climate_entity - data: - temperature: "{{ adjusted_temp | float }}" - hvac_mode: "{{ hvac_mode }}" - fan_mode: "{{ fan_mode }}" + - choose: + - conditions: + - condition: template + value_template: "{{ log_level == 'debug' }}" + sequence: + - service: logbook.log + data: + name: "Smart Climate" + message: > + External temp = {{ outside_temp }}°C, Threshold = {{ threshold }}°C → Mode = {{ hvac_mode }} + entity_id: !input climate_entity - - service: logbook.log - data: - name: "Smart Climate" - message: > - Sent command: HVAC = {{ hvac_mode }}, Temp = {{ adjusted_temp }}°C, Fan = {{ fan_mode }} - entity_id: !input climate_entity + - service: logbook.log + data: + name: "Smart Climate DEBUG" + message: > + Current state = {{ states(climate) }}, HVAC = {{ state_attr(climate, 'hvac_modes') or 'unknown' }}, + Temp = {{ state_attr(climate, 'temperature') }}, Fan = {{ state_attr(climate, 'fan_mode') or 'unknown' }}; + Target: HVAC = {{ hvac_mode }}, Temp = {{ adjusted_temp }}, Fan = {{ fan_mode }} + entity_id: !input climate_entity + - conditions: + - condition: template + value_template: "{{ log_level == 'info' }}" + sequence: + - service: logbook.log + data: + name: "Smart Climate" + message: "Automation triggered (log level: info)" + entity_id: !input climate_entity - - delay: - minutes: 1 + - condition: or + conditions: + - condition: template + value_template: > + {{ states(climate) in ['off', 'unavailable', 'unknown'] }} + - condition: template + value_template: > + {% set state = states(climate) %} + {% set fan = (state_attr(climate, 'fan_mode') or 'unknown') | string %} + {% set temp = state_attr(climate, 'temperature') | float(999) %} + {{ state != hvac_mode or fan != fan_mode or (temp | round(1)) != (adjusted_temp | round(1)) }} + + - service: climate.set_temperature + target: + entity_id: !input climate_entity + data: + temperature: "{{ adjusted_temp | float }}" + hvac_mode: "{{ hvac_mode }}" + fan_mode: "{{ fan_mode }}" + + - service: logbook.log + data: + name: "Smart Climate" + message: > + Sent command: HVAC = {{ hvac_mode }}, Temp = {{ adjusted_temp }}°C, Fan = {{ fan_mode }} + entity_id: !input climate_entity + + - delay: + minutes: 1