Siirry sisältöön
Automate the North

Autolämmitys, joka lämmittää auton juuri lähtöaikaan

Home Assistant -blueprint käynnistää auton lohkolämmittimen lähtöajan ja ulkolämpötilan mukaan ja sammuttaa sen, kun olet lähtenyt.

Julkaistu
Taso
Keskitaso
Laitteet
Matter-ulkopistorasia, ulkolämpötila-anturi

Suomen talvessa auto on töpselissä joka yö. Tavallinen ajastin lämmittää yhtä kauan, oli ulkona −2 °C tai −25 °C, joten auto on joko kylmä tai lämmitin käy turhaan. Tämä toteutus aloittaa lämmityksen sopivan ajan ennen lähtöä, valitsee lämmitysajan ulkolämpötilan mukaan ja sammuttaa lämmittimen, kun olet lähtenyt.

Jokaiselle autolle asetetaan kaksi asiaa: lähtöaika ja se, onko ajastettu lämmitys päällä. Kaikki muu hoituu itsestään.

Home Assistant -dashboardin osio yhdelle autolle: tilarivi, lämmitin, ajastettu lämmitys, lähtöaika ja lämmitysaika.

Mitä se tekee

  • Aloittaa ajoissa. Lämmitys alkaa lämmitysajan verran ennen lähtöä. Kun ulkona on +5 °C tai lämpimämpää, lämmitysaika on nolla eikä mitään käynnisty.
  • Sammuu lähdön jälkeen. Lämmitin sammuu 15 minuuttia lähtöajan jälkeen.
  • Hoitaa käsin käynnistyksen. Kun kytket lämmittimen itse päälle, se sammuu lämmitysajan ja 15 minuutin jälkeen. Unohtunut lämmitin ei siis jää päälle koko päiväksi.
  • Reagoi muutoksiisi. Jos siirrät lähtöaikaa niin, että lämmityksen pitäisi jo olla käynnissä, se käynnistyy heti.
  • Ei sahaa sään mukana. Jos ulkona kylmenee ja lämmitysikkunan pitäisi jo olla alkanut, lämmitys käynnistyy heti. Kun lämmitys on kerran alkanut, lämpötilan nousu ei enää katkaise sitä.
  • Kestää uudelleenkäynnistyksen. Jos Home Assistant käynnistyy uudelleen kesken lämmitysikkunan, lämmitys jatkuu. Viiden minuutin välein ajettava tarkistus sammuttaa lämmittimen, joka on jäänyt päälle uudelleenkäynnistyksen jälkeen.
  • Lämmitysajat säädetään dashboardilta. Jokaisella lämpötila-alueella on oma minuuttimääränsä, eikä YAMLia tarvitse muokata.
  • Ei koske lämmittimeen, kun ajastus on pois. Silloin rasia on tavallinen älypistorasia.

Mitä tarvitset

  • Älypistorasian, joka kestää lämmittimen kuorman ja sopii ulkokäyttöön. Itse käytän Matter-ulkopistorasioita, mutta mikä tahansa Home Assistantissa switch-entiteettinä näkyvä rasia käy.
  • Ulkolämpötila-anturin Home Assistantissa.

Vaihe 1: apuentiteetit ja lämmitysaika

Alla oleva paketti luo lähtöajan, ajastuksen kytkimen, neljä lämmitysaikaa (yksi kullekin lämpötila-alueelle) ja kaksi template-sensoria: montako minuuttia lämmitetään juuri nyt ja milloin lämmitys alkaa. Tallenna se nimellä config/packages/car_block_heater.yaml ja vaihda sensor.outdoor_temperature omaan anturiisi.

Näytä paketti
packages/car_block_heater.yaml
# Car block heater: helpers and heating time.
# Save as config/packages/car_block_heater.yaml (packages must be enabled in configuration.yaml).
# Replace sensor.outdoor_temperature with your own outdoor temperature sensor.
# For a second car, copy the block and change "car" to e.g. "car_2".
input_datetime:
car_departure_time:
name: Car departure time
has_date: false
has_time: true
icon: mdi:clock-outline
input_boolean:
car_heating_schedule:
name: Car scheduled heating
icon: mdi:calendar-clock
# Heating time for each temperature band. Adjust these from the dashboard;
# Home Assistant remembers the values across restarts.
input_number:
car_heating_minus_20:
name: Car heating time at −20 °C or colder
min: 0
max: 180
step: 5
mode: box
unit_of_measurement: min
car_heating_minus_10:
name: Car heating time at −10 to −20 °C
min: 0
max: 180
step: 5
mode: box
unit_of_measurement: min
car_heating_minus_5:
name: Car heating time at −5 to −10 °C
min: 0
max: 180
step: 5
mode: box
unit_of_measurement: min
car_heating_below_5:
name: Car heating time below +5 °C
min: 0
max: 180
step: 5
mode: box
unit_of_measurement: min
template:
- sensor:
# Minutes of heating at the current outdoor temperature, from the times above
- name: Car heating time
unique_id: car_heating_time
unit_of_measurement: min
icon: mdi:timer-outline
state: >
{% set t = states('sensor.outdoor_temperature') | float(99) %}
{% if t <= -20 %}{{ states('input_number.car_heating_minus_20') | int(0) }}
{% elif t <= -10 %}{{ states('input_number.car_heating_minus_10') | int(0) }}
{% elif t <= -5 %}{{ states('input_number.car_heating_minus_5') | int(0) }}
{% elif t < 5 %}{{ states('input_number.car_heating_below_5') | int(0) }}
{% else %}0
{% endif %}
# When heating starts, for the dashboard
- name: Car heating starts
unique_id: car_heating_starts
icon: mdi:clock-start
state: >
{% set h = state_attr('input_datetime.car_departure_time', 'hour') | int(0) %}
{% set m = state_attr('input_datetime.car_departure_time', 'minute') | int(0) %}
{% set dep = h * 60 + m %}
{% set dur = states('sensor.car_heating_time') | int(0) %}
{% if dur == 0 %}none{% else %}
{% set start = (dep - dur) % 1440 %}
{{ '%02d:%02d' | format(start // 60, start % 60) }}
{% endif %}

Mistä lämmitysajat säädetään: vaiheen 4 dashboardilta, Lämmitysajat-kortista. Ne löytyvät myös kohdasta Asetukset → Laitteet ja palvelut → Entiteetit hakemalla sanalla “heating time”. Uudet apuentiteetit alkavat arvosta 0 minuuttia, eli lämmitystä ei tule, joten syötä omat aikasi kerran käyttöönoton jälkeen.

Yhden auton arvot ovat minulla nämä:

Ulkolämpötila Lämmitysaika
−20 °C tai kylmempää 60 min
−10 °C … −20 °C 50 min
−5 °C … −10 °C 30 min
alle +5 °C 20 min
+5 °C tai lämpimämpää ei lämmitystä

Toinen auto saa 90, 60, 45 ja 30 minuuttia. Kahta autoa varten kopioi paketin lohkot ja vaihda car esimerkiksi muotoon car_2.

Paketit otetaan käyttöön kerran configuration.yaml-tiedostossa:

configuration.yaml
homeassistant:
packages: !include_dir_named packages

Lataa sen jälkeen uudelleen kohdasta Kehitystyökalut → YAML: template-entiteetit, input boolean-, input datetime- ja input number -apuentiteetit. Uudelleenkäynnistystä ei tarvita.

Vaihe 2: blueprint

Blueprint hoitaa ajastuksen. Tallenna se nimellä config/blueprints/automation/automate_the_north/car_block_heater.yaml ja lataa automaatiot uudelleen kohdasta Kehitystyökalut → YAML. Blueprintin tekstit ovat englanniksi, koska Home Assistant ei tue blueprintien kääntämistä.

Näytä blueprint
blueprints/automation/automate_the_north/car_block_heater.yaml
blueprint:
name: Car block heater by departure time
author: Automate the North
description: >
Switches a car engine block heater on so the car is warm at your departure time,
and off again shortly after you leave.
**How it works**
- Heating starts *heating time* minutes before the departure time. The heating
time comes from a sensor you choose (minutes), so you decide how long to heat
at each outdoor temperature. A heating time of 0 means no heating that day.
- The heater switches off a few minutes after departure.
- If you switch the heater on by hand, it switches itself off after the heating
time plus the after-departure buffer, so a forgotten heater never runs all day.
- If you change the departure time so heating should already be running, it
starts immediately.
- When the schedule toggle is off, this automation never touches the heater.
domain: automation
input:
heater:
name: Heater switch
description: The smart plug or relay that powers the block heater.
selector:
entity:
filter:
- domain: switch
departure_time:
name: Departure time
description: An input_datetime helper with time only.
selector:
entity:
filter:
- domain: input_datetime
schedule_enabled:
name: Scheduled heating toggle
description: An input_boolean that turns scheduled heating on or off.
selector:
entity:
filter:
- domain: input_boolean
heating_time:
name: Heating time sensor
description: A sensor whose state is the heating time in minutes, usually a template based on the outdoor temperature.
selector:
entity:
filter:
- domain: sensor
after_departure:
name: Keep heating after departure
description: Minutes the heater stays on after the departure time. Also the run time of a manual start on a warm day.
default: 15
selector:
number:
min: 0
max: 60
unit_of_measurement: min
mode: queued
max: 10
trigger_variables:
heater: !input heater
departure: !input departure_time
heating_time: !input heating_time
buffer: !input after_departure
triggers:
# Departure minus heating time
- trigger: template
id: start
value_template: >
{% set dep = (state_attr(departure, 'hour') | int(0)) * 60 + (state_attr(departure, 'minute') | int(0)) %}
{% set dur = states(heating_time) | int(0) %}
{{ dur > 0 and (now().hour * 60 + now().minute) == (dep - dur) % 1440 }}
# Departure plus buffer
- trigger: template
id: end
value_template: >
{% set dep = (state_attr(departure, 'hour') | int(0)) * 60 + (state_attr(departure, 'minute') | int(0)) %}
{{ (now().hour * 60 + now().minute) == (dep + buffer | int(0)) % 1440 }}
# Any run (manual or scheduled) ends after heating time + buffer at the latest
- trigger: state
id: timeout
entity_id: !input heater
to: 'on'
for:
minutes: '{{ [states(heating_time) | int(0), 0] | max + buffer | int(0) }}'
# Settings changed: start right away if we're already inside the heating window
- trigger: state
id: settings
entity_id:
- !input departure_time
- !input schedule_enabled
# Heating time grew so that the window now includes the current minute
- trigger: state
id: heating_time
entity_id: !input heating_time
# After a restart: resume a heating window that started while HA was down
- trigger: homeassistant
id: ha_start
event: start
# Safety net for runs whose timer was lost in a restart
- trigger: time_pattern
id: watchdog
minutes: /5
conditions:
- condition: state
entity_id: !input schedule_enabled
state: 'on'
variables:
now_min: '{{ now().hour * 60 + now().minute }}'
dep_min: "{{ (state_attr(departure, 'hour') | int(0)) * 60 + (state_attr(departure, 'minute') | int(0)) }}"
end_min: '{{ (dep_min + buffer | int(0)) % 1440 }}'
# Is now_min inside [departure - heating time, departure + buffer)? Wraps past midnight.
in_window: >-
{%- set dur = states(heating_time) | int(0) -%}
{%- set start = (dep_min - dur) % 1440 -%}
{{ dur > 0 and ((start <= end_min and start <= now_min and now_min < end_min)
or (start > end_min and (now_min >= start or now_min < end_min))) }}
# Same test with the heating time before this change (only for heating_time triggers)
was_in_window: >-
{%- set dur = trigger.from_state.state | int(0) if trigger.id == 'heating_time' else 0 -%}
{%- set start = (dep_min - dur) % 1440 -%}
{{ dur > 0 and ((start <= end_min and start <= now_min and now_min < end_min)
or (start > end_min and (now_min >= start or now_min < end_min))) }}
actions:
- choose:
- conditions:
- condition: trigger
id: start
- condition: template
value_template: "{{ is_state(heater, 'off') }}"
sequence:
- action: switch.turn_on
target:
entity_id: !input heater
- conditions:
- condition: trigger
id: [settings, heating_time, ha_start]
- condition: template
value_template: "{{ in_window | bool and not was_in_window | bool and is_state(heater, 'off') }}"
sequence:
- action: switch.turn_on
target:
entity_id: !input heater
- conditions:
- condition: trigger
id: [end, timeout]
- condition: template
value_template: "{{ is_state(heater, 'on') }}"
sequence:
- action: switch.turn_off
target:
entity_id: !input heater
# Heater left on outside the heating window for longer than a run may last
- conditions:
- condition: trigger
id: [watchdog, ha_start]
- condition: template
value_template: >-
{%- set on_min = (now() - states[heater].last_changed).total_seconds() / 60 -%}
{%- set limit = [states(heating_time) | int(0), 0] | max + buffer | int(0) -%}
{{ is_state(heater, 'on') and not in_window | bool and on_min >= limit }}
sequence:
- action: switch.turn_off
target:
entity_id: !input heater

Vaihe 3: yksi automaatio per auto

Avaa Asetukset → Automaatiot ja tilanteet → Blueprintit, valitse Car block heater by departure time ja täytä:

  • Heater switch: älypistorasiasi
  • Departure time: input_datetime.car_departure_time
  • Scheduled heating toggle: input_boolean.car_heating_schedule
  • Heating time sensor: sensor.car_heating_time

Tallenna. Toiselle autolle luodaan oma automaatio samasta blueprintista sen auton entiteeteillä.

Vaihe 4: dashboard

Osio käyttää vain Home Assistantin omia kortteja. Ylin rivi kertoo selkokielellä, mitä seuraavaksi tapahtuu, esimerkiksi “Lämmitys alkaa klo 06:55”. Alimmasta Lämmitysajat-kortista säädetään minuutit kullekin lämpötila-alueelle. Lisää Sections-näkymään osio, avaa Muokkaa YAML:na ja liitä:

Näytä dashboardin YAML
Dashboard-osio
# Yhden auton dashboard-osio. Sections-näkymässä: lisää osio → ⋮ → Muokkaa YAML:na ja liitä tämä.
type: 'grid'
cards:
- type: 'heading'
heading: 'Auto'
heading_style: 'title'
icon: 'mdi:car'
badges:
- type: 'entity'
entity: 'sensor.outdoor_temperature'
name: 'Ulkona'
show_name: false
show_icon: true
icon: 'mdi:thermometer'
show_state: true
- type: 'markdown'
text_only: true
content: |-
{%- set t = states('sensor.outdoor_temperature') | float(none) -%}
{%- set tt = (t | round(1) | string) | replace('.', ',') if t is not none else '–' -%}
{%- set dur = states('sensor.car_heating_time') | int(0) -%}
{%- set dep = states('input_datetime.car_departure_time')[:5] -%}
{%- if is_state('switch.car_block_heater','on') and is_state('input_boolean.car_heating_schedule','off') -%}
## Lämmitin päällä
Ajastus on pois, joten lämmitin on päällä, kunnes sammutat sen.
{%- elif is_state('switch.car_block_heater','on') -%}
## Lämmitys päällä
Valmis lähtöön klo {{ dep }}.
{%- elif is_state('input_boolean.car_heating_schedule','off') -%}
## Ajastus pois
Lämmitin on päällä vain, kun kytket sen itse.
{%- elif dur == 0 -%}
## Lämmitystä ei tarvita
Ulkona on {{ tt }} °C. Auto on valmis klo {{ dep }} sellaisenaan.
{%- else -%}
## Lämmitys alkaa klo {{ states('sensor.car_heating_starts') }}
{{ dur }} minuuttia, kun ulkona on {{ tt }} °C. Lämmin klo {{ dep }}.
{%- endif -%}
grid_options:
columns: 'full'
- type: 'tile'
entity: 'switch.car_block_heater'
name: 'Lämmitin'
icon: 'mdi:car-seat-heater'
vertical: false
grid_options:
columns: 6
tap_action:
action: 'toggle'
icon_tap_action:
action: 'toggle'
hide_state: true
- type: 'tile'
entity: 'input_boolean.car_heating_schedule'
name: 'Ajastettu lämmitys'
icon: 'mdi:calendar-clock'
vertical: false
grid_options:
columns: 6
tap_action:
action: 'toggle'
icon_tap_action:
action: 'toggle'
- type: 'tile'
entity: 'input_datetime.car_departure_time'
name: 'Lähtöaika'
icon: 'mdi:clock-outline'
vertical: false
grid_options:
columns: 6
- type: 'tile'
entity: 'sensor.car_heating_time'
name: 'Lämmitysaika'
icon: 'mdi:timer-outline'
vertical: false
grid_options:
columns: 6
- type: 'entities'
title: 'Lämmitysajat'
state_color: false
grid_options:
columns: 'full'
entities:
- entity: 'input_number.car_heating_minus_20'
name: '−20 °C tai kylmempää'
icon: 'mdi:thermometer'
- entity: 'input_number.car_heating_minus_10'
name: '−10 … −20 °C'
icon: 'mdi:thermometer'
- entity: 'input_number.car_heating_minus_5'
name: '−5 … −10 °C'
icon: 'mdi:thermometer'
- entity: 'input_number.car_heating_below_5'
name: 'alle +5 °C'
icon: 'mdi:thermometer'

Lämmitin-kortin tila on piilotettu tarkoituksella. Kuvakkeen väri ja tilarivi kertovat jo, onko lämmitin päällä. Lisäksi Home Assistantin suomennoksessa pistorasian tila näkyy englanniksi (“On”/“Off”).

Hyvä tietää

  • Miksi lämmitysaika on sensori. Blueprint tarvitsee vain minuuttimäärän. Lämpötilataulukon voi korvata millä tahansa: tuulen viilentävällä vaikutuksella, eri taulukolla viikonlopuille tai kiinteällä arvolla.
  • Käsin käynnistetty lämmitys päättyy viimeistään 15 minuuttia lähtöajan jälkeen, kun ajastus on päällä. Jos kytket lämmittimen 10 minuuttia ennen lähtöä, se sammuu 15 minuuttia lähdön jälkeen eikä vasta täyden lämmitysjakson päästä.