Il DSL di automazione può essere utilizzato per creare automazioni più complesse di quelle descritte in Guida al DSL - Automazioni di base su iOS.
Sequenziale con più azioni
Un'automazione può eseguire più di un'azione. Ad esempio, al posto del singolo nodo action, potresti avere più nodi action, che vengono eseguiti in ordine sequenziale:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
action {...}
action {...}
}
Sequenziale con più azioni parallele
Se inserisci più nodi action in un nodo parallel, le azioni vengono eseguite contemporaneamente.
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
Se nel nodo sequential sono presenti nodi action che seguono il nodo parallel, questi attendono l'esecuzione fino al completamento di tutti i nodi all'interno del nodo parallel.
Esecuzione condizionale
Per impostazione predefinita, un'automazione esegue i nodi in sequenza o in parallelo. Se hai
bisogno di una logica di ramificazione condizionale, ovvero di eseguire azioni o percorsi diversi in base alle
condizioni di runtime, utilizza le istruzioni if-then-else, che vengono create utilizzando i
blocchi DSL del flusso di controllo condizionale:
ifThen,
elseIf,
e
orElse.
Mentre un nodo condition standard limita l'intera automazione (se la condizione restituisce false, l'esecuzione dell'automazione termina immediatamente), i blocchi ifThen consentono il flusso di controllo di ramificazione:
- Nodo
condition: interrompe l'esecuzione dell'intera automazione (o del percorso di esecuzione corrente) se l'espressione èfalse. ifThen/elseIf/orElse: valuta le condizioni in ordine. Se una condizione èfalse, l'esecuzione passa al ramoelseIfsuccessivo, al ramo di fallbackorElseo continua ai nodi successivi dell'automazione se non viene soddisfatta alcuna condizione.
Eseguire un'azione in base a una condizione
Il blocco ifThen valuta un'espressione condizionale. Se l'espressione restituisce true, vengono eseguite le azioni o i nodi DSL nidificati all'interno del blocco. Se restituisce false, le azioni vengono ignorate e l'automazione continua con i nodi successivi nel flusso sequenziale.
Puoi utilizzare un blocco ifThen autonomo quando vuoi eseguire un'azione in modo condizionale senza bloccare o terminare i nodi successivi nell'automazione:
// When a door opens, turn on the light only if it is off,
// and always broadcast an announcement.
typealias ContactSensorDevice = Matter.ContactSensorDeviceType
typealias BooleanStateTrait = Matter.BooleanStateTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait
automation {
let contactState = starter(
contactSensor,
ContactSensorDevice.self,
BooleanStateTrait.self
)
let lightState = stateReader(
light,
DimmableLightDevice.self,
OnOffTrait.self
)
contactState
lightState
condition {
// Door opened (contact sensor open)
contactState.stateValue.equals(false)
}
// Conditionally turn on the light if it's off
ifThen(lightState.onOff.equals(false)) {
action(light, DimmableLightDevice.self) {
OnOffTrait.on()
}
}
// Continue executing subsequent actions in the sequential flow
action(structure) {
Google.AssistantBroadcastTrait.broadcast(msg: "The door was opened.")
}
}
Eseguire azioni diverse in base a una condizione
Per eseguire un insieme di azioni quando una condizione è vera e un insieme alternativo di azioni quando è falsa, collega il blocco .orElse { ... } facoltativo dopo ifThen(...) { ... }:
// When the door is unlocked, turn on the entryway light if it is off;
// otherwise, broadcast a welcome message.
typealias DoorLockDevice = Matter.DoorLockDeviceType
typealias DoorLockTrait = Matter.DoorLockTrait
typealias DimmableLightDevice = Matter.DimmableLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait
automation {
let doorLockEvent = starter(
doorLock,
DoorLockDevice.self,
DoorLockTrait.LockOperationEvent.self
)
let lightState = stateReader(
light,
DimmableLightDevice.self,
OnOffTrait.self
)
doorLockEvent
lightState
condition {
doorLockEvent.lockOperationType.equals(.unlock)
}
ifThen(lightState.onOff.equals(false)) {
action(light, DimmableLightDevice.self) {
OnOffTrait.on()
}
}.orElse {
action(structure) {
Google.AssistantBroadcastTrait.broadcast(msg: "Welcome home!")
}
}
}
Concatenare più condizioni in sequenza
Puoi concatenare uno o più blocchi .elseIf(...) { ... } facoltativi per valutare più condizioni in sequenza. Viene eseguito il primo ramo la cui condizione restituisce true e tutti i rami rimanenti vengono ignorati. Se nessuna delle condizioni restituisce true, viene eseguito un blocco .orElse { ... } facoltativo (se fornito):
// Adjust climate controls based on room temperature changes.
typealias TemperatureSensorDeviceType = Matter.TemperatureSensorDeviceType
typealias TemperatureMeasurementTrait = Matter.TemperatureMeasurementTrait
typealias ThermostatDeviceType = Matter.ThermostatDeviceType
typealias SimplifiedThermostatTrait = Google.SimplifiedThermostatTrait
typealias FanDeviceType = Matter.FanDeviceType
typealias OnOffTrait = Matter.OnOffTrait
automation {
let tempStarter = starter(
tempSensor,
TemperatureSensorDeviceType.self,
TemperatureMeasurementTrait.self
)
tempStarter
// If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
ifThen(tempStarter.measuredValue.greaterThanOrEquals(2800)) {
action(thermostat, ThermostatDeviceType.self) {
SimplifiedThermostatTrait.setSystemMode(systemMode: .cool)
}
}.elseIf(tempStarter.measuredValue.lessThan(1800)) {
// If temperature is low (< 18°C / 1800 mC), switch to Heat mode
action(thermostat, ThermostatDeviceType.self) {
SimplifiedThermostatTrait.setSystemMode(systemMode: .heat)
}
}.orElse {
// Otherwise, turn on the fan
action(fan, FanDeviceType.self) {
OnOffTrait.on()
}
}
}
Flussi condizionali nidificati
I blocchi condizionali possono essere nidificati all'interno di altri blocchi ifThen, elseIf o orElse, nonché combinati con i nodi parallel, delay(for:) e stateReader.
I blocchi ifThen, elseIf e orElse eseguono i contenuti come flussi sequenziali. Puoi inserire qualsiasi nodo sequenziale all'interno di ogni ramo, inclusi i blocchi action, stateReader, parallel, delay(for:) e ifThen nidificati.
Ritardi
Puoi introdurre pause nelle automazioni utilizzando il
delay(for:) metodo,
che accetta un
Duration
argomento che rappresenta la durata della pausa prima di continuare l'esecuzione. La durata della pausa può essere di soli cinque secondi o fino a 24 ore.
Ad esempio, per attivare e disattivare una luce quattro volte con una pausa di cinque secondi tra ogni attivazione/disattivazione:
typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias OnOffTrait = Matter.OnOffTrait
sequential {
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
delay(for:.seconds(5))
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
delay(for:.seconds(5))
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
delay(for:.seconds(5))
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}
Soppressione dell'attivatore
La soppressione dell'attivatore è una funzionalità che consente all'automazione di ignorare un starter per un periodo di tempo specificato dopo l'evento di attivazione iniziale. Ad esempio, se l'automazione ha un starter attivato dal rilevamento del movimento e specifichi una durata di soppressione dell'attivatore di cinque minuti, quando l'attivatore starter viene attivato, non verrà attivato di nuovo per i successivi cinque minuti. In questo modo, l'automazione non viene attivata ripetutamente in rapida successione.
Per applicare la soppressione dell'attivatore all'automazione, utilizza la
suppress(for:)
parola chiave con un
Duration
argomento che rappresenta il tempo di attesa prima di rispondere agli attivatori successivi.
La durata della soppressione può essere di soli cinque secondi o fino a 24 ore.
typealias OccupancySensorDevice = Matter.OccupancySensorDeviceType
typealias OnOffLightDevice = Matter.OnOffLightDeviceType
typealias MotionDetectionTrait = Google.MotionDetectionTrait
typealias OnOffTrait = Matter.OnOffTrait
automation {
let starterNode = starter(device, OccupancySensorDevice.self, MotionDetectionTrait.self)
starterNode
suppress(for: .seconds(30 * 60)) // 30 minutes
action(light, OnOffLightDevice.self) { OnOffTrait.toggle() }
}
Tieni presente che la soppressione dell'attivatore influisce su tutti gli starters di un'automazione che precedono la Suppression.
Limitare il numero di esecuzioni
Puoi limitare il numero di volte in cui è consentito eseguire un'automazione.
Ad esempio, potresti voler configurare un'automazione una tantum che avvii l'aspirapolvere mentre sei fuori casa per la giornata.
Per farlo, imposta il campo dei metadati maxExecutionCount dell'automazione.
L'esempio seguente mostra un'automazione che può essere eseguita una sola volta:
import GoogleHomeSDK
import GoogleHomeTypes
typealias RoboticVacuumCleanerDevice = Matter.RoboticVacuumCleanerDeviceType
typealias RvcRunModeTrait = Matter.RvcRunModeTrait
typealias AreaPresenceStateTrait = Google.AreaPresenceStateTrait
let draftAutomation = automation(
name: "Vacuum home away",
description: "Run the vacuum once when everyone is away.",
maxExecutionCount: 1
) {
let homeAwayState = starter(structure, AreaPresenceStateTrait.self)
homeAwayState
condition {
homeAwayState.presenceState.equals(.presenceStateVacant)
}
action(vacuum, RoboticVacuumCleanerDevice.self) {
RvcRunModeTrait.changeToMode(newMode: 1)
}
}
L'automazione viene eliminata immediatamente al termine dell'ultima esecuzione e al raggiungimento di maxExecutionCount. La voce della cronologia dell'automazione rimane
nella scheda Google Home app (GHA) Attività, incluso il automation_id.
Impostare gli attributi dei tratti in un'azione
Per impostare il valore di un attributo del tratto:
- Crea un nodo
updateall'interno di un nodoaction, includendo il tratto pertinente come argomento del nodoupdatenodo:action(deviceReference, deviceType) { update(trait) { } } - All'interno del nodo
update, per ogni attributo da modificare, utilizza una funzione di mutazione e passagli il nuovo valore. Per formare il nome della funzione di mutazione:- Metti in maiuscolo il nome dell'attributo
- Aggiungi il prefisso
set.
defaultMoveRate, utilizzeresti una funzione di mutazione denominatasetDefaultMoveRate.
Tieni presente che un nodo update può avere più funzioni di mutazione. Ecco un esempio in cui vengono aggiornati due attributi:
typealias FanDeviceType = Matter.FanDeviceType
typealias FanControlTrait = Matter.FanControlTrait
action(fan, FanDeviceType.self) {
update(FanControlTrait.self) {
$0.setFanMode(.on)
}
}