A DSL de automação pode ser usada para criar automações mais complexas do que as discutidas no guia de DSL: automações básicas no Android.
Sequencial com várias ações
Uma automação pode fazer mais de uma coisa. Por exemplo, em vez de um único nó
action, é possível ter vários nós action, que são executados em ordem
sequencial:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
Sequencial com várias ações paralelas
Se você colocar vários nós action em um nó parallel, as ações serão executadas
simultaneamente.
automation {
sequential {
starter<_>(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
}
Se houver nós action no nó sequential que vêm depois do nó parallel, eles vão aguardar a execução até que todos os nós dentro do nó parallel tenham terminado de ser executados.
Execução condicional
Por padrão, uma automação executa nós de forma sequencial ou em paralelo. Se você
precisar de uma lógica de ramificação condicional (executar ações ou caminhos diferentes com base em
condições de execução), use instruções if-then-else, que são criadas usando os
blocos de DSL de fluxo de controle condicional:
ifThen,
elseIf
e
orElse.
Enquanto um nó condition padrão controla toda a automação (se a condição
for avaliada como false, a automação encerra a execução imediatamente), os blocos ifThen
permitem o fluxo de controle de ramificação:
- Nó
condition: interrompe a execução de toda a automação (ou do caminho de execução atual) se a expressão forfalse. ifThen/elseIf/orElse: avalia as condições em ordem. Se uma condição forfalse, a execução passará para a próxima ramificaçãoelseIf, a ramificação de fallbackorElseou continuará para os nós seguintes na automação se nenhuma condição for atendida.
Executar uma ação com base em uma condição
O bloco ifThen avalia uma expressão condicional. Se a expressão
for avaliada como true, as ações ou os nós da DSL aninhados no bloco serão
executados. Se for avaliada como false, as ações serão ignoradas e a
automação vai continuar para os nós seguintes no fluxo sequencial.
É possível usar um bloco ifThen independente quando você quer realizar uma ação
condicionalmente sem bloquear ou encerrar os nós subsequentes na
automação:
// When a door opens, turn on the light only if it is off,
// and always broadcast an announcement.
automation {
sequential {
val contactState = starter<_>(
contactSensor,
ContactSensorDevice,
BooleanState,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
// Door opened (contact sensor open)
expression = contactState.stateValue equals false
}
// Conditionally turn on the light if it's off
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}
// Continue executing subsequent actions in the sequential flow
action(structure) {
command(AssistantBroadcast.broadcast("The door was opened."))
}
}
}
Executar ações diferentes com base em uma condição
Para executar um conjunto de ações quando uma condição for verdadeira e um conjunto alternativo de
ações quando for falsa, encadeie o bloco opcional .orElse { ... } após ifThen(...) { ... }:
// When the door is unlocked, turn on the entryway light if it is off;
// otherwise, broadcast a welcome message.
automation {
sequential {
val doorLockEvent = starter<_>(
doorLock,
DoorLockDevice,
LockOperationEvent,
)
val lightState = stateReader<_>(
light,
DimmableLightDevice,
OnOff,
)
condition {
expression =
doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock
}
ifThen(lightState.onOff equals false) {
action(light, DimmableLightDevice) { command(OnOff.on()) }
}.orElse {
action(structure) {
command(AssistantBroadcast.broadcast("Welcome home!"))
}
}
}
}
Encadear várias condições em sequência
É possível encadear um ou mais blocos .elseIf(...) { ... } opcionais para avaliar várias
condições em sequência. A primeira ramificação com condição avaliada como true é
executada, e todas as ramificações restantes são ignoradas. Se nenhuma das condições for avaliada como true, um bloco .orElse { ... } opcional será executado (se fornecido):
// Adjust climate controls based on room temperature changes.
automation {
sequential {
val tempStarter = starter<_>(
tempSensor,
TemperatureSensorDevice,
TemperatureMeasurement,
)
// If temperature is high (>= 28°C / 2800 mC), switch thermostat to Cool mode
ifThen(tempStarter.measuredValue greaterThanOrEquals 2800) {
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Cool
)
)
}
}.elseIf(tempStarter.measuredValue lessThan 1800) {
// If temperature is low (< 18°C / 1800 mC), switch to Heat mode
action(thermostat, ThermostatDevice) {
command(
SimplifiedThermostat.setSystemMode(
SimplifiedThermostatSystemModeEnum.Heat
)
)
}
}.orElse {
// Otherwise, turn on the fan
action(fan, FanDevice) {
command(OnOff.on())
}
}
}
}
Fluxos condicionais aninhados
Os blocos condicionais podem ser aninhados dentro de outros blocos ifThen, elseIf ou orElse,
além de serem combinados com nós parallel, delayFor
e stateReader.
Os blocos ifThen, elseIf e orElse executam o conteúdo como fluxos sequenciais. É possível colocar qualquer nó sequencial dentro de cada ramificação, incluindo
action, stateReader, parallel, delayFor e blocos ifThen aninhados.
Atrasos
É possível introduzir pausas nas automações usando a palavra-chave
delayFor, que usa um argumento
java.time.Duration
que representa o tempo de pausa antes de continuar a execução. A duração da pausa pode ser de cinco segundos a 24 horas.
Por exemplo, para acender e apagar uma luz quatro vezes com uma pausa de cinco segundos entre cada ação:
sequential {
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
delayFor(Duration.ofSeconds(5))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
Supressão de acionadores
A supressão de acionadores é um recurso que permite que a automação ignore um
starter por um período especificado após o evento de acionamento inicial. Por
exemplo, se a automação tiver um starter acionado pela detecção de movimento
e você especificar uma duração de supressão de acionador de cinco minutos, quando o
starter for acionado, ele não será acionado novamente pelos próximos cinco minutos. Isso
evita que a automação seja acionada repetidamente.
Para aplicar a supressão de ativação à automação, use a palavra-chave
suppressFor
com um argumento
java.time.Duration
que representa o tempo de espera antes de responder às ativações seguintes.
A duração da supressão pode ser de cinco segundos a 24 horas.
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
A supressão de acionadores afeta todos os starters em uma automação que
precedem o suppressFor.
Limitar o número de execuções
É possível limitar o número de vezes que uma automação pode ser executada.
Por exemplo, você pode configurar uma automação única que passa o aspirador de pó enquanto você está fora de casa durante o dia.
Para fazer isso, defina o campo de metadados
maxExecutionCount
da automação.
O exemplo a seguir é uma automação que só pode ser executada uma vez:
automation { // The automation can only be executed once. maxExecutionCount = 1 // When the door lock state changes sequential { val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent) // if the door is unlocked condition() { expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock) } // turn the light on action(light, DimmableLightDevice) { command(OnOff.on()) } } }
A automação é excluída imediatamente após a última execução,
quando maxExecutionCount é alcançado. A entrada do histórico da automação permanece
na guia Atividade do Google Home app (GHA), incluindo o automation_id.
Definir atributos de trait em uma ação
Para definir o valor de um atributo de trait:
- Crie um nó
updateem um nóaction, incluindo o atributo relevante como um argumento para o nóupdate:action(deviceReference, deviceType) { update(trait) { } } - No nó
update, para cada atributo a ser modificado, use uma função mutadora e transmita o novo valor. Para formar o nome da função mutadora:- Escreva o nome do atributo com letras maiúsculas
- Insira o prefixo com a palavra
set.
defaultMoveRate, use uma função mutadora chamadasetDefaultMoveRate.
Um nó update pode ter várias funções mutadoras. Veja um
exemplo em que dois atributos são atualizados:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}