Consulta la seguente guida per capire come vari nodi DSL di automazione possono essere utilizzati per creare un'automazione.
Tutto il DSL di automazione viene inserito in un singolo nodo automation
. Il node automation
costituisce il confine tra il contesto del linguaggio Swift esterno e il contesto DSL incorporato.
Flusso sequenziale
Il flusso sequenziale è il tipo predefinito di flusso di automazione.
Ecco un modello DSL di automazione molto semplice che utilizza un flusso sequenziale costituito da un comando iniziale, una condizione e un'azione:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
}
Questo può essere perfezionato aggiungendo altri nodi.
Starter
I nodi iniziali definiscono le circostanze iniziali che attivano un'automazione. Ad esempio, una variazione di stato o di valore. Un'automazione deve avere almeno un comando iniziale, altrimenti la convalida non andrà a buon fine. Per aggiungere più di un comando iniziale a un'automazione, devi utilizzare un nodo select
.
Iniziale basata sull'attributo tratto
Quando dichiari un nodo iniziale basato su un attributo tratto, specifica:
- il dispositivo
- il tipo di dispositivo a cui appartiene la caratteristica
- il tratto
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
Il parametro del tipo di dispositivo è obbligatorio perché ti consente di specificare il tipo di dispositivo all'interno di un dispositivo a cui si rivolge l'automazione. Ad esempio, un dispositivo potrebbe essere composto da un FanDeviceType
e un HeatingCoolingUnitDeviceType
, entrambi contenenti l'attributo OnOffTrait
. Se specifichi il tipo di dispositivo, non c'è ambiguità su quale parte del dispositivo attiva l'automazione.
Comando iniziale basato su evento
Quando dichiari un nodo iniziale basato su un evento, specifica:
- il dispositivo
- il tipo di dispositivo a cui appartiene la caratteristica
- l'evento
starter(
doorbell,
Google.GoogleDoorbellDeviceType.self,
Google.DoorbellPressTrait.DoorbellPressedEvent
)
Comando iniziale basato su una struttura e un evento, con parametri
Alcuni eventi possono avere parametri, pertanto questi parametri devono essere inclusi anche nel comando iniziale.
Ad esempio, questo comando iniziale utilizza ScheduledEvent
di TimeTrait
per attivare l'automazione alle 07:00:
typealias TimeTrait = Google.TimeTrait
let earlyMorning = starter(
structure,
TimeTrait.ScheduledEvent.self
) {
TimeTrait.ScheduledEvent.clockTime(TimeOfDay(hours: 7, minutes: 0))
}
Manual Starter
Un comando iniziale manuale è un tipo speciale di comando iniziale che consente all'utente di eseguire manualmente l'automazione.
Quando dichiari un comando iniziale manuale:
- Non specificare una caratteristica o un tipo di dispositivo.
- Fornisci un elemento dell'interfaccia utente che chiami
Automation.execute()
.
Quando inserisci un comando iniziale manuale in un flusso select
insieme a un altro comando iniziale, il comando iniziale manuale sostituisce l'altro:
select {
manualStarter()
starter(
thermostat,
Matter.TemperatureSensorDeviceType.self,
Matter.TemperatureMeasurementTrait.self
)
}
Tieni presente che tutti i nodi condition
che seguono un comando iniziale manuale verranno valutati e potrebbero bloccare l'esecuzione dell'automazione, a seconda dell'espressione condition
.
Un modo per strutturare l'automazione in modo che i nodi condition
non blocchino un'automazione attivata con un comando iniziale manuale è inserire l'altro comando iniziale in un flusso sequenziale separato insieme al relativo condition
:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
select {
sequential {
starter(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
Fare riferimento al valore di un attributo
Per utilizzare il valore di un attributo in un'espressione, utilizza la seguente sintassi.
Con un stateReader
:
typealias TimeTrait = Google.TimeTrait
let time = stateReader(structure, TimeTrait.self)
time
let currTime = time.currentTime
Con un starter
:
typealias LaundryWasherDeviceType = Matter.LaundryWasherDeviceType
typealias OnOffTrait = Google.OnOffTrait
let starterNode = starter(device1, LaundryWasherDeviceType.self, OnOffTrait.self)
starterNode
condition {
starterNode.onOff.equals(true)
}
Nodi ed espressioni di condizione
Un nodo condizione rappresenta un punto decisionale che determina se l'automazione deve continuare o meno. Un'automazione può avere più nodi condition
.
Se l'espressione di un nodo condition
ha il valore false
, l'esecuzione dell'intera automazione termina.
All'interno di un nodo condition
, puoi combinare più criteri di condizione utilizzando diversi operatori, a condizione che l'espressione restituisca un singolo valore booleano. Se il valore risultante è
true
, la condizione è soddisfatta e l'automazione continua l'esecuzione del
nodo successivo. Se è false
, l'automazione smette di essere eseguita a quel punto.
Le espressioni sono formate in modo simile a quelle in Swift e possono contenere valori primitivi come numeri, caratteri, stringhe e booleani, nonché valori Enum. Raggruppare le sottoespressioni con le parentesi ti consente di controllare l'ordine in cui vengono valutate.
Ecco un esempio di condition
che combina più sottoespressioni in un'unica espressione:
condition {
let exp1 = starterNode.lockState.equals(.unlocked)
let exp2 = stateReaderNode.lockState.equals(true)
let exp3 = occupancySensingDevice.occupied.notEquals(0)
(exp1.and(exp2)).or(exp3)
}
Puoi fare riferimento al valore di un tratto a cui accedi tramite un comando iniziale:
typealias OnOffTrait = Matter.OnOffTrait
let starterNode = starter(device, OnOffTrait.self)
starterNode
condition {
starterNode.onOff.equals(true)
}
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
L'altro modo per fare riferimento ai valori degli attributi dei tratti in un nodo condition
è con un nodo stateReader
.
Per farlo, acquisisci prima il valore dell'attributo tratto in un nodo stateReader
. Un
stateReader
prende structure
e il tratto come argomenti:
typealias ActivatedCarbonFilterMonitoringTrait = Matter.ActivatedCarbonFilterMonitoringTrait
let filterMonitoringState = stateReader(structure, ActivatedCarbonFilterMonitoringTrait.self)
Poi fai riferimento a stateReader
nel nodo condition
:
condition {
filterMonitoringState.changeIndication.equals(.warning)
}
Utilizzando gli operatori di confronto
e
logici,
è possibile utilizzare più stateReaders
in un nodo condition
:
typealias ArmDisarm = Google.ArmDisarmTrait
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLock = Matter.DoorLockTrait
let armState = stateReader(doorLock, DoorLockDevice.self, ArmDisarm )
let doorLockState = stateReader(doorLock, DoorLockDevice.self, DoorLock)
armState
doorLockState
condition {
let exp1 = armState.armState
let exp2 = doorLockState.lockState
exp1.and(exp2)
}
Durata della condizione
Oltre a un'espressione booleana in una condizione, puoi specificare un periodo di tempo durante il quale l'espressione deve essere vera per eseguire l'automazione. Ad esempio, puoi definire una condizione che si attiva solo se una luce è accesa da dieci minuti.
condition(for: .seconds(600)) {
lightStateReader.onOff.equals(true)
}
La durata può variare da 1 a 30 minuti.
Nodi di azione
Il nodo di azione è il luogo in cui viene eseguito il lavoro dell'automazione.
In questo esempio, l'azione richiama il comando broadcast()
di AssistantBroadcastTrait
:
action(speaker, SpeakerDeviceType.self) {
Google.AssistantBroadcastTrait.broadcast(msg: "Oven Cycle Complete")
}