Руководство по Android DSL для комплексной автоматизации

Язык автоматизации Automation DSL позволяет создавать автоматизации, более сложные, чем те, которые описаны в руководстве по DSL — базовые автоматизации на Android .

Последовательный, с несколькими действиями

Последовательный, с несколькими действиями

Автоматизация может выполнять несколько действий. Например, вместо одного узла action можно использовать несколько узлов action , которые выполняются последовательно:

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

Последовательный, с множеством параллельных действий

Последовательный, с множеством параллельных действий

Если разместить несколько узлов action в parallel узле, действия будут выполняться одновременно.

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

Если в sequential узле есть узлы action , следующие за parallel узлом, они ожидают завершения выполнения всех узлов в parallel узле.

Условное исполнение

По умолчанию автоматизация выполняет узлы последовательно или параллельно. Если вам нужна логика условного ветвления — выполнение различных действий или путей в зависимости от условий во время выполнения — используйте операторы if-then-else , которые строятся с использованием блоков DSL условного управления потоком: ifThen , elseIf и orElse .

В то время как стандартный узел 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."))
    }
  }
}

Выполнять различные действия в зависимости от условия.

Чтобы выполнить один набор действий, когда условие истинно, и альтернативный набор действий, когда оно ложно, добавьте необязательный блок .orElse { ... } после ifThen(...) { ... } :

// 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 , указывающий, как долго нужно приостановить выполнение перед продолжением. Длительность паузы может составлять от пяти секунд до 24 часов.

Например, чтобы четыре раза переключить свет с пятисекундной паузой между каждым переключением:

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()) }
}

Подавление триггера

Trigger suppression is a capability that allows your automation to ignore a starter for a specified period of time after the initial triggering event. For example, if the automation has a starter that's triggered by motion detection, and if you specify a trigger suppression duration of five minutes, then when the starter triggers, it won't trigger again for the next five minutes. This prevents the automation from rapidly triggering over and over.

Для подавления срабатываний триггеров в вашей автоматизации используйте ключевое слово suppressFor с аргументом java.time.Duration , указывающим, как долго нужно ждать перед реагированием на последующие триггеры. Длительность подавления может составлять от пяти секунд до 24 часов.

automation {
  sequential {
    val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
    suppressFor(Duration.ofMinutes(30))
    action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}

Обратите внимание, что подавление триггеров затрагивает все starters автоматизации, предшествующие suppressFor .

Ограничьте количество выполнений.

Вы можете ограничить количество запусков автоматизации.

Например, вы можете настроить одноразовую автоматизацию, которая будет запускать пылесос, пока вас нет дома в течение дня.

Для этого установите значение поля метаданных 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 . Запись в истории автоматизации остается на вкладке «Активность» Google Home app (GHA) , включая automation_id .

Задайте атрибуты характеристик в действии

Чтобы задать значение атрибута признака:

  1. Создайте узел update внутри узла action , включив соответствующий признак в качестве аргумента для узла 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)
  }
}