I’ve been spending some time to get my AC’s to not only use the temperature sensor in the room, but also to also take into account the outside temperature and UV index. The main reason was that we have large windows in our house and just automating the AC mode based on the inside temperature did not seem to work well. Example: 22 deg C in the room didn’t feel the same when it’s cloudy outside compared to a very hot and sunny day. Another factor was the heat transfer through the windows… Example: when it’s cold outside, I might want the AC to “try” and heat the room more due to the heat constantly transferring to the outside. I live in South Africa and due to our climate conditions, there are little to no building regulations around insulation, glazed windows etc so this plays a larger role.
One of the main reasons I started with this is because I don’t always want to have the AC on hot/cold because if the room is at the correct temperature it should just be on “fan_mode”. If it’s always on hot/cold it uses between 400 and 800 W, whereas the fan mode uses 15W. Then the temperature goes outside of the automation figure, then only does it go to hot/cold and similarly it goes to fan if it managed to cool the room by a figure set via input slider.
So to get to it. I measure the following, which allows me to build the logic and automations:
- The outside temperature, via a Sonoff Basic with a waterproof temperature sensor (ESPHome). This has to be installed in a ventilated area with no direct sunlight to better measure the ambient temperature without other factor affecting the reading
- The inside temperature is based on the attributes directly from the Midea AC component attributes
The DarkSky UV index for my location, there is about a 10 minute delay, but the sun and overcast conditions don’t really change over a shorter period of time
First I created “heat_index template sensor”:
- platform: template
sensors:
living_room_heat_index:
value_template: "{{ (
((states.sensor.living_room_temperature.state | float) * ((states.input_number.living_room_inside_temperature_percentage.state | float) / 100)) +
((states.sensor.ac_outside_temperature.state | float) * (1 - ((states.input_number.living_room_inside_temperature_percentage.state | float) / 100))) +
(((states.sensor.dark_sky_uv_index.state | float) * (states.input_number.living_room_uv_index.state | float)) / 500)
) | round(2) }}"
friendly_name: "Living Room Heat Index"
icon_template: mdi:thermometer
unit_of_measurement: "°C"
The “input_number.living_room_inside_temperature_percentage” is a variable number that is multiplied by the inside temperature, where (1 - “input_number.living_room_inside_temperature_percentage”) is multiplied by the outside temperature. These two figures are then added up, given a weighted average of the two temperatures based on how many % is allocated to them.
The “input_number.living_room_uv_index” is a variable number that is multiplied by the outside UV index. This number is then added to the sum of the two values above.
Since all the variable inputs are between 0 and 100, I had to divide by 100 to get to % weightings. With the UV index I divide by 500, it basically means that if the UV index is 10, I’m dividing by 5 and thus adding 2 deg C to my heat_index when the input slider is at 100%.
So this template sensor calculates a heat_index, which is the “new” temperature that I use in automations instead of the actual inside temperature. The formula does the following:
“heat_index” = (“inside_temperature” * “%_of_inside_temperature_to_use” / 100) + (“outside_temperature” * (1 - “%_of_inside_temperature_to_use” / 100) + (“outside_uv” * “%_of_outside_to_use” / 500).
Then we get to the automations, which are a bit complex because of the preference to have the AC on fan mode. I’m not going into detail, but I’ll explain the main logic and give an example:
###########################################|###########################################
# #
# SET LIVING ROOM AC TO COOL #
# #
# Check if Living Room AC is NOT OFF and set to low cool mode when room is warm #
# #
###########################################|###########################################
- id: '1533333569253'
alias: Living Room AC Cool Mode
initial_state: 'true'
trigger:
- minutes: /1
seconds: 30
platform: time_pattern
condition:
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'off') %}true{% endif %}"
- condition: template
value_template: "{% if not is_state('binary_sensor.chimney_is_use', 'on') %}true{% endif %}"
- condition: template
value_template: "{{ states('sensor.living_room_heat_index') | float > states('input_number.living_room_start_cool') | float }}"
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'cool') %}true{% endif %}"
action:
- service: climate.set_hvac_mode
data:
entity_id: climate.lounge_kitchen
hvac_mode: "cool"
- service: climate.set_temperature
data:
entity_id: climate.lounge_kitchen
temperature: 22
- service: climate.set_fan_mode
data:
entity_id: climate.lounge_kitchen
fan_mode: "Low"
So this checks that the AC is not OFF, the Chimney is not being used (this was because when I used the fireplace, the room would get hot and the AC went to cool mode ), the heat_index is larger than my start_cool temperature set point (different input slider) and also that the AC is not currently in COOL mode. When all of this is true, the AC will set to COOL, low fan speed and 22 deg. One thing I could not get right was to have the 22 deg C use the information from another input number, it kept seeing the input as a string, maybe someone can help me there?
###########################################|###########################################
# #
# SET LIVING ROOM AC TO HEAT #
# #
# Check if Living Room AC is NOT OFF and set to low heat mode when room is cold #
# #
###########################################|###########################################
- id: '1532244299253'
alias: Living Room AC Heat Mode
initial_state: 'true'
trigger:
- minutes: /1
seconds: 30
platform: time_pattern
condition:
- condition: state
entity_id: binary_sensor.chimney_in_use
state: 'off'
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'off') %}true{% endif %}"
- condition: template
value_template: "{{ states('sensor.living_room_heat_index') | float < states('input_number.living_room_start_heat') | float }}"
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'heat') %}true{% endif %}"
action:
- service: climate.set_hvac_mode
data:
entity_id: climate.lounge_kitchen
hvac_mode: "heat"
- service: climate.set_temperature
data:
entity_id: climate.lounge_kitchen
temperature: 22
- service: climate.set_fan_mode
data:
entity_id: climate.lounge_kitchen
fan_mode: "Low"
So this checks that the AC is not OFF, the Chimney is not being used, the heat_index is smaller that my start_heat temperature set point (different input slider) and also that the AC is not currently in HEAT mode. When all of this is true, the AC will set to HEAT, low fan speed and 22 deg.
Then I created two additional automations, which sets the AC to fan_mode after being on COOL or HEAT, if the heat_index has gone up (heating) or down (cooling) by an amount set in another input_slider:
###########################################|###########################################
# #
# SET LIVING ROOM AC TO FAN AFTER HEAT #
# #
# Check if Living Room AC is NOT OFF and set to low fan mode when room heated enough #
# #
###########################################|###########################################
- id: '1533223456853'
alias: Living Room AC Fan Mode After Heating
initial_state: 'true'
trigger:
- minutes: /1
seconds: 0
platform: time_pattern
condition:
- condition: state
entity_id: input_boolean.heat_overdrive_boolean
state: 'off'
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'off') %}true{% endif %}"
- condition: or
conditions:
- condition: template
value_template: "{{ states('sensor.living_room_heat_index') | float >= (states('input_number.living_room_start_heat') | float + states('input_number.living_room_temperature_variance') | float) }}"
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'fan_only') %}true{% endif %}"
- condition: template
value_template: "{% if is_state('climate.lounge_kitchen', 'heat') %}true{% endif %}"
action:
- service: climate.set_hvac_mode
data:
entity_id: climate.lounge_kitchen
hvac_mode: "fan_only"
- service: climate.set_fan_mode
data:
entity_id: climate.lounge_kitchen
fan_mode: "Low"
###########################################|###########################################
# #
# SET LIVING ROOM AC TO FAN AFTER COOL #
# #
# Check if Living Room AC is NOT OFF and set to low fan mode when room heated enough #
# #
###########################################|###########################################
- id: '1533986637853'
alias: Living Room AC Fan Mode After Cooling
initial_state: 'true'
trigger:
- minutes: /1
seconds: 0
platform: time_pattern
condition:
- condition: state
entity_id: input_boolean.heat_overdrive_boolean
state: 'off'
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'off') %}true{% endif %}"
- condition: template
value_template: "{{ states('sensor.living_room_heat_index') | float <= (states('input_number.living_room_start_cool') | float - states('input_number.living_room_temperature_variance') | float) }}"
- condition: template
value_template: "{% if not is_state('climate.lounge_kitchen', 'fan_only') %}true{% endif %}"
- condition: template
value_template: "{% if is_state('climate.lounge_kitchen', 'cool') %}true{% endif %}"
action:
- service: climate.set_hvac_mode
data:
entity_id: climate.lounge_kitchen
hvac_mode: "fan_only"
- service: climate.set_fan_mode
data:
entity_id: climate.lounge_kitchen
fan_mode: "Low"
I’ve added some screenshots below to show the UI with the variables. I hope this gives someone an idea for an integration or Lovelace card, as I definitely don’t know how to do any of that.