Al momento stai visualizzando State Enforcer: assicurati che le luci e le prese si accendano o si spengano davvero!

State Enforcer: assicurati che le luci e le prese si accendano o si spengano davvero!

Quante volte hai dato il comando di spegnere una luce o una presa smart in Home Assistant, ma poi scopri che in realtà è rimasta accesa? Magari a causa di un problema di connessione, un’interferenza o semplicemente perché il dispositivo non ha ricevuto correttamente il comando. Questa dovrebbe essere una funzione base di Home Assistant, ma purtroppo non c’è un controllo nativo che verifichi se un’entità ha effettivamente cambiato stato dopo il comando. Ma ora c’è State Enforcer!

State Enforcer si applica a qualunque dispositivo come luci o prese comandate ma ci sono diversi casi che rendono questo approccio quasi obbligatorio. Pensa infatti se il problema si verificasse spegnendo l’irrigazione che anzi che andare per 20 minuti andasse per 10 ore finché non ti accorgi di avere un lago in giardino quando torni a casa dal lavoro…. Oppure non si spenga il boiler raggiunta la temperatura. O ancora le luci del giardino restassero accese anche per tutto il giorno, finita la notte. Un bello spreco no?

Gestione di dispositivi critici
Ho fatto gli esempi del boiler o dell’irrigazione perché so che tanti gestiscono in tal modo queste applicazioni. Secondo me, però, non è corretto automatizzare degli oggetti critici come questi tramite Home Assistant, tramite una connessione wifi in particolar modo. Troppe cose possono non funzionare come devono e compromettere la sicurezza di casa, anche usando questo script (che comunque alza di tanto la sicurezza dell’azione).
Molto meglio, invece, un controller locale, ad esempio basato su ESPHOME, che spenga e accenda la resistenza in funzione della temperatura ma lo faccia localmente, informando Home Assistant dello stato così da permettere ulteriori automazioni. Meglio ancora avere anche una sicurezza meccanica intrinseca. Ad esempio nel caso del boiler un termofusibile che, oltre una certa temperatura, stacca l’alimentazione alla resistenza.

Per risolvere questo problema ho creato State Enforcer, uno script che si assicura che una luce, una presa o qualsiasi altra entità di Home Assistant si accenda o si spenga davvero, riprovando più volte se necessario. Se, nonostante i tentativi, il cambio di stato non avviene entro un timeout impostato, riceverai una notifica con due opzioni: riprova o annulla.

Come funziona State Enforcer

Lo script funziona in modo molto semplice:

  1. Dai il comando di accensione o spegnimento per un’entità (ad esempio una luce o una presa smart).
  2. Lo script attende qualche secondo e controlla se il cambio di stato è avvenuto.
  3. Se l’entità non ha cambiato stato, riprova il comando più volte fino a raggiungere il timeout impostato.
  4. Se il dispositivo ha cambiato stato, tutto ok! Se invece, dopo vari tentativi, il cambio di stato non è riuscito, riceverai una notifica interattiva.
  5. La notifica ti permetterà di riprovarci manualmente o di annullare il tentativo.

Come installarlo

Per utilizzare State Enforcer, devi aggiungere il package YAML al tuo Home Assistant. Lo script richiede due dipendenze:

Puoi trovare il package completo e le istruzioni dettagliate nel repository GitHub

Una volta installato, puoi usare State Enforcer con un’azione simile nelle tue automazioni e script:

actions:
  - action: script.turn_on
    target:
      entity_id: script.state_enforcer
    data:
      variables:
        entity_id: light.living_room
        action: off
        timeout: 30

Se non specifichi il timeout, verrà usato il valore predefinito di 30 secondi.

Le notifiche interattive

Se lo script non riesce a cambiare lo stato dell’entità entro il tempo impostato, ti arriverà una notifica con queste opzioni:

🔄 Riprova → Lo script tenterà nuovamente di cambiare lo stato.

Annulla → Ferma il tentativo e segnala il problema.

Ecco un esempio di messaggio:

Notifica HTML5 Push su PC
Notifica da app companion Android

Questo ti permette di gestire il problema direttamente dal telefono o da qualsiasi altro dispositivo connesso a Home Assistant e di venire a conoscenza del problema, che altrimenti avresti ignorato per chissà quanto tempo.

Come funziona?

Se hai letto altri miei articoli sai che non mi piace condividere un lavoro se non ti spiego come funziona, così che possa essere didattico e darti degli spunti per migliorare le tue capacità di scrittura di script e automazioni per Home Assistant o, se sei già esperto, esserti di ispirazione per qualche tua creazione o, capendone il principio, possa tu personalizzare questo package per le tue specifiche esigenze.

Spezzerò nei singoli blocchi lo script per spiegarti cosa fanno i singoli pezzi. Tieni presente che il package potrebbe evolversi su github e le informazioni che seguono sono relative alla versione 1.0, che saranno comunque valide e interessanti per capire il principio di funzionamento del package.
Partiamo dallo script principale.

Lo script state_enforcer

Saltando le banalità come la definizione dei campi con i selettori per essere di comodo uso da strumenti per sviluppatori e dalla UI soffermiamoci su mode: parallel che permette allo script di essere eseguito più volte contemporaneamente. Visto che richiamiamo lo script tramite script.turn_on, come descritto sopra, questo permette a più istanze dello script di restare in esecuzione in background a cercare di attivare lo stato voluto, un’istanza indipendente per ogni entità (su quest’ultima parte ci ritorniamo dopo).

    variables:
      service_name: "{{ 'homeassistant.turn_on' if action == 'on' else 'homeassistant.turn_off' }}"
      expected_state: "{{ action }}" # "on" or "off"
      entity_lock: "tmp.lock_toggle_{{ entity_id | replace('.', '_') }}" # Entity name we will use to lock the execution based on the specific entity
      timeout_sec: "{{ timeout | default(30) }}" # Timeout with default value
      start_time: "{{ now().timestamp() }}" # Start time we will use to evaluate time elapsed for timeout

Qui impostiamo le variabili che useremo in seguito nello script:

  • service_name: sarà il nome del servizio da usare per accendere o spegnere come richiesto dal parametro dello script
  • expected_state: sarà il valore che verificheremo per controllare se l’entità è passata allo stato richiesto
  • entity_lock: generiamo un nome di entità temporanea (che creeremo o aggiorneremo con set_state) che ci servirà poi per garantire che ci sia un solo script in esecuzione per ogni entità richiesta dall’utente. Immagina che richiamiamo lo script per spegnere una luce e subito dopo, mentre lo script ci sta ancora provando, ne richiamiamo uno per accenderla e questi vengano eseguiti contemporaneamente! Questo meccanismo fa si che la seconda istanza faccia terminare la prima (quella per spegnere la luce), ne attenda la conclusione e poi inizi il suo lavoro di accendere la luce. Vedrai più avanti come viene fatto.
  • timeout_sec: è il timeout sicuramente valorizzato con un eventuale valore di default, visto che possiamo non specificare il timeout
  • start_time: data/ora di partenza, usato per calcolare quando viene raggiunto il timeout
      - alias: "Create a persistent notification"
        action: persistent_notification.create
        continue_on_error: true
        data:
          title: State enforcer running
          message: "Enforcing state **{{ expected_state }}** for **{{ states[entity_id].name }}** (max {{ timeout_sec }} seconds)..."
          notification_id: "{{ entity_id }}"

Con questa azione creiamo una notifica persistente che rimarrà visibile durante l’esecuzione dello script, così che se c’è un’entità che sta facendo fatica ad essere modificata di stato ne avremo l’evidenza in modo semplice, risultando in una sorta di “Task manager” di State Enforcer, ci permetterò cioè di vedere quali attività State Enforcer stia correntemente eseguendo, visto che al termine dello script la notifica persistente viene rimossa.

      # We stop other instance of this script that is working on the same entity, if present. 
      # So if wanted to turn on a light and, while trying to do it, we issue the command to turn it off this will shit down the turn on trial and start the turn off one.
      # It's like having "mode: restart" for the script but based on the specific entity you requested (Home Assistant don't have such a feature, we implement it in that way)
      - alias: "Stop another instance on the same light, if running"
        if: "{{ is_state(entity_lock, 'running') }}"
        then:
          - alias: "Stop other instance"
            action: python_script.set_state
            continue_on_error: true
            data:
              allow_create: true
              entity_id: "{{ entity_lock }}"
              state: "stop"
          - wait_template: "{{ is_state(entity_lock, 'stopped') }}"
            timeout: "00:00:10"
            continue_on_timeout: true
          - if: "{{ not is_state(entity_lock, 'stopped') }}"
            then:
              - alias: "Inform of the failure"
                action: persistent_notification.create
                continue_on_error: true
                data:
                  title: State enforcer warning
                  message: >
                    **{{ now().timestamp() | timestamp_custom("%Y-%m-%d %H:%M:%S") }}**
                    State enforcer could not stop a previous instance while enforcing state **{{ expected_state }}** of **{{ states[entity_id].name }}**.
                    Current entity lock value: **{{ states(entity_lock) }}**"

Questo è il punto dove, tramite l’if, verifichiamo che non ci siano istanze in esecuzione dello script sulla stessa entità (verificando se l’entità entity_lock è in stato running). Se lo è impostiamo tale entità sul valore “stop”, che farà terminare l’esecuzione della precedente istanza. In seguito attendiamo che entity_lock valga stopped, ovvero che l’istanza precedente sia terminata (viene impostato tale valore al termine dello script). Se questo non avviene nell’arco di 10 secondi viene creata un’altra notifica persistente, che questa volta non verrà cancellata.

      # Here we set the lock that allows us to do what described in the previous block
      - alias: "Set the lock"
        action: python_script.set_state
        continue_on_error: true
        data:
          allow_create: true
          entity_id: "{{ entity_lock }}"
          state: "running"

A questo punto informiamo eventuali istanze future dello script con questa entità che lo script è in esecuzione, impostando running nell’entità entity_lock

      # This is the real core: a cycle that will exit when the state is what we desire, the lock is telling us to stop (another instance) or timeout occured
      - alias: "Cycle to do the action and check the state"
        repeat:
          while:
            - "{{ not is_state(entity_id, expected_state) }}" # State check
            - "{{ is_state(entity_lock, 'running') }}" # Lock check
            - "{{ (now().timestamp() - start_time) | int < timeout }}" # Timeout check
          sequence:
            - alias: "Try to set the state"
              action: "{{ service_name }}"
              continue_on_error: true
              target:
                entity_id: "{{ entity_id }}"
            - alias: "Wait 5 sec but exit if the lock requests to stop"
              wait_template: "{{ is_state(entity_lock, 'stop') or is_state(entity_id, expected_state) }}"
              timeout: "00:00:05"
              continue_on_timeout: true

Questo è il cuore dello script. Effettuiamo un ciclo finchè una delle seguenti condizioni non intervenga:

  • lo stato dell’entità desiderata diventi quello quello voluto
  • Lo stato della entity_lock diventi diversa da running (ovvero una nuova istanza sta chiedendo di terminare l’esecuzione di questa istanza)
  • E’ trascorso il tempo massimo impostato tramite il parametro timeout (o 30 secondi se non impostato)

Nel ciclo viene poi eseguito il servizio per spegnere o accendere l’entità voluta e quindi vengono attesi 5 secondi ma terminando l’attesa nei casi che farebbero terminare l’esecuzione ovvero se ricevuto il comando di fermare l’istanza da una nuova istanza (stop) o l’entità specificata raggiunge finalmente lo stato desiderato.

      # If we failed to set the state after the timeout specified we will call the state_enforcer_notifications script, in the other file
      - alias: "If could not set the desired state we have failed. Notify it to the user"
        if: "{{ not is_state(entity_id, expected_state) }}"
        then:
          - alias: "Async notification about the failure"
            action: script.turn_on
            continue_on_error: true
            target:
              entity_id: script.state_enforcer_notifications
            data:
              variables:
                entity_id: "{{ entity_id }}"
                expected_state: "{{ expected_state }}"
                timeout: "{{ timeout_sec }}"

Terminato il ciclo i casi sono due: o l’entità ha assunto lo stato desiderato oppure viene avviato lo script state_enforcer_notifications, che vedremo in seguito, per informare del fallimento dell’operazione.

      # Now we remove the lock as the script is ended, allowing new instances to know there is no other instance running
      - alias: "Remove the lock"
        action: python_script.set_state
        continue_on_error: true
        data:
          allow_create: true
          entity_id: "{{ entity_lock }}"
          state: "stopped"

A questo punto impostiamo la nostra entity_lock a stopped per informare eventuali nuove istanze dello script su questa entità che non c’è più alcuna attività in corso.

      # At last we remove the persistent notification that is telling us there is an instance of State Enforcer running
      - alias: "Eventually clear a previous persistent notification"
        action: persistent_notification.dismiss
        continue_on_error: true
        data:
          notification_id: "{{ entity_id }}"

Infine togliamo la notifica persistente che ci informava dell’esecuzione in corso dello script su questa entità.

Le notifiche tramite lo script state_enforcer_notifications

Se i dispositivi che usiamo funzionano correttamente l’esecuzione si conclude con lo script State Enforcer visto sopra. Se invece per tutto il tempo specificato in cui sono stati fatti i retry lo script non riuscisse a spegnere o accendere il dispositivo allora interviene lo script che andiamo ora ad analizzare.

Vediamone sempre i pezzi salienti seguiti dalla descrizione del blocco di codice.

      - action: script.multinotify
        data:
          title: "State enforcer timeout"
          message: "Non è stato possibile {{'accendere' if expected_state == 'on' else 'spegnere'}} l'entità {{ entity_name }} entro {{ timeout }} secondi. Valore attuale: {{ entity_state }}"
          notify_app: notify.mobile_app_tel_henrik
          alexa_target: media_player.piani_inferiori
          notify_pushover: notify.pushover
          notify_html5: notify.html5_hsozziedge
          notify_ha: true
          icon: warning
          group: state_enforcer
          channel: warning
          subtitle: "Timeout {{'accensione' if expected_state == 'on' else 'spegnimento'}} {{ entity_name }} dopo {{ timeout }} sec"
          app_actions:
            - action: "state_enforcer_retry|{{ entity_id }}|{{ expected_state }}|{{ timeout }}"
              icon: /local/refresh.png
              title: "Riprova"
              data:
                entity_id: "{{ entity_id }}"
            - action: "state_enforcer_cancel|{{ entity_id }}|{{ expected_state }}|{{ timeout }}"
              icon: /local/cancel.png
              title: "Annulla"
              data:
                entity_id: "{{ entity_id }}"

In sostanza lo script è tutto qui, in questa unica azione. Sembrerebbe una normale notifica tramite Multinotify invece nasconde uno spunto che secondo me val la pena approfondire. Ma andiamo con ordine.

La notifica ha un messaggio simile a “Non è stato possibile spegnere l’entità Pompa piscina entro 30 secondi. Valore attuale: on”. Viene inviata su uno smartphone, dei dispositivi Alexa, su Pushover, su client registrati HTML5, e come notifica persistente su Home Assistant (grazie a multinotify tutto questo si può fare in una unica azione!).
La peculiarità sono le azioni che vengono fornite con la notifica (e possono essere usate su smartphone e HTML5): Riprova e Annulla.

Il problema è che quando l’utente clicca su una azione (ad es. “Riprova”) di una notifica l’unico dato utile che viene passato ad Home Assistant, tramite il relativo evento che poi vediamo, è il nome dell’azione che abbiamo definito.
Ma non possiamo usare un’azione tipo “retry” in quanto dobbiamo anche indicare ad Home Assistant di quale entità vogliamo fare il retry, cosa vogliamo farci (accenderla o spegnerla?) e il timeout che era stato richiesto. Come fare? Lo mettiamo tutto nell’azione, che poi nell’automazione scomporremo in parti.

E così l’azione diventa una cosa come: state_enforcer_retry|switch.pompa_piscina|off|30 dove il carattere pipe “|” separa le parti:

  1. l’azione scelta dall’utente “state_enforcer_retry”
  2. l’entità in questione “switch.pompa_piscina”
  3. quale stato desideriamo che abbia “off”
  4. Il tempo di timeout: 30 secondi

L’annullamento invia un’azione simile ma con la prima componente “state_enforcer_cancel”. Attualmente non ci facciamo molto se non inserire una notifica persistente ma, funzionalmente, questa azione equivale a eliminare la notifica. Ma essendo gli utenti abituati ad avere messaggi di sistema con le opzioni “Riprova” e “Annulla” il fatto di poter premere “Annulla” anzi che eliminare la notifica, anche se l’effetto è del tutto simile, rende molto intuitivo capire cosa accade premendo il tasto.

Gestiamo ora le azioni “Riprova” e “Annulla”

automation:
  # Action from state enforcer notify
  - id: 2408f862-1045-4eb4-91f1-f5a47bc05c55
    alias: "Azione - Notifica - State enforcer"
    description: "Actions from state enforcer notifications"
    trigger:
      # We get actions from mobile app and from HTML5 push notifications the same way
      - trigger: event
        event_type:
          - "mobile_app_notification_action"
          - "html5_notification.clicked"
    variables:
      # Here we set the minimun needed variables to use in conditions
      event_action_complete: "{{ trigger.event.data['action'] }}"
      action: "{{ event_action_complete | regex_findall('^([^|]+)') | first }}"
    conditions:
      # We check that the action is one of managed ones
      - "{{ action in ['state_enforcer_retry', 'state_enforcer_cancel']}}"
    action:
      # Here we set more variables. There is no way to "transport" some information (like entity_id, expected state and timeout) with the notification
      # so that they'll be posted back when the user press the action. So I've put them in the action itself and I separate the components with regex.
      # The action format is thus: <action>|<entity_id>|<expected_state>|<timeout>
      # For example if we tried to turn off light.kitchen for 60 seconds, it failed and send the notification to the user that pressed the "Retry" button
      # we will receive an action like this: "state_enforcer_retry|light.kitchen|off|60"
      - variables:
          entity_id: "{{ event_action_complete | regex_findall('^[^|]+\\|([^|]+)') | first }}"
          expected_state: "{{ event_action_complete | regex_findall('^[^|]+\\|[^|]+\\|([^|]+)') | first }}"
          timeout: "{{ (event_action_complete | regex_findall('^[^|]+\\|[^|]+\\|[^|]+\\|([^|]+)') | first | int(30)) }}"
          entity_name: "{{ states[entity_id].name }}"
      - alias: "Depending on user reply"
        choose:
          - conditions:
              - "{{ action == 'state_enforcer_retry'}}"
            # User preseend "Retry"
            sequence:
              - alias: "Async retry state enforcer"
                action: script.turn_on
                continue_on_error: true
                target:
                  entity_id: script.state_enforcer
                data:
                  variables:
                    entity_id: "{{ entity_id }}"
                    action: "{{ expected_state }}"
                    timeout: "{{ timeout }}"
          - conditions:
              - "{{ action == 'state_enforcer_cancel' }}"
            # User preseend "Cancel"
            sequence:
              - alias: "Inform that user cancelled"
                action: persistent_notification.create
                continue_on_error: true
                data:
                  title: "State enforcer: annullato dall'utente"
                  message: >
                    Non è stato possibile {{'accendere' if action == 'on' else 'spegnere'}} l'entità {{ entity_name }} entro {{ timeout }} secondi
                    In seguito (**{{ now().timestamp() | timestamp_custom("%Y-%m-%d %H:%M:%S") }}**) un utente ha annullato eventuali ulteriori tentativi

Questa automazione può spaventare vista così ma è più semplice di quanto sembri, vediamola.

      - trigger: event
        event_type:
          - "mobile_app_notification_action"
          - "html5_notification.clicked"

Il trigger gestisce sia l’evento mobile_app_notification_action che html5_notification.clicked ovvero sia le azioni che arrivano dalle notifiche alle app companion che dai client HTML5.

    variables:
      # Here we set the minimun needed variables to use in conditions
      event_action_complete: "{{ trigger.event.data['action'] }}"
      action: "{{ event_action_complete | regex_findall('[^|]+') | first }}"
    conditions:
      # We check that the action is one of managed ones
      - "{{ action in ['state_enforcer_retry', 'state_enforcer_cancel']}}"

Qui estraiamo le variabili minime per determinare se l’azione è derivata da State Enforcer oppure da altro che dobbiamo ignorare.

Per farlo impostiamo la variabile event_action_complete che contiene l’intera azione composta di più parti come spiegato sopra e da essa estraiamo action che contiene solo la prima parte dell’azione, ovvero state_enforcer_retry o state_enforcer_cancel. Lo facciamo tramite una Regular Expression usando la funzione regex_findall.

A questo punto, come condizione, verifichiamo che l’azione sia una tra le due previste. Se così è andiamo ad estrarre anche gli altri parametri tramite le seguenti impostazioni di ulteriori variabili:

      - variables:
          entity_id: "{{ (event_action_complete | regex_findall('[^|]+'))[1] }}"
          expected_state: "{{ (event_action_complete | regex_findall('[^|]+'))[2] }}"
          timeout: "{{ (event_action_complete | regex_findall('[^|]+'))[3] | int(30) }}"
          entity_name: "{{ states[entity_id].name }}"

In entity_id mettiamo la seconda componente, in expected_state la terza ed in timeout la quarta. Infine in entity_name preleviamo il nome dell’entità per scrivere un messaggio di senso compiuto.

Da qui in poi è semplice: se è stato cliccato Riprova viene ora richiamato nuovamente lo script state_enforcer con i parametri estratti sopra, se invece è stato premuto Annulla viene aggiunta una persistent notification ad Home Assistant.

Conclusione

State Enforcer è una soluzione semplice ma efficace per evitare che le tue automazioni falliscano senza che tu te ne accorga. Ora puoi essere sicuro che le luci e le prese si accendano o si spengano davvero, e in caso di problemi, sarai subito informato con la possibilità di intervenire.

Se vuoi provarlo, trovi il codice completo nel mio blog! Se hai domande o suggerimenti, scrivimi nei commenti. 😉

Henrik Sozzi

Sono un analista programmatore per lavoro e per passione. Amo la domotica, la stampa 3D e la tecnologia in generale. Mastodon: @pixel

Questo articolo ha 5 commenti

  1. daniele

    Buongiorno Henrik, grazie della condivisione, idea molto utile soprattutto per gli esempi che hai riportato. Giusta la Nota ‘dispositivi critici’: se non sbaglio i controlli possono essere anche implementati a cascata?Personalmente mi viene in mente il mio termo-arredo: se non si accendesse o peggio non si spegnesse sarebbero guai, ma oltre all’interruttore il dispositivo è dotato di un termostato e in questo caso la sicurezza c’è (almeno finche il termostato funziona!!), proverò ad applicare senz’altro il tuo script.
    Avrei bisogno di capire meglio ESPHOME come controllo locale e Home Assitant solo ‘informato’…
    Comunque un saluto e un grazie.

    P.S.: un problema simile è quello delle integrazioni, nello specifico l’integrazione del termostato bTicino che spesso si trova in ‘state: unavailable’, e allora succede che se automatizzi il termostato ti puoi trovare con la casa fredda o viceversa.
    Ho provato a risolvere il problema con una soluzione assai meno sofisticata della tua: – ho creato un’automazione con un choose che se l’integrazione è in ‘state: unavailable’ allora utilizzo la funzione ‘homeassistant.reload_config_entry’ fino alla sua uscita dallo stato di ‘unavailable’ (monitoro le volte di reaload con un counter.retry_count, ultimamente sono sempre zero o max. 1 reload; forse l’integrazione è stata aggiornata e funziona meglio).

    1. Henrik Sozzi

      Ciao Daniele, grazie mille per le parole gentili 😊
      I controlli possono essere effettuati a cascata senza problemi. Se mentre il mio script cerca di spegnere senza riuscirci un dispositivo e questo si spegne di sua spontanea volontà e poi torna online ad un certo punto dei retry il mio script lo troverà spento uscendo come “tutto ok, missione compiuta” 😉
      Il tuo termoarredo sicuramente ha integrato un termostato e quindi in caso resti acceso il rischio è di consumare tanta corrente, non di compromettere la sicurezza di casa (ho fatto delle assunzioni senza conoscere bene la situazione, spero di aver compreso bene la situazione)
      Che brutto il comportamento dell’integrazione BTicino di cui parli caspita! Hai fatto bene, come workaround, di ricaricare l’integrazione, se questo riporta online il suo stato.
      Speriamo abbiano risolto a monte il problema cmq. Se quel che fai con il termostato è usare un servizio turn_on o turn_off di un entità switch puoi usare questo script. Se invece agisci su un’entità climate allora no.

  2. daniele

    Dimenticavo, impagabile davvero la spiegazione, anzi direi la lezione, dello script, merita una lode.

  3. daniele

    Difficoltà: purtroppo utilizzo da più tempo del tuo Multinotify il pacchetto di notifiche di hassiohelp.eu direi con soddisfazione, e le automazioni sono implementate tutte con questo servizio, sono implementabili entrambi o entrano in conflitto ? Il tuo pacchetto non dipende dall’ add-on AppDeamon se ho capito bene?

    1. Henrik Sozzi

      Per Multinotify vs pacchetto notifiche non ti preoccupare, non sono geloso 🤣 So che è valido il loro pacchetto. È molto diverso e si sovrappone al mio solo parzialmente. Ci sono cose del loro che il mio non fa e viceversa.
      Usa quel che preferisci 😉
      Multinotify non richiede appdaemon, lo puoi usare insieme al loro (non stravolge niente di HA, è un po’ come questo script, se non lo usi non cambia niente in HA).
      Puoi anche pensare di usare il loro pacchetto oppure i servizi singoli di HA senza usare Multinotify riscrivendo solo lo script delle notifiche che contiene una sola azione che chiama Multinotify. In tal caso resterebbe solo la dipendenza allo script python set_state. Ma perdere Multinotify, se usi Alexa, sarebbe un peccato 😜

Rispondi

This site uses Akismet to reduce spam. Learn how your comment data is processed.