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 conditionTemplate, nei parametri delle action (es.brightness_pct: "{{ 100 if is_state('binary_sensor.notte','off') else 30 }}"). - Notifiche: nel
messagee neltitleper 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
| Funzione | Cosa 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.
| Filtro | Cosa 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 è:
- Developer tools → Template (sidebar, penultima icona).
- Nel riquadro di sinistra scrivi il template.
- Nel riquadro di destra vedi il risultato aggiornato in real time.
- Correggi finché non ti dà quello che vuoi.
- 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
triggerinvece distate: 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 suunavailable. - 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.