I Template, parte due: i modelli nelle automazioni

Leggi questo articolo grazie alle donazioni di Giacomo Tacconi, Roberto Pinna, Vincenzo Lapenta, Simone Pignatti, Fabrizio Calabrese, Roberto Vazzoler, Michele Sartori.
♥ Partecipa anche tu alle donazioni: sostieni SaggiaMente, sostieni le tue passioni!

Nella parte uno sui template abbiamo imparato le loro principali caratteristiche, la sintassi di base e le espressioni, ora passiamo alla pratica con alcuni esempi di modelli (se preferite il termine italiano) applicati a casi e necessità reali nella scrittura di automazioni.

Esempio 1: notifica aggiornamenti

- alias: Notifica aggiornamento
  trigger:
    - platform: state
      entity_id: updater.updater
  action:
    service: notify.ios_iphone_di_alberto
    data_template:
      message: "È disponibile Home Assistant {{ states.updater.updater.state }}."

Il template scritto nel campo message permette di inserire “dinamicamente” il numero della nuova versione nella notifica. L’entità updater.updater si genera quando è disponibile un’aggiornamento di Hassio e presenta il numero di versione come suo stato. Notate che quando è richiesta l’esecuzione di un template all’interno dei “dati” passati ad una chiamata di un servizio è obbligatorio l’uso di data_template: invece del tradizionale data:, come descritto nella documentazione.

Esempio 2: backup automatico

- alias: Backup Automatico
  trigger:
    platform: time
    at: '3:00:00'
  condition:
    condition: time
    weekday:
      - mon
  action:
    service: hassio.snapshot_full
    data_template:
      name: Automated Backup {{ now().strftime('%Y-%m-%d') }}

Questo è un esempio analogo al precedente, si tratta sempre dell’uso di un modello per determinare i dati da passare ad una chiamata di un servizio. In questo caso è un’automazione che esegue un backup completo di hassio (sfruttando l’utility Snapshot di Hassio) alle 3 del mattino di ogni lunedì. Il nome del file di backup sarà scritto in funzione del momento in cui viene creato, come ad esempio Automated Backup 2018-10-01, grazie all’uso della funzione strftime() di Python.

Blackout

- alias: Blackout
  trigger:
    platform: template
    value_template: "{{ (states.sensor.nut_ups_status_data.state | truncate(2,false,'',0)) == 'OB' }}"
  action:
    - service: light.turn_on
      data:
        entity_id: light.gateway_light_7811dcb0727e
        color_name: red
        brightness_pct: 100
    - wait_template: "{{ (states.sensor.nut_ups_status_data.state | truncate(2,false,'',0)) == 'OL' }}"
    - service: light.turn_off

Qui le cose cominciano a complicarsi un pochino. L’automazione qui sopra entra in gioco in caso di un blackout in casa, eseguendo queste azioni:

  • segnala l’assenza di corrente elettrica accendendo la luce del gateway Xiaomi al 100% di luminosità e di colore rosso (il mio gateway è collegato ad un UPS, perciò rimane alimentato)
  • tornata la corrente spegne le luci che si sono accese (comportamento classico delle Philips Hue, purtroppo)

L’informazione dell’assenza di corrente elettrica arriva da un UPS collegato via usb ad un NAS Synology, che funge da NUT server. Il component NUT sensor ci permette di raccogliere questa informazione in HA, sotto forma di una serie di sensori, come quelli mostrati qui di seguito:

Quello utilizzato nell’automazione è il primo, chiamato “NUT UPS Status Data”. Il suo stato corrisponde ad una stringa che contiene alcune informazioni, ma a noi interessano solo le prime due lettere per ora, cioè OL (On Line). Questo stato diventerà OB (On Battery) durante il blackout, per poi tornare in OL con il ritorno della corrente.

{{ (states.sensor.nut_ups_status_data.state | truncate(2,false,'',0)) == 'OB' }}

Quello qui sopra è il contenuto del value_template dell'automazione Blackout e ci dà l'occasione di parlare dei filtri di Jinjia: si tratta di funzioni che “filtrano” – appunto – il risultato del template che gli viene passato mediante l’uso del carattere “|”, detto pipe o barra verticale. Vediamo come si modifica l’informazione aggiungendo passo passo i singoli elementi:

Template Risultato
{{ states.sensor.nut_ups_status_data.state }} OL LB
{{ states.sensor.nut_ups_status_data.state | truncate(2,false,'',0) }} OL
{{ (states.sensor.nut_ups_status_data.state | truncate(2,false,'',0)) == 'OB' }} False

Il filtro truncate “tronca” – guarda caso – la stringa completa che gli viene fornita (ovvero OL LB) dopo due caratteri, dando come risultato (OL). Questo può essere confrontato tramite == per trasformare il valore in un booleano vero/falso che innesca il Trigger Template all'assenza di corrente. Gli argomenti forniti al filtro truncate si trovano tra parentesi, sono quattro e separati da virgole:

  1. il primo è un numero che indica dopo quanti caratteri dall'inizio della stringa avverrà la troncatura;
  2. il secondo è un booleano e viene utilizzato per far capire al sistema che vogliamo una troncatura netta (true) o che completi l’ultima parola (false);
  3. il terzo serve a specificare un segno di ellissi differente da quello di default (…) ed è racchiuso tra due apici;
  4. il quarto è un numero che può indicare un minimo di caratteri che deve avere una parola per non essere troncata.

Un modello simile è usato anche nel wait_template, che attende che la corrente torni per proseguire nell’esecuzione della fase action.

Tra gli altri filtri disponibili uno che si usa spesso è round(n), dove n è il numero di cifre decimali che vogliamo ottenere. Vediamone un esempio:

Template Risultato
{{ 22.57575756422 | round(0) }} 23
{{ 22.57575756422 | round(1) }} 22.6
{{ 22.57575756422 | round(5) }} 22.5757576

Corsa

- alias: Corsa
  trigger:
    platform: event
    event_type: click
    event_data:
      entity_id: binary_sensor.switch_158d0001f3ad33
      click_type: double
  action:
    - service_template: >
        {% if is_state("input_boolean.corsa", "off") %}
          input_boolean.turn_on
        {% else %}
          input_boolean.turn_off
        {% endif %}
      entity_id: input_boolean.corsa
    - service: notify.ios_iphone_di_alberto
      data_template:
        title: "Corsa"
        message: >
          {% if is_state("input_boolean.corsa", "on") %} Alby è uscito a correre.
          {% else %} Alby è rientrato dalla corsa.
          {% endif %}

Altra “new entry” nelle nostre competenze: il ciclo if. Questa è un’automazione che ho usato in passato per segnalare al sistema che sono andato a correre, ma dal momento che spesso non porto il telefono con me HA non è in grado di "capire" che sono uscito di casa.  Quindi innesco manualmente l'automazione con un doppio clic su un pulsante Xiaomi:

  • se lo stato del booleano corsa era su off al momento del clic, questo viene impostato su on mediante il servizio input_boolean.turn_on;
  • viene quindi inviata una notifica “Alby è uscito a correre.” se lo stato del booleano è su on (appena cambiato dal servizio).

Oppure (else):

  • se lo stato del booleano corsa era su on al momento del click, questo viene impostato su off mediante il servizio input_boolean.turn_off;
  • viene quindi inviata una notifica “Alby è rientrato dalla corsa.” se lo stato del booleano è su off (appena cambiato dal servizio).

In questo caso l’uso del modello mi permette di condensare le mie precedenti automazioni “Corsa_ON” e “Corsa_OFF” in una singola. Notiamo anche l’uso di service_template:, che è obbligatorio al pari del data_template: citato in precedenza qualora si intenda utilizzare dei modelli nel contenuto.

Faccio presente che l’utilizzo di un template nel primo caso (nella parte del primo servizio della fase action che richiede il service_template) potrebbe essere evitato grazie al servizio input_boolean.toggle: che alterna gli stati ma richiede di conoscere lo stato iniziale del booleano per inviare notifiche corrette.

Dopo qualche test mi sono reso conto che la comunicazione tra il bottone Xiaomi e il Gateway era inaffidabile, a causa della distanza tra i due componenti: dal momento che la copertura Wi-Fi è sufficiente, ora utilizzo un Dash Button grazie all’addon Dasshio.

E qui concludiamo la seconda parte di questa serie di articoli: nella prossima (ed ultima) parte utilizzeremo i modelli per creare dei sensori e degli interruttori, e soprattutto vi parlerò dell’automation templating, una feature molto interessante e potente che ci permetterà di creare un semplice sistema di allarme con notifiche “adattive”.

Autore:
Alberto Zamboni (@albyzambo)

Revisore:
Davide (@daxda)
Maurizio Natali (@simplemal)

SmartHome Channel

Special Team - I SaggiUtenti del canale #SmartHome presente sul nostro Slack uniti per creare guide e recensioni dedicate all'automazione. Partecipa anche tu entrando nel gruppo effettuando una donazione dal SaggioSupporto.

Commenti controllati Oltre a richiedere rispetto ed educazione, vi ricordiamo che tutti i commenti con un link entrano in coda di moderazione e possono passare diverse ore prima che un admin li attivi. Anche i punti senza uno spazio dopo possono essere considerati link causando lo stesso problema.