自動化 DSL 可用於建立比 DSL 指南 - iOS 基本自動化動作中討論的更複雜的自動化動作。
依序執行多項動作
自動化動作可以執行多項操作。舉例來說,您可以有多個 action 節點,依序執行,而不是單一 action 節點:
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
action {...}
action {...}
action {...}
}
依序執行多項平行動作
如果在 parallel 節點中放置多個 action 節點,系統會同時執行這些動作。
import GoogleHomeSDK
import GoogleHomeTypes
automation (
...
) {
starter(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
如果 parallel 節點後方的 sequential 節點中有 action 節點,這些節點會等到 parallel 節點中的所有節點都執行完畢後,才會執行。
條件式執行
根據預設,自動化動作會依序或平行執行節點。如需條件分支邏輯 (根據執行階段條件執行不同動作或路徑),請使用 if-then-else 陳述式,這些陳述式是使用條件控制流程 DSL 區塊建構而成:ifThen、elseIf 和 orElse。
標準 condition 節點會控制整個自動化動作 (如果條件評估為 false,自動化動作會立即終止執行),而 ifThen 區塊則可啟用分支控制流程:
condition節點:如果運算式為false,則停止執行整個自動化動作 (或目前的執行路徑)。ifThen/elseIf/orElse:依序評估條件。如果條件為false,執行作業會進入下一個elseIf分支、orElse備用分支,或在不符合任何條件時繼續執行自動化動作中的後續節點。
根據條件執行動作
ifThen 區塊會評估條件運算式。如果運算式評估為 true,系統會執行巢狀結構在區塊內的 DSL 動作或節點。如果評估結果為 false,系統會略過動作,並繼續執行依序流程中的後續節點。
如果只想在符合條件時執行動作,而不封鎖或終止自動化動作中的後續節點,可以使用獨立的 ifThen 區塊:
// 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.")
}
}
根據條件執行不同動作
如要在條件為 true 時執行一組動作,並在條件為 false 時執行另一組動作,請在 ifThen(...) { ... } 後方鏈結選用的 .orElse { ... } 區塊:
// 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!")
}
}
}
依序鏈結多個條件
您可以鏈結一或多個選用的 .elseIf(...) { ... } 區塊,依序評估多個條件。系統會執行條件評估為 true 的第一個分支,並略過其餘所有分支。如果沒有任何條件評估為 true,則會執行選用的 .orElse { ... } 區塊 (如有提供):
// 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()
}
}
}
巢狀條件式流程
條件式區塊可以巢狀結構置於其他 ifThen、elseIf 或 orElse 區塊中,也可以與 parallel、delay(for:) 和 stateReader 節點結合。
ifThen、elseIf 和 orElse 區塊會以依序流程執行內容。您可以在每個分支中放置任何依序節點,包括 action、stateReader、parallel、delay(for:) 和巢狀 ifThen 區塊。
延遲入帳
您可以使用 delay(for:) 方法在自動化動作中加入暫停,該方法會採用 Duration 引數,代表繼續執行前要暫停多久。暫停時間最短為 5 秒,最長為 24 小時。
舉例來說,如要切換燈具四次,每次切換間隔五秒:
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() }
}
觸發條件抑制
觸發條件抑制功能可讓自動化動作在初始觸發事件發生後,在指定時間內忽略 starter。舉例來說,如果自動化動作有由動作偵測觸發的 starter,且您指定觸發條件抑制時間長度為五分鐘,則 starter 觸發後,在接下來五分鐘內不會再次觸發。避免自動化動作在短時間內反覆觸發。
如要對自動化動作套用觸發條件抑制,請使用 suppress(for:) 關鍵字,並搭配 Duration 引數,代表回應後續觸發條件前要等待的時間。抑制時間最短為 5 秒,最長為 24 小時。
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() }
}
請注意,觸發條件抑制會影響自動化動作中,位於 Suppression 之前的所有 starters。
限制執行次數
你可以限制自動化動作的執行次數。
舉例來說,你可以設定一次性自動化動作,在你外出時執行吸塵器。
如要這麼做,請設定自動化動作的 maxExecutionCount 中繼資料欄位。以下範例是只能執行一次的自動化動作:
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)
}
}
自動化動作最後一次執行完畢並達到 maxExecutionCount 後,就會立即刪除。自動化動作的記錄項目會保留在 Google Home app (GHA)「活動」分頁中,包括automation_id。
在動作中設定特徵屬性
如要設定特質屬性的值,請按照下列步驟操作:
- 在
action節點中建立update節點,並將相關特徵做為update節點的引數:action(deviceReference, deviceType) { update(trait) { } } - 在
update節點中,針對要修改的每個屬性,使用變異函式並傳遞新值。如要建立變異函式的名稱,請按照下列步驟操作:- 屬性名稱首字母大寫
- 在開頭加上
set。
defaultMoveRate的屬性,您可以使用名為setDefaultMoveRate的變異函式。
請注意,update 節點可以有多個變異函式。以下是更新兩個屬性的範例:
typealias FanDeviceType = Matter.FanDeviceType
typealias FanControlTrait = Matter.FanControlTrait
action(fan, FanDeviceType.self) {
update(FanControlTrait.self) {
$0.setFanMode(.on)
}
}