Hi,
I’m planning to automate my car heating setup and would appreciate some advice on the best approach.
Current situation
- I have 2* standard 230V outlet for engine/block heating.
- Control is currently manual or based on simple timers.
What I want to achieve
- Set a departure time (e.g. 07:30), and have the system automatically determine when to start heating.
- Heating duration should adapt based on outdoor temperature:
- colder weather → longer heating
- milder weather → shorter heating
- Heating should continue for 30 minutes after the departure time.
- If the departure time has passed and no power is being consumed, the system should turn off automatically.
- I want it to work like smartphone alarmclock, if you select days it will repeat on those days and if you don’t then it will heat just next day.
Manual control requirement
- Each outlet (shelly 1PM gen4) has a physical button (via Shelly input) to turn it on manually.
- When activated manually:
- the outlet should turn on immediately (it does because of shelly)
- and then automatically turn off after a configurable time (set via a variable/helper)
Data sources I’m considering
- Weather forecast (online API)
- Local sensors:
- 2*Hue outdoor motion sensors)
Goal
A reliable, mostly automated system where I only need to:
- set the departure time
- and everything else happens automatically
What have I achieved already
- Script that calculates heating start time and how logn to heat. Is this logic DST proof?:
car_heating_time_calculator:
alias: Car Heating Time Calculator
mode: single
sequence:
# ===== Car 1, Profile 1 =====
- service: input_number.set_value
target:
entity_id: input_number.car1_heat_duration_1
data:
value: >
{% set outdoor = states('sensor.outdoor_temperature_min') | float(999) %}
{% set e = 2.718281828459045 %}
{% set val = 0.5 * (e ** (0.075 * (4 - outdoor))) %}
{{ [4, [0.5, val] | max] | min | round(2) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.car1_heat_start_1
data:
time: >
{% set dep_time = states('input_datetime.autostart_1_1')[0:5] %}
{% set dep_today = today_at(dep_time) %}
{% set dep_dt = dep_today if dep_today > now() else dep_today + timedelta(days=1) %}
{% set dep_ts = as_timestamp(dep_dt) %}
{% set heat_h = states('input_number.car1_heat_duration_1') | float(4) %}
{{ (dep_ts - (heat_h * 3600)) | timestamp_custom('%H:%M', true) }}
# ===== Car 1, Profile 2 =====
- service: input_number.set_value
target:
entity_id: input_number.car1_heat_duration_2
data:
value: >
{% set outdoor = states('sensor.outdoor_temperature_min') | float(999) %}
{% set e = 2.718281828459045 %}
{% set val = 0.5 * (e ** (0.075 * (4 - outdoor))) %}
{{ [4, [0.5, val] | max] | min | round(2) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.car1_heat_start_2
data:
time: >
{% set dep_time = states('input_datetime.autostart_1_2')[0:5] %}
{% set dep_today = today_at(dep_time) %}
{% set dep_dt = dep_today if dep_today > now() else dep_today + timedelta(days=1) %}
{% set dep_ts = as_timestamp(dep_dt) %}
{% set heat_h = states('input_number.car1_heat_duration_1') | float(4) %}
{{ (dep_ts - (heat_h * 3600)) | timestamp_custom('%H:%M', true) }}
# ===== Car 1, Profile 3 =====
- service: input_number.set_value
target:
entity_id: input_number.car1_heat_duration_3
data:
value: >
{% set outdoor = states('sensor.outdoor_temperature_min') | float(999) %}
{% set e = 2.718281828459045 %}
{% set val = 0.5 * (e ** (0.075 * (4 - outdoor))) %}
{{ [4, [0.5, val] | max] | min | round(2) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.car1_heat_start_3
data:
time: >
{% set dep_time = states('input_datetime.autostart_1_3')[0:5] %}
{% set dep_today = today_at(dep_time) %}
{% set dep_dt = dep_today if dep_today > now() else dep_today + timedelta(days=1) %}
{% set dep_ts = as_timestamp(dep_dt) %}
{% set heat_h = states('input_number.car1_heat_duration_1') | float(4) %}
{{ (dep_ts - (heat_h * 3600)) | timestamp_custom('%H:%M', true) }}
# ===== Car 2, Profile 1 =====
- service: input_number.set_value
target:
entity_id: input_number.car2_heat_duration_1
data:
value: >
{% set outdoor = states('sensor.outdoor_temperature_min') | float(999) %}
{% set e = 2.718281828459045 %}
{% set val = 0.5 * (e ** (0.075 * (4 - outdoor))) %}
{{ [4, [0.5, val] | max] | min | round(2) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.car2_heat_start_1
data:
time: >
{% set dep_time = states('input_datetime.autostart_2_1')[0:5] %}
{% set dep_today = today_at(dep_time) %}
{% set dep_dt = dep_today if dep_today > now() else dep_today + timedelta(days=1) %}
{% set dep_ts = as_timestamp(dep_dt) %}
{% set heat_h = states('input_number.car1_heat_duration_1') | float(4) %}
{{ (dep_ts - (heat_h * 3600)) | timestamp_custom('%H:%M', true) }}
# ===== Car 2, Profile 2 =====
- service: input_number.set_value
target:
entity_id: input_number.car2_heat_duration_2
data:
value: >
{% set outdoor = states('sensor.outdoor_temperature_min') | float(999) %}
{% set e = 2.718281828459045 %}
{% set val = 0.5 * (e ** (0.075 * (4 - outdoor))) %}
{{ [4, [0.5, val] | max] | min | round(2) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.car2_heat_start_2
data:
time: >
{% set dep_time = states('input_datetime.autostart_2_2')[0:5] %}
{% set dep_today = today_at(dep_time) %}
{% set dep_dt = dep_today if dep_today > now() else dep_today + timedelta(days=1) %}
{% set dep_ts = as_timestamp(dep_dt) %}
{% set heat_h = states('input_number.car1_heat_duration_1') | float(4) %}
{{ (dep_ts - (heat_h * 3600)) | timestamp_custom('%H:%M', true) }}
# ===== Car 2, Profile 3 =====
- service: input_number.set_value
target:
entity_id: input_number.car2_heat_duration_3
data:
value: >
{% set outdoor = states('sensor.outdoor_temperature_min') | float(999) %}
{% set e = 2.718281828459045 %}
{% set val = 0.5 * (e ** (0.075 * (4 - outdoor))) %}
{{ [4, [0.5, val] | max] | min | round(2) }}
- service: input_datetime.set_datetime
target:
entity_id: input_datetime.car2_heat_start_3
data:
time: >
{% set dep_time = states('input_datetime.autostart_2_3')[0:5] %}
{% set dep_today = today_at(dep_time) %}
{% set dep_dt = dep_today if dep_today > now() else dep_today + timedelta(days=1) %}
{% set dep_ts = as_timestamp(dep_dt) %}
{% set heat_h = states('input_number.car1_heat_duration_1') | float(4) %}
{{ (dep_ts - (heat_h * 3600)) | timestamp_custom('%H:%M', true) }}
I also have UI cards:
type: vertical-stack
title: Lämmityspistorasia A
cards:
- type: entities
title: Lämpötila
entities:
- entity: sensor.outdoor_temperature_min
name: Kylmin ulkolämpötila
icon: mdi:snowflake
- entity: input_button.update_car_heating_calc
name: Päivitä lämmityslaskenta
icon: mdi:refresh
- type: entities
title: Manuaalinen lämmitys
entities:
- entity: switch.autolammitys_a
name: Lämmitys päälle/pois
- entity: input_number.manual_heat_duration_1
name: Lämmityksen kesto (h)
- entity: sensor.shelly1pmg4_xxx_current
name: Virta (A)
- type: entities
title: Profiili 1
entities:
- entity: input_boolean.autostart_1_1_enabled
name: Profiili käytössä
- entity: input_datetime.autostart_1_1
name: Lähtöaika
- entity: sensor.car_1_heat_start_1
name: Laskettu aloitusaika
- type: section
label: Toistuvat päivät
- entity: input_boolean.autostart_1_1_mon
name: Maanantai
- entity: input_boolean.autostart_1_1_tue
name: Tiistai
- entity: input_boolean.autostart_1_1_wed
name: Keskiviikko
- entity: input_boolean.autostart_1_1_thu
name: Torstai
- entity: input_boolean.autostart_1_1_fri
name: Perjantai
- entity: input_boolean.autostart_1_1_sat
name: Lauantai
- entity: input_boolean.autostart_1_1_sun
name: Sunnuntai
- type: entities
title: Profiili 2
entities:
- entity: input_boolean.autostart_1_2_enabled
name: Profiili käytössä
- entity: input_datetime.autostart_1_2
name: Lähtöaika
- entity: sensor.car_1_heat_start_2
name: Laskettu aloitusaika
- type: section
label: Toistuvat päivät
- entity: input_boolean.autostart_1_2_mon
name: Maanantai
- entity: input_boolean.autostart_1_2_tue
name: Tiistai
- entity: input_boolean.autostart_1_2_wed
name: Keskiviikko
- entity: input_boolean.autostart_1_2_thu
name: Torstai
- entity: input_boolean.autostart_1_2_fri
name: Perjantai
- entity: input_boolean.autostart_1_2_sat
name: Lauantai
- entity: input_boolean.autostart_1_2_sun
name: Sunnuntai
- type: entities
title: Profiili 3
entities:
- entity: input_boolean.autostart_1_3_enabled
name: Profiili käytössä
- entity: input_datetime.autostart_1_3
name: Lähtöaika
- entity: sensor.car_1_heat_start_3
name: Laskettu aloitusaika
- type: section
label: Toistuvat päivät
- entity: input_boolean.autostart_1_3_mon
name: Maanantai
- entity: input_boolean.autostart_1_3_tue
name: Tiistai
- entity: input_boolean.autostart_1_3_wed
name: Keskiviikko
- entity: input_boolean.autostart_1_3_thu
name: Torstai
- entity: input_boolean.autostart_1_3_fri
name: Perjantai
- entity: input_boolean.autostart_1_3_sat
name: Lauantai
- entity: input_boolean.autostart_1_3_sun
name: Sunnuntai
I’m really new to HA and this is my first real automation ![]()
Thanks in advance for any suggestions or examples!


