Esta é uma visão geral dos conceitos fundamentais da DSL de automação no Android.
Componentes de automação
Uma automação consiste nos seguintes componentes básicos, geralmente avaliados nesta ordem:
- Ativação: define as condições iniciais que ativam a automação, como uma mudança em uma característica. Uma automação precisa ter uma ativação.
- Condição: qualquer restrição adicional a ser avaliada depois que uma automação
for ativada. A expressão em uma condição precisa ser avaliada como
true
para que as ações de uma automação sejam executadas. - Ação: comandos ou atualizações de estado realizados quando todas as condições são atendidas.
Por exemplo, talvez você tenha uma automação que diminua as luzes de um cômodo quando a TV desse cômodo for ligada entre o pôr e o nascer do sol. Neste exemplo:
- Inicialização: a TV foi ligada, o que é uma mudança de estado em uma característica da TV.
- Condição: o horário atual da casa em que a TV está é avaliado.
- Ação: as luzes no mesmo ambiente da TV são diminuídas.
A automação seria ativada quando a TV da sala fosse ligada, mas só seria executada se a condição "o horário está entre o pôr e o nascer do sol" fosse atendida.
Além da estrutura básica, as automações nas APIs Home também contêm metadados, como name e description, que podem ser usados para identificar automações para desenvolvedores e usuários.
Nós
Nas APIs Home, a estrutura lógica de uma automação consiste em nós. Os nós são unidades abstratas e reutilizáveis que representam comportamentos de entidades ou fluxos de execução. Cada nó pode ter variáveis de entrada e de saída que podem ser consumidas por outros nós.
Nó | Tipo do nó | Implementação em Kotlin | Descrição |
---|---|---|---|
Starter | Comportamental |
StarterNodeDsl
|
Inicia uma automação quando o estado de uma característica (qualquer atributo) muda. |
StateReader | Comportamental |
StateReaderNodeDsl
|
Lê um atributo de traço e permite capturar o valor dele para uso em nós de condição. |
Ação | Comportamental |
ActionNodeDsl
|
Invoca comandos de traços. |
Sequencial | Fluxo de execução |
SequentialFlow
|
Executa nós de ação aninhados em sequência. Esse é o comportamento padrão de execução. |
Paralela | Fluxo de execução |
ParallelFlow
|
Executa nós de ação aninhados em paralelo. |
Condição | Fluxo de execução |
ConditionNodeDsl
|
Mudar condicionalmente o fluxo de execução com base em avaliações de expressões lógicas. As condições podem ser associadas a uma ação inicial (condições específicas da ação inicial) ou ser globais (aplicadas a todas as ações iniciais). |
Selecionar | Fluxo de execução |
SelectFlow
|
Permite que mais de uma ativação inicie uma automação. |
Expressão | Valor |
Expression
|
Pode ser o valor de um atributo de característica, uma constante ou um valor literal e precisa ser avaliado como uma lista, um número, um booleano ou uma string. |
Nós comportamentais
Nós como ativações e ações são comportamentais. As ativações iniciam uma automação com base em mudanças nos atributos do dispositivo. As ações emitem comandos de dispositivo ou atualizam atributos.
Os nós comportamentais geralmente estão vinculados a características do dispositivo e geram o estado da característica de saída para uso como entrada em outros nós.
Nós de fluxo de execução
Alguns nós representam fluxos de execução, como sequenciais e paralelos. Cada um desses nós contém os nós comportamentais que definem a automação.
Por exemplo, um fluxo sequencial pode conter nós que são executados em ordem sequencial. Normalmente, são ativação, condição e ação.
Um fluxo paralelo pode ter vários nós de ação em execução ao mesmo tempo, como acender várias luzes simultaneamente. Os nós que seguem um fluxo paralelo não serão executados até que todas as ramificações do fluxo paralelo sejam concluídas.
Outro tipo de fluxo de execução é um fluxo condicional, que pode mudar o fluxo de execução com base na avaliação de uma expressão.
Por exemplo, talvez você tenha uma automação que execute uma ação com base em se é noite. Um nó de condição verifica a hora do dia e segue o caminho de execução apropriado com base nessa avaliação.
Um fluxo de seleção é útil quando você quer ter mais de um
início que pode ativar sua automação. Quando você inclui duas ou mais ativações em um fluxo select
, qualquer uma delas pode ativar a automação.
Por exemplo, é possível escrever uma automação que abaixe as persianas ao pôr do sol, se a temperatura subir acima de um determinado limite ou se o brilho exceder um limite. Três inicializadores separados processam cada um desses cenários, e todos os três
seriam envolvidos em um fluxo select
.
Fluxos aninhados
Em automações complexas, os nós de fluxo de execução também podem ser aninhados. Por exemplo, é possível ter um fluxo sequencial que executa um fluxo paralelo.
Os nós da DSL podem ser aninhados e combinados de várias maneiras para atender às suas necessidades específicas, de acordo com as restrições descritas na tabela a seguir. A coluna "Builder" tem um link para a documentação do builder com segurança de tipo do Kotlin, que detalha o que pode ser usado em cada tipo de nó.
Nó | Pode conter o seguinte tipo de nó e dados | Precisa estar em um dos seguintes tipos de nó |
---|---|---|
Starter | Expressão | Selecionar, sequencial |
ManualStarter | Selecionar, sequencial | |
StateReader | Expressão (normalmente consistindo em um valor de atributo de traço) | Ação, condição |
Ação | Comando, Entidade, Expressão | Paralela, de seleção, sequencial |
Sequencial | Paralela, de seleção, sequencial | |
Paralela | Ação | Sequencial |
Condição | Expressão | Paralelo, sequencial |
Selecionar | Condition, Sequential, Starter, ManualStarter | Sequencial e precisa ser o primeiro nó no fluxo |
DSL de automação
Nas APIs Home, as automações são definidas usando a DSL de automação (linguagem específica de domínio). A DSL de automação é implementada como uma DSL do Kotlin (linguagem específica do domínio), usando builders com segurança de tipos do Kotlin e foi projetada especificamente para definir modelos de automação.
Quando uma automação é compilada, os builders com segurança de tipo do Kotlin geram classes de dados do Kotlin que são serializadas em JSON de buffer de protocolo, usado para fazer chamadas aos Serviços de automação do Google.
A DSL de automação simplifica e otimiza o processo de criação de automações. Ele usa nativamente o mesmo modelo de dados de características padrão Matter e smart home apresentadas na API Device.
A DSL de automação também define a lógica de uma automação em termos de tipos de dispositivos abstratos, em vez de instâncias específicas localizadas na casa de um usuário. Ele permite que o desenvolvedor forneça parâmetros de entrada que podem ser usados no ambiente de execução para especificar instâncias reais de dispositivos, bem como outros valores de parâmetros importantes.
A sintaxe da DSL é semelhante à do Kotlin e igualmente segura em relação a tipos, mas uma automação escrita na DSL de automação é mais simples e concisa do que a mesma automação escrita em Kotlin puro.
Exemplo
Confira a seguir um exemplo de automação que liga um dispositivo, escrito usando a DSL de automação:
val automation = automation {
name = "MyFirstAutomation"
description = "If light1 is on, turn on light2."
isActive = true
sequential {
val onOffTrait = starter<_>(device1, OnOffLightDevice, OnOff)
condition() { expression = onOffTrait.onOff equals true }
action(device2, OnOffLightDevice) { command(OnOff.on()) }
}
}
Essa automação é muito básica: quando device1
, uma luz acende (o atributo onOff
muda para true
) e envia o comando on()
para acender
device2
.
A automação usa um nó sequential
, o que indica que os nós serão executados em ordem sequencial.
No nó sequential
, há nós comportamentais, como starter
, condition
e action
. A saída do nó starter
é atribuída a uma variável para uso no nó condition
.