Android DSL 指南

請參閱下列指南,瞭解如何使用各種自動化 DSL 節點建構自動化動作。

所有自動化 DSL 都會放在單一 automation 節點中。automation 節點會在外層 Kotlin 語言情境和內嵌 DSL 情境之間形成邊界。

依序流程

依序流程是預設的自動化動作流程類型。

依序 DSL 範例

以下是相當基本的自動化動作 DSL 範本,使用由啟動條件、限制條件和動作組成的依序流程:


import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.condition
import com.google.home.automation.sequential
import com.google.home.automation.starter

...

automation {
  sequential {
    starter<_>(...)
    condition {...}
    action {...}
  }
}

您可以新增節點,進一步調整。

Starter

啟動條件節點定義了啟動自動化動作的初始條件。例如狀態或值的變更。自動化動作必須至少有一個啟動條件,否則無法通過驗證。如要在自動化動作中新增多個啟動條件,必須使用 select 節點。

依特質屬性決定先發

宣告以特徵屬性為基礎的起始節點時,請指定:

  • 裝置
  • 特徵所屬的裝置類型
  • 特徵
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)

裝置類型參數為必填,因為您必須指定自動化動作要處理的裝置類型。舉例來說,裝置可能由 FanDevice 和 HeatingCoolingUnitDevice 組成,兩者都包含 OnOff 特性。指定裝置類型後,就能明確知道裝置的哪個部分會觸發自動化動作。

以事件為準的啟動條件

宣告以事件為基礎的啟動條件節點時,請指定:

  • 裝置
  • 特徵所屬的裝置類型
  • 活動
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)

根據住家結構和事件建立啟動條件,並設定參數

部分事件可能含有參數,因此這些參數也必須包含在啟動器中。

舉例來說,這個啟動條件會使用 Time 特性的 ScheduledTimeEvent,在上午 7:00 啟動自動化動作:

val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
  parameter(Time.ScheduledTimeEvent.clockTime(
    LocalTime.of(7, 0, 0, 0)))
}

根據天氣啟動

您可以使用天氣特徵,在啟動條件中指定目前或預測的天氣狀況:

val weatherState = starter<_>(structure, trait = Weather)

請參閱「自動化動作範例」頁面上的「如果可能下雨,請關上百葉窗」。

手動啟動條件

手動啟動條件是一種特殊類型的啟動條件,可讓使用者手動執行自動化動作。

宣告手動啟動條件時:

在 select 流程中,如果手動啟動條件與其他啟動條件並存,手動啟動條件會覆寫其他啟動條件:

select {
  manualStarter()
  starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}

請注意,系統會評估手動啟動條件後方的任何 condition 節點,並可能根據 condition 運算式,封鎖自動化動作的執行。

將手動啟動條件與條件式啟動條件分開

如要避免 condition 節點封鎖手動啟動條件啟動的自動化動作,可以將其他啟動條件和 condition 放在另一個依序流程中:

automation_graph {
  sequential {
    select {
      sequential {
        starter<_>(...)
        condition {...}
      }
      sequential {
        manualStarter()
      }
    }
    action {...}
  }
}

參照屬性值

如要在運算式中使用屬性值,請使用下列語法。

使用 stateReader:

val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime

使用 starter:

val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
  expression = starterNode.onOff equals true
}

條件節點和運算式

條件節點代表決定自動化動作是否繼續執行的決策點。自動化動作可以有多個 condition 節點。如果任何 condition 節點的運算式評估為 false,整個自動化動作就會停止執行。

在 condition 節點中,您可以使用各種運算子結合多個條件準則,只要運算式評估為單一布林值即可。如果結果值為 true,則表示符合條件,自動化動作會繼續執行下一個節點。如果為 false,自動化動作就會在該點停止執行。

運算式的形式與 Kotlin 中的運算式類似,可能包含原始值 (例如數字、字元、字串和布林值) 以及 Enum 值。使用括號將子運算式分組,即可控制評估順序。

以下是 condition 的範例,可將多個子運算式合併為單一運算式:

condition() {
  val expr1 = starterNode.lockState equals DlLockState.Unlocked
  val expr2 = stateReaderNode.lockState equals true

  val expr3 = occupancySensingDevice.occupied notEquals 0
  val expr4 = timeStateReaderNode
    .currentTime
    .between(
      timeStateReaderNode.sunsetTime,
      timeStateReaderNode.sunriseTime)
  expression = (expr1 and expr2) or (expr3 and expr4)
}

您可以參照透過啟動器存取的特質值:

val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }

stateReader

在 condition 節點中參照特徵屬性值的另一種方法是使用 stateReader 節點。

方法是先在 stateReader 節點中擷取特徵屬性值。stateReader 會將 structure 和特徵做為引數:

import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)

接著,在 condition 節點中參照 stateReader:

condition() {
  expression =
    filterMonitoringState.changeIndication
      .equals(ChangeIndicationEnum.Warning)
}

您可以使用比較和邏輯運算子,在 condition 節點中使用多個 stateReaders:

val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
  expression =
    (armState.armState equals true)
    and
    (doorLockState.lockState equals true)
}

條件持續時間

除了條件中的布林運算式外,您還可以指定運算式必須為 true 的時間範圍,才能執行自動化動作。舉例來說,你可以定義條件,讓動作只在燈亮起十分鐘後觸發。

  condition {
    expression(lightStateReader.onOff == true)
    forDuration(Duration.ofMinutes(10))
  }

時間長度可介於 5 秒到 24 小時之間。

動作節點

動作節點是自動化動作執行的位置。在這個範例中,動作會叫用 AssistantBroadcast 特性的 broadcast() 指令:

action(device, SpeakerDevice) {
  command(AssistantBroadcast.broadcast("Intruder detected!"))
}

匯入陳述式

開發自動化動作時,不一定能清楚瞭解如何將 Home API 的各種元素匯入程式碼。

特徵屬性是從特徵的 Companion 物件匯入:

import com.google.home.matter.standard.OnOff.Companion.onOff

由特徵定義的資料結構會從特徵類別匯入,其名稱結尾為「-Trait」:

import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum

特徵指令是從特徵的 Companion 物件匯入:

import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold