自動化 DSL 可用於建立比Android 自動化 DSL 指南 - 基本自動化動作中討論的動作更複雜的自動化動作。
依序執行多項動作
自動化動作可以執行多項操作。舉例來說,您可以有多個 action 節點,而不是單一 action 節點,這些節點會依序執行:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
依序執行多項平行動作
如果在 parallel 節點中放置多個 action 節點,系統會同時執行動作。
automation {
sequential {
starter<_>(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
}
如果 sequential 節點中有 action 節點位於 parallel 節點之後,這些節點會等待,直到 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.
automation {
sequential {
val contactState = starter<_>(
contactSensor,
ContactSensorDevice,
BooleanState,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
// Door opened (contact sensor open)
expression = contactState.stateValue equals false
}
// Conditionally turn on the light if it's off
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}
// Continue executing subsequent actions in the sequential flow
action(structure) {
command(AssistantBroadcast.broadcast("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.
automation {
sequential {
val doorLockEvent = starter<_>(
doorLock,
DoorLockDevice,
LockOperationEvent,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
expression =
doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock
}
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}.orElse {
action(structure) {
command(AssistantBroadcast.broadcast("Welcome home!"))
}
}
}
}
依序串連多個條件
您可以串連一或多個選用 .elseIf(...) { ... } 區塊,依序評估多個條件。系統會執行條件評估結果為 true 的第一個分支,並略過所有其餘分支。如果沒有任何條件評估為 true,則會執行選用的 .orElse { ... } 區塊 (如有提供):
// Adjust climate controls based on room temperature changes.
automation {
sequential {
val tempStarter = starter<_>(
tempSensor,
TemperatureSensorDevice,
TemperatureMeasurement,
)
// If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
ifThen(tempStarter.measuredValue greaterThanOrEquals 2800) {
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Cool
)
)
}
}.elseIf(tempStarter.measuredValue lessThan 1800) {
// If temperature is low (< 18°C / 1800 mC), switch to Heat mode
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Heat
)
)
}
}.orElse {
// Otherwise, turn on the fan
action(fan, FanDevice) {
command(OnOff.on())
}
}
}
}
巢狀條件式流程
條件式區塊可以巢狀結構的形式,內嵌在其他 ifThen、elseIf 或 orElse 區塊中,也可以與 parallel、delayFor 和 stateReader 節點合併。
「ifThen」、「elseIf」和「orElse」區塊會依序執行內容。您可以在每個分支中放置任何連續節點,包括 action、stateReader、parallel、delayFor 和巢狀 ifThen 區塊。
延遲入帳
您可以使用 delayFor 關鍵字在自動化程序中暫停,這個關鍵字會採用 java.time.Duration 引數,代表繼續執行前要暫停多久。暫停時間最短為五秒,最長為 24 小時。
舉例來說,如要切換燈光四次,每次切換間隔五秒,請執行下列操作:
sequential {
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
觸發條件抑制
觸發條件抑制功能可讓自動化動作在初始觸發事件發生後,於指定時間內忽略 starter。舉例來說,如果自動化動作有starter,且是由動作偵測功能觸發,而您指定了五分鐘的觸發抑制時間,那麼當starter觸發後,接下來五分鐘內就不會再次觸發。這樣可避免自動化程序快速重複觸發。
如要對自動化動作套用觸發條件抑制功能,請使用 suppressFor 關鍵字,並搭配 java.time.Duration 引數,代表在回應後續觸發條件前要等待的時間長度。封鎖時間可能短至五秒,也可能長達 24 小時。
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
請注意,觸發條件抑制功能會影響自動化動作中所有位於 suppressFor 前的 starters。
限制執行次數
您可以限制自動化動作的執行次數。
舉例來說,你可能想設定一次性自動化動作,在白天外出時啟動吸塵器。
如要執行這項操作,請設定自動化功能的 maxExecutionCount 中繼資料欄位。以下範例是只能執行一次的自動化動作:
automation { // The automation can only be executed once. maxExecutionCount = 1 // When the door lock state changes sequential { val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent) // if the door is unlocked condition() { expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock) } // turn the light on action(light, DimmableLightDevice) { command(OnOff.on()) } } }
自動化動作最後一次執行完畢並達到 maxExecutionCount 後,就會立即刪除。自動化動作的記錄項目仍會保留在「活動」Google Home app (GHA)分頁中,包括 automation_id。
在動作中設定特徵屬性
如要設定特徵屬性的值,請按照下列步驟操作:
- 在
action節點中建立update節點,並將相關特徵做為update節點的引數:action(deviceReference, deviceType) { update(trait) { } } - 在
update節點中,針對要修改的每個屬性,使用變異函式並傳遞新值。如要組成變異子函式的名稱:- 將屬性名稱設為大寫
- 在開頭加上「
set」一詞。
defaultMoveRate的屬性, 請使用名為setDefaultMoveRate的變動函式。
請注意,update 節點可以有多個變異函式。以下範例說明如何更新兩個屬性:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}