Questa è una panoramica dei concetti fondamentali dell'Automation DSL.
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, come la modifica di un tratto. 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
perché le azioni di un'automazione possano procedere. - Azione: comandi o aggiornamenti dello stato che vengono eseguiti quando tutte le condizioni sono soddisfatte.
Ad esempio, potresti avere un'automazione che attenua le luci di una stanza quando la TV è accesa tra il tramonto e l'alba. In questo esempio:
- Starter: la TV è stata accesa, ovvero si è verificata una variazione di stato in un attributo della TV.
- Condizione: viene valutato l'ora corrente della casa in cui si trova la TV.
- Azione: le luci nella stessa stanza della TV vengono attenuate.
L'automazione viene attivata quando la TV in camera viene 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 identificarli per sviluppatori e utenti.
Nodi
Nelle API Home, la struttura logica di un'automazione è costituita da nodes. I nodi sono unità astratte riutilizzabili che rappresentano i comportamenti delle entità o i flussi di esecuzione. 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 |
---|---|---|---|
Comando iniziale | Comportamentale |
StarterNodeDsl
|
Avvia un'automazione quando cambia lo stato di un tratto (qualsiasi attributo). |
StateReader | Comportamentale |
StateReaderNodeDsl
|
Legge un attributo tratto e ti consente di acquisire il relativo valore per utilizzarlo nei nodi condizione. |
Azione | Comportamentale |
ActionNodeDsl
|
Richiama i comandi del tratto. |
Sequenziale | Flusso di esecuzione |
SequentialFlow
|
Esegue i nodi di azioni nidificati in sequenza. Questo è il comportamento di esecuzione predefinito. |
Parallelo | Flusso di esecuzione |
ParallelFlow
|
Esegue i nodi di azioni 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 per i comandi iniziali) o essere globali (si applicano a tutti i comandi iniziali). |
Seleziona | Flusso di esecuzione |
SelectFlow
|
Consente di attivare un'automazione con più di un comando iniziale. |
Espressione | Valore |
Expression
|
Può essere il valore dell'attributo di un tratto, una costante o un valore letterale e deve restituire un elenco, un numero, un valore booleano o una stringa. |
Nodi di comportamento
Nodi come comandi iniziali e azioni sono nodi di comportamento. I comandi iniziali attivano un'automazione in base alle modifiche degli attributi del dispositivo. Le azioni inviano comandi ai dispositivi o aggiornano gli attributi.
I nodi di comportamento sono in genere collegati alle caratteristiche del dispositivo e allo stato della caratteristica di output per essere utilizzati 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 di comportamento che definiscono l'automazione.
Ad esempio, un flusso sequenziale può contenere nodi che vengono eseguiti in ordine sequenziale. In genere, si tratta di comandi iniziali, condizioni e azioni.
Un flusso parallelo può avere più nodi di azioni in esecuzione contemporaneamente, ad esempio l'accensione di più luci contemporaneamente. I nodi che seguono un flusso parallelo non verranno eseguiti fino al termine di tutti i rami del flusso parallelo.
Un altro tipo di flusso di esecuzione è il flusso condizionale, 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 al fatto che sia notte. Un nodo 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 comando iniziale che può attivare l'automazione. Quando racchiudi due o più comandi iniziali
in un flusso select
, uno qualsiasi di questi può attivare l'automazione.
Ad esempio, puoi scrivere un'automazione che abbassa le persiane al tramonto, se la temperatura supera una determinata soglia o se la luminosità supera una soglia. Tre comandi iniziali separati gestiscono ciascuno di questi scenari e tutti e tre
vengono inseriti in un flusso select
.
Flussi nidificati
Nelle automazioni complesse, i nodi del flusso di esecuzione possono anche essere nidificati. Ad esempio, puoi 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 contiene link alla documentazione del costruttore sicuro di Kotlin, che descrive in dettaglio cosa è consentito utilizzare in ogni tipo di nodo.
Nodo | Builder | Può contenere i seguenti tipi di nodi e dati | Deve rientrare in uno dei seguenti tipi di nodi |
---|---|---|---|
Comando iniziale |
AutomationBuilder
|
Espressione | Seleziona, Sequenziale |
ManualStarter |
AutomationBuilder
|
Seleziona, Sequenziale | |
StateReader |
AutomationBuilder
|
Espressione (in genere costituita da un valore dell'attributo tratto) | Azione, Condizione |
Azione |
ActionBuilder
|
Comando, Entità, Espressione | Parallelo, Seleziona, Sequenziale |
Sequenziale |
SequentialFlowBuilder
|
Parallelo, Seleziona, Sequenziale | |
Parallelo |
ParallelFlowBuilder
|
Azione | Sequenziale |
Condizione | ConditionBuilder |
Espressione | Parallelo, sequenziale |
Seleziona |
AutomationBuilder
|
Condition, Sequential, Starter, ManualStarter | 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 le automazioni. L'Automation DSL è implementato come Kotlin DSL (linguaggio specifico per il dominio), utilizzando i costruttori sicuri di tipo Kotlin ed è progettato specificamente per definire i modelli di automazione.
Quando un'automazione viene compilata, i costruttori sicuri di tipo Kotlin generano classi di dati Kotlin che vengono poi serializzate in JSON del buffer di protocollo, che viene utilizzato per effettuare chiamate ai servizi di automazione di Google.
Il DSL di automazione semplifica e snellisce il processo di creazione delle automazioni. Utilizza in modo nativo lo stesso modello di dati dei tratti Matter standard e dei tratti smart home presenti nell'API Device.
L'Automation DSL definisce anche la logica di un'automazione in termini di tipi di dispositivi astratti, anziché di istanze di dispositivi specifici situate nella casa di un utente. Consente allo sviluppatore di fornire parametri di input che possono essere utilizzati in fase di esecuzione per specificare le istanze di dispositivi effettive, nonché altri valori di parametro importanti.
La sintassi del DSL è simile a quella di Kotlin ed è altrettanto sicura in termini di tipi, ma un'automazione scritta in Automation DSL è più semplice e concisa rispetto alla stessa automazione scritta in puro Kotlin.
Esempio
Di seguito è riportato un esempio di automazione che accende un dispositivo, scritta 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 di base: quando device1
, una luce, si accende (l'attributo onOff
si modifica in true
), viene inviato il comando on()
per accendere
device2
.
L'automazione utilizza un nodo sequential
, che indica che i relativi nodi verranno eseguiti
in ordine sequenziale.
All'interno del nodo sequential
sono presenti nodi di comportamento come starter
,
condition
e action
. L'output del nodo starter
viene assegnato a una variabile per l'utilizzo nel nodo condition
.