В этом руководстве рассказывается, как использовать различные узлы DSL автоматизации для создания автоматизации.
Весь DSL автоматизации размещается в одном узле automation. Узел automation формирует границу между внешним контекстом языка Kotlin и встроенным контекстом 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 {...}
}
}
Вы можете добавить дополнительные узлы.
Для начинающих
Узлы условий определяют начальные обстоятельства, которые активируют автоматизацию. Например, изменение состояния или значения. В автоматизации должно быть хотя бы одно условие, иначе она не пройдет проверку. Чтобы добавить в автоматизацию несколько условий запуска, используйте узел select.
Стартовое условие на основе атрибута свойства
При объявлении начального узла, основанного на атрибуте признака, укажите:
- устройство
- тип устройства, к которому относится свойство;
- трейт
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
Параметр device type обязателен, поскольку он позволяет указать, к какому типу устройств относится автоматизация. Например, устройство может состоять из 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)))
}
Триггер на основе погоды
Вы можете указать текущие или прогнозируемые погодные условия в стартовом запросе, используя типаж "Погода":
val weatherState = starter<_>(structure, trait = Weather)
См. пример Закрыть жалюзи, если возможен дождь на странице Примеры автоматизаций.
Ручной стартер
Условие запуска вручную – это особый тип условия, который позволяет пользователю запускать автоматизацию вручную.
При объявлении условия запуска вручную:
- Не указывайте тип устройства или его характеристики.
- Добавьте элемент интерфейса, который вызывает
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.
Для этого сначала запишите значение атрибута trait в узел 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))
}
Продолжительность может составлять от 5 секунд до 24 часов.
Узлы действий
Узел действия – это место, где выполняется работа автоматизации.
В этом примере действие вызывает команду broadcast() типажа AssistantBroadcast:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Операторы import
При разработке автоматизаций не всегда очевидно, как импортировать различные элементы 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