Android DSL 개념

다음은 Android의 자동화 DSL 기본 개념에 관한 개요입니다.

자동화 구성요소

자동화는 다음 기본 구성요소로 구성되며 일반적으로 다음 순서로 평가됩니다.

  1. 시작 조건 — 특성 변경과 같이 자동화를 활성화하는 초기 조건을 정의합니다. 자동화에는 시작 조건이 있어야 합니다.
  2. 조건 — 자동화가 활성화된 후 평가할 추가 제약 조건입니다. 자동화의 작업을 진행하려면 조건의 표현식이 true로 평가되어야 합니다.
  3. 작업: 모든 조건이 충족되면 실행되는 명령어 또는 상태 업데이트입니다.

예를 들어 일몰과 일출 사이에 방의 TV가 켜지면 방의 조명을 어둡게 하는 자동화가 있다고 가정해 보겠습니다. 예를 들면 다음과 같습니다.

  1. 시작 조건 — TV가 켜졌습니다. 이는 TV 속성의 상태가 변경된 것입니다.
  2. 조건: TV가 있는 홈의 현재 시간이 평가됩니다.
  3. 작업 — TV와 같은 방에 있는 조명이 어두워집니다.

방의 TV가 켜지면 자동화가 활성화되지만 '일몰과 일출 사이의 시간' 조건이 충족되는 경우에만 자동화가 실행됩니다.

기본 구조 외에도 Home API의 자동화에는 개발자와 사용자가 자동화를 식별하는 데 사용할 수 있는 name 및 description과 같은 메타데이터도 포함됩니다.

노드

Home API에서 자동화의 논리적 구조는 노드로 구성됩니다. 노드는 항목 동작 또는 실행 흐름을 나타내는 추상적이고 재사용 가능한 단위입니다. 각 노드에는 입력 변수와 다른 노드에서 사용할 수 있는 출력 변수가 있을 수 있습니다.

표: 자동화 노드 유형
노드 노드 유형 Kotlin 구현 설명
Starter 행동 StarterNodeDsl 특성의 상태 (모든 속성)가 변경되면 자동화를 시작합니다.
StateReader 행동 StateReaderNodeDsl 특성 속성을 읽고 조건 노드에서 사용할 값을 캡처할 수 있습니다.
작업 행동 ActionNodeDsl 특성 명령어를 호출합니다.
순차 실행 흐름 SequentialFlow 중첩된 작업 노드를 순서대로 실행합니다. 이는 기본 실행 동작입니다.
Parallel 실행 흐름 ParallelFlow 중첩된 작업 노드를 동시에 실행합니다.
조건 실행 흐름 ConditionNodeDsl 논리 표현식 평가에 따라 실행 흐름을 조건부로 변경합니다. 조건은 시작 조건과 연결되거나 (시작 조건별 조건) 전역적 (모든 시작 조건에 적용)일 수 있습니다.
선택 실행 흐름 SelectFlow 2개 이상의 시작 조건으로 자동화를 활성화할 수 있습니다.
IfFlow 실행 흐름 IfFlowDsl true로 평가되는 조건 (있는 경우)에 따라 최대 하나의 작업 (또는 브랜치)을 실행합니다 (if-then-else 문과 유사).
표현식 값 Expression 특성 속성, 상수 또는 리터럴 값의 값일 수 있으며 목록, 숫자, 불리언 또는 문자열로 평가되어야 합니다.

행동 노드

시작 조건 및 작업과 같은 노드는 동작 노드입니다. 시작 조건은 기기 속성 변경사항을 기반으로 자동화를 활성화합니다. 작업은 기기 명령어를 실행하거나 속성을 업데이트합니다.

동작 노드는 일반적으로 기기 특성에 연결되며 다른 노드에서 입력으로 사용할 수 있도록 특성 상태를 출력합니다.

실행 흐름 노드

일부 노드는 순차 및 병렬과 같은 실행 흐름을 나타냅니다. 이러한 각 노드에는 자동화를 정의하는 동작 노드가 포함되어 있습니다.

예를 들어 순차 흐름에는 순차적으로 실행되는 노드가 포함될 수 있습니다. 일반적으로 시작 조건, 조건, 작업이 포함됩니다.

순차적 실행 흐름
그림 1: 순차적 자동화 흐름

병렬 흐름에는 여러 조명을 동시에 켜는 것과 같이 동시에 실행되는 여러 작업 노드가 있을 수 있습니다. 병렬 흐름을 따르는 노드는 병렬 흐름의 모든 브랜치가 완료될 때까지 실행되지 않습니다.

병렬 실행 흐름
그림 2: 동시 자동화 흐름

또 다른 유형의 실행 흐름은 조건 흐름으로, 표현식 평가에 따라 실행 흐름을 변경할 수 있습니다.

예를 들어 밤인지 여부에 따라 작업을 실행하는 자동화가 있을 수 있습니다. 조건 노드는 시간을 확인한 후 해당 평가에 따라 적절한 실행 경로를 따릅니다.

조건 흐름
그림 3: 조건 흐름

선택 흐름은 자동화를 활성화할 수 있는 시작 조건이 두 개 이상인 경우에 유용합니다. select 흐름에 시작 조건을 2개 이상 포함하면 시작 조건 중 하나만 만족해도 자동화가 활성화됩니다.

예를 들어 일몰 시, 온도가 특정 기준을 초과하거나 밝기가 기준을 초과하는 경우 블라인드를 내리는 자동화를 작성할 수 있습니다. 세 개의 개별 스타터가 이러한 각 시나리오를 처리하며 세 스타터 모두 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
Parallel 작업 IfFlow, Sequential
조건 표현식 IfFlow, Parallel, Sequential
선택 Condition, Sequential, Starter, ManualStarter 순차적이며 흐름의 첫 번째 노드여야 함
IfFlow Action, Condition, Delay, IfFlow, Parallel, Sequential, StateReader, Suppression 순차형

자동화 DSL

Home API에서 자동화는 자동화 DSL(도메인별 언어)을 사용하여 정의됩니다. 자동화 DSL은 Kotlin 유형 안전 빌더를 사용하여 Kotlin DSL (도메인별 언어)로 구현되며 자동화 템플릿을 정의하기 위해 특별히 설계되었습니다.

자동화가 컴파일되면 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 노드에서 사용할 변수에 할당됩니다.