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

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

여러 작업이 포함된 순차적 자동화

여러 작업이 있는 순차적

자동화는 두 가지 이상의 작업을 실행할 수 있습니다. 예를 들어 단일 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, and 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 블록을 비롯한 순차적 노드를 각 분기 내에 배치할 수 있습니다.

지연

자동화에 일시중지를 도입할 수 있습니다. 실행을 계속하기 전에 일시중지할 기간을 나타내는 java.time.Duration 인수를 사용하는 delayFor 키워드를 사용하여 일시중지 기간은 5초에서 24시간까지 다양합니다.

예를 들어 각 전환 사이에 5초 일시중지를 두고 전구를 4번 전환하려면 다음 안내를 따르세요.

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분 동안 다시 트리거되지 않습니다. 이렇게 하면 자동화가 빠르게 반복적으로 트리거되는 것을 방지할 수 있습니다.

자동화에 트리거 억제를 적용하려면 후속 트리거에 응답하기 전에 대기할 기간을 나타내는 java.time.Duration 인수와 함께 suppressFor 키워드를 사용합니다. 억제 기간은 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)
  }
}