Android DSL 概念

本文概略介紹 Android 自動化 DSL 的基本概念。

自動化元件

自動化動作包含下列基本元件,通常會依下列順序評估:

  1. 啟動條件:定義啟用自動化動作的初始條件,例如特徵變更。自動化動作必須有啟動條件。
  2. 條件:自動化動作啟用後,要評估的任何其他限制。條件中的運算式必須評估為 true,自動化動作才能繼續執行。
  3. 動作:符合所有條件時執行的指令或狀態更新。

舉例來說,假設你設定了自動化動作,在日落到日出之間,只要房間的電視開啟,就會調暗房間的燈光。在這個例子中:

  1. 啟動條件:電視已開啟,這是電視特性的狀態變更。
  2. 條件:系統會評估電視所在住家的目前時間。
  3. 動作:電視所在房間的燈光會調暗。

當房間內的電視開啟時,自動化動作就會啟動,但只有在符合「時間介於日落和日出之間」的條件時,自動化動作才會執行。

除了基本結構外,Home API 中的自動化動作也包含中繼資料,例如 name 和 description,可用於向開發人員和使用者識別這些動作。

節點

在 Home API 中,自動化動作的邏輯結構是由節點組成。節點是抽象的可重複使用單位,代表實體行為或執行流程。每個節點都可以有輸入變數,以及可能由其他節點使用的輸出變數。

表格:自動化動作節點類型
節點 節點類型 Kotlin 實作 說明
Starter 行為 StarterNodeDsl 在特性的狀態 (任何屬性) 變更時啟動自動化動作。
StateReader 行為 StateReaderNodeDsl 讀取特徵屬性,並擷取其值,以便在條件節點中使用。
動作 行為 ActionNodeDsl 叫用特徵指令。
依序 執行流程 SequentialFlow 依序執行巢狀動作節點。這是預設的執行行為。
平行 執行流程 ParallelFlow 同時執行巢狀動作節點。
狀況 執行流程 ConditionNodeDsl 根據邏輯運算式的評估結果,有條件地變更執行流程。條件可以與啟動條件建立關聯 (啟動條件專屬條件),也可以是全域條件 (適用於所有啟動條件)。
選取 執行流程 SelectFlow 允許使用多個啟動條件來啟動自動化動作。
IfFlow 執行流程 IfFlowDsl 根據評估為 true 的條件 (如有),執行最多一個動作 (或分支) (類似於 if-then-else 陳述式)。
運算式 值 Expression 可以是特徵屬性的值、常數或常值,且必須評估為清單、數字、布林值或字串。

行為節點

啟動條件和動作等節點屬於行為節點。啟動條件會根據裝置屬性變更啟動自動化動作。動作會發出裝置指令或更新屬性。

行為節點通常與裝置特性和輸出特性狀態相關聯,可做為其他節點的輸入內容。

執行流程節點

部分節點代表執行流程,例如依序和並行。每個節點都包含定義自動化動作的行為節點。

例如,「依序」流程可能包含依序執行的節點。通常是啟動條件、限制條件和動作。

依序執行流程
圖 1:依序自動化流程

平行流程可能有多個動作節點同時執行,例如同時開啟多盞燈。平行流程後方的節點,會等到平行流程的所有分支都完成後才執行。

平行執行流程
圖 2:平行自動化流程

另一種執行流程是「條件流程」,可根據運算式的評估結果變更執行流程。

舉例來說,您可能有一個自動化動作,會根據是否為夜間執行動作。條件節點會檢查時間,然後根據評估結果,遵循適當的執行路徑。

條件式流程
圖 3:條件式流程

如果想讓多個啟動條件都能觸發自動化動作,可以使用選取流程。在 select 流程中加入兩個以上的啟動條件時,只要符合其中一個條件,就會啟動自動化動作。

舉例來說,你可以編寫自動化動作,在日落時、溫度高於特定門檻,或亮度超過門檻時,降低百葉窗。這三種情況分別由三個獨立的啟動器處理,且這三個啟動器都會包裝在 select 流程中。

選取流程
圖 4:選取流程

if-then-else 流程 (IfFlow) 可在自動化動作中執行分支條件式。如果條件為 false,condition 節點會停止整個自動化動作,但 if-then-else 流程則不同,會在條件為 true 時,有條件地執行特定動作,並可改用替代條件或備用動作,或繼續執行自動化動作中的後續節點。詳情請參閱「條件式執行」。

巢狀流程

在複雜的自動化動作中,執行流程節點也可以巢狀。例如,您可能會有執行平行流程的依序流程。

巢狀執行流程
圖 5:巢狀執行流程

您可以根據下表所述的限制,以各種方式巢狀和組合 DSL 節點,以符合特定需求。「Builder」欄會連結至 Kotlin 類型安全建構工具說明文件,詳細說明每種節點允許使用的內容。

表格:節點的合併方式
節點 可能包含下列節點類型和資料 必須屬於下列其中一種節點類型
Starter 運算式 選取「依序」
ManualStarter 選取「依序」
StateReader 運算式 (通常由特徵屬性值組成) IfFlow、Parallel、Sequential
動作 指令、實體、運算式 IfFlow、Parallel、Select、Sequential
依序 IfFlow、Parallel、Select、Sequential
平行 動作 IfFlow、Sequential
狀況 運算式 IfFlow、Parallel、Sequential
選取 Condition、Sequential、Starter、ManualStarter 依序,且必須是流程中的第一個節點
IfFlow Action、Condition、Delay、IfFlow、Parallel、Sequential、StateReader、Suppression 循序

自動化動作 DSL

在 Home API 中,自動化動作是使用自動化動作 DSL (特定領域語言) 定義。自動化動作 DSL 是以 Kotlin DSL (網域特定語言) 的形式實作,使用 Kotlin 類型安全建構工具,專門用於定義自動化動作範本。

編譯自動化動作時,Kotlin 類型安全建構工具會產生 Kotlin 資料類別,然後序列化為通訊協定緩衝區 JSON,用於呼叫 Google 的自動化服務。

自動化 DSL 可簡化建構自動化動作的程序。它原生使用與 Device API 中 Matter 標準特徵和 smart home 特徵相同的資料模型。

自動化動作 DSL 也會根據抽象裝置類型定義自動化動作的邏輯,而非使用者住家中的特定裝置執行個體。開發人員可以提供輸入參數,在執行階段指定實際裝置執行個體,以及其他重要參數值。

DSL 語法與 Kotlin 類似,且同樣具有類型安全,但以 Automation DSL 編寫的自動化動作,比以純 Kotlin 編寫的相同自動化動作更簡單、更精簡。

範例

以下是使用自動化動作 DSL 編寫的自動化動作範例,可開啟裝置:

val automation = automation {
  name = "MyFirstAutomation"
  description = "If light1 is on, turn on light2."
  isActive = true
  sequential {
    val onOffTrait = starter<_>(device1, OnOffLightDevice, OnOff)
    condition() { expression = onOffTrait.onOff equals true }
    action(device2, OnOffLightDevice) { command(OnOff.on()) }
  }
}

這項自動化動作非常基本:當 device1 (燈) 開啟時 (onOff 屬性變更為 true),系統會傳送 on() 指令來開啟 device2。

自動化動作使用 sequential 節點,表示節點會依序執行。

sequential 節點內有行為節點,例如 starter、condition 和 action。starter 節點的輸出內容會指派給變數,以便在 condition 節點中使用。