Концепции Android DSL

Ниже приведен обзор основных концепций Automation DSL на Android.

Компоненты автоматизации

Автоматизация состоит из следующих основных компонентов, которые обычно оцениваются в таком порядке:

  1. Условие. Определяет начальные условия, которые активируют автоматизацию, например изменение характеристики. У автоматизации должно быть условие запуска.
  2. Условие – дополнительные ограничения, которые проверяются после активации автоматизации. Чтобы действия автоматизации выполнялись, выражение в условии должно иметь значение true.
  3. Действие – команды или обновления статуса, которые выполняются, когда соблюдены все условия.

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

  1. Стартер. Телевизор был включен, что является изменением состояния в свойстве телевизора.
  2. Условие. Оценивается текущее время в доме, где находится телевизор.
  3. Действие. Свет в комнате с телевизором приглушается.

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

Помимо базовой структуры, автоматизации в Home API также содержат метаданные, такие как name и description, которые можно использовать для их идентификации разработчиками и пользователями.

Узлы

В Home API логическая структура автоматизации состоит из узлов. Узлы – это абстрактные многократно используемые единицы, которые представляют поведение объектов или потоки выполнения. У каждого узла могут быть входные переменные, а также выходные переменные, которые могут использоваться другими узлами.

Таблица. Типы узлов автоматизации
Узел Тип узла Реализация Kotlin Описание
Starter Поведенческие StarterNodeDsl Запускает автоматизацию, когда меняется состояние (любой атрибут) признака.
StateReader Поведенческие StateReaderNodeDsl Считывает атрибут признака и позволяет зафиксировать его значение для использования в узлах условий.
Действие Поведенческие ActionNodeDsl Вызывает команды, связанные с функцией.
Последовательная ротация Процесс выполнения SequentialFlow Последовательно выполняет вложенные узлы действий. Это поведение по умолчанию.
Параллельное отслеживание Процесс выполнения ParallelFlow Параллельно выполняет вложенные узлы действий.
Condition Процесс выполнения ConditionNodeDsl Условно изменяйте поток выполнения на основе вычислений логических выражений. Условия могут быть связаны с триггером (условия, относящиеся к триггеру) или быть глобальными (применяться ко всем триггерам).
Выбрать Процесс выполнения SelectFlow Теперь для запуска автоматизации можно использовать несколько условий.
IfFlow Процесс выполнения IfFlowDsl Выполняет не более одного действия (или ветви) в зависимости от того, какое условие (если оно есть) оценивается как истинное (аналогично оператору if-then-else).
Expression Значение Expression Может быть значением атрибута признака, константой или литеральным значением. Должно быть списком, числом, логическим значением или строкой.

Поведенческие узлы

Узлы, такие как условия и действия, являются поведенческими. Триггеры запускают автоматизацию на основе изменений атрибутов устройства. Действия отправляют команды устройствам или обновляют атрибуты.

Поведенческие узлы обычно привязаны к характеристикам устройства и выводят состояние характеристики для использования в качестве входных данных в других узлах.

Узлы потока выполнения

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

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

Последовательное выполнение процессов
Рисунок 1. Последовательная автоматизация

В параллельном потоке может быть несколько узлов действий, выполняющихся одновременно, например включение нескольких светильников. Узлы, следующие за параллельным потоком, не будут выполняться, пока не завершатся все ветви параллельного потока.

Параллельное выполнение процессов
Рисунок 2. Параллельный процесс автоматизации

Другой тип потока выполнения – условный поток, который может изменять поток выполнения на основе оценки выражения.

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

Процесс с условием
Рисунок 3. Процесс с условием

Выбор полезен, когда у вас есть несколько условий, которые могут запустить автоматизацию. Если вы добавите в блок select два или более условий, любое из них сможет запустить автоматизацию.

Например, можно создать автоматизацию, которая будет опускать жалюзи на закате, если температура или яркость превысит определенный порог. Для каждого из этих сценариев используется отдельный стартер, и все три будут объединены в поток select.

Выбрать процесс
Рисунок 4. Выбор потока

Условный поток (IfFlow) позволяет выполнять действия в рамках автоматизации в зависимости от условий. В отличие от узла condition, который останавливает всю автоматизацию, если условие false, поток "если – то – иначе" условно выполняет определенные действия, когда условие истинно, и может возвращаться к альтернативным условиям или резервным действиям или переходить к последующим узлам в автоматизации. Подробнее об условном выполнении…

Вложенные потоки

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

Вложенные процессы выполнения
Рисунок 5. Вложенные процессы выполнения

Узлы DSL можно вкладывать и комбинировать различными способами в соответствии с вашими потребностями и ограничениями, описанными в таблице ниже. В столбце Builder (Конструктор) приведены ссылки на документацию по типобезопасному конструктору Kotlin, в которой подробно описано, что можно использовать в каждом типе узла.

Таблица. Как можно объединять узлы
Узел Может содержать следующие типы узлов и данные: Должен находиться в узле одного из следующих типов:
Starter Выражение Выбрать, последовательно
ManualStarter Выбрать, последовательно
StateReader Выражение (обычно состоит из значения атрибута признака) IfFlow, Parallel, Sequential
Действие Команда, объект, выражение IfFlow, Parallel, Select, Sequential
Последовательная ротация IfFlow, Parallel, Select, Sequential
Параллельное отслеживание Действие IfFlow, последовательно
Condition Выражение IfFlow, Parallel, Sequential
Выбрать Condition, Sequential, Starter, ManualStarter Последовательный, должен быть первым узлом в потоке.
IfFlow Action, Condition, Delay, IfFlow, Parallel, Sequential, StateReader, Suppression Последовательно

DSL для автоматизации

В Home API автоматизация определяется с помощью Automation DSL (предметно-ориентированного языка). DSL автоматизации реализован как Kotlin DSL (предметно-ориентированный язык) с использованием типобезопасных построителей Kotlin и специально разработан для определения шаблонов автоматизации.

При компиляции автоматизации типобезопасные построители Kotlin генерируют классы данных Kotlin, которые затем сериализуются в JSON буфера протокола, используемый для вызовов сервисов автоматизации Google.

DSL автоматизации упрощает и оптимизирует процесс создания автоматизаций. В нем используется та же модель данных, что и в Device API, со стандартными характеристиками Matter и характеристиками smart home.

Кроме того, Automation 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.