Pojęcia dotyczące DSL w Androidzie

To jest przegląd podstawowych koncepcji języka DSL automatyzacji na Androidzie.

Komponenty automatyzacji

Automatyzacja składa się z tych podstawowych komponentów, które są zwykle oceniane w tej kolejności:

  1. Polecenie inicjujące – określa warunki początkowe, które aktywują automatyzację, np. zmianę cechy. Automatyzacja musi mieć element uruchamiający.
  2. Warunek – wszelkie dodatkowe ograniczenia, które należy ocenić po aktywowaniu automatyzacji. Aby działania automatyzacji mogły zostać wykonane, wyrażenie w warunku musi mieć wartość true.
  3. Działanie – polecenia lub aktualizacje stanu, które są wykonywane po spełnieniu wszystkich warunków.

Możesz na przykład mieć automatyzację, która przyciemnia światła w pomieszczeniu, gdy telewizor w tym pomieszczeniu jest włączony między zachodem a wschodem słońca. W tym przykładzie:

  1. Starter – telewizor został włączony, co jest zmianą stanu cechy telewizora.
  2. Warunek – sprawdzany jest aktualny czas w domu, w którym znajduje się telewizor.
  3. Działanie – światła w tym samym pomieszczeniu co telewizor zostaną przyciemnione.

Automatyzacja zostanie aktywowana po włączeniu telewizora w pomieszczeniu, ale zostanie wykonana tylko wtedy, gdy zostanie spełniony warunek „czas jest między zachodem a wschodem słońca”.

Oprócz podstawowej struktury automatyzacje w interfejsach Home API zawierają też metadane, takie jak nazwaopis, które mogą być używane do identyfikowania ich przez deweloperów i użytkowników.

Węzły

W interfejsach Home API logiczna struktura automatyzacji składa się z węzłów. Węzły to abstrakcyjne jednostki wielokrotnego użytku, które reprezentują zachowania jednostek lub przepływy wykonania. Każdy węzeł może mieć zmienne wejściowe i wyjściowe, które mogą być używane przez inne węzły.

Tabela: rodzaje węzłów automatyzacji
Węzeł Typ węzła Implementacja w języku Kotlin Opis
Starter Behawioralne StarterNodeDsl Uruchamia automatyzację, gdy zmieni się stan cechy (dowolny atrybut).
StateReader Behawioralne StateReaderNodeDsl Odczytuje atrybut cechy i umożliwia przechwytywanie jego wartości do użycia w węzłach warunków.
Działanie Behawioralne ActionNodeDsl Wywołuje polecenia atrybutów.
Sekwencyjna Przebieg wykonania SequentialFlow Wykonuje zagnieżdżone węzły działań po kolei. Jest to domyślne działanie.
Równoległe Przebieg wykonania ParallelFlow Wykonuje zagnieżdżone węzły działań równolegle.
Warunek Przebieg wykonania ConditionNodeDsl Warunkowo zmieniaj przepływ wykonywania na podstawie oceny wyrażeń logicznych. Warunki mogą być powiązane z początkiem rutyny (początek rutyny – określone warunki) lub być globalne (dotyczyć wszystkich początków rutyny).
Wybierz Przebieg wykonania SelectFlow Umożliwia aktywowanie automatyzacji przez więcej niż 1 element uruchamiający.
Wyrażenie Wartość Expression Może to być wartość atrybutu cechy, stała lub wartość literału i musi być obliczana jako lista, liczba, wartość logiczna lub ciąg znaków.

Węzły behawioralne

Węzły takie jak polecenia inicjujące i działania to węzły behawioralne. Elementy uruchamiające aktywują automatyzację na podstawie zmian atrybutów urządzenia. Działania wysyłają polecenia do urządzenia lub aktualizują atrybuty.

Węzły behawioralne są zwykle powiązane z cechami urządzenia i stanem cechy wyjściowej, aby można było ich używać jako danych wejściowych w innych węzłach.

Węzły przepływu wykonania

Niektóre węzły reprezentują przepływy wykonywania, np. sekwencyjne i równoległe. Każdy z tych węzłów zawiera węzły behawioralne, które definiują automatyzację.

Na przykład przepływ sekwencyjny może zawierać węzły, które są wykonywane w kolejności sekwencyjnej. Zwykle są to polecenie inicjujące, warunek i działanie.

Przepływy wykonywane sekwencyjnie
Ilustracja 1. Sekwencyjny przepływ automatyzacji

Przepływ równoległy może mieć wiele węzłów działania wykonywanych w tym samym czasie, np. włączanie kilku świateł jednocześnie. Węzły następujące po przepływie równoległym nie zostaną wykonane, dopóki nie zakończą się wszystkie gałęzie tego przepływu.

Przepływy wykonywane równolegle
Ilustracja 2. Równoległy przepływ automatyzacji

Innym typem przepływu wykonania jest przepływ warunkowy, który może zmieniać przepływ wykonania na podstawie oceny wyrażenia.

Możesz na przykład mieć automatyzację, która wykonuje działanie w zależności od tego, czy jest noc. Węzeł warunku sprawdza porę dnia, a następnie wybiera odpowiednią ścieżkę wykonania na podstawie tej oceny.

Przepływ warunku
Ilustracja 3. Przepływ warunku

Przepływ wyboru przydaje się, gdy chcesz mieć więcej niż 1 element początkowy, który może aktywować automatyzację. Jeśli umieścisz co najmniej 2 elementy początkowe w select, automatyzację może aktywować dowolny z nich.

Możesz na przykład utworzyć automatyzację, która opuszcza rolety o zachodzie słońca, jeśli temperatura wzrośnie powyżej określonego progu lub jeśli jasność przekroczy określony próg. Każdy z tych scenariuszy jest obsługiwany przez 3 osobne elementy początkowe, a wszystkie 3 są zawarte w select.

Wybierz przepływ
Rysunek 4. Wybierz ścieżkę

Zagnieżdżone przepływy

W przypadku złożonych automatyzacji węzły przepływu wykonania mogą być też zagnieżdżone. Możesz na przykład mieć przepływ sekwencyjny, który wykonuje przepływ równoległy.

Zagnieżdżone przepływy wykonania
Rysunek 5. Zagnieżdżone przepływy wykonywania

Węzły DSL można zagnieżdżać i łączyć na różne sposoby, aby spełnić konkretne potrzeby, zgodnie z ograniczeniami opisanymi w tabeli poniżej. Kolumna Builder zawiera link do dokumentacji bezpiecznego pod względem typów narzędzia do tworzenia w języku Kotlin, w której znajdziesz szczegółowe informacje o tym, co można używać w przypadku każdego typu węzła.

Tabela: sposób łączenia węzłów
Węzeł Może zawierać te typy węzłów i dane: Musi znajdować się w jednym z tych typów węzłów:
Starter Wyrażenie Wybierz opcję Sekwencyjne.
ManualStarter Wybierz opcję Sekwencyjne.
StateReader Wyrażenie (zwykle składające się z wartości atrybutu cechy) Działanie, warunek
Działanie Polecenie, Element, Wyrażenie Równoległe, Wybierz, Sekwencyjne
Sekwencyjna Równoległe, Wybierz, Sekwencyjne
Równoległe Działanie Sekwencyjny
Warunek Wyrażenie Równoległe, sekwencyjne
Wybierz Condition, Sequential, Starter, ManualStarter Sekwencyjny i musi być pierwszym węzłem w procesie.

DSL automatyzacji

W interfejsach Home API automatyzacje są definiowane za pomocą języka DSL (Domain-Specific Language) automatyzacji. DSL automatyzacji jest zaimplementowany jako Kotlin DSL (język specyficzny dla domeny) z użyciem bezpiecznych pod względem typów konstruktorów Kotlin i został zaprojektowany specjalnie do definiowania szablonów automatyzacji.

Gdy automatyzacja jest kompilowana, bezpieczne pod względem typów konstruktory Kotlin generują klasy danych Kotlin, które są następnie serializowane do formatu JSON bufora protokołu. Jest on używany do wykonywania wywołań usług automatyzacji Google.

Język DSL automatyzacji upraszcza i usprawnia proces tworzenia automatyzacji. Korzysta on natywnie z tego samego modelu danych, który jest używany w interfejsie Device API i zawiera Matter standardowe cechy oraz smart home cechy.

Język DSL automatyzacji określa też logikę automatyzacji w kategoriach abstrakcyjnych typów urządzeń, a nie konkretnych instancji urządzeń znajdujących się w domu użytkownika. Umożliwia deweloperowi podawanie parametrów wejściowych, które mogą być używane w czasie działania programu do określania rzeczywistych instancji urządzeń, a także innych ważnych wartości parametrów.

Składnia DSL jest podobna do składni języka Kotlin i jest równie bezpieczna pod względem typów, ale automatyzacja napisana w języku Automation DSL jest prostsza i bardziej zwięzła niż ta sama automatyzacja napisana w czystym języku Kotlin.

Przykład

Poniżej znajdziesz przykład automatyzacji, która włącza urządzenie. Jest ona napisana w języku DSL automatyzacji:

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()) }
  }
}

Ta automatyzacja jest bardzo prosta: gdy włącza się device1, czyli lampa (atrybut onOff zmienia się na true), wysyła polecenie on(), aby włączyć device2.

Automatyzacja korzysta z węzła sequential, co oznacza, że węzły będą uruchamiane w kolejności sekwencyjnej.

W węźle sequential znajdują się węzły związane z zachowaniem, takie jak starter, conditionaction. Dane wyjściowe węzła starter są przypisywane do zmiennej do użycia w węźle condition.