Используйте следующее руководство, чтобы понять, как различные узлы 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)))
}
Ручной стартер
Ручной пускатель — это особый тип пускателя, который позволяет пользователю вручную запускать автоматику.
При объявлении ручного стартера:
- Не указывайте характеристику или тип устройства.
- Предоставьте элемент пользовательского интерфейса, который вызывает
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