Questa è una panoramica dei concetti fondamentali del linguaggio DSL di automazione su Android.
Componenti di automazione
Un'automazione è costituita dai seguenti componenti di base, in genere valutati in questo ordine:
- Comando iniziale: definisce le condizioni iniziali che attivano l'automazione, ad esempio una modifica a una caratteristica. Un'automazione deve avere un comando iniziale.
- Condizione: eventuali vincoli aggiuntivi da valutare dopo l'attivazione di un'automazione. L'espressione in una condizione deve restituire
true
affinché le azioni di un'automazione possano procedere. - Azione: comandi o aggiornamenti di stato eseguiti quando tutte le condizioni sono soddisfatte.
Ad esempio, potresti avere un'automazione che abbassa l'intensità delle luci in una stanza quando la TV della stanza viene accesa tra il tramonto e l'alba. In questo esempio:
- Avvio: la TV è stata accesa, il che rappresenta una modifica dello stato di una caratteristica della TV.
- Condizione: viene valutata l'ora attuale della casa in cui si trova la TV.
- Azione: le luci nella stessa stanza della TV vengono attenuate.
L'automazione si attiverebbe quando la TV nella stanza è accesa, ma viene eseguita solo se è soddisfatta la condizione "l'ora è compresa tra il tramonto e l'alba".
Oltre alla struttura di base, le automazioni nelle API Home contengono anche metadati, come name e description, che possono essere utilizzati per identificarle per sviluppatori e utenti.
Nodi
Nelle API Home, la struttura logica di un'automazione è costituita da nodi. I nodi sono unità astratte e riutilizzabili che rappresentano i comportamenti o i flussi di esecuzione delle entità. Ogni nodo può avere variabili di input, nonché variabili di output che possono essere utilizzate da altri nodi.
Nodo | Tipo di nodo | Implementazione di Kotlin | Descrizione |
---|---|---|---|
Starter | Comportamentale |
StarterNodeDsl
|
Avvia un'automazione quando cambia lo stato di una caratteristica (qualsiasi attributo). |
StateReader | Comportamentale |
StateReaderNodeDsl
|
Legge un attributo del tratto e ti consente di acquisirne il valore da utilizzare nei nodi di condizione. |
Azione | Comportamentale |
ActionNodeDsl
|
Richiama i comandi delle caratteristiche. |
Sequenziale | Flusso di esecuzione |
SequentialFlow
|
Esegue i nodi di azione nidificati in sequenza. Questo è il comportamento di esecuzione predefinito. |
Parallelo | Flusso di esecuzione |
ParallelFlow
|
Esegue i nodi di azione nidificati in parallelo. |
Condizione | Flusso di esecuzione |
ConditionNodeDsl
|
Modifica in modo condizionale il flusso di esecuzione in base alle valutazioni delle espressioni logiche. Le condizioni possono essere associate a un comando iniziale (condizioni specifiche del comando iniziale) o essere globali (si applicano a tutti i comandi iniziali). |
Seleziona | Flusso di esecuzione |
SelectFlow
|
Consente a più di un comando iniziale di attivare un'automazione. |
Expression | Valore |
Expression
|
Può essere il valore di un attributo di un tratto, una costante o un valore letterale e deve restituire un elenco, un numero, un valore booleano o una stringa. |
Nodi comportamentali
I nodi come i comandi iniziali e le azioni sono nodi comportamentali. I comandi iniziali attivano un'automazione in base alle modifiche degli attributi del dispositivo. Le azioni inviano comandi al dispositivo o aggiornano gli attributi.
I nodi comportamentali sono in genere associati alle caratteristiche del dispositivo e allo stato delle caratteristiche di output da utilizzare come input in altri nodi.
Nodi del flusso di esecuzione
Alcuni nodi rappresentano flussi di esecuzione, ad esempio sequenziali e paralleli. Ciascuno di questi nodi contiene i nodi comportamentali che definiscono l'automazione.
Ad esempio, un flusso sequenziale può contenere nodi che vengono eseguiti in ordine sequenziale. In genere, si tratta di comando iniziale, condizione e azione.
Un flusso parallelo può avere più nodi di azione in esecuzione contemporaneamente, ad esempio l'accensione di più luci contemporaneamente. I nodi che seguono un flusso parallelo non vengono eseguiti finché non terminano tutti i rami del flusso parallelo.
Un altro tipo di flusso di esecuzione è un flusso di condizione, che può modificare il flusso di esecuzione in base alla valutazione di un'espressione.
Ad esempio, potresti avere un'automazione che esegue un'azione in base all'ora del giorno. Un nodo di condizione controlla l'ora del giorno, quindi segue il percorso di esecuzione appropriato in base a questa valutazione.
Un flusso di selezione è utile quando vuoi avere più di un
trigger che può attivare l'automazione. Quando includi due o più comandi iniziali
in un flusso select
, uno qualsiasi dei comandi iniziali può attivare l'automazione.
Ad esempio, puoi scrivere un'automazione che abbassi le tapparelle al tramonto, se
la temperatura supera una determinata soglia o se la luminosità supera una
soglia. Tre diversi starter gestiscono ciascuno di questi scenari e tutti e tre
sarebbero inclusi in un flusso select
.
Flussi nidificati
Nelle automazioni complesse, i nodi del flusso di esecuzione possono anche essere nidificati. Ad esempio, potresti avere un flusso sequenziale che esegue un flusso parallelo.
I nodi DSL possono essere nidificati e combinati in vari modi per soddisfare le tue esigenze specifiche, in base ai vincoli descritti nella tabella seguente. La colonna Builder rimanda alla documentazione del builder typesafe Kotlin, che descrive in dettaglio cosa è consentito per l'utilizzo in ogni tipo di nodo.
Nodo | Potrebbe contenere il seguente tipo di nodo e dati | Deve rientrare in uno dei seguenti tipi di nodi |
---|---|---|
Starter | Espressione | Seleziona, Sequenziale |
ManualStarter | Seleziona, Sequenziale | |
StateReader | Espressione (in genere costituita da un valore dell'attributo caratteristica) | Azione, Condizione |
Azione | Command, Entity, Expression | Parallel, Select, Sequential |
Sequenziale | Parallel, Select, Sequential | |
Parallelo | Azione | Sequenziale |
Condizione | Espressione | Parallel, Sequential |
Seleziona | Condizione, Sequenziale, Iniziale, ManualeIniziale | Sequenziale e deve essere il primo nodo del flusso |
DSL di automazione
Nelle API Home, le automazioni vengono definite utilizzando il linguaggio specifico del dominio (DSL) per l'automazione. La DSL di automazione è implementata come DSL Kotlin (linguaggio specifico del dominio), utilizzando builder Kotlin type-safe ed è progettata specificamente per definire i modelli di automazione.
Quando un'automazione viene compilata, i builder Kotlin type-safe generano classi di dati Kotlin che vengono poi serializzate in JSON di protocol buffer, utilizzato per effettuare chiamate ai servizi di automazione di Google.
Il linguaggio DSL di automazione semplifica e ottimizza il processo di creazione delle automazioni. Utilizza in modo nativo lo stesso modello di dati delle caratteristiche standard Matter e delle caratteristiche smart home presenti nell'API Device.
L'DSL di automazione definisce anche la logica di un'automazione in termini di tipi di dispositivi astratti, anziché istanze di dispositivi specifiche che si trovano nella casa di un utente. Consente allo sviluppatore di fornire parametri di input che possono essere utilizzati in fase di runtime per specificare le istanze effettive del dispositivo, nonché altri valori di parametri importanti.
La sintassi DSL è simile a quella di Kotlin ed è altrettanto sicura per i tipi, ma un'automazione scritta in DSL di automazione è più semplice e concisa della stessa automazione scritta in Kotlin puro.
Esempio
Di seguito è riportato un esempio di automazione che accende un dispositivo, scritto utilizzando il linguaggio DSL di automazione:
val automation = automation {
name = "MyFirstAutomation"
description = "If light1 is on, turn on light2."
isActive = true
sequential {
val onOffTrait = starter<_>(device1, OnOffLightDevice, OnOff)
condition() { expression = onOffTrait.onOff equals true }
action(device2, OnOffLightDevice) { command(OnOff.on()) }
}
}
Questa automazione è molto semplice: quando device1
, una luce si accende (l'attributo onOff
cambia in true
), quindi invia il comando on()
per accendere
device2
.
L'automazione utilizza un nodo sequential
, il che indica che i nodi verranno eseguiti
in ordine sequenziale.
All'interno del nodo sequential
si trovano nodi comportamentali come starter
,
condition
e action
. L'output del nodo starter
viene assegnato a una
variabile da utilizzare nel nodo condition
.