В этом руководстве рассказывается, как использовать различные узлы Automation DSL для создания автоматизации.
Весь код DSL для автоматизации размещается в одном узле automation. Узел automation образует границу между внешним контекстом языка Kotlin и встроенным контекстом DSL.
Последовательный поток
Последовательный процесс автоматизации используется по умолчанию.
Вот простой шаблон Automation 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)
Параметр типа устройства обязателен, поскольку позволяет указать, к какому устройству в составе устройства относится автоматизация. Например, устройство может состоять из 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.
Для этого сначала получите значение атрибута признака в узле 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!"))
}
Операторы импорта
При разработке автоматизаций не всегда очевидно, как импортировать различные элементы API Google Home в код.
Атрибуты признака импортируются из объекта 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