El DSL de automatización se puede usar para crear automatizaciones más complejas que las que se analizan en la guía de DSL: Automatizaciones básicas en Android.
Secuencial con varias acciones
Una automatización puede hacer más de una cosa. Por ejemplo, en lugar del nodo action único, podrías tener varios nodos action, que se ejecutan en orden secuencial:
automation {
sequential {
starter<_>(...)
condition {...}
action {...}
action {...}
action {...}
}
}
Secuencial con varias acciones paralelas
Si colocas varios nodos action en un nodo parallel, las acciones se ejecutan
de forma simultánea.
automation {
sequential {
starter<_>(...)
condition {...}
parallel {
action {...}
action {...}
action {...}
}
}
}
Si hay nodos action en el nodo sequential que vienen después del
nodo parallel, esperan para ejecutarse hasta que todos los nodos dentro del nodo parallel
hayan terminado de ejecutarse.
Ejecución condicional
De forma predeterminada, una automatización ejecuta nodos de forma secuencial o en paralelo. Si
necesitas una lógica de ramificación condicional (ejecutar diferentes acciones o rutas de acceso según
las condiciones del entorno de ejecución), usa declaraciones if-then-else, que se compilan con los
bloques de DSL de flujo de control condicional:
ifThen,
elseIf
y
orElse.
Mientras que un nodo condition estándar controla toda la automatización (si la condición
se evalúa como false, la automatización finaliza la ejecución de inmediato), los bloques ifThen
permiten ramificar el flujo de control:
- Nodo
condition: Detiene la ejecución de toda la automatización (o la ruta de ejecución actual) si la expresión esfalse. ifThen/elseIf/orElse: Evalúa las condiciones en orden. Si una condición esfalse, la ejecución pasa a la siguiente ramaelseIf, a la rama de resguardoorElseo continúa con los nodos posteriores de la automatización si no se cumple ninguna condición.
Ejecuta una acción según una condición
El bloque ifThen evalúa una expresión condicional. Si la expresión
se evalúa como true, se ejecutan las acciones o los nodos de DSL anidados dentro del
bloque. Si se evalúa como false, se omiten las acciones y la automatización continúa con los nodos posteriores en el flujo secuencial.
Puedes usar un bloque ifThen independiente cuando solo quieras realizar una acción de forma condicional sin bloquear ni finalizar los nodos posteriores de la automatización:
// 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."))
}
}
}
Ejecutar diferentes acciones según una condición
Para ejecutar un conjunto de acciones cuando una condición es verdadera y un conjunto alternativo de
acciones cuando es falsa, encadena el bloque .orElse { ... } opcional después de 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!"))
}
}
}
}
Encadena varias condiciones en secuencia
Puedes encadenar uno o más bloques .elseIf(...) { ... } opcionales para evaluar varias
condiciones en secuencia. Se ejecuta la primera rama cuya condición se evalúa como true y se omiten todas las ramas restantes. Si ninguna de las condiciones
se evalúa como true, se ejecuta un bloque .orElse { ... } opcional (si se proporciona):
// 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())
}
}
}
}
Flujos condicionales anidados
Los bloques condicionales se pueden anidar dentro de otros bloques ifThen, elseIf o orElse,
así como combinarse con nodos parallel, delayFor
y stateReader.
Los bloques ifThen, elseIf y orElse ejecutan su contenido como flujos secuenciales. Puedes colocar cualquier nodo secuencial dentro de cada rama, incluidos los bloques action, stateReader, parallel, delayFor y ifThen anidados.
Demoras
Puedes introducir pausas en tus automatizaciones con la palabra clave delayFor, que toma un argumento java.time.Duration que representa cuánto tiempo se debe pausar antes de continuar con la ejecución. La duración de la pausa puede ser de cinco segundos o de hasta 24 horas.
Por ejemplo, para activar o desactivar una luz cuatro veces con una pausa de cinco segundos entre cada activación o desactivación, haz lo siguiente:
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()) }
}
Supresión de activadores
La supresión de activadores es una función que permite que tu automatización ignore un
starter durante un período específico después del evento de activación inicial. Por
ejemplo, si la automatización tiene un starter que se activa con la detección de movimiento
y especificas una duración de supresión de activadores de cinco minutos, cuando se active el
starter, no se volverá a activar durante los próximos cinco minutos. Esto
evita que la automatización se active rápidamente una y otra vez.
Para aplicar la supresión de activadores a tu automatización, usa la palabra clave
suppressFor
con un argumento
java.time.Duration
que represente el tiempo de espera antes de responder a los activadores posteriores.
La duración de la supresión puede ser de tan solo cinco segundos o de hasta 24 horas.
automation {
sequential {
val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
suppressFor(Duration.ofMinutes(30))
action(light, OnOffLightDevice) { command(OnOff.toggle()) }
}
Ten en cuenta que la supresión de activadores afecta a todos los starters de una automatización que
preceden al suppressFor.
Limita la cantidad de ejecuciones
Puedes limitar la cantidad de veces que se permite ejecutar una automatización.
Por ejemplo, tal vez quieras configurar una automatización única que ejecute la aspiradora mientras estás fuera de casa durante el día.
Para ello, configura el campo de metadatos maxExecutionCount de la automatización.
El siguiente ejemplo es una automatización que solo se puede ejecutar una 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()) } } }
La automatización se borra de inmediato una vez que completa la ejecución por última
vez y se alcanza el maxExecutionCount. La entrada del historial de la automatización permanece
en la pestaña Actividad de Google Home app (GHA), incluida la automation_id.
Establece atributos de rasgos en una acción
Para establecer el valor de un atributo de rasgo, haz lo siguiente:
- Crea un nodo
updatedentro de un nodoaction, incluido el atributo relevante como argumento para el nodoupdate:action(deviceReference, deviceType) { update(trait) { } } - Dentro del nodo
update, para cada atributo que se modificará, usa una función mutadora y pásale el valor nuevo. Para formar el nombre de la función mutadora, sigue estos pasos:- Escribe el nombre del atributo con mayúscula inicial.
- Agrega el prefijo con la palabra
set.
defaultMoveRate, usarías una función mutadora llamadasetDefaultMoveRate.
Ten en cuenta que un nodo update puede tener varias funciones mutadoras. Este es un ejemplo en el que se actualizan dos atributos:
action(device, Fan) {
update(FanControl) {
setPercentSetting(50u)
setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
}
}