I template sono il modo in cui Home Assistant permette di scrivere piccoli frammenti di logica dinamica: leggere lo stato di un’entità, fare calcoli, comporre stringhe, valutare condizioni. La sintassi è Jinja, un linguaggio di templating molto diffuso in Python (Flask, Ansible, Salt lo usano). Non serve conoscere Jinja a fondo: per il 90% degli usi in HA bastano cinque funzioni e sei filtri. In questo capitolo li vediamo, con la promessa che alla fine saprai leggere qualsiasi template trovi online, e adattarlo al tuo caso.

Dove appaiono i template in HA

I template compaiono in punti diversi:

  • Template sensor e template binary_sensor, entità il cui stato è calcolato via template a partire da altre entità.
  • Automazioni: nei trigger Template, nelle condition Template, nei parametri delle action (es. brightness_pct: "{{ 100 if is_state('binary_sensor.notte','off') else 30 }}").
  • Notifiche: nel message e nel title per costruire testi dinamici.
  • Card Markdown: per mostrare valori calcolati nella dashboard.
  • Developer tools → Template: il playground per provare template al volo senza salvare nulla.

Ovunque HA accetta un valore, spesso accetta anche un template racchiuso in {{ ... }}.

La sintassi minima da sapere

Un template è un pezzo di testo con espressioni (fra {{ }}) e/o blocchi di controllo (fra {% %}).

{{ states('sensor.temperatura_salotto') }}                → il valore corrente
{{ states('sensor.temperatura_salotto') | float(0) + 1 }} → il valore + 1
{% if is_state('binary_sensor.presenza','on') %}          → blocco condizionale
  C'è qualcuno
{% else %}
  Nessuno
{% endif %}

I {{ }} restituiscono un valore. I {% %} controllano il flusso (if, for). Un template semplice sta tutto in una riga con {{ }}, non serve altro.

Le 5 funzioni che coprono l’80% dei casi

FunzioneCosa fa
states('sensor.x')Il valore corrente dell’entità come stringa.
state_attr('sensor.x','friendly_name')Un attributo specifico dell’entità.
is_state('sensor.x','on')True se lo stato è “on” (comodo per confronti stringa).
is_state_attr('sensor.x','battery_level',100)True se l’attributo ha quel valore.
now()Timestamp corrente. Combinato con .hour, .weekday(), ecc.

Esempi pratici:

{{ states('sensor.consumo_istantaneo') | float(0) > 3500 }}       → true/false
{{ state_attr('climate.termostato','current_temperature') }}      → temperatura letta
{{ (now() - states.sun.sun.last_changed).total_seconds() > 3600 }}→ è passato un'ora dall'alba/tramonto?

I 6 filtri più utili

I filtri si applicano con | (pipe). Trasformano il valore.

FiltroCosa fa
`float(0)`
`int(0)`
`round(1)`
`default(‘nessuno’)`
`lower/
`join(’, ’)`

Il filtro | float(0) è di gran lunga il più importante: le entità che sono unavailable o unknown fanno crashare i template numerici se non hai il default. Regola pratica: ogni volta che leggi un sensore numerico, aggiungi | float(0) (o | int(0)).

Template sensor: creare un’entità calcolata

Dai template puoi generare nuove entità. La via più moderna è tramite l’editor Helper.

Impostazioni → Helper → Aggiungi → Template a sensore.

Compili:

  • Nome (es. “Consumo istantaneo in euro/h”)
  • Template stato (es. {{ (states('sensor.consumo_watt') | float(0) / 1000) * states('input_number.prezzo_kwh') | float(0) | round(3) }})
  • Template icona (opzionale, es. mdi:currency-eur)
  • Unità di misura (es. €/h)

Salvi, ottieni sensor.consumo_istantaneo_in_euro_h che si aggiorna automaticamente quando cambiano le entità referenziate. Il resto di HA la tratta come qualunque altro sensore: puoi metterla in una card, usarla come trigger di automazioni, mostrarne lo storico.

Esempio tipico: contatore giorni dall’ultima manutenzione.

{{ ((now() - as_datetime(states('input_datetime.ultima_manutenzione_caldaia'))).days) }}

Sensore sensor.giorni_ultima_manutenzione_caldaia, unità giorni, e nella dashboard puoi metterci sopra un badge che diventa rosso oltre 365.

Template binary_sensor: on/off calcolato

Come sopra ma con un template che restituisce true/false, e HA lo tratta come entità on/off.

Esempi:

{{ states('sensor.temperatura_salotto') | float(0) > 25 and states('sensor.umidita_salotto') | float(0) > 70 }}

→ binary_sensor.caldo_e_umido, on quando entrambi i parametri sono oltre soglia. Un’automazione può triggerarsi al cambio a on per accendere il deumidificatore.

Il playground: Developer tools → Template

L’errore classico è scrivere un template dentro un’automazione, salvare, aspettare che scatti, verificare, correggere, salvare, ecc. Perdi mezz’ora.

Il modo giusto è:

  1. Developer tools → Template (sidebar, penultima icona).
  2. Nel riquadro di sinistra scrivi il template.
  3. Nel riquadro di destra vedi il risultato aggiornato in real time.
  4. Correggi finché non ti dà quello che vuoi.
  5. Copia-incolla nell’automazione o nel template sensor.

Nel template puoi mescolare più espressioni per esplorare:

{{ states('sensor.temperatura_salotto') }}
{{ states('sensor.temperatura_salotto') | float(0) }}
{{ states('sensor.temperatura_salotto') | float(0) > 22 }}

Vedi le tre righe di output e capisci al volo se un cast fallisce, se un confronto ritorna quello che ti aspetti, ecc.

Il costo dei template: attenzione

I template sensor si aggiornano ogni volta che cambia una delle entità referenziate. Se un template referenzia sensor.consumo_istantaneo che aggiorna ogni secondo, il template ricalcola ogni secondo. Se il template è pesante o ne hai molti, il DB si riempie di history e la CPU si carica.

Modi per contenere:

  • Non referenziare entità troppo frequenti se non serve. Se ti basta l’ultimo minuto, un sensor.consumo_istantaneo_avg_1min (statistics helper) come sorgente riduce la frequenza.
  • Usa trigger invece di state: un template sensor moderno può essere configurato per aggiornarsi solo su un trigger (es. ogni 5 minuti, o al cambio di un flag), non ad ogni cambio delle entità referenziate. Richiede un template sensor definito in YAML (l’editor helper non espone questa opzione).
  • Un template è meglio di due: se calcoli due volte la stessa cosa in due sensor diversi, refattorizza in uno solo.

Errori tipici

“UndefinedError: ‘states’ has no attribute ‘sensor’“. Hai scritto states.sensor.x invece di states('sensor.x'). Le due sintassi sono simili ma differiscono: la seconda è più robusta ai casi in cui l’entità non esiste ancora.

“None + int”. Stai facendo un calcolo su una entità unavailable. Fix: | float(0) prima del calcolo.

Template che restituisce None quando dovrebbe dare un numero. Se una funzione fallisce silenziosamente, controlla i tipi con {{ x | type }} nel playground.

Data/ora confuse fra stringa e datetime. states('input_datetime.x') restituisce una stringa. Per fare confronti/aritmetica su date, converti con as_datetime(...).

Template sensor che non compare in HA. Errore di sintassi nel template lo blocca al caricamento. Controlla i log (Impostazioni → Sistema → Log) subito dopo aver aggiunto/modificato.

Ricapitolando

  • Template = frammenti Jinja che HA valuta con stato corrente delle entità.
  • 5 funzioni bastano: states(), state_attr(), is_state(), is_state_attr(), now().
  • 6 filtri bastano; il più importante è | float(0) per non crashare su unavailable.
  • I template sensor/binary_sensor creano entità nuove calcolate, usabili come qualsiasi altra.
  • Developer tools → Template è il playground; usalo prima di salvare i template dentro le automazioni.
  • Attenzione al costo: template che ricalcolano ogni secondo caricano DB e CPU.