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 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 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 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 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 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. 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_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 log_level: name: Logging Level default: info selector: select: options: - info - debug 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 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 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 }} 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 }} {% else %} {{ desired_temp + adjust_amount }} {% 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 {% 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 - 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: template value_template: > {{ away == '' or is_state(away, 'off') }} - 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 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 - 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