Руководство DSL – базовая автоматизация,Руководство DSL – базовая автоматизация

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

Все DSL автоматизации размещаются в одном узле automation . Узел automation образует границу между внешним контекстом языка Kotlin и встроенным контекстом DSL.

Последовательный поток

Последовательный поток является типом потока автоматизации по умолчанию.

Пример последовательного DSL

Вот очень простой шаблон DSL автоматизации, в котором используется последовательный поток, состоящий из стартера, условия и действия:


import com.google.home.automation.action
import com.google.home.automation.automation
import com.google.home.automation.condition
import com.google.home.automation.sequential
import com.google.home.automation.starter

...

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

Это можно уточнить, добавив дополнительные узлы.

Стартер

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

Стартер на основе атрибута черты

При объявлении стартового узла, основанного на атрибуте типажа, укажите:

  • устройство
  • тип устройства, к которому принадлежит признак
  • черта
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)

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

Стартер по событию

При объявлении стартового узла, основанного на событии, укажите:

  • устройство
  • тип устройства, к которому принадлежит признак
  • событие
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)

Стартер на основе структуры и события, с параметрами

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

Например, этот стартер использует ScheduledTimeEvent свойства Time для активации автоматизации в 7:00 утра:

val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
  parameter(Time.ScheduledTimeEvent.clockTime(
    LocalTime.of(7, 0, 0, 0)))
}

Ручной стартер

Ручной пускатель – это особый тип пускателя, который позволяет пользователю вручную запускать автоматику.

При заявлении ручного пускателя:

  • Не указывайте характеристику или тип устройства.
  • Предоставьте элемент пользовательского интерфейса, который вызывает Automation.execute() .

При включении ручного пускателя в select поток вместе с другим пускателем ручной пускатель имеет приоритет над другим пускателем:

select {
  manualStarter()
  starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}

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

Отделение ручного пускателя от условного

Один из способов структурировать автоматизацию так, чтобы узлы condition не блокировали автоматику, активированную с помощью ручного пускателя, — это поместить другой пускатель в отдельный последовательный поток вместе с его condition :

automation_graph {
  sequential {
    select {
      sequential {
        starter<_>(...)
        condition {...}
      }
      sequential {
        manualStarter()
      }
    }
    action {...}
  }
}

Ссылка на значение атрибута

Чтобы использовать значение атрибута в выражении, используйте следующий синтаксис.

С помощью stateReader :

val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime

Со starter :

val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
  expression = starterNode.onOff equals true
}

Узлы условий и выражения

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

В узле condition вы можете комбинировать несколько критериев условия с помощью различных операторов , если выражение оценивается как одно логическое значение. Если полученное значение true , условие выполнено и автоматизация продолжает выполнение следующего узла. Если оно false , автоматизация прекращает выполнение в этот момент.

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

Вот пример condition , которое объединяет несколько подвыражений в одно выражение:

condition() {
  val expr1 = starterNode.lockState equals DlLockState.Unlocked
  val expr2 = stateReaderNode.lockState equals true

  val expr3 = occupancySensingDevice.occupied notEquals 0
  val expr4 = timeStateReaderNode
    .currentTime
    .between(
      timeStateReaderNode.sunsetTime,
      timeStateReaderNode.sunriseTime)
  expression = (expr1 and expr2) or (expr3 and expr4)
}

Вы можете ссылаться на значение признака, доступ к которому осуществляется через стартер:

val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }

StateReader

Другой способ ссылаться на значения атрибутов признаков в узле condition — с помощью узла stateReader .

Для этого сначала зафиксируйте значение атрибута типажа в узле stateReader . stateReader принимает structure и признак в качестве аргументов:

import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)

Затем обратитесь к stateReader в узле condition :

condition() {
  expression =
    filterMonitoringState.changeIndication
      .equals(ChangeIndicationEnum.Warning)
}

Используя операции сравнения и логические операторы , в узле condition можно использовать несколько stateReaders :

val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
  expression =
    (armState.armState equals true)
    and
    (doorLockState.lockState equals true)
}

Продолжительность состояния

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

  condition {
    expression(lightStateReader.onOff == true)
    forDuration(Duration.ofMinutes(10))
  }

Продолжительность может варьироваться от одной до 30 минут.

Узлы действий

Узел действия — это место, где происходит работа автоматизации. В этом примере действие вызывает команду broadcast() свойства AssistantBroadcast :

action(device, SpeakerDevice) {
  command(AssistantBroadcast.broadcast("Intruder detected!"))
}

Операторы импорта

При разработке средств автоматизации не всегда очевидно, как импортировать в код различные элементы Home API.

Атрибуты признака импортируются из объекта Companion признака:

import com.google.home.matter.standard.OnOff.Companion.onOff

Структуры данных, определенные признаком, импортируются из класса признака, имя которого заканчивается на «-Trait»:

import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum

Команды признака импортируются из объекта Companion признака:

import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold