Universal Thermostat is designed to complete almost all climate control tasks in a certain zone.
Component grew out of Smart Thermostat from hacker-cb, who did the great job I am extremely appreciated for!
- supports multiple heating and cooling entities
- supports various target entity domains:
switch
,climate
,input_boolean
,number
,input_number
- supports invert logic for any heater or cooler
- supports PID/PWM regulation for supported entities
- supports
auto
mode with adjustable cooling and heating deltas - supports
heat_cool
mode with separate temperature cooling and heating setpoints - supports templates for configurable parameters
- supports presets with flexible parameters
- supports multiple windows openings (or other devices that should prevent heater/cooler working) with individual timers and inversions
switch
,input_boolean
- basic toggling mode or PWM modeclimate
- basic toggling mode or PID regulator modenumber
+switch
,input_number
+switch
- PID regulator mode with toggleable switch
This is recommended way, which will handle one-click upgrade in HACS.
- Install hacs if it is not installed.
- Open HACS -> Integrations. Click 3 dots in the upper right corner.
- Click Custom repositories.
- Add
vaproloff/universalThermostat
repository. - Find
Universal Thermostat
in HACS catalog and clickinstall
button.
NOTE: This is not recommended way, because you will need to upgrade component manually.
-
Copy
/custom_components/universal_thermostat
to your<config_dir>/custom_components/
directory.- On HassIO the final location will be
/config/custom_components/universal_thermostat
. - On Supervised the final location will be
/usr/share/hassio/homeassistant/custom_components/universal_thermostat
. - NOTE: You will need to create the
custom_components
folder if it does not exist.
- On HassIO the final location will be
-
Restart Home Assistant Core.
climate:
- platform: universal_thermostat
target_sensor: sensor.kitchen_temperature
cooler: switch.kitchen_cooler_switch
climate:
- platform: universal_thermostat
name: Kitchen Thermostat
unique_id: kitchen_thermostat
object_id: kitchen_thermostat
target_sensor: sensor.kitchen_temperature
min_temp: 18
max_temp: 28
precision: 0.1
target_temp_step: 0.5
target_temp: 24.5
target_temp_low: 24
target_temp_high: 25
auto_cool_delta: "{{ states('input_number.auto_cool_delta') | float }}"
auto_heat_delta: 1.0
heat_cool_disabled: false
initial_hvac_mode: heat_cool
heater:
- entity_id: climate.kitchen_heating_floor_thermostat
kp: 1.3
ki: 0.5
kd: 10
pid_sample_period: 300
min: 16
max: 35
- entity_id: switch.kitchen_heater_switch
inverted: false
cold_tolerance: 0.3
hot_tolerance: 0.3
min_cycle_duration: 600
cooler:
- entity_id: number.kitchen_cooler_regulator
switch_entity_id: switch.kitchen_cooler_regulator_switch
switch_inverted: true
kp: 20
ki: 0.01
kd: 2
min: 0
max: 10
- entity_id: climate.kitchen_cooler_thermostat
cold_tolerance: 0.3
hot_tolerance: 0.3
target_temp_delta: 1.0
ignore_windows: true
windows:
- entity_id: switch.window_1
timeout:
seconds: 2
- entity_id: input_boolean.window_2
inverted: true
timeout: "{{ states('input_number.window_open_timeout') | float }}"
- binary_sensor.window_3
presets:
sleep:
temp_delta: "{{ states('input_number.sleep_temp_delta') | float }}"
away:
heat_delta: -1.0
cool_delta: 2.0
eco:
target_temp: 18.0
heat_target_temp: 18.0
cool_target_temp: 29.0
target_temp
- Climate target temperature, can be changed in UI. Initial can be set viatarget_temp
config option.cur_temp
- Current sensor temperature. Will be reported bytarget_sensor
entity.CONFIG.xxx
- Reference to the config option.CONFIG.CONTROLLER.xxx
- Reference to the config controller option (heater/cooler).
name
(Required) - Climate entity nameunique_id
(Optional) - Climate entityunique_id
object_id
(Optional) - Climate entity suggestedentity_id
cooler
(Optional) - String, Array or Map of the coolers.heater
(Optional) - String, Array or Map of the heaters.target_sensor
(Required) - Target temperature sensormin_temp
(Optional, default=7) - Set minimum set point available.max_temp
(Optional, default=35) - Set maximum set point available.target_temp
(Optional) - Initial target temperature.target_temp_low
(Optional) - Initial target low temperature (forheat_cool
mode).target_temp_high
(Optional) - Initial target high temperature (forheat_cool
mode).auto_cool_delta
(Optional) - Target temperature delta for Coolers inauto
mode. Could be a template. Default: 1.0.auto_heat_delta
(Optional) - Target temperature delta for Heaters inauto
mode. Could be a template. Default: 1.0.heat_cool_disabled
(Optional) - Disablesheat_cool
mode. Default: false.initial_hvac_mode
(Optional) - Initial HVAC mode.precision
(Optional) - Precision for this device. Supported values are 0.1, 0.5 and 1.0. Default: 0.1 for Celsius and 1.0 for Fahrenheit.target_temp_step
(Optional) - Temperature set point step. Supported values are 0.1, 0.5 and 1.0. Default: equals toprecision
.windows
(Optional) - String, Array or Map of the window entities.presets
(Optional) - Map of presets.
NOTE: at least one of heater
or cooler
is required.
Initial HVAC mode can be set via initial_hvac_mode
config option.
Thermostat behavior will depend on active HVAC mode. HVAC mode can be set in UI.
NOTE: available if at least one CONFIG.heater
was defined.
- All heater controllers will be turned on. Specific behavior of each heater will depend on the controller type.
- All cooler controllers will be turned off.
NOTE: available if at least one CONFIG.coller
was defined.
- All cooler controllers will be turned on. Specific behavior of each cooler will depend on the controller type.
- All heater controllers will be turned off.
NOTE: available if at least one CONFIG.heater
and at least one CONFIG.cooler
were defined.
- All cooler and heater controllers will be turned on.
- Specific behavior of each heater and cooler will depend on the controller type.
- All cooler controllers will pick
target_temp_high
as theirtarget_temp
. - All heater controllers will pick
target_temp_low
as theirtarget_temp
.
NOTE: available if at least one CONFIG.heater
and at least one CONFIG.cooler
were defined.
- All cooler and heater controllers will be turned on.
- Specific behavior of each heater and cooler will depend on the controller type.
- All cooler controllers will pick
target_temp + auto_cool_delta
as theirtarget_temp
. - All heater controllers will pick
target_temp - auto_heat_delta
as theirtarget_temp
.
NOTE: turning on controller DOES NOT MEANS turning on CONFIG.CONTROLLER.enitity_id
inside controller.
Controller behavior depends on the specific controller logic and described below for each controller.
Specific controller will be created for each heater
/cooler
config option based on CONFIG.CONTROLLER.enitity_id
domain.
Supported domains: switch
,input_boolean
entity_id
(Required) - Target entity ID.inverted
(Optional, default=false) - Need to invertentity_id
logic.keep_alive
(Optional) - Send keep-alive interval. Use with heaters, coolers, A/C units that shut off if they don’t receive a signal from their remote for a while.ignore_windows
(Optional, default=false) - Need to ignore windows logic.min_cycle_duration
(Optional, default=null) - Minimal cycle duration. Used to protect from on/off cycling.cold_tolerance
(Optional, default=0.3) - Cold tolerance.hot_tolerance
(Optional, default=0.3) - Hot tolerance.
- Turn on
entity_id
ifcur_temp <= target_temp - cold_tolerance
(heater) orcur_temp >= target_temp + self._hot_tolerance
(cooler) - No
entity_id
changes will be performed if configmin_cycle_duration
was set and enough time was not passed since last switch. - Behavior on/off will be inverted if
inverted
config option was set totrue
Domains: switch
,input_boolean
.
- Internal PID limits are integers, defined as constants
PWM_SWITCH_MIN_VALUE
andPWM_SWITCH_MAX_VALUE
(0, 100). So, you must use this limits when tuningpid_params
terms.
entity_id
(Required) - Target entity ID.inverted
(Optional, default=false) - Need to invertentity_id
logic.keep_alive
(Optional) - Send keep-alive interval. Use with heaters, coolers, A/C units that shut off if they don’t receive a signal from their remote for a while.ignore_windows
(Optional, default=false) - Need to ignore windows logic.kp
(Required) - PID proportional coefficient, could be a template (Always positive, will be inverted internally for cool mode).ki
(Required) - PID integral coefficient, could be a template (Always positive, will be inverted internally for cool mode).kd
(Required) - PID derivative coefficient, could be a template (Always positive, will be inverted internally for cool mode).pid_sample_period
(Optional) - PID constant sample time period.pwm_period
(Required) - PWM period. Switch will be turned on and turned off according internal PID output once in this period.
- PID output will be calculated internally based on provided PID coefficients.
pwm_period
will be separated to two parts:ON
andOFF
. Each part duration will depend on PID output.- PWM on/off need will be checked every
pwm_period/100
time but not often than each 1 second. (PWM_SWITCH_MAX_VALUE
internal const variable) - Behavior on/off will be inverted if
inverted
config option was set totrue
. - It is keep on/off state duration before Home Assistant restart. Last change time is saved in thermostat state attributes.
NOTE: This mode will be set if entity domain is one of the listed above and pid_params
config entry is present.
Domains: climate
entity_id
(Required) - Target entity ID.inverted
(Optional, default=false) - Need to invertentity_id
logic.keep_alive
(Optional) - Send keep-alive interval. Use with heaters, coolers, A/C units that shut off if they don’t receive a signal from their remote for a while.ignore_windows
(Optional, default=false) - Need to ignore windows logic.min_cycle_duration
(Optional, default=null) - Minimal cycle duration. Used to protect from on/off cycling.cold_tolerance
(Optional, default=0.3) - Cold tolerance. Could be a template.hot_tolerance
(Optional, default=0.3) - Hot tolerance. Could be a template.target_temp_delta
(Optional, default=None) - Delta between Thermostat set point and target climate entity. Could be a template. If not mentioned - temperature control will be disabled.
- Climate
entity_id
will be turned on when controller is active. - Climate
entity_id
will be turned off when controller is not active. - Climate
entity_id
temperature set point will be adjusted takingtarget_temp_delta
into account if it specified:- Thermostat set point +
target_temp_delta
- for heaters; - Thermostat set point -
target_temp_delta
- for coolers;
- Thermostat set point +
Domains: climate
entity_id
(Required) - Target entity ID.inverted
(Optional, default=false) - Need to invertentity_id
logic.keep_alive
(Optional) - Send keep-alive interval. Use with heaters, coolers, A/C units that shut off if they don’t receive a signal from their remote for a while.ignore_windows
(Optional, default=false) - Need to ignore windows logic.kp
(Required) - PID proportional coefficient, could be a template (Always positive, will be inverted internally for cool mode).ki
(Required) - PID integral coefficient, could be a template (Always positive, will be inverted internally for cool mode).kd
(Required) - PID derivative coefficient, could be a template (Always positive, will be inverted internally for cool mode).pid_sample_period
(Optional) - PID constant sample time period.min
(Optional) - Minimum temperature which can be set. Attributemin_temp
fromentity_id
will be used if not specified. Could be a template.max
(Optional) - Maximum temperature which can be set. Attributemax_temp
fromentity_id
will be used if not specified. Could be a template.
- Climate
entity_id
will be turned on when controller is active. - Climate
entity_id
will be turned off when controller is not active. - Climate
entity_id
temperature will be adjusted everypid_sample_period
it is provided, or on everyCONFIF.target_sensor
update ifpid_sample_period
is not provided. - PID parameters will be inverted if
inverted
was set totrue
Domains: number
,input_number
entity_id
(Required) - Target entity ID.inverted
(Optional, default=false) - Need to invertentity_id
logic.keep_alive
(Optional) - Send keep-alive interval. Use with heaters, coolers, A/C units that shut off if they don’t receive a signal from their remote for a while.ignore_windows
(Optional, default=false) - Need to ignore windows logic.pid_params
(Required) - PID params comma-separated string or array in the formatKp, Ki, Kd
(Always positive, will be inverted internally for cool mode).pid_sample_period
(Optional) - PID constant sample time period.min
(Optional) - Minimum temperature which can be set. Attributemin
fromentity_id
will be used if not specified.max
(Optional) - Maximum temperature which can be set. Attributemax
fromentity_id
will be used if not specified.switch_entity_id
(Optional) - Switch entity which belongs toswitch
,input_boolean
domains.switch_inverted
(Optional, default=false) - Isswitch_entity_id
inverted?
- Switch
switch_entity_id
will be turned on when controller is active if it is set. - Switch
switch_entity_id
will be turned off when controller is not active if it is set. - Number
entity_id
temperature will be adjusted everypid_sample_period
it is provided, or on everyCONFIF.target_sensor
update ifpid_sample_period
is not provided. pid_params
will be inverted ifinverted
was set totrue
switch_entity_id
behavior will be inverted ifswitch_inverted
was set totrue
Windows are optional and their logic will be available if at least one window entity added to the config.
switch
input_boolean
binary_sensor
windows: binary_sensor.my_window
windows:
- binary_sensor.my_window
- input_boolean.heater_block
windows:
- entity_id: binary_sensor.my_window
timeout: "{{ states('input_number.window_open_timeout') | float }}"
- entity_id: input_boolean.heater_can_work
inverted: true
windows:
- binary_sensor.my_window_1
- entity_id: binary_sensor.my_window_2
timeout:
minutes: 2
- entity_id: input_boolean.heater_can_work
inverted: true
entity_id
(Required) - Target entity ID.inverted
(Optional, default=false) - Need to invertentity_id
logic.timeout
(Optional, default=none) - time period to wait until stop/start controller after window opening/closing. Can be a template.
- after any window entity turns
on
, controller stops working (off
ifinverted: true
) - after all window entities turn
off
, controller starts working (on
ifinverted: true
) - if controller has
ignore_windows
config option - it doesn't take into account windows states - if window has a
timeout
config option - it stops/starts controllers after time period mentioned
Presets are optional and will be available if at least one preset mode added to the config. All preset modes are equal in functionality, their behaviour depends only on used config parameters.
Mapping key will be a preset name. Preset can have any name, but it is recommended to use defaults, that support icons and translations:
eco
away
sleep
boost
comfort
home
activity
- if any preset is active, changing
hvac_mode
manually resets current preset toNone
- if any preset is active, activating
None
preset_mode
restores thermostat parameters to None-preset state - if any preset is active, activating another delta
preset_mode
applies all changes relatively to None-preset state - preset activation can change
hvac_mode
if preset config needs it - if you want to decrease target temperature, use negative float number.
presets:
sleep:
temp_delta: -1.0
temp_delta
(Required) - single target temperature delta, signed float, can be a template
- changes thermostat target temperatures (both ranged and non-ranged):
target_temp + temp_delta
target_temp_low + temp_delta
target_temp_high + temp_delta
presets:
away:
heat_delta: -1.0
cool_delta: 2.0
heat_delta
(Required) - heating target temperature delta, signed float, can be a templatecool_delta
(Required) - heating target temperature delta, signed float, can be a template
- if
hvac_mode
isCOOL
- changes thermostat target temperature:target_temp + cool_delta
- if
hvac_mode
isHEAT
- changes thermostat target temperature:target_temp + heat_delta
- if
hvac_mode
isHEAT_COOL
- changes thermostat target temperature:target_temp_low + heat_delta
target_temp_high + cool_delta
- if
hvac_mode
isAUTO
- doesn't change thermostat target temperature, but creates additional deltas toauto_cool_delta
andauto_heat_delta
forcontrollers
:- heaters'
target_temp
s will betarget_temp - auto_heat_delta + heat_delta
- coolers'
target_temp
s will betarget_temp + auto_cool_delta + cool_delta
- heaters'
presets:
eco:
heat_target_temp: 18.0
cool_target_temp: 28.0
comfort:
target_temp: 25.0
target_temp
(Optional) - single target temperature, signed float, can be a templateheat_target_temp
(Optional) - heating target temperature, signed float, can be a templatecool_target_temp
(Optional) - cooling target temperature, signed float, can be a template
- if
hvac_mode
isCOOL
- changes thermostat target temperature tocool_target_temp
if available or totarget_temp
: - if
hvac_mode
isHEAT
- changes thermostat target temperature toheat_target_temp
if available or totarget_temp
: - if
hvac_mode
isHEAT_COOL
- changes thermostat target temperatures:target_temp_low
will beheat_target_temp
if available ortarget_temp
target_temp_high
will becool_target_temp
if available ortarget_temp
- if
hvac_mode
isAUTO
and onlytarget_temp
is available - changes thermostat target temperature totarget_temp
: - if
hvac_mode
isAUTO
andheat_target_temp
andcool_target_temp
are available - doesn't change thermostat target temperature, but creates additional target temperatures forcontrollers
:- heaters'
target_temp
s will beheat_target_temp
- coolers'
target_temp
s will becool_target_temp
- heaters'
NOTE: Any of these config schemas could be used, but not mixed!
- Adjustable delays for turning heater/cooler on/off.
- Add support templates for
pwm_period
.
- Set up your logger to print debug messages for this component using:
logger:
default: info
logs:
custom_components.universal_thermostat: debug
- Restart HA
- Verify you're still having the issue
- File an issue in this GitHub Repository containing your HA log (Developer section > Info > Load Full Home Assistant Log)
- You can paste your log file at pastebin https://pastebin.com/ and submit a link.
- Please include details about your setup (Pi, NUC, etc, docker?, HassOS?)
- The log file can also be found at
/<config_dir>/home-assistant.log