Conceitos de DSL

Esta é uma visão geral dos conceitos fundamentais da DSL de automação.

Componentes de automação

Uma automação consiste nos seguintes componentes básicos, geralmente avaliados nesta ordem:

  1. Ativação: define as condições iniciais que ativam a automação, como uma mudança em um atributo. Uma automação precisa ter uma ativação.
  2. 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 prossigam.
  3. Ação: comandos ou atualizações de estado que são realizadas quando todas as condições foram atendidas.

Por exemplo, talvez você tenha uma automação que diminua o brilho das luzes de um cômodo quando a TV nesse cômodo estiver ligada entre o pôr e o nascer do sol. Neste exemplo:

  1. Inicialização: a TV foi ligada, o que é uma mudança de estado em um recurso de TV.
  2. Condição: o horário atual da casa em que a TV está é avaliado.
  3. Ação: as luzes no mesmo ambiente que a TV estão apagadas.

A automação seria ativada quando a TV no ambiente fosse ligada, mas só seria executada se a condição de "time is between sunset and sunrise" 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 identificá-los para desenvolvedores e usuários.

Nós

Nas APIs Home, a estrutura lógica de uma automação consiste em nodes. Os nós são unidades abstratas e reutilizáveis que representam comportamentos de entidade 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.

Tabela: tipos de nós de automação
Tipo do nó Implementação do Kotlin Descrição
Iniciante Comportamental StarterNodeDsl Inicia uma automação quando o estado de um recurso (qualquer atributo) muda.
StateReader Comportamental StateReaderNodeDsl Lê um atributo de característica e permite capturar o valor dele para uso em nós de condição.
Ação Comportamental ActionNodeDsl Invoca comandos de traço.
Sequencial Fluxo de execução SequentialFlow Executa nós de ação aninhados em sequência. Esse é o comportamento de execução padrão.
Paralelo 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 nas avaliações de expressões lógicas. As condições podem ser associadas a um ativador (condições específicas do ativador) ou globais (aplicáveis a todos os ativadores).
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 do atributo de um elemento, 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 comportamentos. As ativações ativam uma automação com base nas mudanças de atributo do dispositivo. As ações emitem comandos do dispositivo ou atualizam atributos.

Os nós comportamentais geralmente são vinculados a características do dispositivo e ao estado da característica de saída para uso como entrada em outros nós.

Nós do 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.

Fluxos de execução sequenciais
Figura 1: fluxo de automação sequencial

Um fluxo paralelo pode ter vários nós de ação sendo executados ao mesmo tempo, como acender várias luzes ao mesmo tempo. Os nós que seguem um fluxo paralelo não são executados até que todos os ramos do fluxo paralelo terminem.

Fluxos de execução paralelos
Figura 2: fluxo de automação paralela

Outro tipo de fluxo de execução é o fluxo de condição, 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 realiza 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.

Fluxo de condição
Figura 3: fluxo de condição

Um fluxo de seleção é útil quando você quer ter mais de um acionador que possa ativar a automação. Quando você inclui dois ou mais ativações em um fluxo select, qualquer uma delas pode ativar a automação.

Por exemplo, você pode 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 agrupados em um fluxo select.

Selecionar fluxo
Figura 4: fluxo de seleção

Fluxos aninhados

Em automações complexas, os nós do fluxo de execução também podem ser aninhados. Por exemplo, você pode ter um fluxo sequencial que executa um fluxo paralelo.

Fluxos de execução aninhados
Figura 5: fluxos de execução aninhados

Os nós de 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 faz referência à documentação do builder com segurança de tipo do Kotlin, que detalha o que é permitido usar em cada tipo de nó.

Tabela: como os nós podem ser combinados
Builder Pode conter o tipo de nó e os dados a seguir Precisa estar em um dos seguintes tipos de nó
Iniciante AutomationBuilder Expressão Selecionar, sequencial
ManualStarter AutomationBuilder Selecionar, sequencial
StateReader AutomationBuilder Expressão (normalmente consiste em um valor de atributo de característica) Ação, condição
Ação ActionBuilder Comando, entidade, expressão Paralelo, seleção, sequencial
Sequencial SequentialFlowBuilder Paralelo, seleção, sequencial
Paralelo ParallelFlowBuilder Ação Sequencial
Condição ConditionBuilder Expressão Paralelo, sequencial
Selecionar AutomationBuilder Condição, sequencial, inicializador, 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 (linguagens específicas de 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, que é usado para fazer chamadas aos Serviços de automação do Google.

O Automation DSL simplifica e agiliza o processo de criação de automações. Ele usa de forma nativa o mesmo modelo de dados de características padrão Matter e características smart home apresentadas na API Device.

O Automation DSL também define a lógica de uma automação em termos de tipos de dispositivos abstratos, em vez de instâncias de dispositivos específicos localizadas na casa de um usuário. Ele permite que o desenvolvedor forneça parâmetros de entrada que podem ser usados no momento da execução para especificar instâncias de dispositivo reais, além de outros valores de parâmetro importantes.

A sintaxe da DSL é semelhante à do Kotlin e tem a mesma segurança de 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 ativa um dispositivo, escrito usando o 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), ele envia o comando on() para acender device2.

A automação usa um nó sequential, 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.