복잡한 자동화를 위한 Android DSL 가이드

자동화 DSL을 사용하면 DSL 가이드 - Android의 기본 자동화에서 설명한 것보다 더 복잡한 자동화를 만들 수 있습니다.

여러 작업이 포함된 순차적 워크플로

여러 작업이 포함된 순차적 작업

자동화는 두 가지 이상의 작업을 수행할 수 있습니다. 예를 들어 단일 action 노드 대신 순차적으로 실행되는 여러 action 노드를 사용할 수 있습니다.

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

여러 동시 작업이 있는 순차적

여러 동시 작업이 있는 순차적

parallel 노드에 여러 action 노드를 배치하면 작업이 동시에 실행됩니다.

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

parallel 노드 뒤에 오는 sequential 노드에 action 노드가 있는 경우 parallel 노드 내의 모든 노드가 실행을 완료할 때까지 실행을 기다립니다.

조건부 실행

기본적으로 자동화는 노드를 순차적으로 또는 동시에 실행합니다. 런타임 조건에 따라 다른 작업이나 경로를 실행하는 조건부 분기 로직이 필요한 경우 조건부 제어 흐름 DSL 블록(ifThen, elseIf, orElse)을 사용하여 빌드된 if-then-else 문을 사용하세요.

표준 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 인수를 사용합니다. 일시중지 기간은 최소 5초에서 최대 24시간까지 가능합니다.

예를 들어 조명을 4번 전환하고 각 전환 사이에 5초 동안 일시중지하려면 다음을 실행합니다.

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가 있고 트리거 억제 기간을 5분으로 지정한 경우 starter가 트리거되면 다음 5분 동안 다시 트리거되지 않습니다. 이렇게 하면 자동화가 반복적으로 빠르게 트리거되는 것을 방지할 수 있습니다.

자동화에 트리거 억제를 적용하려면 suppressFor 키워드를 사용하고, 후속 트리거에 응답하기 전에 대기할 시간을 나타내는 java.time.Duration 인수를 사용합니다. 억제 기간은 최소 5초에서 최대 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에 도달하면 즉시 삭제됩니다. automation_id를 포함한 자동화 기록 항목은 Google Home app (GHA) 활동 탭에 남아 있습니다.

작업에서 특성 속성 설정

특성 속성 값을 설정하려면 다음 단계를 따르세요.

  1. action 노드 내에 update 노드를 만들고 관련 특성을 update 노드의 인수로 포함합니다.
    action(deviceReference, deviceType) {
      update(trait) {
    
      }
    }
  2. update 노드 내에서 수정할 각 속성에 대해 변형자 함수를 사용하고 새 값을 전달합니다. 변형자 함수 이름을 구성하려면 다음 안내를 따르세요.
    1. 속성 이름의 첫 글자를 대문자로 표기
    2. set라는 단어를 프리픽스로 사용합니다.
    예를 들어 defaultMoveRate라는 속성을 업데이트하려면 setDefaultMoveRate라는 변형자 함수를 사용합니다.

update 노드에는 여러 변형자 함수가 있을 수 있습니다. 다음은 두 속성이 업데이트되는 예시입니다.

action(device, Fan) {
  update(FanControl) {
    setPercentSetting(50u)
    setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
  }
}