Use o guia a seguir para entender como vários nós da DSL de automação podem ser usados para criar uma automação.
Todo o DSL de automação é colocado em um único nó automation
. O
nó automation
forma o limite entre o contexto externo da linguagem Kotlin
e o contexto DSL incorporado.
Fluxo sequencial
O fluxo sequencial é o tipo padrão de fluxo de automação.
Confira um modelo de DSL de automação muito básico que usa um fluxo sequencial composto por uma ativação, uma condição e uma ação:
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 {...}
}
}
Isso pode ser refinado adicionando outros nós.
Starter
Os nós de ativação definem as circunstâncias iniciais que ativam uma automação. Por exemplo, uma mudança de estado ou valor. Uma automação precisa ter pelo menos um iniciador. Caso contrário, a validação vai falhar. Para adicionar mais de um iniciador a uma automação, use um nó de seleção.
Starter com base no atributo de traço
Ao declarar um nó inicializador baseado em um atributo de traço, especifique:
- o dispositivo
- o tipo de dispositivo ao qual o atributo pertence
- o traço
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
O parâmetro de tipo de dispositivo é obrigatório porque permite especificar qual tipo de dispositivo
a automação aborda. Por exemplo, um dispositivo pode ser
composto por um
FanDevice
e um
HeatingCoolingUnitDevice
,
ambos contendo o
traço
OnOff
. Ao especificar o tipo de dispositivo, não há ambiguidade sobre qual parte
do dispositivo aciona a automação.
Ativação com base em eventos
Ao declarar um nó inicializador baseado em um evento, especifique:
- o dispositivo
- o tipo de dispositivo ao qual o atributo pertence
- o evento
starter<_>(doorBell, GoogleDoorbellDevice, DoorbellPressed)
Ativação com base em uma estrutura e um evento, com parâmetros
Alguns eventos podem ter parâmetros. Portanto, eles também precisam ser incluídos no iniciador.
Por exemplo, esta inicialização usa o
ScheduledTimeEvent
do atributo Time
para ativar a automação às 7h:
val earlyMorning = starter<_>(structure, Time.ScheduledTimeEvent) {
parameter(Time.ScheduledTimeEvent.clockTime(
LocalTime.of(7, 0, 0, 0)))
}
Ativação manual
Um ativador manual é um tipo especial de ativador que permite que o usuário execute a automação manualmente.
Ao declarar um ativador manual:
- Não especifique um tipo de característica ou dispositivo.
- Forneça um elemento de IU que chame
Automation.execute()
.
Ao colocar um inicializador manual em um fluxo select
com outro inicializador, o
inicializador manual substitui o outro:
select {
manualStarter()
starter<_>(thermostat, TemperatureSensorDevice, TemperatureMeasurement)
}
Todos os nós condition
que seguem um iniciador manual serão avaliados
e poderão bloquear a execução da automação, dependendo da expressão condition
.
Uma maneira de estruturar a automação para que os nós condition
não bloqueiem uma
automação ativada com um ativador manual é colocar o outro ativador
em um fluxo sequencial separado com o condition
:
automation_graph {
sequential {
select {
sequential {
starter<_>(...)
condition {...}
}
sequential {
manualStarter()
}
}
action {...}
}
}
Fazer referência ao valor de um atributo
Para usar o valor de um atributo em uma expressão, use a seguinte sintaxe.
Com um stateReader
:
val time = stateReader<_>(structure, Structure, Time)
val currTime = time.currentTime
Com um starter
:
val starterNode = starter<_>(device1, LaundryWasherDevice, OnOff)
condition() {
expression = starterNode.onOff equals true
}
Nós e expressões de condição
Um nó de condição representa um ponto de decisão que determina se a
automação continua ou não. Uma automação pode ter vários nós condition
.
Se a expressão de qualquer nó condition
for avaliada como false
, a execução de toda
a automação será encerrada.
Em um nó condition
, é possível combinar vários critérios de condição usando
vários operadores, desde que a expressão seja avaliada como um único
valor booleano. Se o valor resultante for true
, a condição será atendida e a
automação continuará a execução do próximo nó. Se for false
, a automação
vai parar de ser executada nesse ponto.
As expressões são formadas de maneira semelhante às expressões em Kotlin e podem conter valores primitivos, como números, caracteres, strings e booleanos, além de valores de tipo enumerado. O agrupamento de subexpressões com parênteses permite controlar a ordem em que elas são avaliadas.
Confira um exemplo de condition
que combina várias subexpressões em uma
única expressão:
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)
}
É possível fazer referência ao valor de um recurso acessado por um ativador:
val starterNode = starter<_>(device, OnOff)
condition() { expression = starterNode.onOff equals true }
stateReader
A outra maneira de referenciar valores de atributos de traço em um nó condition
é com
um nó stateReader
.
Para fazer isso, primeiro capture o valor do atributo de característica em um nó stateReader
. Um
stateReader
usa o structure
e o atributo como argumentos:
import com.google.home.automation.stateReader
...
val filterMonitoringState = stateReader<_>(structure, ActivatedCarbonFilterMonitoring)
Em seguida, faça referência ao stateReader
no nó condition
:
condition() {
expression =
filterMonitoringState.changeIndication
.equals(ChangeIndicationEnum.Warning)
}
Usando comparação e
operadores lógicos, é possível usar vários
stateReaders
em um nó condition
:
val armState = stateReader<_>(doorLock, DoorLockDevice, ArmDisarm )
val doorLockState = stateReader<_>(doorLock, DoorLockDevice, DoorLock)
condition() {
expression =
(armState.armState equals true)
and
(doorLockState.lockState equals true)
}
Duração da condição
Além de uma expressão booleana em uma condição, você pode especificar um período em que a expressão precisa ser verdadeira para executar a automação. Por exemplo, é possível definir uma condição que é acionada somente se uma luz estiver acesa por dez minutos.
condition {
expression(lightStateReader.onOff == true)
forDuration(Duration.ofMinutes(10))
}
A duração pode variar de um a 30 minutos.
Nós de ação
O nó de ação é onde o trabalho da automação acontece.
Neste exemplo, a ação invoca o comando
broadcast()
do atributo
AssistantBroadcast
:
action(device, SpeakerDevice) {
command(AssistantBroadcast.broadcast("Intruder detected!"))
}
Declarações de importação
Ao desenvolver automações, nem sempre é óbvio como importar vários elementos das APIs Home para o código.
Os atributos de traço são importados do objeto Companion
do traço:
import com.google.home.matter.standard.OnOff.Companion.onOff
Estruturas de dados definidas por um recurso são importadas da classe de recursos com nome que termina em "-Trait":
import com.google.home.matter.standard.MediaPlaybackTrait.PlaybackStateEnum
Os comandos de atributo são importados do objeto Companion
do atributo:
import com.google.home.matter.standard.Thermostat.Companion.setTemperatureSetpointHold