Al momento stai visualizzando Template Jinja con Home Assistant

Template Jinja con Home Assistant

Questo articolo rappresenta sia una guida alla scrittura di template Jinja con Home Assistant che un riferimento rapido da usare durante la scrittura dei tuoi template.

Questo articolo non intende sostituire le documentazioni ufficiali (fonte primaria e insostituibile) ma mira a offrire una raccolta di esempi pratici e approfondimenti in un’unica pagina semplice da fruire, in lingua italiana. L’obiettivo è rendere la documentazione di Jinja per Home Assistant più accessibile e leggibile, considerando che le pagine ufficiali sono scritte in modo poco intuitivo, senza esempi o con esempi non inerenti al mondo di Home Assistant. Inoltre la documentazione non è unica ma così suddivisa, rendendone ulteriormente complessa la comprensione e ricerca:

È opportuno sottolineare che le informazioni riguardanti le estensioni di Home Assistant sono aggiornate alla versione 2024.4.

Si noti infine che nel presente articolo non sono presenti il 100% dei concetti dei template Jinja, ma i più importanti e significativi considerandone l’utilizzo nella realtà di Home Assistant, con un esempio per ogni concetto a chiarirne concretamente il modo di utilizzo pratico.

Le Basi

Ma prima di iniziare: cos’è un template Jinja in Home Assistant? (spesso chiamato anche Jinja2)
E’ un insieme di istruzioni per sostituire ad un valore statico un valore calcolato da uno script dinamico. Puoi immaginarlo come un piccolo pezzo di codice sorgente che determina un risultato che sarà calcolato al momento dell’esecuzione e il cui risultato sarà quindi usato laddove il template è stato posto.
Un esempio è meglio di mille parole, per capire il concetto: immagina di voler far pronunciare un testo dinamico ad un dispositivo multimediale, ad esempio usando multinotify. Al posto di un messaggio statico come
message: "Ciao Mario, come stai?"
puoi scrivere un semplice template
message: "Ciao {{nome_utente}}, come stai alle {{ now().strftime('%H:%M') }}?".
All’esecuzione verrà interpretato e generato un messaggio come “Ciao Mario, come stai alle 16:35?”
Non ti soffermare sui dettagli, era solo per capire il principio di funzionamento.

Questo era un esempio molto semplice ma nei template ci possono essere condizioni, cicli, analisi di liste e dizionari, per citarne qualcuna. Possiamo quindi creare delle logiche molto complesse con una discreta semplicità (una volta imparata la sintassi 🙂 ).

I template possono essere utilizzati in svariati contesti riguardanti la configurazione di Home Assistant: nelle automazioni, script, sensori ed altre componenti del sistema per manipolare dati, creare espressioni condizionali o generare valori dinamici.

I template in Home Assistant sono fondati sulla sintassi di Jinja2 con alcune estensioni specifiche di Home Assistant.

Per completare questa operazione, è necessario diventare familiari con la scheda “Modelli” nell’ambiente degli strumenti per sviluppatori. Questa scheda consente di testare e valutare i modelli direttamente dall’interfaccia utente. Questo strumento è particolarmente utile per sviluppare e risolvere problemi nei modelli senza doverli collaudare direttamente in automazioni, script o sensori, riducendo parecchio la complessità di debug.

Open your Home Assistant instance and show your template developer tools.

Delimitatori

I delimitatori sono segni o simboli che vengono utilizzati per racchiudere e identificare l’inizio e la fine di un blocco di codice all’interno di un template. Questi delimitatori servono a indicare al motore di templating di Jinja2 quali parti del testo devono essere interpretate per esprimere variabili, creare istruzioni condizionali, cicli, per inserire commenti o stampare output.

{{ ... }}: Utilizzati per racchiudere espressioni. Ad esempio, {{ 'HomeAssistant' }}

{#...#} Utilizzati per commentare il codice. Il testo compreso tra questi delimitatori non verrà interpretato.

{% ... %}}: Utilizzati per racchiudere istruzioni, come cicli, variabili o condizioni. Ad esempio, {% if condizione %} ... {% endif %} indica un blocco condizionale.

⬇️ Il carattere - vicino all’indentazione viene utilizzato per gestire lo spazio in eccesso o in meno che potrebbe essere generato durante il rendering del template.

Nel primo esempio, i numeri vengono stampati con uno spazio bianco sia prima che dopo ciascuno di essi. mentre nel secondo esempio li spazi bianchi iniziali e finali attorno al valore di i vengono rimossi.

{% for i in range(5) %}
    {{ i }}
{% endfor %}

{#  otuput:
    0

    1

    2

    3

    4
#}    

{%- for i in range(5) %}
    {{- i -}}
{% endfor %}
{# outpu: 01234 #}

Indentazione

In Home Assistant, puoi definire i template sia come stringhe multilinea che come stringhe su una singola linea. Tuttavia, è importante prestare attenzione alla formattazione e all’indentazione quando si lavora con YAML.

Nel caso di stringhe multilinea, il carattere > in YAML indica di unire le linee separatamente da uno spazio, preservando comunque gli a capo.

Quando si scrive un template su una singola linea, è necessario racchiudere il template tra virgolette doppie " o singole '. Questo assicura che il template venga interpretato correttamente all’interno della struttura YAML, evitando problemi di parsing.

message: >
  {{ 'Questo è un esempio di
  template su più linee in YAML.' }}

message: "{{ 'Questo è un esempio di template su una singola linea.' }}"
message: '{{ "Questo è un esempio di template su una singola linea." }}'

Variabili

Un’altra caratteristica fondamentale sono le variabili. A volte è necessario richiamare alcuni valori nel template. Per fare ciò, puoi creare una variabile, che memorizzerà il valore per te. Una variabile ha sempre un nome, con il quale può essere chiamata durante il rendering, e ha anche un tipo. Prima di poter utilizzare la variabile, è necessario inizializzarla. Puoi farlo usando il comando '{% set nome_variabile = ... %}'

{% set stato_allarme = states('alarm_control_panel.home_alarm')%}
{{ stato_allarme }}   {# output verrà restituito lo stato dell'allarme #}

Quella dell’esempio sono le variabili globali più comunemente usate ed accessibile in tutto il template, ma è possibile avere anche variabile locali anche se poco utilizzate. Questa è definita all’interno di un blocco specifico e sarà limitata a quel blocco.

{% set var_globale = 'Sono globale' %}  {# Definizione di una variabile globale #}
{% block my_block %}
  {% set var_locale = 'Sono locale' %}  {# Definizione di una variabile locale all'interno del blocco #}
  {{ var_locale }}
{% endblock %}                          {# Il blocco my_block termina qui #}
{{ var_globale }}                       {# Stampa della variabile globale che può essere usata sia dentro che fuori dal blocco #}

Tipi di risultati

In un template, il risultato di un’espressione può essere di vari tipi di dati, come stringhe, numeri, booleani, liste, dizionari o variabili non definite. Questo dipende dalle operazioni specifiche eseguite nell’espressione. La flessibilità di Jinja2 consente di lavorare con una varietà di tipi di dati nei template.

Stringhe

Il termine ‘stringa’ si riferisce a una sequenza di caratteri, come parole e frasi, racchiuse tra virgolette singole '' o doppie "". Le stringhe sono impiegate per rappresentare testo e possono essere manipolate in vari modi all’interno del template. Quando si utilizzano virgolette per racchiudere un numero, questo viene automaticamente convertito in una stringa.

È possibile concatenare più stringhe utilizzando l’operatore ~ . Quando si utilizza ~ con un numero e una stringa, Jinja2 converte automaticamente il numero in una stringa prima di effettuare la concatenazione.

{{ 'HomeAssistante' }} o {{ " HomeAssistant" }}
{{ "4" }} {# type stringa #} {{ 4 }}    {# type numero #}
{{ 'versione' ~ 2024 }}                 {# versione 2024 #}

Numeri

I numeri sono di due tipi principali: interi (int) e decimali (float). Il tipo esatto dipende dal modo in cui il numero è scritto nel template. Puoi utilizzare questi numeri in operazioni matematiche all’interno dei tuoi template.

{{ 50 }}    {# int #}
{{ 55.3 }}  {# float #}

Liste

Pensa a una lista come a un registro dettagliato di cose che hai, mettendole in fila in un ordine specifico. È come se stessi organizzando i tuoi oggetti preferiti in una fila, dove ogni elemento ha un posto ben definito. Puoi mettere numeri, parole o qualsiasi cosa desideri in questa fila. Basta scrivere gli oggetti separati da virgole e racchiuderli tra parentesi quadre, come se stessi creando un elenco numerato. Quindi, quando dici che le liste sono ordinate, significa che c’è una sequenza specifica in cui gli elementi sono disposti, proprio come quando numeri le tue cose preferite in un elenco dettagliato.

Vediamo un esempio, immagina che la variabile my_list sia come una scatola magica che contiene gli elementi che hai inserito: 'elemento1', 'elemento2', 'elemento3' e il numero 55. Quando mostri my_list, ottieni esattamente quella sequenza.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list }}    {# output ['elemento1', 'elemento2', 'elemento3', 55] #}

Ora, parlando di HomeAssistant, stiamo creando una lista chiamata my_light che contiene gli identificatori di tutte le entità light. È come fare un elenco di tutte le luci nella tua casa. Quindi, quando mostri my_light, ottieni l’elenco di tutte le entità light presenti nel sistema HomeAssistant.

{% set my_light = states.light | map(attribute='entity_id') |list %}
{{ my_light }}    {# output ['light.philips55', 'light.balcone_studio', 'light.luce_corridoio',.....] #}

È possibile applicare diversi filtri a una lista in modo da modificarne o manipolarne gli elementi.

Dettaglio
⬇️ Con gli indici, puoi accedere a elementi specifici nella lista. Ricorda che gli indici iniziano da 0.

Nell’esempio, my_light[0] restituisce il primo elemento della lista, che è ‘light.philips55’, e my_light[2] restituisce il terzo elemento, che è 'light.luce_corridoio'.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list[0] }}           {# output 'elemento1' #}
{{ my_list[2] }}           {# output elemento3 #}

{% set my_light = states.light | map(attribute='entity_id') |list %}
{{ my_light[0] }}          {# output 'light.philips55' #}
{{ my_light[2] }}          {# output 'light.luce_corridoio' #}
⬇️ Con range, puoi visualizzare solo una parte specifica della lista.

Nell’esempio, my_list[0:2] indica di mostrare gli elementi dall’indice 0 al 2 (escluso). Quindi, ottieni ['elemento1', 'elemento2'] come output, che rappresenta i primi due elementi della lista.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list[0:2] }}
{# output ['elemento1', 'elemento2'] #}

{% set my_light = states.light | map(attribute='entity_id') |list %}
{{ my_light[0:2] }}
{# output ['light.philips55','light.balcone_studio']#}

Se vuoi includere tutti gli elementi dall’inizio fino a un certo punto o da un certo punto fino alla fine, puoi lasciare vuoto il campo non desiderato nel range. Ad esempio, my_list[2:] indica di mostrare gli elementi dall’indice 2 fino alla fine della lista, ottenendo ['elemento3', 55]. Mentre my_list[:2] indica di mostrare gli elementi dall’inizio fino all’indice 2 (escluso), ottenendo ['elemento1', 'elemento2']

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list[2:] }}
{# output ['elemento3', 55] #}

{{ my_list[:2] }}
{# output ['elemento1', 'elemento2'] #}
⬇️ Puoi unire più liste usando l’operatore +.

Nell’esempio, my_list + new_list unisce le due liste, aggiungendo gli elementi di new_list alla fine di my_list. Quindi, otterrai una nuova lista combinata con tutti gli elementi: ["elemento1", "elemento2", "elemento3", 55, 'new_elemento1', 'new_elemento2'].

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{% set new_list = ['new_elemento1', 'new_elemento2'] %}
{{ my_list + new_list }}
{# output [ "elemento1", "elemento2", "nuovo_elemento", 55 ,'new_elemento1', 'new_elemento2' ] #}

{% set my_light = states.light | map(attribute='entity_id') |list %}
{% set my_switch = states.switch | map(attribute='entity_id') |list %}
{{ my_light + my_switch }}
{# output ['light.philips55','light.balcone_studio',.....,'switch.lavatrice','switch.forno',...]#}
⬇️ Puoi manipolare la lista sostituendo un elemento specifico.

Nell’esempio, my_list[:2] rappresenta gli elementi fino all’indice 2 (escluso), quindi ['elemento1', 'elemento2']. Aggiungendo [new_element], stai inserendo il nuovo elemento desiderato. Infine, my_list[3:] rappresenta gli elementi dall’indice 3 in poi, quindi [55]. Unendo tutti questi pezzi, ottieni la lista modificata: ["elemento1", "elemento2", "nuovo_elemento", 55].

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{% set new_element = 'nuovo_elemento' %}
{{ my_list[:2] + [new_element] + my_list[3:]}}
{# output [ "elemento1", "elemento2", "nuovo_elemento", 55 ] #}

{% set my_light = states.light | map(attribute='entity_id') |list %}
{% set my_switch = states.switch | map(attribute='entity_id') |list %}
{{ my_light[:2] + [my_switch[8]] + my_light[3:]}}
{# output["light.philips55","light.balcone_studio","switch.fritz_box_6890_lte","light.comodino_mattia",...] #}
⬇️ Puoi conoscere il numero di elementi nella lista utilizzando |count o |length. Entrambi forniscono lo stesso risultato, che è il numero totale di elementi nella lista.
{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list|count }}      {# output 4 #}
{{ my_list|length }}     {# output 4 #}

{% set my_light = states.light | map(attribute='entity_id') | list %}
{{ my_light|count}}      {# output 'numero luci' es.30 #}
{{ my_light|length}}     {# output 'numero luci' es.30 #}
⬇️ Puoi verificare se un elemento è presente nella lista utilizzando l’operatore in.

Nell’esempio, 'elemento1' in my_list restituisce True perché ‘elemento1’ è presente nella lista. D’altra parte, 'elemento_none' in my_list restituisce False poiché 'elemento_none' non è presente nella lista.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ 'elemento1' in my_list }}         {# output True #}
{{ 'elemento_none' in my_list }}     {# output False #}

{% set my_light = states.light | map(attribute='entity_id') |list %}
{{ 'light.philips55' in my_light}}   {# output True #}
{{ 'light.inventata' in my_light }}  {# output False #}
⬇️ Puoi contare quante volte un elemento è presente nella lista usando il metodo count.

Nell’esempio, my_list.count('elemento1') restituisce 1 perché 'elemento1' è presente una volta nella lista. D’altra parte, my_list.count('elemento_none') restituisce 0 perché 'elemento_none' non è presente nella lista.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list.count('elemento1') }}          {# output 1 #}
{{ my_list.count('elemento_none') }}      {# output 0 #}

{% set my_light = states.light | map(attribute='entity_id') |list %}
{{ my_light.count('light.philips55')}}    {# output 1 #}
{{ my_light.count('light.inventata')}}    {# output 0 #}
⬇️ Puoi invertire l’ordine di una lista utilizzando il filtro reverse.

Nell’esempio, my_list|reverse|list restituisce la lista originale invertita, quindi [55, 'elemento3', 'elemento2', 'elemento1'].

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list|reverse|list }}      {# [55, 'elemento3', 'elemento2', 'elemento1'] #}
⬇️ Puoi rimuovere gli elementi duplicati da una lista utilizzando il filtro unique.

Nell’esempio, my_list|unique|list restituisce la lista originale senza duplicati, quindi ['elemento1', 'elemento2', 55, 'elemento3'].

{% set my_list = ['elemento1', 'elemento2', 55, 'elemento3', 55] %}
{{ my_list|unique|list }}     {# output ['elemento1', 'elemento2', 55, 'elemento3'] #}
⬇️ Puoi eseguire operazioni matematiche sugli elementi di una lista, ma è importante assicurarsi che gli elementi siano di tipo numerico.

Nell’esempio, my_list[3] + 22 restituisce 77 perché my_list[3] è un numero, mentre my_list[1] + 22 genera un errore di tipo (TypeError) perché my_list[1] è una stringa, e non può concatenare direttamente una stringa con un numero.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list[3] + 22 }}     {# output 77 #}

{{ my_list[1] + 22 }}     {# output ERORE TypeError: can only concatenate str (not "int") to str #}

{% set my_light = states.sensor | map(attribute='state')| select('is_number')| map('float') |list  %}
{{ my_light[0] + 5}}      {# output [valore primo sensore + 5] #}
⬇️ Puoi utilizzare il filtro sum per ottenere la somma di tutti gli elementi di una lista, ma è importante assicurarsi che gli elementi siano di tipo numerico.

Nell’esempio, my_list_num|sum restituisce la somma di tutti i numeri nella lista, che è 104. È come se stessi facendo la somma dei valori numerici nella tua sequenza di numeri.

{% set my_list_num = [1,5,7,3,56,32] %}
{{ my_list_num|sum }}   {# output 104 #}

{% set my_light = states.sensor | map(attribute='state') | select('is_number') | map('float') |list  %}
{{ my_light|sum}}       {# output somma di tutti li stati numerici dei sensori #}
⬇️ Puoi unire gli elementi di una lista in modo più leggibile utilizzando il filtro join.

Nell’esempio, my_list|join(', ') restituisce una stringa in cui gli elementi della lista sono separati da una virgola seguita da uno spazio, rendendo l’output più leggibile.

{% set my_list = ['elemento1', 'elemento2', 55, 'elemento3', 55] %}
{{ my_list|join(', ') }}     {# output elemento1, elemento2, 55, elemento3, 55 #}
⬇️ Puoi rimuovere gli elementi da una lista utilizzando il filtro reject o la funzione .pop().

Nell’esempio, my_list|reject('eq','elemento2') rimuove gli elementi che sono uguali a 'elemento2' dalla lista, restituendo ['elemento1', 'elemento3', 55].

{% set my_list = ['elemento1', 'elemento2','elemento3', 55] %}
{{ my_list|reject('eq', 'elemento2') | list}}        {# output elemento1, elemento3, 55 #}

{% set my_light = states.switch | map(attribute='state') | unique | list  %}
{{ my_light | reject('eq', 'unavailable') | list}}   {# output: stati che hanno li switch escluso unavailable #}

Nell’esempio fornito, my_list.pop(0) viene utilizzato per rimuovere l’elemento in posizione 0 dall’elenco my_list. Questo metodo restituisce l’elemento rimosso, che nel caso dell’elenco my_list è ‘elemento1’. Successivamente, my_list è modificato e ora contiene solo gli elementi ‘elemento2’, ‘elemento3’ e 55.

{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list.pop(0) }}       {# output 'elemento1' #}
{{ my_list.pop(0) }}       {# output elemento2 #}
{{ my_list[0] }}           {# output elemento3 #}

Nell’esempio fornito, my_light.pop(0) viene utilizzato per rimuovere l’elemento in posizione 0 dall’elenco my_light. Successivamente, my_light è modificato e ora contiene solo gli elementi ‘elemento2’, ‘elemento3’ e 55.

{% set my_light = ['elemento1', 'elemento2', 'elemento3', 55] %}
{% set remove_element = my_light.pop(0) %} 
{{ my_light.pop(0) }}          {# output 'elemento2' #}
⬇️ Puoi selezionare solo gli elementi che soddisfano una condizione specifica utilizzando il filtro select.

Nell’esempio, my_list|select('eq','elemento2') restituisce una nuova lista contenente solo gli elementi che sono uguali a 'elemento2', quindi ['elemento2'].

{% set my_list = ['elemento1', 'elemento2','elemento3', 55] %}
{{ my_list|select('eq','elemento2') |list}}     {# output ['elemento2'] #}

{% set my_light = states.switch| map(attribute='state')|list  %}
{{ my_light|select('eq','unavailable')|list }}  {# output lista di tanti unavailable quanti sono li switch in quello stato #}
⬇️ Puoi ordinare una lista, che può essere composta sia da elementi stringa che numerici, utilizzando il filtro sort.

Nell’esempio, my_list|sort ordina la lista in ordine ascendente. Per le stringhe, l’ordinamento è basato sull’ordine alfabetico, mentre per i numeri, è basato sull’ordine numerico.

{% set my_list = ['elemento3', 'elemento1','elemento2'] %}
{{ my_list|sort}}       {# output ['elemento1', 'elemento2', 'elemento3'] #}

{% set my_list = [55, 2, 24,33] %}
{{ my_list|sort}}       {# output [2,24,33,55] #}

{% set my_light = states.switch| map(attribute='name')|list  %}
{{ my_light|sort}}      {# output tutti i name degli switch in ordine alfabetico #}
⬇️ Puoi sapere un elemento specifico che indice occupa all’interno di una lista, utilizzando la funzione .index(value).
{% set my_list = ['elemento1', 'elemento2', 'elemento3', 55] %}
{{ my_list.index('elemento2') }}           {# output '1' #}
{{ my_list.index('elemento1') }}           {# output '0' #}
⬇️ Se passiamo valori separati dalla virgola il risultato sarà automaticamente convertito in una lista.
{% set my_list = 'elemento1', 'elemento2' %}
{{ my_list }}  {# ['elemento1', 'elemento2'] #}

{% set my_list = 5, 15 %}
{{ my_list }} {# [5, 15] #}

Dizionari

I dizionari sono strutture dati che contengono coppie chiave-valore. Un dizionario è una collezione di elementi, dove ogni elemento è composto da una chiave unica e il valore associato a quella chiave. In termini più semplici è un modo per organizzare informazioni. Puoi immaginarlo come una lista di cose, ma ogni cosa ha un nome speciale chiamato “chiave”. Ogni “chiave” ha un “valore” associato ad essa. L’accesso al valore di una chiave in un dizionario può essere eseguito utilizzando la sintassi dict['key'] o dict.key: consente di ottenere il valore associato a quella chiave all’interno del dizionario.

{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}

{{'Programma ' ~ my_dict['nome'] }} {# Programma Home Assistant #}
{{'In uso: ' ~ my_dict.versione }} {# In uso: 2024.1 #}

Componenti aggiuntivi:
{%- for voto in my_dict['componenti'] %} {# Iterazione attraverso una lista all'interno del dizionario #}
  {{- voto }}
{%- endfor %}
{# Componenti aggiuntivi: File Editor Samba Zigbee2MQTT #}

È possibile applicare diversi filtri a un dizionario in modo da modificarne o manipolarne gli elementi.

Dettaglio
⬇️ .keys(): viene utilizzato per ottenere un elenco delle chiavi di un dizionario.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ my_dict.keys() |list }} 
{# ['nome', 'versione', 'componenti'] #}
⬇️ .values(): viene utilizzato per ottenere un elenco dei valori di un dizionario.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ my_dict.values() | list }}
{# ['Home Assistant', '2024.1', ['File Editor', 'Samba', 'Zigbee2MQTT']] #}

⬇️ .items(): viene utilizzato per ottenere un elenco di coppie chiave-valore da un dizionario.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ my_dict.items() | list }}
{# [('nome', 'Home Assistant'), ('versione', '2024.1'), ('componenti', ['File Editor', 'Samba', 'Zigbee2MQTT'])] #}

{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{% for chiave, valore in my_dict.items() -%}
    {{ chiave }}: {{ valore }}
{% endfor %}
{# 
nome: Home Assistant
versione: 2024.1
componenti: ['File Editor', 'Samba', 'Zigbee2MQTT']
#}
⬇️ .get(key, default) viene utilizzato per ottenere il valore associato a una chiave in un dizionario. L’uso del metodo get() è utile perché consente di specificare un valore predefinito da restituire nel caso in cui la chiave non sia presente nel dizionario.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ 'Chiave nome: ' ~ my_dict.get('nome', 'Valore non presente') }}
{{ 'Altra chiave: ' ~ my_dict.get('altro', 'Valore non presente') }}
{# 
Chiave nome: Home Assistant
Altra chiave: Valore non presente 
#}
⬇️ Se un dizionario contiene un altro dizionario come valore associato a una chiave, puoi accedere ai valori all’interno del dizionario interno in modo concatenato
{% set my_dict = {'chiave1': {'chiave2': 'valore2'}} %}
{{ my_dict['chiave1']['chiave2'] }} {# valore2 #}
{{  my_dict.chiave1.chiave2 }} {# valore2 #}
⬇️ Puoi verificare se una chiave specifica è presente in un dizionario utilizzando l’operatore in.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ 'test' in my_dict }} {# false #}
{{ 'nome' in my_dict }} {# true #}
⬇️ tojson viene utilizzato per convertire il dizionario in una rappresentazione JSON.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ my_dict | tojson }}
{# {"componenti": ["File Editor", "Samba", "Zigbee2MQTT"], "nome": "Home Assistant", "versione": "2024.1"} #}
⬇️ urlencode viene utilizzato per convertire una stringa in una forma codificata URL.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ my_dict | urlencode }}
{# nome=Home+Assistant&versione=2024.1&componenti=%5B%27File+Editor%27%2C+%27Samba%27%2C+%27Zigbee2MQTT%27%5D #}

Booleani

Un booleano è un tipo di dato che può assumere solo due valori: vero (True) o falso (False). Questo tipo di dato è comunemente utilizzato per rappresentare condizioni o verità.

{{ 5 == 4 }} {# False #}
{{ 5 == 5 }} {# True #}

Tuple

Una tupla è una struttura dati che rappresenta una sequenza ordinata e immutabile di elementi. A differenza delle liste, le tuple sono immutabili, il che significa che una volta create non è possibile modificarne gli elementi. Le tuple sono definite utilizzando parentesi tonde () e gli elementi sono separati da virgole.

Jinja supporta nativamente la conversione di un iterabile in una lista, ma non supporta la conversione in un tuple. Per aiutarti nell’uso di questi tipi, puoi utilizzare la funzione tuple(x):

{{ ('elemento1', 'elemento2', 'elemento3', 55) }}  {# restituisce una lista: [  "elemento1",  "elemento2",  "elemento3",  55 ] #}

{{ tuple([1, 2, 3]) }} {# restituisce una tupla: (1, 2, 3) #}
{{ tuple("Hello") }}   {# restituisce una tupla: ('H', 'e', 'l', 'l', 'o') #}

Insiemi / Set

Un set è una collezione di elementi che non può contenere duplicati e non segue un ordine specifico degli elementi. È definito utilizzando parentesi graffe {} e contiene elementi separati da virgole.

Jinja supporta nativamente la conversione di un iterabile in una lista, ma non supporta la conversione in un set. Per aiutarti nell’uso di questi tipi, puoi utilizzare la funzione set(x):

{{ set([1, 2, 3]) }} {# {1, 2, 3} #}
{{ set("Hello") }}   {# {'o', 'e', 'H', 'l'} #}

Test

Operatori Matematici

Le espressioni più basilari in Jinja sono le espressioni matematiche. Spesso devi eseguire operazioni matematiche sui tuoi dati e Jinja2 contiene le operazioni elementari che potresti dover eseguire. Si consiglia di convertire i numeri in float o int utilizzando il rispettivo filtro quando si confrontano i numeri

Dettaglio
⬇️ +: è possibile sommare valori.
{{ 5 + 2.1 }} {# somma di due numeri = '7.1' #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var + 5 }} {# aggiunto un delta di 5 alla temperatura sala #}
⬇️ -: è possibile sottrarre valori.
{{ 5 - 2.1 }} {# sottrazione di due numeri = 2.9 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var - 5 }} {# sottratto un delta di 5 alla temperatura sala #}
⬇️ /: è possibile dividere valori.
{{ 5 / 2 }} {# divisione di due numeri = 2.5 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var / 5 }} {# divisione dello stato di un sensore #}
⬇️ *: è possibile moltiplicare valori.
{{ 5 * 2 }} {# moltiplicazione di due numeri = 10 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var * 5 }} {# moltiplicazione dello stato di un sensore #}
⬇️ //: è possibile ottenere il risultato intero della divisione arrotondato per difetto.
{{ 5 * 2 }} {# mol{{ 5 // 2 }} {# numero intero della divisione di due numeri = 2 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var // 5 }} {# numero intero della divisione dello stato di un sensore #}tiplicazione di due numeri = 10 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var * 5 }} {# moltiplicazione dello stato di un sensore #}
⬇️ %: è possibile calcolare il resto della divisione.
{{ 60 %  55 }} {# resto della divisione di due numeri = 5 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var % 5 }} {# resto della divisione dello stato di un sensore #}
⬇️ **: è possibile calcolare la potenza.
{{ 5 ** 2 }} {# 25 #}

{% set var = states('sensor.temperature_sala_temperature')|int(0) %} 
{{ var ** 5 }} {# calcola potenza di un sensore  #}

Le operazioni matematiche possono essere concatenate, quindi possiamo eseguire una sequenza di operazioni su variabili o valori costanti all’interno dei template. Questa concatenazione consente di eseguire calcoli più complessi, combinando operazioni di somma, sottrazione, moltiplicazione, divisione e altro ancora.

{% set variabile1 = 10 %}
{% set variabile2 = 5 %}

{{ variabile1 + variabile2 * 2 }}

Operatori di confronto

Gli operatori di confronto sono utilizzati per confrontare valori o espressioni e restituire un valore booleano che indica se la condizione è vera o falsa

Dettaglio
⬇️ == Uguaglianza: Questo operatore verifica se due oggetti sono uguali. Restituisce True se sono uguali, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 == 6 }} {# false #}
{{ 5 == 5 }} {# true #}
{{ 'ciao' == var }} {# false #}
{{ 'Ciao' == var }} {# true #}
⬇️ != Disuguaglianza: Questo operatore verifica se due oggetti sono diversi. Restituisce True se sono diversi, altrimenti restituisce False .
{% set var = 'Ciao' %}
{{ 5 != 6 }} {# true #}
{{ 5 != 5 }} {# false #}
{{ 'ciao' != var }} {# true #}
{{ 'Ciao' != var }} {# false #}
⬇️ > Maggiore: Restituisce True se il lato sinistro è maggiore del lato destro.
{% set var = 'Ciao' %}
{{ 5 > 6 }} {# false #}
{{ 5 > 5 }} {# false #}
{{ 'ciao' > var }} {# true #}
{{ 'Ciao' > var }} {# false #}
⬇️ >= Maggiore o Uguale: Restituisce True se il lato sinistro è maggiore o uguale al lato destro.
{% set var = 'Ciao' %}
{{ 5 >= 6 }} {# false #}
{{ 5 >= 5 }} {# true #}
{{ 'ciao' >= var }} {# true #}
{{ 'Ciao' >= var }} {# true #}
⬇️ < Minore: Restituisce True se il lato sinistro è minore del lato destro.
{% set var = 'Ciao' %}
{{ 5 < 6 }} {# true #}
{{ 5 < 5 }} {# false #}
{{ 'ciao' < var }} {# false #}
{{ 'Ciao' < var }} {# false #}
⬇️ <= Minore o Uguale: Restituisce True se il lato sinistro è minore o uguale al lato destro.
{% set var = 'Ciao' %}
{{ 5 <= 6 }} {# true #}
{{ 5 <= 5 }} {# true #}
{{ 'ciao' <= var }} {# false #}
{{ 'Ciao' <= var }} {# true #}

Espressioni logiche

Le espressioni logiche sono come “domande” attraverso le quali chiediamo al sistema di valutare la veridicità di una determinata affermazione. La risposta finale a questa “domanda” è sempre booleana, ossia True (vero) o False (falso).

Dettaglio
⬇️ and: Restituisce True se sia l’operando sinistro che quello destro sono valutati come True. In altre parole, se entrambe le condizioni sono soddisfatte, l’espressione complessiva restituisce True; altrimenti, restituirà False.
{% set condizione_true = 5 == 5 %} {# true #}
{% set cond_num_false = 5 == 6 %} {# false #}
{{ condizione_true and cond_num_false }} {# solo una condizione è true: false #}
{{ condizione_true and condizione_true }} {# entrambe le condizioni sono true: true #}
{{ cond_num_false and cond_num_false }} {# entrambe le condizioni sono false: false #}
⬇️ or: restituisce True se almeno uno tra l’operando sinistro e quello destro è valutato come True. In altre parole, se almeno una delle condizioni è soddisfatta, l’espressione complessiva restituirà True; restituirà False solo se entrambi gli operandi sono valutati come False.
{% set condizione_true = 5 == 5 %} {# true #}
{% set cond_num_false = 5 == 6 %} {# false #}
{{ condizione_true or cond_num_false }} {# un condizione è triue: true #}
{{ condizione_true or condizione_true }} {# entrambe le condizioni sono true: true #}
{{ cond_num_false or cond_num_false }} {# entrambe le condizioni sono false: false #}
⬇️ not: viene utilizzato per negare un’affermazione. In altre parole, restituisce True se l’affermazione è falsa, e False se l’affermazione è vera.
{% set condizione_true = 5 == 5 %} {# true #}
{% set cond_num_false = 5 == 6 %} {# false #}
{{ not condizione_true}} {# false #}
{{ not cond_num_false}} {# true #}
⬇️ in: utilizzato per verificare se un valore è contenuto in una sequenza. La sequenza può essere una lista, una stringa, un dizionario o un’altra struttura dati iterabile. L’operatore restituisce True se il valore è presente nella sequenza, altrimenti restituirà False.
{% set my_list = ['elemento1','elemento2','elemento3'] %}
{{ 'elemento1' in my_list }} {# elemento presente nella lista: True #}
{{ 'elemento4' in my_list }} {# elemento non presente nella lista: False #}

{% set my_dict = { 'chiave1' : 'valore1', 'chiave2' : 'valore2'} %}
{{ 'chiave1' in my_dict }}  {# key presente nel dict: True #}
{{ 'chiave3' in my_dict }} {# key non presente nel dict: True #}
⬇️ is: viene utilizzato per applicare test specifici a una variabile. Consente di eseguire un test specificato dal lato destro dell’espressione su una variabile situata sul lato sinistro.
  • is divisibleby: viene utilizzato per verificare se il primo valore è divisibile per il secondo valore(solo numeri).
{{ 4 is divisibleby 2 }} {# true #}
{{ 5 is divisibleby 3 }} {# false #}
  • is defined: viene utilizzato per verificare se una variabile è stata definita nel contesto del template.
{% set variabile = 'Variabile' %}
{{ variabile is defined }} {# true #}
{{ variabile_inventata is defined  }} {# false #}
{{ 5 is defined }} {# true #}
  • is undefined: viene utilizzato per verificare se una variabile non è stata definita nel contesto del template.
{% set variabile = 'Variabile' %}
{{ variabile is undefined }} {# false #}
{{ variabile_inventata is undefined  }} {# true #}
{{ 5 is undefined }} {# false #}
  • is eq: è equivalente all’operatore == e restituisce True se la variabile è uguale al secondo valore, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 is eq 6 }} {# false #}
{{ 5 is eq 5 }} {# true #}
{{ 'ciao' is eq var }} {# false #}
{{ 'Ciao' is eq var }} {# true #}
  • is ge: è equivalente all’operatore >= e restituisce True se la variabile è maggiore o uguale al secondo valore, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 is ge 6 }} {# false #}
{{ 5 is ge 5 }} {# true #}
{{ 'ciao' is ge var }} {# true #}
{{ 'Ciao' is ge var }} {# true #}
  • is le: è equivalente all’operatore <= e restituisce True se la variabile è minore o uguale al secondo valore, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 is le 6 }} {# true #}
{{ 5 is le 5 }} {# true #}
{{ 'ciao' is le var }} {# false #}
{{ 'Ciao' is le var }} {# true #}
  • is gt: è equivalente all’operatore > e restituisce True se la variabile è maggiore al secondo valore, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 is gt 6 }} {# false #}
{{ 5 is gt 5 }} {# false #}
{{ 'ciao' is gt var }} {# true #}
{{ 'Ciao' is gt var }} {# false #}
  • is lt: è equivalente all’operatore < e restituisce True se la variabile è minore al secondo valore, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 is lt 6 }} {# true #}
{{ 5 is lt 5 }} {# false #}
{{ 'ciao' is lt var }} {# false #}
{{ 'Ciao' is lt var }} {# false #}
  • is ne: è equivalente all’operatore != e restituisce True se la variabile non è uguale al secondo valore, altrimenti restituisce False.
{% set var = 'Ciao' %}
{{ 5 is ne 6 }} {# true #}
{{ 5 is ne 5 }} {# false #}
{{ 'ciao' is ne var }} {# true #}
{{ 'Ciao' is ne var }} {# false #}
  • is none: restituisce True se la variabile è None, altrimenti restituisce False.
{% set variabile = 'Variabile' %}
{{ variabile is none }} {# false #}
{{ variabile_inventata is none  }} {# false #}
{{ none is none }} {# true #}
  • is number: restituisce True se la variabile è di tipo numerico, altrimenti restituisce False.
{{ 'Variaile' is number }} {# false #}
{{ 6 is number }} {# true #}
  • is even: restituisce True se la variabile è un numero pari, altrimenti restituisce False (solo numeri).
{{ 3 is even }} {# false #}
{{ 4 is even }} {# true #}
  • is odd: restituisce True se la variabile è un numero dispari, altrimenti restituisce False.
{{ 3 is odd }} {# true #}
{{ 4 is odd }} {# false #}
  • is sequence: restituisce True se la variabile è una sequenza, altrimenti restituisce False.
{{ 3 is sequence }} {# false #}
{{ 'HOMEASSISTI' is sequence }} {# true (viene considerato ogni singolo carattere) #}
{{ ['A','B'] is sequence  }}  {# true #}
{{ { 'nome' : 'marco', 'città': 'Roma' } is sequence }} {# true #}
  • is string: restituisce True se la variabile è una stringa, altrimenti restituisce False.
{{ 3 is string }} {# false #}
{{ 'HomeAssistant' is string }} {# true #}
{{ ['a','b'] is string  }}  {# false #}
{{ { 'nome' : 'marco', 'città': 'roma' } is string }} {# false #}
  • is list: restituisce True se la variabile è una lista, altrimenti restituisce False.
{{ ['elemento1', 12, 'elemento3' ] is list }} {# True #}
{{ 'elemtento1' is list }} {# False #}
  • is tuple: restituisce True se la variabile è una tupla, altrimenti restituisce False.
{{ [1, 2] is tuple }} {# False #}
{{ (1, 2) is tuple }} {# True #}
  • is datetime: restituisce True se la variabile è un ogetto datetime, altrimenti restituisce False.
{{ '26, 12, 2024' is datetime }} {# False #}
{{ states['light.luce_studio'].last_changed is datetime }} {# True #}
  • is lower: restituisce True se la variabile è scritta in minuscolo, altrimenti restituisce False.
{{ 3 is lower }} {# false #}
{{ 'HomeAssistant' is lower }} {# false #}
{{ 'homeassistant' is lower }} {# true #}
{{ ['a','b'] is lower  }}  {# true #}
{{ ['a','B'] is lower  }}  {# false #}
{{ { 'nome' : 'marco', 'città': 'Roma' } is lower }} {# false #}
{{ { 'nome' : 'marco', 'città': 'roma' } is lower }} {# true #}
  • is upper: restituisce True se la variabile è scritta in maiuscolo, altrimenti restituisce False.
{{ 3 is upper }} {# false #}
{{ 'homeassistant' is upper }} {# false #}
{{ 'HOMEASSISTI' is upper }} {# true #}
{{ ['A','B'] is upper  }}  {# true #}
{{ ['a','B'] is upper  }}  {# false #}
{{ { 'nome' : 'marco', 'città': 'Roma' } is upper }} {# false #}
{{ { 'NOME' : 'MARCO', 'CITTA': 'ROMA' } is upper }} {# true #}
  • is iterable: verifica se un oggetto può essere iterato o attraversato elemento per elemento. Un oggetto iterable può essere utilizzato in un ciclo.
{{ 3 is iterable }} {# false #}
{{ 'HOMEASSISTI' is iterable }} {# true (viene considerato ogni singolo carattere) #}
{{ ['A','B'] is iterable  }}  {# true #}
{{ { 'nome' : 'marco', 'città': 'Roma' } is iterable }} {# true #}
  • is mapping: verifica se un oggetto è un mapping, come un dizionario.
{% set my_dict = {'chiave1': 'valore1', 'chiave2': 'valore2'} %}
{{ my_dict is mapping }} {# true #}
{{ 'testo' is mapping }} {# false #}
  • is boolean: restituisce True se la variabile è un boolean, altrimenti restituisce False.
{{ 'testo' is boolean }} {# false #}
{{ ( 5 == 5 ) is boolean }} {# true #}
{{ 5 is boolean }} {# false #}
  • is match(find, ignorecase=False): verifica se la stringa inizia con find. Quando ignorecase è impostato su True, la ricerca delle corrispondenze non terrà conto delle differenze tra maiuscole e minuscole.
{% set test_string = "Ciao, testiamo la funzione" %}

{{ test_string is match('Ciao') }} {# True #}
{{ test_string is match('ciao') }} {# False #}
{{ test_string is match('iao') }} {# False #}
{{ test_string is match('ciao', ignorecase=True) }} {# True #}
  • is search(find, ignorecase=False): verifica se find è presente in qualsiasi punto della stringa. Quando ignorecase è impostato su True, la ricerca delle corrispondenze non terrà conto delle differenze tra maiuscole e minuscole.
{% set test_string = "Ciao, testiamo la funzione" %}

{{ test_string is search('testiamo') }} {# True #}
{{ test_string is search('ciao') }} {# False #}
{{ test_string is search('iao') }} {# True #}
{{ test_string is search('Testiamo', ignorecase=True) }} {# True #}

Maggior Controllo

Filtri

I Filtri sono potenti strumenti che consentono di manipolare e formattare i dati all’interno dei template
Puoi utilizzare i filtri per eseguire varie operazioni come formattare stringhe, effettuare operazioni aritmetiche e altro ancora. I filtri sono separati dalla variabile da un simbolo pipe |. È possibile concatenare più filtri. L’output di un filtro viene applicato a quello successivo.

Dettaglio
⬇️ string:  viene utilizzato per convertire una variabile in una stringa.
{{ 44 | string }} {# numero in stringa #}
{{ ['elemento1','elemento2']  }} {# lista in stringa #}
{{ {'chiave1':'valoreq','chiave2':'valore2' } | string }} {# dizionario in stringa #}
⬇️ int: è utilizzato per convertire una variabile in un intero. Può anche accettare un valore di default che verrà utilizzato se la conversione non ha esito positivo. È importante notare che il filtro int non fornisce la possibilità di rilevare variabili non definite.
{{ 5 | int }} {# 5 #}
{{ 5.5 | int }} {# 5 #}
{{ -5.8 | int }} {# -5 #}
{{ 'variabile_definita' | int(0) }} {# 0 #}
{{ variabile_non_definita | int(0) }} {# UndefinedError #}

{% set list_num = [4, 34.4, 6, 44] %}
{{ list_num | map('int') | list }} {# [4, 34, 6, 44] #}
⬇️ float: è utilizzato per convertire una variabile in un numero decimale (virgola mobile). Può anche accettare un valore di default che verrà utilizzato se la conversione non ha esito positivo. È importante notare che il filtro float non fornisce la possibilità di rilevare variabili non definite.
{{ 5 | float }} {# 5.0 #}
{{ 5.5 | float }} {# 5.0 #}
{{ -5.8 | float }} {# -5.8 #}
{{ 'variabile_definita' | float(0) }} {# 0 #}
{{ variabile_non_definita | float(0) }} {# UndefinedError #}

{% set list_num = [4, 34.4, 6, 44] %}
{{ list_num | map('float') | list }} {# [4.0, 34.4, 6.0, 44.0] #}
⬇️ abs: è utilizzato per restituire il valore assoluto di un numero, ovvero il valore non negativo di quel numero. Indipendentemente dal fatto che il numero iniziale sia positivo o negativo, l’applicazione del filtro abs restituirà il suo valore positivo o zero.
{{ 5 | abs }} {# 5.0 #}
{{ 5.5 | abs }} {# 5.0 #}
{{ -5.8 | abs }} {# 5.8 #}

{% set list_num = [4, 34.4, -6, 44] %}
{{ list_num | map('abs') | list }} {# [4, 34.4, 6, 44] #}
⬇️ batch: è utilizzato per suddividere una sequenza (come una lista) in sotto-liste più piccole, chiamate “batch” o “gruppi”. Questo può essere utile quando si desidera suddividere un elenco di elementi in gruppi più gestibili.
{% set lista = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] %} {# stiamo creando una lista di numeri da 1 a 10 #} 
{% set gruppi = lista | batch(3) %} {# suddividiamo la lista in gruppi da 3 elementi #}
{% for gruppo in gruppi %}
    Gruppo: {{ gruppo }}
{% endfor %}
{# output:  Gruppo: [1, 2, 3] Gruppo: [4, 5, 6]  Gruppo: [7, 8, 9]  Gruppo: [10] #}
⬇️ center: è utilizzato per centrare una stringa all’interno di una lunghezza specificata. Può essere utile per la formattazione di testo in contesti come le schede Markdown.
{{ "Titolo centrato" | center(30) }} {# stringa centrata all'interno di uno spazio di lunghezza 30 #}
⬇️ capitalize: è utilizzato per trasformare la prima lettera di una stringa in maiuscolo e tutte le altre lettere in minuscolo.
{{ 'ciao' | capitalize }} {# Ciao #}
{{ 'CIAO' | capitalize }} {# Ciao #}
{{ 'CiaO' | capitalize }} {# Ciao #}
⬇️ default: è utilizzato per restituire un valore predefinito se il valore iniziale è indefinito (o valutato come falso in caso di configurazione con il secondo parametro a true).
{{ non_definito | default('Valore non definito') }} {# Valore non definito #}
{{ 'Valore definito' | default('Valore non definito') }} {# Valore definito #}
{{ true |default('Variabile false', true) }} {# True #}
{{ false |default('Variabile false', true) }} {# Variabile false #}
⬇️ dictsort: è utilizzato per ordinare un dizionario in base alle sue chiavi o valori. Questo filtro restituisce una lista di tuple, dove ogni tupla contiene una chiave e il corrispondente valore del dizionario.
{% set dizionario = {'z': 2, 'a': 3, 'b': 1} %}
{{ dizionario | dictsort }} {# Dizionario ordinato per chiavi #}
{{ dizionario | dictsort(false, 'value') }} {# Dizionario ordinato per valori #}
⬇️ filesizeformat: è utilizzato per formattare una dimensione di file espressa in byte in un formato più leggibile, come kilobyte (KB), megabyte (MB) o gigabyte (GB), a seconda dell’ordine di grandezza.
{% set dimensione_file = 1024 * 1024 * 5 %}  {# 5 megabyte #}
{{ dimensione_file | filesizeformat }} {# 5.2 MB #}

{% set b_received = states('sensor.fritz_box_6890_lte_b_received') %} {# 2189181518 #}
{{ b_received | filesizeformat }} {# 2.2 GB #}
⬇️ first: è utilizzato per restituire il primo elemento di una sequenza (come una lista o una stringa).
{% set lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{{ lista | first }} {# 'elemento1' #}

{{ 'Ciao' | first }} {# 'C' #}
⬇️ last: è utilizzato per restituire l’ultimo elemento di una sequenza, come una lista o una stringa.
{% set lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{{ lista | last }} {# elemento4 #}

{{ 'Ciao' | last }} {# 'o' #}
⬇️ groupby: è utilizzato per raggruppare una sequenza di oggetti in base a una chiave specificata. Restituisce un dizionario in cui le chiavi sono i valori della chiave specificata e i valori sono liste di oggetti corrispondenti a ciascun valore della chiave.
{% set lista_dict = [
    {'nome': 'Marco', 'gruppo': 'A'},
    {'nome': 'Henrik', 'gruppo': 'B'},
    {'nome': 'Pippo', 'gruppo': 'A'},
    {'nome': 'Pluto', 'gruppo': 'B'},
    {'nome': 'Paperino', 'gruppo': 'A'},
] %}
{{ lista_dict | groupby('gruppo') }} 
{# [('A', [{'nome': 'Marco', 'gruppo': 'A'}, {'nome': 'Pippo', 'gruppo': 'A'}, {'nome': 'Paperino', 'gruppo': 'A'}]), ('B', [{'nome': 'Henrik', 'gruppo': 'B'}, {'nome': 'Pluto', 'gruppo': 'B'}])] #}
⬇️ join: è utilizzato per unire una lista di elementi in una singola stringa, separati da un delimitatore specificato.
{% set lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{{ lista | join(', ') }}
{# elemento1, elemento2, elemento3, elemento4 #}
⬇️ length: è utilizzato per restituire il numero di elementi in un contenitore, come una lista, una stringa o un dizionario.
{% set lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{{ lista | length }} {# 4 #}

{% set dizionario = {'chiave1': 'valore1', 'chiave2': 'valore2', 'chiave3': 'valore3'} %}
{{ dizionario | length }} {# 3 #}

{{ 'HomeAssistant' | length }} {# 13 #}
⬇️ list: è utilizzato per convertire un valore in una lista.
{{ 'HomeAssistant' | list }} {# ['H', 'o', 'm', 'e', 'A', 's', 's', 'i', 's', 't', 'a', 'n', 't']
 #}
⬇️ lower: è utilizzato per convertire una stringa in caratteri minuscoli.
{{ 'Ciao' | lower }} {# ciao #}
{{ 'CiaO' | lower }} {# ciao #}
{{ 'CIAO' | lower }} {# ciao #}
{{ 'ciao' | lower }} {# ciao #}
{{ 5.5 | lower }} {# 5.5 #}
⬇️ upper: è utilizzato per convertire una stringa in caratteri maiuscoli.
{{ 'Ciao' | upper }} {# CIAO #}
{{ 'CiaO' | upper }} {# CIAO #}
{{ 'CIAO' | upper }} {# CIAO #}
{{ 'ciao' | upper }} {# CIAO #}
{{ 5.5 | upper }} {# 5.5 #}
⬇️ max: restituisce l’elemento più grande o il massimo valore all’interno di una sequenza.
{% set my_list = [6, 2, 3, 4, 5, 11, 7, 8, 10] %}
{{ my_list | max }} {# 11 #}

{% set my_list = ['a', 'd', 'c' ,'b'] %}
{{ my_list | max }} {# d #}
⬇️ min: restituisce l’elemento più piccolo o il valore minimo all’interno di una sequenza.
{% set my_list = [6, 2, 3, 4, 5, 11, 7, 8, 10] %}
{{ my_list | min}} {# 2 #}

{% set my_list = ['a', 'd', 'c' ,'b'] %}
{{ my_list | min}} {# a #}
⬇️ random: restituisce un elemento casuale dalla sequenza fornita.
{% set my_list = [6, 2, 3, 4, 5, 11, 7, 8, 10] %}
{{ my_list | random }} {# elemento casuaule #}

{% set my_list = ['a', 'd', 'c' ,'b'] %}
{{ my_list | random }} {# elemento casuale #}
⬇️ reject: utilizzato per filtrare gli elementi di una sequenza rimuovendo quelli che soddisfano una determinata condizione rispetto a un attributo specifico di ciascun elemento
{% set my_list = [6, 2, 3, 4, 5, 11, 7, 8, 10]  %}
{{ my_list | reject('odd') | list }} {# rimuove numeri dispari #}
{# [6, 2, 4, 8, 10] #}
⬇️ select: utilizzato per selezionare gli elementi da una sequenza che soddisfano una condizione specifica. Questo filtro è utile quando si desidera filtrare gli elementi che rispettano una certa condizione.
{% set my_list = [6, 2, 3, 4, 5, 11, 7, 8, 10]  %}
{{ my_list | select('odd') | list }} {# lascia numeri dispari #}
{# [3, 5, 11, 7] #}
⬇️ rejectattr: utilizzato per filtrare gli elementi di una sequenza rimuovendo quelli che soddisfano una determinata condizione rispetto a un attributo specifico.
{% set my_dict = [
    {'nome': 'Marco', 'età': 25},
    {'nome': 'Henrik', 'età': 32},
    {'nome': 'Pippo', 'età': 21},
    {'nome': 'Pluto', 'età': 28}
] %}
{{ my_dict | rejectattr('età', 'odd') | list }} {# esclude persone con età (valore) dispari #}
{# 
[
  { "nome": "Henrik", "età": 32  },
  { "nome": "Pluto", "età": 28 }
]
#}
⬇️ selectattr: utilizzato per filtrare gli elementi di una sequenza selezionando quelli che soddisfano una determinata condizione rispetto a un attributo specifico di ciascun elemento.
{% set my_dict = [
    {'nome': 'Marco', 'età': 25},
    {'nome': 'Henrik', 'età': 32},
    {'nome': 'Pippo', 'età': 21},
    {'nome': 'Pluto', 'età': 28}
] %}
{{ my_dict | selectattr('età', 'odd') | list }} {# seleziona persone con età (valore) dispari #}
{# 
[
  { "nome": "Marco", "età": 25  },
  { "nome": "Pippo", "età": 21 }
]
#}
⬇️ replace: utilizzato per sostituire tutte le occorrenze di una sottostringa con un’altra all’interno di una stringa. Questo può essere utile quando si desidera modificare il contenuto di una variabile di testo.
{% set testo = "Questo è un esempio di replace." %}
{{ testo | replace('replace', 'sostituisci') }}
{# Questo è un esempio di sostituisci. #}
⬇️ reverse: utilizzato per invertire l’ordine degli elementi in una sequenza, come una lista.
{% set lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{{ lista | reverse |list }}
{# [ "elemento4", "elemento3", "elemento2", "elemento1" ] #}

{{ 'ROMA' | reverse }}
{# AMOR #}
⬇️ round: utilizzato per arrotondare un numero a un numero specifico di cifre decimali.

round(precision, method, default: Il method di arrotondamento ha quattro modalità e predefinita sarà l’arrotondamento all’intero più vicino.

Se il valore di input non può essere convertito in un float, restituisce il valore default o, se omesso, genera un errore.

{{ 1.22188 | round }}  {# 1 #}
{{ 1.22188 | round(3) }} {# 1.222 #}
{{ 1.22188 | round(3,'floor', 0) }} {# Arrotonda per difetto: 1.221 #}
{{ 1.22188 | round(3,'ceil') }} {# Arrotonda al numero decimale: 1.222 #}
{{ 1.22188 | round(3,'half') }} {# Arrotonda al valore 0,5 più vicino: 1.0 #}
{{ 'valore errato' | round(3,'half', 0) }} {# restituisce default: 0 #}
{{ 'valore errato' | round(3, default=0) }} {# restituisce default: 0 #}
⬇️ map: è utilizzato per applicare una funzione o un altro filtro a ciascun elemento di una sequenza, come una lista. Questa operazione è particolarmente utile quando si desidera eseguire una trasformazione coerente su tutti gli elementi di una sequenza.
{% set my_list = ['ciao', 'UppeR'] %} 
{{ my_list | map('upper') | list }} {# ['CIAO', 'UPPER'] #}

{{ states.climate | map(attribute='name') | list }} {# lista di nome entità clima #}
⬇️ is_defined: consente di generare un errore se un valore o un oggetto non è definito.
Questo può essere utile per convalidare un payload JSON. Il is_defined filtro consente di generare un errore se un valore o un oggetto non è definito.
{{ value_json.val | is_defined }}      {# ERROR: 'value_json' NON è definito #}
{{ 'esempio definito' | is_defined }}  {# esempio definito #}
⬇️ contains: può essere considerato simile all’operatore in, ma con un comportamento opposto.

Mentre l’operatore in permette di verificare se un valore è presente in una sequenza, il filtro contains permette di testare se una sequenza contiene un valore. Questa funzione può essere utilizzata come filtro o come test.

{% set my_list = ['21', '55', '15'] %}
{{ my_list | contains('15') }} {# True #}

{{ state_attr('light.libreria', 'supported_color_modes') | contains('inventato') }} {# false #}
{{ state_attr('light.libreria', 'supported_color_modes') | contains('brightness') }} {# true #}

{{ states.light | selectattr("attributes.supported_color_modes", 'contains', 'brightness') | list }} {# lista luci con supported_color_modes: brightness #}

{% set stagioni = [
  {'name':'Primavera', 'month': [3,4,5]},
  {'name':'Estate', 'month': [6,7,8]},
  {'name':'Autunno', 'month': [9,10,11]},
  {'name':'Inverno', 'month': [12,1,2]}
]%}
{{ stagioni | selectattr('month', 'contains', now().month ) | map(attribute='name') | first }}
⬇️ timestamp_custom: serve per formattare un timestamp (un momento specifico nel tempo) secondo il formato desiderato per la rappresentazione della data e dell’ora.
{{ as_timestamp(now()) | timestamp_custom('%Y-%m-%d %H:%M:%S') }}  {# es. 2024-01-25 21:07:30 #}
⬇️ timestamp_local(default): è un filtro che converte un timestamp UNIX in una stringa nel formato ISO con fuso orario.

E’ possibile applicare un valore predefinito per evitare che il filtro generi un errore nel caso in cui la conversione del timestamp UNIX in formato ISO fallisca. In questo modo, se la conversione non è possibile, il filtro restituirà il valore predefinito invece di generare un errore.

{{ 1707125400.0 | timestamp_local }}            {# 2024-02-05T10:30:00+01:00 #}
{{ errato | timestamp_local }}            {# Template error #}

{{ 1707125400.0 | timestamp_local('Valore default') }} {# 2024-02-05T10:30:00+01:00 #}
{{ errato | timestamp_local('Valore default') }}       {# Valore default #}
⬇️ timestamp_utc(default): è un filtro che converte un timestamp UNIX in una stringa nel formato ISO senza fuso orario (UTC).#

E’ possibile applicare un valore predefinito per evitare che il filtro generi un errore nel caso in cui la conversione del timestamp UNIX in formato ISO fallisca. In questo modo, se la conversione non è possibile, il filtro restituirà il valore predefinito invece di generare un errore.

{{ 1707125400.0 | timestamp_utc }}      {# 2024-02-05T09:30:00+00:00 #}
{{ errato | timestamp_utc }}            {# Template error #}

{{ 1707125400.0 | timestamp_utc('Valore default') }} {# 2024-02-05T09:30:00+00:00 #}
{{ errato | timestamp_utc('Valore default') }}       {# Valore default #}
⬇️ bitwise: è possibile eseguire operazioni con bit.

value_one|bitwise_and(value_two): esegue un’operazione bit per bit di “AND” tra i due valori

{{ 7 | bitwise_and(3) }} {# 1 #}

value_one|bitwise_or(value_two): Questo filtro esegue un’operazione bit per bit di “OR” tra i due valori.

{{ 7 | bitwise_or(3) }} {# 7 #}

value_one|bitwise_xor(value_two): Questo filtro esegue un’operazione bit per bit di “XOR” (o esclusivo OR) tra i due valori.

{{ 7 | bitwise_xor(3) }} {# 6 #}

ord: restituirà per una stringa di lunghezza uno un numero intero che rappresenta il punto di codice Unicode del carattere quando l’argomento è un oggetto Unicode o il valore del byte quando l’argomento è una stringa a 8 bit

{{ "A" | ord }} {# 65 #}
{{ "1" | ord }} {# 49 #}
⬇️ state_translated; restituisce lo stato tradotto di un’entità utilizzando la lingua attualmente configurata in homeassistant.
{{ 'light.luce_studio' | state_translated }} {# Spento/a - Acceso/a #}
⬇️ urlencode viene utilizzato per convertire una stringa in una forma codificata URL.
{% set my_dict = { 'nome' : 'Home Assistant' , 'versione' : '2024.1' , 'componenti' : ['File Editor', 'Samba', 'Zigbee2MQTT'] } %}
{{ my_dict | urlencode }}
{# nome=Home+Assistant&versione=2024.1&componenti=%5B%27File+Editor%27%2C+%27Samba%27%2C+%27Zigbee2MQTT%27%5D #}
⬇️ slugify(separator="default= '_' "): viene utilizzato per convertire una stringa in un “slug”, sostituendo gli spazi con il separatore specificato (di default, trattino basso _).
{% set title = "Ciao, aggiungi un separatore!" %}
{{ title | slugify }} {# ciao_aggiungi_un_separatore #}
{{ title | slugify(separator="default= '_' ") }} {# ciaodefault= '_' aggiungidefault= '_' undefault= '_' separatore #}
⬇️ ordinal: viene utilizzato per converte i numeri interi in numeri ordinali.
{{ 1 | ordinal }} {# 1st #}
{{ 2 | ordinal }} {# 2nd #}
{{ 3 | ordinal }} {# 3rd #}
{{ 4 | ordinal }} {# 4th #}
⬇️ regex_replace(find='', replace='', ignorecase=False): viene utilizzato per sostituire l’espressione find con la stringa replace.

Quando ignorecase è impostato su True, la ricerca delle corrispondenze non terrà conto delle differenze tra maiuscole e minuscole.

{% set test_string = "Ciao, testiamo la funzione" %}
{{ test_string|regex_replace(find='la funzione', replace='regex_replace', ignorecase=False) }} {# Ciao, testiamo regex_replace #}
{{ test_string|regex_replace(find='la funzione', replace='regex_replace') }}                    {# Ciao, testiamo regex_replace #}
{{ test_string|regex_replace(find='La funzione', replace='regex_replace', ignorecase=False) }} {# Ciao, testiamo la funzione #}
{{ test_string|regex_replace(find='La funzione', replace='regex_replace', ignorecase=True) }}  {# Ciao, testiamo regex_replace #}
⬇️ regex_findall(find='', ignorecase=False): viene utilizzato per trovare tutte le corrispondenza di find e restituirle sotto forma di lista.

Quando ignorecase è impostato su True, la ricerca delle corrispondenze non terrà conto delle differenze tra maiuscole e minuscole.

{% set test_string = "Ciao, testiamo la funzione" %}
{{ test_string | regex_findall(find='ia', ignorecase=False) }}   {# ['ia', 'ia'] #}
{{ test_string | regex_findall(find='ciao', ignorecase=False) }} {# [] #}
{{ test_string | regex_findall(find='ciao', ignorecase=True) }}  {# 'Ciao #}
{{ test_string | regex_findall(find='Ciao', ignorecase=False) }} {# 'Ciao #}
⬇️ regex_findall_index(find='', index=0, ignorecase=False): viene utilizzato per trovare tutte le corrispondenza di find e la corrispondenza indice.

Index se non specificato viene considera zero (0) di default.

Quando ignorecase è impostato su True, la ricerca delle corrispondenze non terrà conto delle differenze tra maiuscole e minuscole.

{% set test_string = "Ciao, testiamo la funzione" %}
{{ test_string | regex_findall_index(find='ia') }}            {# ia #}
{{ test_string | regex_findall_index(find='ia', index=0) }}   {# ia #}
{{ test_string | regex_findall_index(find='ia', ignorecase=False, index=0) }}   {# ia #}
{{ test_string | regex_findall_index(find='Ciao', index=0, ignorecase=False) }} {# Ciao #}
{{ test_string | regex_findall_index(find='Ciao', index=1, ignorecase=False) }} {# IndexError #}
{{ test_string | regex_findall_index(find='Ciao', index=0, ignorecase=True) }} {# IndexError #}
⬇️ expand: viene utilizzare per convertire entità, liste ed entità dei gruppi in oggetto di stato.
{{ 'light.bagno_specchio' | expand }}
{{ 'group.automation_action_armed' | expand }}
{{ ['light.bagno_specchio' ,'light.luce_studio'] | expand }}

Condizione if

La struttura condizionale if, elif, else, e endif è un modo per controllare il flusso del template in base a condizioni.

Dettaglio

if: L’istruzione if inizia una sezione di codice condizionale, e il blocco di codice successivo verrà eseguito solo se la condizione associata all’if è valutata come vera. In altre parole, il codice all’interno del blocco if viene eseguito solo quando la condizione specificata è verificata come true. Grazie per la chiara riformulazione.

elif (else if): L’istruzione elif (else if) inizia una sezione di codice condizionale aggiuntiva. Il blocco di codice successivo verrà eseguito solo se la condizione associata all’elif è valutata come vera. In caso contrario, se la condizione dell’elif è falsa, il flusso del codice continuerà a valutare le successive clausole elif o, in mancanza di ulteriori clausole, passerà all’eventuale blocco else.

else: L’istruzione else inizia una sezione di codice condizionale alternativo. Il blocco di codice successivo verrà eseguito solo se nessuna delle condizioni precedenti (if o eventuali clausole elif) è valutata come vera. In altre parole, il blocco di codice else rappresenta il caso di fallback, che viene eseguito quando tutte le condizioni precedenti risultano false.

endif: L’istruzione endif segna la fine della sezione di codice condizionale in Jinja2. Tutte le istruzioni successive a endif verranno eseguite indipendentemente dalle condizioni precedenti. In pratica, endif chiude la costruzione condizionale aperta con if, elif, e else, indicando che tutte le alternative condizionali sono state considerate e che il flusso del codice dovrebbe continuare normalmente.

{% set numero = 54 %} {# Inizializza una variabile numero es.54 #}
{% if numero > 90 %}  {# Inizia un blocco condizionale. Se il valore della variabile è maggiore di 90, eseguirà il blocco di codice successivo #}
    Il numero è maggiore di 90.
{% elif numero > 70 %} {# Altra condizione. Se la condizione precedente non è vera, verifica se il numero è maggiore di 70. Se è vero, eseguirà il blocco di codice successivo. #}
    Il numero è maggiore di 70.
{% elif numero >= 50 %} {# Altra condizione. Se la condizione precedente non è vera, verifica se il numero è maggiore o uguale a 50. Se è vero, eseguirà il blocco di codice successivo #}
    Il numero è maggiore o uguale a 50.
{% else %} {# Questo blocco viene eseguito se nessuna delle condizioni precedenti è vera #}
    Il numero è minore di 50.
{% endif %}

In Home Assistant, è possibile scrivere condizioni in una sintassi più breve quando non è necessario specificare una clausola “elif“.

{{ 'ACCESA' if is_state('light.luce_studio', 'on') else 'SPENTA' }} 

Inoltre, Home Assistant offre il filtro iif, che consente di esprimere condizioni in modo più breve ed immediato. La sintassi di base è: {{ iif(condition, if_true, if_false, if_none) }}

  • condition: La condizione da valutare.
  • if_true: Il valore restituito se la condizione è vera. Opzionale; se omesso, restituisce True.
  • if_false: Il valore restituito se la condizione è falsa. Opzionale; se omesso, restituisce False.
  • if_none: Il valore restituito se la condizione è None. Opzionale; se omesso, restituisce None.
{{ iif(is_state('light.luce_studio', 'on'), 'ACCESA', 'SPENTA', 'ERRORE') }}

{{ is_state('light.luce_studio', 'on') | iif('ACCESA', 'SPENTA', 'ERRORE') }}

{{ (states('light.luce_studio') == 'on') | iif('ACCESA', 'SPENTA', 'ERRORE') }}

Si noti che il filtro iif non segue il comportamento di cortocircuito tipico di un’istruzione condizionale standard, che interrompe l’esecuzione al primo risultato positivo.

Invece, tutte le espressioni fornite (if_true, if_false, if_none) vengono valutate indipendentemente dalla condizione. Questo significa che entrambe le espressioni vengono esaminate, indipendentemente dal risultato della condizione, il che può causare problemi, specialmente in situazioni complesse o con valori che potrebbero causare errori.

Ciclo For

Il ciclo for è una struttura di programmazione che ti permette di ripetere un blocco di istruzioni per ogni elemento in una sequenza di dati. Ogni volta che il ciclo “gira” (itera), il tuo programma può fare qualcosa con l’elemento corrente della sequenza. In termini più semplici, il ciclo for è come un incaricato di eseguire una serie di compiti, uno alla volta, per ciascun elemento in una lista o un’altra collezione di dati.

In questo esempio, viene creata una variabile my_list contenente una lista di tre elementi (‘Primo’, ‘Secondo’, ‘Terzo’). Successivamente, un ciclo for attraversa ogni elemento della lista, stampando ciascun elemento. L’output finale è la stringa concatenata degli elementi della lista, senza spazi tra di essi: ‘PrimoSecondoTerzo’.

{% set my_list = ['Primo', 'Secondo', 'Terzo'] %}
  {% for ordine in my_list %}
    {{ ordine }}
  {% endfor %}
{# 'Primo Secondo Terzo' #}

Può essere impiegata per iterare su ogni coppia chiave-valore presente nel dizionario.

{% set my_dict = {'Primo': 1, 'Secondo': 2, 'Terzo': 3} %}
{% for chiave, valore in my_dict.items() %}
  {{ chiave }}: {{ valore }}
{% endfor %}
{# 'Primo: 1 Secondo: 2 Terzo: 3' #}
⬇️ else: Se non è avvenuta alcuna iterazione perché la sequenza era vuota o il filtro ha rimosso tutti gli elementi dalla sequenza, puoi eseguire il rendering di un blocco predefinito utilizzando else.
{% set my_lista = [ 5, 55 ] %} {# lista composta da numeri #}
{% for valore in my_lista if valore is string %} {# applicato filtro string #}
  Stringa
{% else %}
  Numero
{% endfor %}
{# Numero #}
⬇️ break: è un’estensione aggiunta ad HomeAssistant utilizzata per interrompere immediatamente l’esecuzione del loop quando una specifica condizione viene soddisfatta.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {% if valore == 'elemento2' %}
    {{ valore }}
    {% break %} {# Esci dal ciclo quando si verifica la condizione desiderata #}
  {% else %}
    {{ valore }}
  {% endif %}
{% endfor %}
{# 
elemento1
elemento2
#}
⬇️ continue: è un’estensione aggiunta ad Home Assistant utilizzata che, quando viene eseguita, interrompe immediatamente l’esecuzione dell’iterazione corrente del ciclo e passa immediatamente alla successiva.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {% if valore == 'elemento2' %}
    {% continue %} {# Salta alla prossima iterazione se il valore da evitare è trovato #}
  {% else %}
    {{ valore }}
  {% endif %}
{% endfor %}
{# 
elemento1
elemento3
elemento4
#}
All'interno di un blocco for, puoi accedere ad alcune variabili speciali
⬇️ loop.index: rappresenta l’indice corrente durante l’iterazione di un ciclo. Esso restituisce la posizione numerica dell’elemento in questione, partendo da 1.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.index }}
{% endfor %}
{# 
1 
2 
3 
4
#}
⬇️ loop.index0: rappresenta l’indice corrente durante l’iterazione di un ciclo, partendo da 0. A differenza di loop.index che inizia da 1, loop.index0 restituisce l’indice partendo da 0.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.index0 }}
{% endfor %}
{# 
0
1
2
3
#}
⬇️ loop.revindex: rappresenta l’indice inverso corrente durante l’iterazione di un ciclo. Esso restituisce la posizione inversa numerica dell’elemento in questione, partendo da 1 per l’ultimo elemento, 2 per il penultimo, e così via.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.revindex }}
{% endfor %}
{# 
4
3
2
1
#}
⬇️ loop.revindex0: rappresenta l’indice inverso corrente durante l’iterazione di un ciclo, partendo da 0 per l’ultimo elemento, 1 per il penultimo, e così via. A differenza di loop.revindex che inizia da 1, loop.revindex0 restituisce l’indice inverso partendo da 0
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.revindex0 }}
{% endfor %}
{# 
3
2
1
0
#}
⬇️ loop.first: restituisce True durante la prima iterazione di un ciclo e False durante le iterazioni successive.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.first }}
{% endfor %}
{# 
True
False
False
False
#}
⬇️ loop.last: restituisce True durante l’ultima iterazione di un ciclo e False durante le iterazioni precedenti.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.last }}
{% endfor %}
{# 
False
False
False
True
#}
⬇️ loop.length: restituisce il numero totale degli elementi nella sequenza su cui si sta iterando.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.length }}
{% endfor %}
{# 
4
4
4
4
#}
⬇️ loop.cycle: consente di assegnare dinamicamente diversi valori in modo sequenziale a ciascun elemento all’interno di un ciclo.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for valore in my_lista %}
  {{ loop.cycle('primo', 'secondo') }}
{% endfor %}
{# 
primo
secondo
primo
secondo
#}
⬇️ loop.previtem: rappresenta l’elemento della precedente iterazione del ciclo. Indefinito durante la prima iterazione.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for elemento in my_lista %}
  Elemento corrente: {{ elemento }}
  {%- if loop.previtem is defined %}
    Elemento precedente: {{ loop.previtem }}
  {% else %}
    Nessun elemento precedente (siamo al primo elemento)
  {% endif %}
{% endfor %}
{#
Elemento corrente: elemento1
Nessun elemento precedente (siamo al primo elemento)
  
Elemento corrente: elemento2
Elemento precedente: elemento1

Elemento corrente: elemento1
Elemento precedente: elemento2

Elemento corrente: elemento4
Elemento precedente: elemento1
#}
⬇️ loop.nextitem: rappresenta l’elemento della successiva iterazione del ciclo. Non definito durante l’ultima iterazione.
{% set my_lista = ['elemento1', 'elemento2', 'elemento3', 'elemento4'] %}
{% for elemento in my_lista -%}
  Elemento corrente: {{ elemento }}
  {%- if loop.nextitem is defined %}
    Elemento successivo: {{ loop.nextitem }}
  {% else %}
    Nessun elemento successivo (siamo all'ultimo elemento)
  {% endif %}
{% endfor %}
{#
Elemento corrente: elemento1
Elemento successivo: elemento2
  
Elemento corrente: elemento2
Elemento successivo: elemento3
  
Elemento corrente: elemento3
Elemento successivo: elemento4
  
Elemento corrente: elemento4
Nessun elemento successivo (siamo all'ultimo elemento)
#}
⬇️ loop.changed(*val): restituisce True se uno o più valori sono cambiati rispetto all’iterazione precedente del ciclo.
{% set my_lista = ['elemento1', 'elemento2', 'elemento2', 'elemento4'] %}
{% for valore in my_lista %}
{{- loop.changed(valore)}}
{% endfor %}
{#
True ("elemento1: Prima iterazione")
True ("elemento2: Il valore è cambiato rispetto all'iterazione precedente.")
False ("elemento2: Il valore è lo stesso dell'iterazione precedente.")
True ("elemento4: Il valore è cambiato rispetto all'iterazione precedente.")
#}

Macro

Le macro sono blocchi di codice riutilizzabili che puoi definire una volta e poi chiamare più volte.
Immagina una macro come un “pezzetto” di codice che crei una volta e poi puoi “incollarlo” nel tuo template ogni volta che ne hai bisogno. È come avere un piccolo blocco di istruzioni che puoi riutilizzare senza riscrivere tutto il codice ogni volta. Semplicemente lo richiami quando serve, rendendo il tuo template più pulito e facile da gestire.

Per definirla, utilizza la parola chiave macro, seguita da un nome a tua scelta per la macro e dalle variabili desiderate racchiuse tra parentesi. Puoi specificare più variabili nelle macro di Jinja2, separandole con virgole, e puoi assegnare valori di default a ciascuna variabile.

{% macro test(test_varibile, variabile_con_default='Italiano') %}
Ciao {{ test_varibile }} sei {{ variabile_con_default }}?
{% endmacro %}

{{ test('Marco') }} {# Ciao Marco sei Italiano? #}
{{ test('Henrik', 'Francese') }} {# Ciao Henrik sei Francese? #}

In Home Assistant, è possibile organizzare modelli Jinja2 riutilizzabili nella cartella custom_templates all’interno della directory config. Questa pratica aiuta a semplificare il codice, evitando la ripetizione di codice complesso in più template. I file contenenti i modelli devono avere estensione .jinja.

Esempio

Crei un file chiamato test_macro.jinja nella cartella custom_templates con una macro chiamata format_entity.

{% macro format_entity(entity_id) %}
    {{ state_attr(entity_id, 'friendly_name') }} - {{ states(entity_id) }}
{% endmacro %}

Quindi, puoi riutilizzare la macro importandola in un template.

{% from 'test_macro.jinja' import format_entity %}
{{ format_entity('sensor.temperature') }}
{# Temperatura - 21 #}}

In questo modo, hai dichiarato la macro format_entity nel file test_macro.jinja e poi l’hai importata e utilizzata in un altro template. La macro prende una variabile entity_id e restituisce una stringa formattata con il nome e lo stato dell’entità specificata (‘sensor.temperature’ nell’esempio).

Namespace

La funzione namespace è utilizzata per organizzare e gestire i dati all’interno dei template.

È possibile creare un namespace utilizzando la funzione namespace() per organizzare variabili correlate.

{% set my_namespace = namespace(count=0, devices=[]) %}

In questo esempio, my_namespace è un namespace che contiene una variabile count e una lista vuota chiamata devices.

È possibile aggiornare i valori all’interno del namespace utilizzando la sintassi my_namespace.variable = valore.
Mentre puoi accedere direttamente ai valori del namespace utilizzando la sintassi namespace.variablename.

{% set my_namespace = namespace(count=0, devices=[]) %}
{% set my_namespace.count = my_namespace.count + 1 %}
{{ my_namespace.count }} {# output 1 #}

{% set my_namespace = namespace(count=0, devices=[]) %}
{% set my_namespace.devices = my_namespace.devices + ['a'] + ['b','c'] %}
{{ my_namespace.devices }} {# output ['a','b','c'] #}
Dettaglio

L’utilizzo del namespace può essere estremamente comodo per estrapolare i dati all’interno di un ciclo for e consentire una seconda iterazione su di essi o ottenere una semplice lista.

{%- for a in device_entities('c145d6e3182ba054d154c689b25cd881') %}
{{- a }}
{%- endfor %}
{# output = esempio,binary_sensor.luce_studiosensor.wifi_luce_studiosensor.luce_studio_uptimeupdate.studio_firmwarebutton.luce_studio_restartswitch.detached_luce_studiolight.luce_studio #}

{% set my_namespace = namespace(devices=[]) %}
{%- for a in device_entities('c145d6e3182ba054d154c689b25cd881') %}
{% set my_namespace.devices = my_namespace.devices + [a] %}
{%- endfor %}
{{ my_namespace.devices }}
{# output = ['binary_sensor.luce_studio', 'sensor.wifi_luce_studio', 'sensor.luce_studio_uptime', 'update.studio_firmware', 'button.luce_studio_restart', 'switch.detached_luce_studio', 'light.luce_studio'] #}

Nell’esempio fornito, vediamo due approcci diversi per gestire le entità di un dispositivo all’interno di un template.

  • Senza utilizzo del namespace: Utilizzando un semplice ciclo for, otteniamo una stringa che rappresenta l’elenco delle entità del dispositivo. Questo approccio è limitato perché otteniamo solo una stringa e non possiamo facilmente utilizzare questa lista di entità in altre parti del template.
  • Con utilizzo del namespace: Utilizzando il namespace, creiamo una lista di entità del dispositivo durante l’iterazione. Questo ci permette di mantenere una lista organizzata e riutilizzabile delle entità all’interno del template. Il namespace offre un modo conveniente per organizzare e gestire questi dati, rendendo più semplice l’accesso e l’utilizzo delle informazioni all’interno del template.

Estensione template HomeAssistant

Nell’ambito di Home Assistant, le “estensioni di template” si riferiscono a personalizzazioni e funzionalità aggiuntive integrate nei modelli. Queste estensioni consentono di arricchire e adattare le configurazioni, aggiungendo nuovi filtri, e funzioni.

Puoi pensare a queste estensioni come a librerie o moduli supplementari, progettati per ampliare le funzionalità di base di Jinja2 specificamente per Home Assistant.

Stati e attributi

È importante comprendere la distinzione tra un ‘oggetto di stato’ e uno ‘stato di un oggetto’.
La differenza tra un “oggetto di stato” e uno “stato di un oggetto” può sembrare sottile, ma è importante comprendere il contesto specifico in cui vengono utilizzati questi termini.

Lo stato di un oggetto: Si riferisce al valore corrente un’entità specifica in un determinato momento. Ad esempio, lo stato di un sensore di temperatura è la temperatura attuale. A questi non è possibile applicare filtri.

Oggetto di stato: Si riferisce alla struttura dati completa che contiene tutte le informazioni associate allo stato di un’entità. Questo oggetto di stato comprende non solo il valore corrente ma anche altri attributi come l’unità di misura, il timestamp dell’ultimo aggiornamento, e altri dati correlati all’entità.

Quindi, puoi dire “lo stato di un oggetto” è più specificamente il valore attuale di un’entità, mentre “oggetto di stato” è un termine più ampio che abbraccia tutte le informazioni correlate a tale stato all’interno del sistema.

Oggetto di stato

Attraverso l’utilizzo della variabile states in Home Assistant, abbiamo la possibilità di esaminare l’intero oggetto di stato, offrendo un ampio margine di flessibilità per l’applicazione di ulteriori filtri. Ad esempio, mediante l’istruzione {{ states | map(attribute='entity_id') | list }}, possiamo generare un elenco completo di tutte le entità attualmente presenti nel sistema.

Se il nostro interesse è rivolto a un particolare dominio, possiamo restringere la nostra ricerca utilizzando {{ states.light | map(attribute='entity_id') | list }}, ottenendo così un elenco di tutti gli oggetti di stato associati al dominio “light” mappando gli entity_id. Lo stesso risultato può essere ottenuto attraverso la sintassi alternativa {{ states['light'] | map(attribute='entity_id') | list }} o utilizzando la funzione expand offrendo la possibilità di creare una lista ordinata e senza entità duplipate.

{{ states.light | map(attribute='entity_id') | list }}
{{ states['light'] | map(attribute='entity_id') | list }}

{{ expand(states.light, states.switch) | map(attribute='entity_id') | list}}
{{ expand(states['light'], states['switch']) | map(attribute='entity_id') | list}}

Per completezza, è possibile accedere rapidamente allo stato e ai vari attributi di una singola entità (chiavi) utilizzando direttamente l’espressione della variabile di stato. Tuttavia, è consigliabile fare attenzione e evitare questa pratica quando possibile, specialmente per evitare errori e messaggi di errore quando l’entità non è ancora completamente pronta o disponibile. Preferibilmente, è consigliato utilizzare le funzioni dello stato di un oggetto per garantire una gestione più robusta delle entità.

{{ states.light.luce_studio.state }}                           {# on/off #}
{{ states['light.luce_studio'].state }}                        {# on/off #}

{{ states.light.luce_studio.attributes.friendly_name }}        {# Luce Studio #}
{{ states['light.luce_studio'].attributes.friendly_name }}     {# Luce Studio #}

Oltre alle chiavi state ed attributes che hanno come detto una funzione personalizzata possiamo accedere alle altre chiavi del oggetto modo simile.

{{ states.light.luce_studio.last_changed }}          {# 2024-02-03 13:41:42.438045+00:00 #}
{{ states['light.luce_studio'].last_changed }}       {# 2024-02-03 13:41:42.438045+00:00 #}

{{ states.light.luce_studio.last_updated }}          {# 2024-02-03 13:41:42.438045+00:00 #}
{{ states['light.luce_studio'].last_updated }}       {# 2024-02-03 13:41:42.438045+00:00 #}

{{ states.light.luce_studio.context.id }}            {# 01HNQK86WKB7DS40RV7CSWTMJR #}
{{ states['light.luce_studio'].context.id }}         {# 01HNQK86WKB7DS40RV7CSWTMJR #}

{{ states.light.luce_studio.context.parent_id }}     {# None #}
{{ states['light.luce_studio'].context.parent_id }}  {# None #}

{{ states.light.luce_studio.context.user_id }}       {# 7cc56e6835544d52884d254cc1c2d471 #}
{{ states['light.luce_studio'].context.user_id }}    {# 7cc56e6835544d52884d254cc1c2d471 #}
Stato di un oggetto

Possiamo ottenere lo stato di un oggetto utilizzando la variabile states in combinazione con funzioni specifiche. Ad esempio, con l’espressione {{ states('light.luce_studio') }}, possiamo estrarre direttamente lo stato dell’entità “luce_studio”.

{{ states('light.luce_studio') }} {# on/off #}

La funzione state_translated restituisce lo stato tradotto di un’entità utilizzando la lingua attualmente configurata in homeassistant. E’ possibile utilizzare la funzione anche come filtro.

{{ state_translated ('light.luce_studio') }} {# Spento/a - Acceso/a #}
{{ 'light.luce_studio' | state_translated }} {# Spento/a - Acceso/a #}

In aggiunta, possiamo controllare la formattazione di output di un sensore utilizzando le funzioni rounded e with_unit. La funzione rounded offre la possibilità di limitare la visualizzazione a due numeri decimali del valore del sensore o di escluderli del tutto. D’altra parte, la funzione with_unit consente di aggiungere l’unità di misura alla visualizzazione del valore del sensore restituendo una stringa.

{{ states('sensor.generale_energy') }} {# 513.703 #}

{{ states('sensor.generale_energy', rounded=false, with_unit=true) }} {# 513.703 kWh #}
{{ states('sensor.generale_energy', rounded=true, with_unit=False) }} {# 513.70 #}
{{ states('sensor.generale_energy', rounded=true, with_unit=true) }} {# 513.70 kWh #}

{{ states.sensor.generale_energy.state_with_unit }} {# alternativa a rounded=true, with_unit=true 513.70 kWh #}

È possibile accedere allo stato di un attributo specifico di un sensore utilizzando la funzione state_attr in Home Assistant. Basta scrivere la funzione state_attr e specificare tra parentesi l’entità del sensore e l’attributo desiderato, separati da una virgola.

{{ state_attr('sensor.generale_energy', 'device_class') }} {# energy #}
{{ state_attr('sensor.generale_energy', 'friendly_name') }} {# Generale energy #}

In Home Assistant, è possibile confrontare lo stato di un’entità o lo stato di un attributo di un’entità con uno stato specificato. Oltre agli operatori di confronto, puoi utilizzare le funzioni specifiche is_state e is_state_attr per effettuare questi confronti in modo più leggibile.

Per quanto riguarda lo stato di un’entità, puoi anche confrontarlo con un elenco di stati, in alternativa alla funzione in, per verificare se lo stato corrisponde a uno qualsiasi degli stati specificati nell’elenco.

{{ is_state('sensor.generale_energy', '513.703') }} {# 513.703 #}
{{ is_state_attr('sensor.generale_energy', 'device_class', 'energy') }} {# true#}

{{ is_state('person.marco', ['home', 'lavoro']) }} {# True #}

È possibile utilizzare le funzioni states, is_state, state_attr, e is_state_attr anche come filtri.

{# map('states') & map('state_attr' #}
{{ ['person.marco', 'person.tata'] | map('states') | list }} {# ['home', 'home'] #}
{{ states['person'] |map(attribute='entity_id') | map('states') | list }} {# ['home', 'home', 'not_home'] #}

{{ ['person.marco', 'person.tata'] | map('state_attr', 'friendly_name')  | list }} {# ['Marco', 'Tata'] #}
{{ states['person'] |map(attribute='entity_id') | map('state_attr', 'friendly_name')  | list }} {# ['Marco', 'Tata', 'Mattia'] #}


{# select('is_state' & select('is_state_attr #}
{{ ['person.marco', 'person.tata'] | select('is_state', 'home') | list }} {# ['person.marco', 'person.tata'] #}
{{ states['person'] |map(attribute='entity_id') | select('is_state', 'home') | list }} {# ['person.marco', 'person.tata'] #}

{{ ['person.marco', 'person.tata'] | select('is_state_attr', 'friendly_name', 'Marco') |list }} {# ['person.marco'] #}
{{ states['person'] |map(attribute='entity_id') | select('is_state_attr', 'friendly_name', 'Marco') | list }} {# ['person.marco'] #}

La funzione has_value verifica se l’entità specificata non è sconosciuta o non disponibile, mentre is_hidden_entity indica se l’entità è stata nascosta, quindi non visualizzabile sulla dashboard. has_value può essere utilizzato come filtro.

{{ has_value('person.marco') }} {# true #}
{{ 'person.marco' | has_value }} {# true esempio utilizzo filtro #}
{{ states |map(attribute='entity_id') | reject('has_value') |list }}

{{ is_hidden_entity('person.marco') }} {# false #}
{{ states |map(attribute='entity_id') | select('is_hidden_entity') |list }}

Dedichiamo una breve nota alla gestione dei gruppi. Nonostante sia possibile accedere alle entità che lo compongono tramite l’attributo entity_id, possiamo anche avvalerci della funzione expand, che ci fornisce un accesso diretto agli oggetti di stato delle entità. Questo ci permette di ordinare e ottenere un elenco unico di entità nel gruppo.

{{ expand('group.automation_action_armed') | map(attribute='entity_id') | select('is_state','on') | list}}

{{ state_attr('group.automation_action_armed', 'entity_id') | select('is_state','on') | list}}

Dispositivi, Piani, Aree, Integrazioni Etichette

Un piccolo riepilogo per capire in linea generale come Home Assistant organizza le informazioni in modo gerarchico e concettuale.

  1. Entità: Un’entità si riferisce a un’unità individuale che rappresenta un elemento specifico all’interno del sistema di Home Assistant. Queste entità possono essere associate a diversi concetti, inclusi automazioni, script o singole caratteristiche di un dispositivo. Ad esempio, consideriamo un dispositivo relè che può essere suddiviso in entità separate per il suo stato (acceso/spento), la potenza assorbita, l’energia consumata e così via. Ad ogni entità è associato un ID univoquo.
  2. Integrazioni: Le integrazioni rappresentano i vari componenti o piattaforme supportate da Home Assistant. Questi possono includere dispositivi hardware, servizi cloud, protocolli di comunicazione, e altro ancora. Ad esempio, l’integrazione ZHA supporta dispositivi Zigbee come luci, sensori, ecc.
  3. Dispositivi: Un dispositivo è un oggetto fisico o virtuale che comunica con Home Assistant tramite un’integrazione. Ad esempio, un dispositivo potrebbe essere una lampada Zigbee, un sensore di temperatura o una videocamera. Ogni dispositivo è associato a un’area ed ha un ID univoquo.
  4. Etichette: consentono di raggruppare elementi, indipendentemente dalla loro posizione fisica o tipo. Puoi assegnare etichette ad aree, dispositivi, entità, automazioni, scene, script e aiutanti.
  5. Aree: Le aree sono utilizzate per organizzare i dispositivi all’interno della tua casa. Possono rappresentare stanze o qualsiasi altra suddivisione logica dello spazio abitativo. Ad esempio, potresti avere un’area chiamata “Salotto” che include tutti i dispositivi presenti in quella stanza. Ad ogni area è associato un ID univoquo.
  6. Piani: rappresenta un raggruppamento logico di aree che corrispondono ai piani fisici della tua casa. I dispositivi e le entità non possono essere assegnati direttamente ai piani, ma sono assegnati alle aree che compongono il piano. I piani possono essere utilizzati nelle automazioni e negli script come destinazione per le azioni. Ad esempio, puoi configurare un’automazione per spegnere tutte le luci del piano terra quando vai a letto.
  7. Zone: Le Zone in Home Assistant costituiscono rappresentazioni di specifiche regioni geografiche sulla Terra. L’utilizzo di queste zone permette di delineare e identificare aree di interesse all’interno del sistema, come ad esempio casa, lavoro, palestra, e così via. Quando un dispositivo autenticato su Home Assistant, con l’app companion installata e l’utente loggato, viene individuato all’interno di una zona designata, il sistema associa automaticamente lo stato di quest’ultimo al nome della zona corrispondente. Ad esempio, se un dispositivo si trova all’interno della zona “home” (casa), il sistema assegnerà lo stato del dispositivo a quella zona specifica, semplificando così il monitoraggio e la gestione dei dispositivi in base alla loro posizione geografica. Ad ogni zona è associato un ID univoquo.
Voce di configurazione
⬇️ config_entry_id: o voce di configurazione rappresenta le informazioni specifiche di configurazione associate a un componente o un’entità.

Una voce di configurazione rappresenta i dettagli specifici di come un componente o un’entità è configurato nel sistema di Home Assistant. Questa funzione può essere utilizzata anche come filtro.

{{ config_entry_id('sensor.comodino_mattia_rssi') }} {# config_entry_id di una entità #}

{{ 'sensor.comodino_mattia_rssi' | config_entry_id }}
{# esempio utilizzo filtro #}

{{ states | map(attribute='entity_id') | map('config_entry_id') | reject('eq', None) | unique | list }}
{# esempio utilizzo #}

{% set target = config_entry_id('update.home_assistant_core_update') %} {# Imposta l'ID della voce di configurazione #}
{%- for entity in states -%}
    {% if config_entry_id(entity.entity_id) == target %}
        {{ entity.entity_id }}
    {%- endif %}
{%- endfor %}
{# elenca gli entity_id associati alla variabile 'target' #}
Dispositivi / Devices
⬇️ device_id(device_or_entity_id): restituisce l’ID del dispositivo associato, ottenibile sia da un entity_id che dal nome dispositivo. Questa funzione può essere utilizzata anche come filtro.
{{ device_id('Studio') }}                         {# c145d6e3182ba054d154c689b25cd881 #}
{{ device_id('light.luce_studio') }}              {# c145d6e3182ba054d154c689b25cd881 #}
{{ 'light.luce_studio' | device_id }} {# es.filtro c145d6e3182ba054d154c689b25cd881 #}
{# esempio utilizzo filtro #} 

{{ states | map(attribute='entity_id') | map('device_id') | reject ('eq', None) | unique  | list }} 
⬇️ device_entities(device_id): restituisce un elenco delle entità collegate a un determinato device_id. Questa funzione può essere utilizzata anche come filtro.
{{ device_entities('c145d6e3182ba054d154c689b25cd881') }}        
{{ 'c145d6e3182ba054d154c689b25cd881' | device_entities }}  {# esempio filtro #}
{# es. [ 'update.studio_firmware', 'button.luce_studio_restart',  'light.luce_studio']#}


{{ states.climate | map(attribute='entity_id') | map('device_id') | reject('eq', None) | unique | map('device_entities') | list }}
⬇️ device_attr(device_id_or_entity_id, attr_name): restituisce il valore dell’attributo del dispositivo, ottenibile sia da un entity_id che dal device_id. Questa funzione può essere utilizzata anche come filtro. È possibile verificare gli attributi disponibili per un dispositivo accedendo al file core.device_registry (importante non effettuare modifiche al file).
{{ device_attr('light.luce_studio', 'manufacturer') }}       {# Espressif #}
{{ device_attr('c145d6e3182ba054d154c689b25cd881', 'manufacturer') }}  {# Espressif #}
{{ 'light.luce_studio' | device_attr('manufacturer')}} {# esempio uso come filtro #}

{{ states.light | map(attribute='entity_id') | map('device_attr','identifiers') |reject('none') | map('first') | select('defined') | map(attribute='0') | unique | list }} {# esempio per conoscere le integrazioni che usano light #}

{% set device_id_or_entity_id =  'light.luce_studio' %}
{{ device_attr(device_id_or_entity_id, 'model') }}           {# esp01_1m #}
{{ device_attr(device_id_or_entity_id, 'name_by_user') }}    {#  None #}
{{ device_attr(device_id_or_entity_id, 'name') }}            {# Studio #}
{{ device_attr(device_id_or_entity_id, 'serial_number') }}   {# None #}
{{ device_attr(device_id_or_entity_id, 'sw_version') }}      {# 2023.12.9 (Jan 24 2024, 20:15:36) #}
{{ device_attr(device_id_or_entity_id, 'via_device_id') }}   {# 1c8cb03f978246150681a93fc2cd93a1 #} 
{{ device_attr(device_id_or_entity_id, 'disabled_by') }}     {# None #}
{{ device_attr(device_id_or_entity_id, 'entry_type') }}      {# None #}
{{ device_attr(device_id_or_entity_id, 'hw_version') }}      {# None #}
{{ device_attr(device_id_or_entity_id, 'id') }}              {# c145d6e3182ba054d154c689b25cd881 #}
{{ device_attr(device_id_or_entity_id, 'identifiers') }}     {# {('fritz', 'C8:2B:96:E9:1A:FA')} #}
{{ device_attr(device_id_or_entity_id, 'connections') }}     {# {('mac', 'c8:2b:96:e9:1a:fa')} #}
{{ device_attr(device_id_or_entity_id, 'area_id') }}         {# a75bbae460334cd1ab6a5b8051f7f190 #}
{{ device_attr(device_id_or_entity_id, 'config_entries') }}  {# {'6e5093b4d7620303c2474f2ebdd20e30', '54071d55c84e7b3861d1fba09680b2fd'} #}
{{ device_attr(device_id_or_entity_id, 'configuration_url') }}  {# http://192.168.178.160:80 #}
{{ device_attr(device_id_or_entity_id, 'add_config_entry_id') }} {# None #}
⬇️ is_device_attr(device_id_or_entity_id, attr_name, attr_value): restituisce True se il valore dell’attributo del dispositivo specificato corrisponde al valore specifico fornito. È possibile verificare gli attributi disponibili per un dispositivo accedendo al file core.device_registry (importante non effettuare modifiche al file).
{{ is_device_attr('light.luce_studio', 'manufacturer', 'Espressif') }}                 {# true #}
{{ is_device_attr('switch.dyson_continuous_monitoring', 'manufacturer', 'Dyson') }}    {# false #}
{{ is_device_attr('c145d6e3182ba054d154c689b25cd881', 'manufacturer', 'Espressif') }}  {# true #}

{{ states | map(attribute='entity_id') | select('is_device_attr', 'manufacturer', 'Shelly')| select('is_device_attr', 'model', 'Shelly 1') | list }}
{# esempio di utilizzo che restituisce tutte le entity_id dei dispositivi shelly 1 #}
Aree / Areas
⬇️ areas(): restituisce una lista di tutte le ID area
{{ areas() }} 
{# ['246326a3d1764a1ca80277498b6512fb', ....... 'a75bbae460334cd1ab6a5b8051f7f190'] #}
⬇️ area_id(device_id_or_entity_id_or_area_name): è possibile recuperare l’ID dell’area associata utilizzando l’ID del dispositivo (device_id), l’ID dell’entità (entity_id) e il nome dell’area.

Questa funzione può essere utilizzata anche come filtro.

{{ area_id('c145d6e3182ba054d154c689b25cd881') }} {# device_id #}
{{ area_id('Studio') }} {# area_name #}
{{ area_id('light.luce_studio') }} {# entity_id #}
{{ 'Studio' | area_id }} {# esempio uso come filtro #}

{# tutte restituisco l'area_id es. a75bbae460334cd1ab6a5b8051f7f190 #}
⬇️ area_name(device_id_or_entity_id_or_area_id): è possibile recuperare nome dell’area associata utilizzando l’ID del dispositivo (device_id), l’ID dell’entità (entity_id) e area id.

Questa funzione può essere utilizzata anche come filtro.

{{ area_name('c145d6e3182ba054d154c689b25cd881') }} {# device_id #}
{{ area_name('a75bbae460334cd1ab6a5b8051f7f190') }} {# area_id #}
{{ area_name('light.luce_studio') }} {# entity_id #}
{{ 'light.luce_studio' | area_name }} {# esempio uso con filtro #}

{# tutte restituisco il nome dell'area es. Studio #}
⬇️ area_entities(area_name_or_area_id): è possibile ottenere una lista delle entity_id associate a un’area, utilizzando sia il nome dell’area che l’ID dell’area.

Questa funzione può essere utilizzata anche come filtro.

{{ area_entities('a75bbae460334cd1ab6a5b8051f7f190') }} {# area_id #}
{{ area_entities('Studio') }} {# area_name #}
{{ 'Studio' | area_entities }} {# esempio uso come filto #}

{# tutte restituisco le entità dell'area es. ['sensor.samsung_m2070_toner', .... 'light.luce_bagno'] #}

{{ states.light | selectattr('entity_id', 'in', area_entities('Studio'))| map(attribute='entity_id') |list}}
{# esempio utilizzo che restituisce le entità id light in Studio #}
⬇️ area_devices(area_name_or_area_id): è possibile ottenere una lista dei device_id associati a un’area, utilizzando sia il nome dell’area che l’ID dell’area.

Questa funzione può essere utilizzata anche come filtro.

{{ area_devices('a75bbae460334cd1ab6a5b8051f7f190') }} {# area_id #}
{{ area_devices('Studio') }} {# area_name #}
{{ 'Studio' | area_devices }} {# esempio uso come filto #}

{# tutte restituisco id_device dell'area es. ['d2f8f1e40c064c318e7539af08a46fb3', ..... 'a7338d3803a3deebf32916471da3051f'] #}

{{ states.light | map(attribute='entity_id') | map('device_id') | reject ('eq', None) | unique | select('in',area_devices('Studio') ) | list }}
{# esempio utilizzo che restituisce id_device delle entità id light in Studio #}
Integrazioni
⬇️ integration_entities(integration_or_title):restituisce una lista delle entity_id collegate a una particolare integrazione. Puoi utilizzare il nome dell’integrazione e, se sono state configurate più istanze per la stessa integrazione, puoi anche fare riferimento al titolo impostato per tale integrazione.
{{ integration_entities('shelly') }} {# [ "button.frigorifero_reboot", ........... "light.luce_cucina" } #}

{{ states.light | selectattr('entity_id', 'in', integration_entities('shelly')) | map(attribute='entity_id') |list}}
{# esempio utilizzo per ottenere elenco di tutte light con integrazione shelly #}
Piani / Floors
⬇️ floors(): restituisce una lista di tutte le ID dei piani.
{{ floors() }} 
{# ['246326a3d1764a1ca80277498b6512fb', ....... 'a75bbae460334cd1ab6a5b8051f7f190'] #}
⬇️ floor_id(device_id_or_entity_id_or_area_name): è possibile recuperare l’ID del piano associata utilizzando l’ID del dispositivo (device_id), l’ID dell’entità (entity_id), il nome dell’area (area_name) e l’ID dell’area (area_id).

Questa funzione può essere utilizzata anche come filtro.

{{ floor_id('c145d6e3182ba054d154c689b25cd881') }} {# device_id #}
{{ floor_id('246326a3d1764a1ca80277498b6512fb') }} {# area_id#}
{{ floor_id('Studio') }} {# area_name #}
{{ floor_id('light.luce_studio') }} {# entity_id #}
{{ 'Primo' | floor_id}} {# esempio uso come filtro #}

{# tutte restituisco l'floor_id es. a75bbae460334cd1ab6a5b8051f7f190 #}
⬇️ floor_name(device_id_or_entity_id_or_area_id): è possibile recuperare nome del piano associata utilizzando l’ID del dispositivo (device_id), l’ID dell’entità (entity_id), l’ID area (area_id) ed l’ID del piano (floor_id).

Questa funzione può essere utilizzata anche come filtro.

{{ floor_name('c145d6e3182ba054d154c689b25cd881') }} {# device_id #}
{{ floor_name('a75bbae460334cd1ab6a5b8051f7f190') }} {# area_id #}
{{ floor_name('v75bbas460fggfgdfcd1ab6a51f7f190') }} {# floor_id #}
{{ floor_name('light.luce_studio') }} {# entity_id #}
{{ 'light.luce_studio' | floor_name}} {# esempio uso con filtro #}

{# tutte restituisco il nome del piano es. Primo #}
⬇️ floor_areas(floor_name_or_id): è possibile recuperare le aree associate al piano utilizzando l’ID del piano (floor_id) ed il nome del piano (floor_name).

Questa funzione può essere utilizzata anche come filtro.

{{ floor_name('Primo') }} {# floor_name#}
{{ floor_name('v75bbas460fggfgdfcd1ab6a51f7f190') }} {# floor_id #}
{{ floor_name('light.luce_studio') }} {# entity_id #}
{{ 'Primo' | floor_name}} {# esempio uso con filtro #}

{# tutte restituisco il le aree associate es. ['Cucina', 'Studio'] #}
Etichette / Labels
⬇️ labels(): è possibile recuperare la lista completa degli ID etichette o l’ID etichette assegnate all’ID area (area_id), ID dispositivo (device_id) o ID entità (entity_id).

Questa funzione può essere utilizzata anche come filtro.

{{ labels() }} {# ['allarme', ....... 'luci'] #}
{{ labels('automation.allarme_a_zone_notte') }} {# entity_id: ['allarme'] #}
{{ labels('08d4254fa8504f9fb0f952010cfe4c56') }} {# device_id: ['allarme'] #}
{{ labels('sdfa08d425sdfgasdsdfasd10cfe4c56') }} {# area_id: ['allarme'] #}

{{'08d4254fa8504f9fb0f952010cfe4c56' | labels }} es. filtro
⬇️ label_id(lookup_value): è possibile recuperare l’ID dell’etichetta (label_id) associata a un determinato nome etichetta (label_name).

Questa funzione può essere utilizzata anche come filtro.

{{ label_id('Allarme') }} {# allarme #}
{{'Allarme' | label_id }} {# allarme #}
⬇️ label_name(lookup_value): è possibile recuperare il nome dell’etichetta (label_name)associata a un determinato ID dell’etichetta (label_id).

Questa funzione può essere utilizzata anche come filtro.

{{ label_name('allarme') }} {# Allarme #}
{{'allarme' | label_name }}
⬇️ label_areas(label_name_or_id): è possibile recuperare la lista degli ID aree (area_id) associate al nome (label_name) o ID etichetta (label_id).

Questa funzione può essere utilizzata anche come filtro.

{{ label_areas('Allarme') }} {# ['08d4254fa8504f9fb0f952010cfe4c56', ..... '08dsadsafa8504f9fb0f952010cfe4c56'] #}
{{'allarme' | label_areas }} {# ['08d4254fa8504f9fb0f952010cfe4c56', ..... '08dsadsafa8504f9fb0f952010cfe4c56'] #}
⬇️ label_devices(label_name_or_id): è possibile recuperare la lista degli ID dispositivi (device_id) associate al nome (label_name) o ID etichetta (label_id).

Questa funzione può essere utilizzata anche come filtro.

{{ label_devices('Allarme') }} {# ['08d4254fa8504f9fb0f952010cfe4c56', ..... '08dsadsafa8504f9fb0f952010cfe4c56'] #}
{{'allarme' | label_devices }} {# ['08d4254fa8504f9fb0f952010cfe4c56', ..... '08dsadsafa8504f9fb0f952010cfe4c56'] #}
⬇️ label_entities(label_name_or_id): è possibile recuperare la lista delle ID entità (entity_id) associate al nome (label_name) o ID etichetta (label_id).

Questa funzione può essere utilizzata anche come filtro.

{{ label_entities('Allarme') }} {# ['input_boolean.alarm_triggered_state', .... 'automation.allarme_a_zone_notte']  #}
{{'allarme' | label_entities }} {# ['input_boolean.alarm_triggered_state', .... 'automation.allarme_a_zone_notte'] #}

Tempo

Esistono diversi formati di rappresentazione della data e dell’ora, ciascuno con la propria convenzione. Ecco alcuni dei formati più comuni:

  • Fuso orario: È una rappresentazione numerica del tempo che restituisce la data e l’ora attuali (datetime) basate sul fuso orario configurato in Home Assistant. Esempio: 2024-02-05 22:10:54.953156+01:00
  • UTC (Coordinated Universal Time): È una rappresentazione numerica del tempo che restituisce l’orario attuale (datetime), ignorando eventuali impostazioni di ora legale. Esempio: 2024-02-05 21:10:54.953167+00:00
  • Unix Timestamp: È una rappresentazione numerica del tempo che conta il numero di secondi trascorsi dal 1° gennaio 1970 00:00:00 UTC. Esempio: 1707167454.953173 rappresenta il 5 febbraio alle 21:10:54
  • ISO 8601: È uno standard internazionale che specifica il formato di rappresentazione delle date e degli orari. Utilizza la lettera “T” come separatore tra la data e l’ora. Esempio: 2024-02-05T22:10:54.953190+01:00
  • Formato H24 (orario militare): È un modo di rappresentare il tempo utilizzando un orologio a 24 ore senza indicare AM o PM. L’orario va da 00:00 a 23:59. Esempio: 22:10 rappresenta le 10:10 del pomeriggio.
Dettaglio
⬇️ now(): È una funzione che restituisce la data e l’ora con fuso orario, altri attributi datetime.

L’utilizzo causerà l’aggiornamento dei template all’inizio di ogni nuovo minuto.

{{ now() }}                    {# 2024-02-05 22:20:11.984532+01:00 #}
{{ now().timestamp() }}        {# UNIX: 1707168011.98455 #}
{{ now().isoformat() }}        {# ISO: 2024-02-05T22:20:11.984568+01:00 #}
{{ now().second }}             {# secondi: 11 #}
{{ now().minute }}             {# minuti: 20 #}
{{ now().hour }}               {# ore: 22 #}
{{ now().day }}                {# giorno: 5 #}
{{ now().month }}              {# mese: 2 #}
{{ now().year }}               {# anno: 2024 #}
{{ now().weekday() }}          {# giorno della settimana da 0 a 6: 0 #}
{{ now().isoweekday() }}       {# giorno iso della settimana da 1 a 7: 1#}
{{ now().microsecond }}        {# microsendi: 984625 #}
{{ now().tzinfo }}             {# timezone: Europe/Rome #}
{{ now().isocalendar() }}      {# datetime.IsoCalendarDate(year=2024, week=6, weekday=1) #}
{{ now().timetuple() }}        {# time.struct_time(tm_year=2024, tm_mon=2, tm_mday=5, tm_hour=22, tm_min=20, tm_sec=11, tm_wday=0, tm_yday=36, tm_isdst=0) #}
{{ now().fromtimestamp(1644028800) }} {# Esempio di timestamp Unix (2022-02-05 03:40:00 UTC) #}
⬇️ utcnow(): È una funzione che restituisce la data e l’ora senza tener conto del fuso orario, altri attributi datetime.

L’utilizzo causerà l’aggiornamento dei template all’inizio di ogni nuovo minuto.

{{ utcnow() }} {# 2024-02-05 22:06:00.134671+00:00 #}
{{ utcnow().timestamp() }} {# UNIX 1707170760.134684 #}
{{ utcnow().isoformat() }} {# ISO 2024-02-05T22:06:00.134741+00:00 #}
{{ utcnow().second }} {# 0 #}
{{ utcnow().minute }} {# 6 #}
{{ utcnow().hour }} {# 22 #}
{{ utcnow().day }} {# 5 #}
{{ utcnow().month }} {# 2 #}
{{ utcnow().year }} {# 2024 #}
{{ utcnow().weekday() }} {# giorno della settimana da 0 a 6: 0 #}
{{ utcnow().isoweekday() }} {# giorno iso della settimana da 1 a 7: 1#}
{{ utcnow().microsecond }} {# 134821 #}
{{ utcnow().tzinfo }} {# timezone:  UTC  #}
{{ utcnow().isocalendar() }} {# datetime.IsoCalendarDate(year=2024, week=6, weekday=1) #}
{{ utcnow().timetuple() }} {# time.struct_time(tm_year=2024, tm_mon=2, tm_mday=5, tm_hour=22, tm_min=6, tm_sec=0, tm_wday=0, tm_yday=36, tm_isdst=-1) #}
{{ utcnow().fromtimestamp(1644028800) }} {# Esempio di timestamp Unix (2022-02-05 03:40:00 UTC) #}
{{ utcnow().timestamp() }} {# restituisce UNIX 1707170760.13488 #}
⬇️ today_at(): è una funzione che converte una stringa contenente un formato H24 in un oggetto datetime con fuso orario, tenendo conto del fuso orario specificato.

L’utilizzo causerà l’aggiornamento dei template all’inizio di ogni nuovo minuto.

{{ today_at() }}                    {# 2024-02-05 00:00:00+01:00 #}

{{ today_at('10:30') }}             {# 2024-02-05 10:30:00+01:00 #}
{{ today_at('10:30').tzinfo }}      {# timezone: Europe/Rome #}
{{ today_at('10:30').timestamp() }} {# timezone: 1707125400.0 #}
{{ today_at('10:30').isoformat() }} {# ISO 2024-02-05T10:30:00+01:00 #}
⬇️ as_datetime(): è una funzione che coverte una stringa con formato Fuso orario, UTC , ISO 8601 o Unix in un oggetto che rappresenta la data e l’ora corrispondenti.

L’utilizzo causerà l’aggiornamento dei template all’inizio di ogni nuovo minuto.

{{ as_datetime('2024-02-05T10:30:00+01:00') }} {# ISO: 2024-02-05 10:30:00+01:00 #}
{{ as_datetime('2024-02-05 10:30:00+01:00') }} {# Con e senza fuso orario: 2024-02-06 10:30:00+01:00 #}
{{ as_datetime('1707125400.0') }}              {# Unix: 2024-02-05 09:30:00+00:00 #}
⬇️ as_timestamp(): è una funzione che coverte una stringa con formato Fuso orario, UTC o ISO 8601 in un oggetto che rappresenta la data e l’ora corrispondenti nel formato Unix.

Se fallisce, restituisce il valore default o, se omesso, genera un errore. Questa funzione può essere utilizzata anche come filtro.

{{ as_timestamp('2024-02-05T10:30:00+01:00') }} {# ISO: 1707125400.0  #}
{{ as_timestamp('2024-02-05 10:30:00+01:00') }} {# Fuso orario: 1707125400.0 #}
{{ as_timestamp('2024-02-05 09:30:00+00:00') }} {# Senza fuso orario: 1707125400.0 #}
{{ as_timestamp('errore','0') }}                {# esempio default: 0 #}
{{ '2024-02-05 09:30:00+00:00' | as_timestamp }}{# esempio filto: 1707125400.0 #}
⬇️ as_local(): è una funzione che converte un oggetto datetime nell’ora locale corrispondente.

Questa funzione può essere utilizzata anche come filtro.

{{ as_local(utcnow()) }} 
{{ as_local(state_attr('script.reset_sensori_frigorifero', 'last_triggered')) }} 
{{ as_local(as_datetime('2024-02-05T10:30:00+00:00')) }}
{{ utcnow() | as_local }}                                                         {# esempio filtro #}
{{ state_attr('script.reset_sensori_frigorifero', 'last_triggered') | as_local}}  {# esempio filtro #}
{{ as_local(as_datetime('2024-02-05T10:30:00+00:00')) | as_local}}                {# esempio filtro #}
{# tutti restituisco la data con formato 2024-02-06 21:49:00.064432+01:00 #}
⬇️ relative_time(): è un funzione che rappresentare l’intervallo di tempo trascorso dalla data fornita fino ad oggi.

Converte un oggetto datetime che rappresenta una data passata e restituisce una stringa che rappresenta l’età relativa in termini di secondi, minuti, ore, giorni, mesi o anni, a seconda dell’unità più grande. L’utilizzo causerà l’aggiornamento dei template all’inizio di ogni nuovo minuto. L’utilizzo causerà l’aggiornamento dei template all’inizio di ogni nuovo minuto.

{% set new_datetime =  as_datetime('2024-02-07 20:46:13.203634+00:00') %} 
{{ relative_time(new_datetime) }}                             {# 19 hours #}

{{ relative_time(states['light.luce_studio'].last_changed) }} {# 3 minutes #}

Per ottenere una traduzione possiamo utilizzare la funzione replace.

{% set new_datetime =  as_datetime('2024-02-07 20:46:13.203634+00:00')%}
{{ relative_time(new_datetime) | replace('years', 'anni') | replace('year', 'anno') | replace('days','giorni') | replace('day','giorno') | replace ('hours','ore') | replace ('hour','ora') | replace ('minutes','minuti') | replace ('minute','minuto') | replace ('seconds','secondi') }}
{# 19 ore#}

{{ relative_time(states['light.luce_studio'].last_changed) | replace('years', 'anni') | replace('year', 'anno') | replace('days','giorno') | replace('day','giorni') | replace ('hours','ore') | replace ('hour','ora') | replace ('minutes','minuti') | replace ('minute','minuto') | replace ('seconds','secondi') }}
{# 3 minuti #}

Un’alternativa che potremmo considerare è lavorare sul futuro anziché solo sul tempo passato.

{% set new_datetime =  as_datetime('2025-02-07 20:46:13.203634+00:00')%}
{% set time_futuro = as_local(new_datetime)  %}
{% set diff_time = time_futuro - now() %}
{{ relative_time(now() - diff_time) }} {# 1 year #}
⬇️ timedelta(): restituisce un oggetto chiamato timedelta, che è utile quando vogliamo aggiungere o sottrarre una quantità di tempo da un oggetto datetime.

Possiamo usare timedelta per rappresentare periodi di tempo specifici, come giorni, ore, minuti, secondi, e così via. I suoi argomenti includono gli stessi valori accettati dalla funzione datetime.timedelta di Python,: days, seconds, microseconds, milliseconds, minutes, hours, weeks.

{{ timedelta( days = 4 ,hours = 1, minutes = 17, seconds = 44, milliseconds=144)}} {# 4 days, 1:17:44.144000 #}
{{ timedelta( weeks = 4 , microseconds=144)}}                                      {# 28 days, 0:00:00.000144 #}
{{ timedelta( days = 4, weeks = 4) }}                                              {# 32 days, 0:00:00 #}

{% set ora_corrente = now() %}
{{ ora_corrente }}                                                                 {# 2024-02-08 20:26:41.109587+01:00 #}
{{ ora_corrente - timedelta( days = 4, hours = 1)}}                                {# 2024-02-04 19:26:41.109587+01:00 #}
⬇️ as_timedelta(string): converte una stringa in un oggetto timedelta. 

Si aspetta dati nel formato DD HH:MM:SS.uuuuuuDD HH:MM:SS,uuuuuu, o come specificato da ISO 8601 o dal formato dell’intervallo diurno di PostgreSQL. Questa funzione può essere utilizzata anche come filtro.

{{ as_timedelta('4 1:15:20,0') }}
{{ as_timedelta('4 1:15:20.0') }}
{{ as_timedelta('P4DT1H15M20S') }}       {# ISO 8601 #}
{{ as_timedelta('4 days 01:15:20') }}    {# PostgreSQL #}

{{ '4 1:15:20,0' | as_timedelta }}       {# filtro #}
{{ '4 1:15:20.0' | as_timedelta }}       {# filtro #}
{{ 'P4DT1H15M20S' | as_timedelta }}      {# filtro ISO 8601 #}
{{ '4 days 01:15:20' | as_timedelta }}   {# filtro PostgreSQL #}

{# Tutti i template restituiscono 4 days, 1:15:20 #}
⬇️ | timestamp_custom('format_string', local=True, default): è un filtro che converte un timestamp UNIX in un formato di stringa personalizzato.

E’ possibile applicare un valore predefinito per evitare che il filtro generi un errore nel caso in cui la conversione del timestamp UNIX in formato ISO fallisca. In questo modo, se la conversione non è possibile, il filtro restituirà il valore predefinito invece di generare un errore. Inoltre, è possibile specificare se la conversione deve tener conto dell’ora legale.

Possibili conversioni in stringhe:

{{ 1707125400.0 | timestamp_custom("%Y-%m-%d %H:%M:%S", default="Valore default") }} {# 2024-02-05 10:30:00 #}
{{ 1707125400.0 | timestamp_custom("%Y-%m-%d %H:%M:%S", local=False, default="Valore default") }} {# 2024-02-05 09:30:00 #}
{{ 1707125400.0 | timestamp_custom("%Y-%m-%d %H:%M:%S", local=True, default="Valore default") }} {# 2024-02-05 10:30:00 #}

{{ errato | timestamp_custom("%Y-%m-%d %H:%M:%S", local=False, default="Valore default") }}  {# Valore default #}
{{ errato | timestamp_custom("%Y-%m-%d %H:%M:%S", local=True, default="Valore default") }}   {# Valore default #}
{{ errato | timestamp_custom("%Y-%m-%d %H:%M:%S", default="Valore default") }}               {# Valore default #}

{{ errato | timestamp_custom("%Y-%m-%d %H:%M:%S") }}   {# Template error #}
⬇️ | timestamp_local(default): è un filtro che converte un timestamp UNIX in una stringa nel formato ISO con fuso orario.

E’ possibile applicare un valore predefinito per evitare che il filtro generi un errore nel caso in cui la conversione del timestamp UNIX in formato ISO fallisca. In questo modo, se la conversione non è possibile, il filtro restituirà il valore predefinito invece di generare un errore.

{{ 1707125400.0 | timestamp_local }}            {# 2024-02-05T10:30:00+01:00 #}
{{ errato | timestamp_local }}            {# Template error #}

{{ 1707125400.0 | timestamp_local('Valore default') }} {# 2024-02-05T10:30:00+01:00 #}
{{ errato | timestamp_local('Valore default') }}       {# Valore default #}
⬇️ | timestamp_utc(default): è un filtro che converte un timestamp UNIX in una stringa nel formato ISO senza fuso orario (UTC).

E’ possibile applicare un valore predefinito per evitare che il filtro generi un errore nel caso in cui la conversione del timestamp UNIX in formato ISO fallisca. In questo modo, se la conversione non è possibile, il filtro restituirà il valore predefinito invece di generare un errore.

{{ 1707125400.0 | timestamp_utc }}      {# 2024-02-05T09:30:00+00:00 #}
{{ errato | timestamp_utc }}            {# Template error #}

{{ 1707125400.0 | timestamp_utc('Valore default') }} {# 2024-02-05T09:30:00+00:00 #}
{{ errato | timestamp_utc('Valore default') }}       {# Valore default #}

To/From JSON

Un oggetto JSON è una collezione di coppie chiave-valore racchiuse tra parentesi graffe {}. Le chiavi sono sempre stringhe, mentre i valori possono essere stringhe, numeri, booleani, array, oggetti JSON annidati o null. La sintassi per definire un oggetto JSON in Jinja2 è identica a quella di un dizionario ma le stringhe devono essere racchiuse tra virgolette doppie ", non tra virgolette singole '.

Dettaglio
⬇️ | to_json: è un filtro che prendere un oggetto (come un dizionario, una lista, una tupla, ecc.) e lo converte in una stringa JSON valida.

Semplifica notevolmente la formattazione di una stringa JSON, specialmente quando si tratta di gestire caratteri speciali e escape di caratteri. Questo filtro si occupa automaticamente di codificare correttamente i caratteri speciali all’interno della stringa JSON, garantendo che il risultato sia correttamente formattato e pronto per essere utilizzato.

Accetta argomenti booleani aggiuntivi:

  • pretty_print: Questo argomento, se impostato su True, formatta il JSON con un rientro di 2 spazi per renderlo più leggibile dall’uomo. Ciò significa che il JSON risultante sarà formattato con una struttura indentata, facilitando la lettura e la comprensione. Se pretty_print è False o non specificato, il JSON verrà restituito senza alcuna formattazione aggiuntiva.
  • sort_keys: Questo argomento, se impostato su True, ordina le chiavi dell’oggetto JSON in ordine alfabetico. Ciò garantisce che la stringa JSON risultante sia coerente per lo stesso input, indipendentemente dall’ordine in cui sono state definite le chiavi nell’oggetto originale. Se sort_keys è False o non specificato, le chiavi verranno mantenute nell’ordine in cui sono state definite nell’oggetto originale.ù
  • ensure_ascii=True: Assicura che tutti i caratteri non ASCII vengano convertiti in sequenze di escape Unicode nella stringa JSON risultante.
{%set persona = {'nome': 'Marco', 'età': 36} %}
{{ persona | to_json }}                       {# {"nome":"Marco","età":36} #}
{{ "Ciao 😊" | to_json(ensure_ascii=True) }} {# "Ciao \ud83d\ude0a" #}

{{ persona | to_json(pretty_print=false, sort_keys=True) }} {# {"età":36,"nome":"Marco"} #}
{{ persona | to_json(pretty_print=True, sort_keys=True) }}
{# 
{
  "età": 36,
  "nome": "Marco"
}
#}
⬇️ | from_json: è un filtro che prendere una stringa JSON e lo converte in un ogetto equivalente.

Una volta che la stringa JSON è stata deserializzata in un oggetto utilizzando il filtro, è possibile utilizzare i dati all’interno. Ad esempio, si potrebbe assegnare l’oggetto deserializzato a una variabile e accedere ai suoi attributi o elementi come si farebbe con qualsiasi altro oggetto.

{% set stringa_json = '{"nome": "Marco", "età": 36}' %}
{% set ogetto = stringa_json | from_json %}
{{ ogetto }}         {# {'nome': 'Marco', 'età': 36} #}
{{ ogetto.nome }}    {# Marco  #}
{{ ogetto['nome'] }} {# Marco  #}

Versione

⬇️ version(): restituisce un oggetto AwesomeVersion per il valore fornito tra parentesi. Questo oggetto consente di eseguire confronti tra versioni.

È anche disponibile come filtro, e può essere utilizzato direttamente su una stringa per convertirla in un oggetto AwesomeVersion.

{# sensor.home_assistant_versions 2024.2.1 #}
{{ version(states('sensor.home_assistant_versions')) < "1900.0.5.1" }} {# False #}
{{ version(states('sensor.home_assistant_versions')).patch }}          {# 1 #}
{{ version(states('sensor.home_assistant_versions')).minor }}          {# 2 #}
{{ version(states('sensor.home_assistant_versions')).major }}          {# 2024 #}

{{ states('sensor.home_assistant_versions')| version }}                {# Filtro: 2024.2.1 #}
{{ states('sensor.home_assistant_versions')| version < "1900.0.5.1" }} {# Filtro: False #}

Issue

⬇️ issues(): restituisce un elenco di tutti i problemi aperti, rappresentati come una mappatura di tuple che associa il dominio e issue_id all’oggetto problema corrispondente.
{{ issues() }}
{# {('homeassistant', 'deprecated_yaml_ping'): {'created': '2023-12-07T07:18:25.832025+00:00', 'dismissed_version': None, 'domain': 'homeassistant', 'is_persistent': False, 'issue_id': 'deprecated_yaml_ping'}, ...... } #}
⬇️ issue(domain, issue_id): restituisce un problema specifico per il dominio e issue_id forniti, rappresentati come un dizionario.
{{ issue('homeassistant','deprecated_yaml_ping') }} {# {  "created": "2023-12-07T07:18:25.832025+00:00", "dismissed_version": null, "domain": "homeassistant", "is_persistent": false, "issue_id": "deprecated_yaml_ping" } #}

{{ issue('homeassistant','deprecated_yaml_ping')['created'] }} {# 2023-12-07T07:18:25.832025+00:00 #}

Distanza

È possibile calcolare la distanza in chilometri e determinare quale entità è più vicina a una zona specifica, coordinata, casa o entità.

⬇️ distance(): consente di misurare la distanza in chilometri.

Se viene passata solo una posizione, Home Assistant calcolerà la distanza dalla posizione di casa.

{{ distance(123.45, 123.45) }}                    {# cordinata distanza da casa es. 11964.533873 #}
{{ distance('device_tracker.motorola_edge_40') }} {# entità distanza da casa es. 5.547777 #}
{{ distance('device_tracker.motorola_edge_40') }} {# entità distanza da casa es. 5.547777 #}
{{ distance('zone.lavoro_marco') }}               {# zona distanza da casa 15.535477 #}
{{ distance('person.marco') }}                    {# person distanza da casa 5.547777 #}
{{ distance(states.device_tracker.motorola_edge_40) }} {# ogetto di stato distanza da casa es. 5.547777 #}

Se viene specificata un’altra posizione, verrà considerata come punto di riferimento per il calcolo della distanza.

{{ distance(123.45, 123.45, 'device_tracker.motorola_edge_40') }} {# entità distanza da cordinata es. 11964.533873 #}
{{ distance('device_tracker.motorola_edge_40', 'device_tracker.samsung_s21') }} {# distanza tra due entità es. 0.011454 #}
{{ distance('person.marco', 'device_tracker.samsung_s21') }} {# distanza tra due entità es. 0.011454 #}
⬇️ closest(): consente di trovare l’entità più vicina.

Questa funzione restituisce un oggetto di stato e può essere utilizzata anche come filtro.

Se viene passata solo una posizione, troveranno l’entità più vicina alla posizione dell’Home Assistant.

{{ closest(states) }} {# tra tutte le entità (ogetti di stato) #}
{{ closest(states).name }} {# tra tutte le entità (ogetti di stato, name) #}

{{ closest(states.device_tracker) }} {# per un dominio specifico (ogetti di stato) #}
{{ closest(states.device_tracker).name }} {# per un dominio specifico (ogetti di stato, name) #}

{{ closest('group.famiglia') }} {# entità di un gruppo #}
{{ closest(expand('group.famiglia')).name }} {# entità di un gruppo, name #}

{{ closest(states.group.famiglia) }} {# entità di un gruppo #}
{{ closest(states.group.famiglia).state }} {# entità di un gruppo, state #}

{{ 'group.famiglia' | closest }} {# esempio filtro #}

Se viene specificata un’altra posizione, verrà considerata come punto di riferimento per il calcolo della distanza.

{{ closest(23.456, 23.456, 'group.famiglia') }} {# tra cordinata e gruppo #}
{{ closest(23.456, 23.456, 'group.famiglia').name }} {# tra cordinata e gruppo, name #}

{{ closest('zone.lavoro', 'group.famiglia') }} {# tra zona(entità) e gruppo #}
{{ closest('zone.lavoro', 'group.famiglia').name }} {# tra zona(entità) e gruppo, name #}

{{ closest(states.zone.lavoro, 'group.famiglia') }} {# tra zona(ogetto di stato) e gruppo #}
{{ closest(states.zone.lavoro, states).name }} {# tra zona(ogetto di stato) e gruppo, name #}

{{ 'group.famiglia' | closest(states.zone.lavoro) }} {# esempio filtro #}

È possibile specificare una lista di entità da controllare per la loro vicinanza.Poiché l’ultimo argomento ha un valore implicito expande, può accettare qualsiasi sequenza iterabile di stati o ID di entità ed espandere i gruppi per includere tutte le entità pertinenti nella verifica della vicinanza.

{{ closest(['group.famiglia', states.device_tracker]) }} {# gruppo e dominio distanti da casa #}
{{ closest(23.456, 23.456, ['group.famiglia', states.device_tracker]) }} {# gruppo e dominio distanti da cordinate #}
{{ closest(states.zone.lavoro, ['group.famiglia', states.device_tracker]) {# gruppo e dominio distanti da entità #}

{{ ['group.famiglia', states.device_tracker] | closest }} {# esempio filtro da casa#}
{{ ['group.famiglia', states.device_tracker] | closest(23.456, 23.456) }} {# esempio filtro #}

Funzioni numeriche e filtri

Le funzioni numeriche e i filtri generano un errore se l’input non è un numero valido, facoltativamente è possibile specificare un valore di default che verrà invece restituito.

⬇️ is_number: restituisce True se l’input è un numero, altrimenti restituisce False.

È da notare che la funzione analizza un valore booleano True e restituisce True. Tuttavia, se viene passata la stringa "True", verrà interpretata come False.

{{ 5 | is_number }}     {# fitro: True #}
{{ 5.5 | is_number }}   {# fitro: True #}
{{ 'non' | is_number }} {# fitro: False #}

{{is_number(5) }}       {# True #}
{{is_number('non') }}   {# False#}

{{ True | is_number }}  {# True #}
{{ False | is_number }} {# True #}
{{ 'True' | is_number }} {# False #}
{{ 'False' | is_number }} {# False #}

{{ states('sensor.0x00158d0006f78450_illuminance_lux') | is_number }} {# fitro #}
{{ is_number(states('sensor.0x00158d0006f78450_illuminance_lux')) }}
⬇️ float: verrà convertito l’input in un numero decimale. E’ possibile usarlo sia come funzione che come filtro.

In entrambi i casi, verrà convertito l’input in un float. Se la conversione fallisce, verrà restituito il default specificato; tuttavia, se il default non è specificato e la conversione non riesce, verrà generato un errore.

{{  float(5) }} {# 5.0 #}
{{ float("non_numero") }} {# Template error #}

{{  float(5, default="Numero non valido!") }} {# 5.0 #}
{{  float('non numero', default="Numero non valido!") }} {# Numero non valido! #}

{{ states('sensor.0x00158d0006f78450_illuminance_lux') | float(0) }}  {# filtro con default #}  
{{ float(states('sensor.0x00158d0006f78450_illuminance_lux'), 0 ) }}  {# funzione con default #}
⬇️ int: verrà convertito l’input in un numero intero. E’ possibile usarlo sia come funzione che come filtro.

In entrambi i casi, verrà convertito l’input in un int. Se la conversione fallisce, verrà restituito il default specificato; tuttavia, se il default non è specificato e la conversione non riesce, verrà generato un errore.

{{ int(5) }} {# 5 #}
{{ int("non_numero") }} {# Template error #}

{{ int(5, default="Numero non valido!") }} {# 5 #}
{{ int('non numero', default="Numero non valido!") }} {# Numero non valido! #}

{{ states('sensor.0x00158d0006f78450_illuminance_lux') | int(0) }}  {# filtro con default #}  
{{ int(states('sensor.0x00158d0006f78450_illuminance_lux'), 0 ) }}  {# funzione con default #}
⬇️ bool(value, default): converte il valore in un valore booleano (vero o falso).

Può anche essere usato come filtro.

{{ bool(True) }} {{ True | bool }}   {# True #}
{{ bool(False) }} {{ False | bool }} {# False #}
{{ bool(True, 'Valore Errato') }} {{ True | bool('Valore errato') }}        {# es. default True #}
{{ bool('errato','Valore Errato') }} {{ 'Errato' | bool('Valore errato') }} {# es. default Valore errato #}

Se il valore è uno dei seguenti, la funzione restituirà True:

  • Il valore booleano True stesso.
  • Qualsiasi numero diverso da zero, sia esso un intero o un numero decimale (float).
  • Le stringhe “true”, “yes”, “on”, “enable” e “1” (senza distinguere tra maiuscole e minuscole).
{{ bool(True) }}
{{ bool(1) }}
{{ bool(1.5) }}
{{ bool('true') }}
{{ bool('True') }}
{{ bool('yes') }}
{{ bool('on') }}
{{ bool('enable') }}
{{ bool('1') }}
{# Tutti restituiscono True #}

Se il valore è uno dei seguenti, la funzione restituirà False:

  • Il valore booleano False stesso.
  • Il numero zero (0), sia esso un intero o un numero decimale (float).
  • Le stringhe “false”, “no”, “off”, “disable” e “0” (senza distinguere tra maiuscole e minuscole).
{{ bool(False) }}
{{ bool(0) }}
{{ bool(0.0) }}
{{ bool('false') }}
{{ bool('False') }}
{{ bool('no') }}
{{ bool('off') }}
{{ bool('disable') }}
{{ bool('0') }}
{# Tutti restituiscono False #}

Se il valore non rientra in nessuna delle categorie elencate, la funzione restituirà il valore predefinito specificato. Se non viene specificato un valore predefinito, verrà generato un errore.

{{ bool('errato', 'Non boolean') }} {# Non boolean #}
{{ bool('errato') }}                {# Template error #}

Come float e int, la funzione bool ha una forma di filtro.

L’uso di none come valore predefinito è particolarmente utile in combinazione con il filtro “if” immediato, poiché può gestire tutti e tre i casi possibili in una sola riga.

{{ bool('errato', none) }} {# Non Boolean #}

{% if bool('errato', none) %}
Valore bool
{% else %}
Valore non Boolean
{% endif %}
{# Valore non Boolean #}
⬇️ log(value, base, default): calcola il logaritmo dell’input.

Se il valore base o value non può essere convertito in un float, la funzione restituirà il valore default specificato.

Se la base viene omessa, viene utilizzata per default la costante matematica e, approssimativamente uguale a 2.71828.

Questa funzione può essere utilizzata anche come filtro.

{{ log('a', 10, 'Valore errato') }}    {# Valore errato #}
{{ log('100', '10', 'Valore errato') }}{# 2.0 #}
{{ log( 100 ) }}                       {# 4.605170185988092 #}

{{ 100 | log(10) }}                    {# 2.0 #}
{{ 'a' | log(10, 'Valore errato') }}   {# Valore errato #}
{{ 100 | log(10, 'Valore errato') }}   {# 2.0 #}
{{ '100' | log(10, 'Valore errato') }} {# 2.0 #}
{{ 100 | log() }}                      {# 4.605170185988092 #}
{{ 100 | log(e) }}                     {# 4.605170185988092 #}
⬇️ sin(value, default): calcola il seno dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ sin('a', 'Valore errato') }}    {# Valore errato #}
{{ sin('100', 'Valore errato') }}  {# -0.5063656411097588 #}
{{ sin( 100 ) }}                   {# -0.5063656411097588 #}

{{ 100 | sin }}                    {# -0.5063656411097588 #}
{{ 'a' | sin('Valore errato') }}   {# Valore errato #}
{{ 100 | sin('Valore errato') }}   {# -0.5063656411097588 #}
{{ '100' | sin('Valore errato') }} {# -0.5063656411097588 #}
⬇️ cos(value, default): calcola il coseno dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ cos('a', 'Valore errato') }}    {# Valore errato #}
{{ cos('100', 'Valore errato') }}  {# 0.8623188722876839 #}
{{ cos( 100 ) }}                   {# 0.8623188722876839 #}

{{ 100 | cos }}                    {# 0.8623188722876839 #}
{{ 'a' | cos('Valore errato') }}   {# Valore errato #}
{{ 100 | cos('Valore errato') }}   {# 0.8623188722876839 #}
{{ '100' | cos('Valore errato') }} {# 0.8623188722876839 #}
⬇️ tan(value, default): calcola la tangente dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ tan('a', 'Valore errato') }}    {# Valore errato #}
{{ tan('100', 'Valore errato') }}  {# -0.5872139151569291 #}
{{ tan( 100 ) }}                   {# -0.5872139151569291 #}

{{ 100 | tan }}                    {# -0.5872139151569291 #}
{{ 'a' | tan('Valore errato') }}   {# Valore errato #}
{{ 100 | tan('Valore errato') }}   {# -0.5872139151569291 #}
{{ '100' | tan('Valore errato') }} {# -0.5872139151569291 #}
⬇️ asin(value, default): calcola l’arcoseno dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ asin('a', 'Valore errato') }}    {# Valore errato #}
{{ asin('0.5', 'Valore errato') }}  {# 0.5235987755982989 #}
{{ asin( 0.5 ) }}                   {# 0.5235987755982989 #}

{{ 0.5 | asin }}                    {# 0.5235987755982989 #}
{{ 'a' | asin('Valore errato') }}   {# Valore errato #}
{{ 0.5 | asin('Valore errato') }}   {# 0.5235987755982989 #}
{{ '0.5' | asin('Valore errato') }} {# 0.5235987755982989 #}
⬇️ acos(value, default): calcola l’arcocoseno dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ acos('a', 'Valore errato') }}    {# Valore errato #}
{{ acos('0.5', 'Valore errato') }}  {# 1.0471975511965979 #}
{{ acos( 0.5 ) }}                   {# 1.0471975511965979 #}

{{ 0.5 | acos }}                    {# 1.0471975511965979 #}
{{ 'a' | acos('Valore errato') }}   {# Valore errato #}
{{ 0.5 | acos('Valore errato') }}   {# 1.0471975511965979 #}
{{ '0.5' | acos('Valore errato') }} {# 1.0471975511965979 #}
⬇️ atan(value, default): calcola l’arcotangente dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ atan('a', 'Valore errato') }}    {# Valore errato #}
{{ atan('100', 'Valore errato') }}  {# 1.0471975511965979 #}
{{ atan( 100 ) }}                   {# 1.0471975511965979 #}

{{ 100 | atan }}                    {# 1.0471975511965979 #}
{{ 'a' | atan('Valore errato') }}   {# Valore errato #}
{{ 100 | atan('Valore errato') }}   {# 1.0471975511965979 #}
{{ '100' | atan('Valore errato') }} {# 1.0471975511965979 #}
⬇️ atan2(y, x, default): calcola arcotangente quadrante dell’input.

Se i volori x o y non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ atan2('a', 50 , 'Valore errato') }}    {# Valore errato #}
{{ atan2('100', 'a', 'Valore errato') }}  {# Valore errato #}
{{ atan2('100', '50', 'Valore errato') }} {# 1.1071487177940904 #}
{{ atan2( 100, 50 ) }}                    {# 1.1071487177940904 #}

{{ 100 | atan2(50) }}                     {# 1.1071487177940904 #}
{{ 'a' | atan2(50, 'Valore errato') }}    {# Valore errato #}
{{ 100 | atan2(50, 'Valore errato') }}    {# 1.1071487177940904 #}
{{ '100' | atan2(50, 'Valore errato') }}  {# 1.1071487177940904 #}
⬇️ sqrt(value, default): calcola la radice quadrata dell’input.

Se il valore non può essere convertito in un float, la funzione restituirà il valore default specificato.

Questa funzione può essere utilizzata anche come filtro.

{{ sqrt('a', 'Valore errato') }}    {# Valore errato #}
{{ sqrt('100', 'Valore errato') }}  {# 10 #}
{{ sqrt( 100 ) }}                   {# 10 #}

{{ 100 | sqrt }}                    {# 10 #}
{{ 'a' | sqrt('Valore errato') }}   {# Valore errato #}
{{ 100 | sqrt('Valore errato') }}   {# 10 #}
{{ '100' | sqrt('Valore errato') }} {# 10 #}
⬇️ max([x, y, ...]): restituisce l’elemento più grande in una sequenza.

Utilizza gli stessi parametri del filtro max.

{{ max(20, 10, 30, 50) }}         {# 50 #}
{{ max('20', '10', '30', '50') }} {# 50 #}
{{ max('a', 'd', 'c', '50') }}    {# d #}
{{ max(['a', 'd', 'c', '50']) }}  {# d #}
⬇️ min([x, y, ...]): restituisce l’elemento più piccolo in una sequenza.

Utilizza gli stessi parametri del filtro min.

{{ min(20, 10, 30, 50) }}    {# 10 #}
{{ min('20', '10', '30', '50') }}    {# 10 #}
{{ min('a', 'd', 'c', '50') }}    {# 50 #}
{{ min(['a', 'd', 'c', '50']) }}    {# 50 #}
⬇️ average([x, y, ...], default): restituisce il valore medio della sequenza di una sequenza.

Se la lista è vuota o contiene valori non numerici, restituisce il valore predefinito. Se il valore predefinito è omesso e la lista è vuota o contiene valori non numerici, genera un errore.

Questa funzione può anche essere utilizzata come filtro.

{{ average(20, 10, 30, 50) }}                         {# 27.5 #}
{{ average(['a', 'd', 'c', '50'], 'Valore errato') }} {# Valore errato #}

{{ [20, 10, 30, 50] | average }}                      {# 27.5 #}
{{ ['a', 'd', 'c', '50'] | average('Valore errato') }}{# Valore errato #}
⬇️ median([x, y, ...], default): restituisce il valore centrale o la media dei due valori centrali, a seconda se la sequenza è ordinata o meno.

Se la lista è vuota o contiene valori non numerici, restituisce il valore predefinito. Se il valore predefinito è omesso e la lista è vuota o contiene valori non numerici, genera un errore.

Questa funzione può anche essere utilizzata come filtro.

{{ median(20, 10, 30, 50) }}                         {# 25 #}
{{ median(['a', 'd', 'c', '50'], 'Valore errato') }} {# Valore errato #}

{{ [20, 10, 30, 50] | median }}                      {# 25 #}
{{ [10, 30, 50] | median }}                           {# 30 #}
{{ ['a', 'd', 'c', '50'] | median('Valore errato') }}{# Valore errato #}
⬇️ median([x, y, ...], default): restituisce il valore moda statistico, che è l’occorrenza più frequente, all’interno della sequenza fornita.

Se la lista è vuota, restituisce il valore predefinito. Se il valore predefinito viene omesso e la lista è vuota, potrebbe generare un errore.

Questa funzione può anche essere utilizzata come filtro.

{{ statistical_mode(20, 10, 10, 30, 50) }}                           {# 10 #}
{{ statistical_mode(['a', 'd', '50', 'c', '50'], 'Valore errato') }} {# 50 #}
{{ statistical_mode([], 'Valore errato') }}                          {# Valore errato #}

{{ [20, 10, 30, 50] | statistical_mode }}                      {# 20 #}
{{ [10, 30, 30, 150] | statistical_mode }}                     {# 30 #}
{{ ['a', 'd', 'c', '50'] | statistical_mode('Valore errato') }}{# Valore errato #}

Elaborare dati grezzi

I dati grezzi, o dati non elaborati, sono dati che non sono stati processati, filtrati o trasformati in alcun modo, sono la forma originale dei dati, talvolta rappresentati in un formato base come byte o bit, senza alcuna interpretazione o struttura applicata. Queste funzioni vengono utilizzate per elaborare i valori grezzi in formato di byte in valori di tipo Python nativo o viceversa e fanno uso della libreria struct di Python 3.

⬇️ pack(value, format_string): è utilizzata per convertire un tipo di dato nativo in un oggetto di tipo byte.

Questo processo avviene utilizzando un modello di formattazione specificato dalla stringa format_string, che determina come il valore deve essere convertito in byte. Se si verifica un errore durante il processo di conversione o se la stringa di formato non è valida, la funzione restituirà None per indicare che si è verificato un problema.

Questa funzione può anche essere utilizzata come filtro.

esempio con formato di conversione come intero
{{ pack(42, 'i') }}  {# b'*\x00\x00\x00' #}
{{ 42 | pack('i') }} {# b'*\x00\x00\x00' #}
⬇️ unpack(value, format_string, offset=0): è utilizzato per convertire un oggetto di tipo byte in un oggetto di tipo Python nativo.

Quando si utilizza, è possibile specificare un modello di formattazione (format_string) che indica come interpretare i byte e un parametro opzionale offset che indica da quale posizione all’interno dell’oggetto di byte iniziare a leggere i dati. È importante notare che se si verifica un errore durante il processo di conversione o se il modello di formattazione non è valido, la funzione restituirà None.

Questa funzione può anche essere utilizzata come filtro.

{% set a = 42 | pack(">I") %}

{{ unpack(a, '>I') }}            {# 42 #}
{{ unpack(a, '>H', offset=1) }}  {# 0 #}

{{ a | unpack(">I") }}           {# 42 #}
{{ a | unpack(">H", offset=1) }} {# 0 #}

Conclusione

Spero che questo titanico lavoro di Marco Picardo ti possa essere d’aiuto quanto merita in quanto è stata davvero un’impresa colossale per lui stendere questo testo e credo che possa essere davvero utile sia per imparare che ai più esperti come riferimento rapido durante la stesura del proprio codice.

Un sentito ringraziamento a Marco da parte mia (Henrik) per l’impegno, la dedizione e la pignoleria con cui ha steso questo articolo, che intende anche tenere aggiornato man mano che escono nuove funzioni con gli aggiornamenti di Home Assistant!

Ti va di darmi una mano?

Il contenuto di questo sito è completamente gratuito senza pubblicità invasive e il fine non è certo guadagnare …ma mantenere un sito ha un costo. Se ti va di darmi una mano per sostenere le spese o ti va di sostenere questo progetto hai le seguenti modalità:


  • Donazione con Paypal:

  • Regalami un caffè su Buymeacoffee:


  • Effettua i tuoi acquisti Amazon a partire da QUESTO LINK (o tramite i prodotti sotto)

  • Effettuare i tuoi acquisti AliExpress usando QUESTO LINK

Questo articolo ha un commento

  1. Corrado

    Immane lavoro, molto interessante ed esaustivo per chi vuole approfondire.
    Personalmente mi mancava una guida così dettagliata sull’argomento !
    Grazie Henrik

Rispondi

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.