This is an overview of the fundamental concepts of the Automation DSL on
Android.

## Automation components

An automation consists of the following basic components, typically evaluated in
this order:

1. **Starter** --- Defines the initial conditions that activate the automation, such as a change to a trait. An automation must have a starter.
2. **Condition** --- Any additional constraints to evaluate after an automation has been activated. The expression in a Condition must evaluate to `true` in order for the actions of an automation to proceed.
3. **Action** --- Commands or state updates that are performed when all conditions have been met.

For example, perhaps you have an automation that dims the lights in a room when
the TV in that room is turned on between sunset and sunrise. In this example:

1. **Starter** --- The TV was turned on, which is a change in state on a TV trait.
2. **Condition**--- The current time for the home the TV is in is evaluated.
3. **Action** --- The lights in the same room as the TV are dimmed.

The automation would be activated when the TV in the room is turned on, but the
automation only executes if the condition of "time is between sunset and
sunrise" is met.

In addition to the basic structure, automations in the Home APIs also contain
metadata, such as **name** and **description**, which can be used to identify
them for developers and users.

## Nodes

In the Home APIs, the logical structure of an automation consists of **nodes**.
Nodes are abstract, reusable units that represent entity behaviors or execution
flows. Each node can have input variables, as well as output variables that may
be consumed by other nodes.

| Node | Node Type | Kotlin implementation | Description |
|---|:---:|:---:|---|
| **Starter** | Behavioral | ` `[StarterNodeDsl](https://developers.home.google.com/reference/kotlin/com/google/home/automation/StarterNodeDsl)` ` | Starts an automation when a trait's state (any attribute) changes. |
| **StateReader** | Behavioral | ` `[StateReaderNodeDsl](https://developers.home.google.com/reference/kotlin/com/google/home/automation/StateReaderNodeDsl)` ` | Reads a trait attribute and lets you to capture its value for use in condition nodes. |
| **Action** | Behavioral | ` `[ActionNodeDsl](https://developers.home.google.com/reference/kotlin/com/google/home/automation/ActionNodeDsl)` ` | Invokes trait command(s). |
| **Sequential** | Execution flow | ` `[SequentialFlow](https://developers.home.google.com/reference/kotlin/com/google/home/automation/SequentialFlow)` ` | Executes nested action nodes in sequence. This is the default execution behavior. |
| **Parallel** | Execution flow | ` `[ParallelFlow](https://developers.home.google.com/reference/kotlin/com/google/home/automation/ParallelFlow)` ` | Executes nested action nodes in parallel. |
| **Condition** | Execution flow | ` `[ConditionNodeDsl](https://developers.home.google.com/reference/kotlin/com/google/home/automation/ConditionNodeDsl)` ` | Conditionally change execution flow based on evaluations of logical expressions. Conditions may be associated with a starter (starter specific conditions) or be global (apply to all starters). |
| **Select** | Execution flow | ` `[SelectFlow](https://developers.home.google.com/reference/kotlin/com/google/home/automation/SelectFlow)` ` | Allows more than one starter to activate an automation. |
| **Expression** | Value | ` `[Expression](https://developers.home.google.com/reference/kotlin/com/google/home/automation/Expression)` ` | May be the value of a trait's attribute, a constant, or a literal value, and must evaluate to a list, number, boolean, or string. |
[*Table: Types of automation nodes*]

### Behavioral nodes

Nodes such as starters and actions are behavioral nodes. Starters activate an
automation based on device attribute changes. Actions issue device
commands or update attributes.

Behavioral nodes are typically tied to device traits and output trait state for
use as input in other nodes.

### Execution flow nodes

Some nodes represent execution flows, such as sequential and parallel.
Each of these nodes contain the behavioral nodes that define the automation.

For example, a **sequential** flow may contain nodes that execute in
sequential order. Typically, these would be starter, condition, and action.
![Sequential execution flows](https://developers.home.google.com/static/apis/images/apis-automation-flow-sequential.svg) *Figure 1: Sequential automation flow*

A **parallel** flow may have multiple action nodes executing at the same time,
such as turning on multiple lights at the same time. Nodes following a parallel
flow won't execute until all branches of the parallel flow finish.
![Parallel execution flows](https://developers.home.google.com/static/apis/images/apis-automation-flow-parallel.svg) *Figure 2: Parallel automation flow*

Another type of execution flow is a **condition flow**, which can change the
execution flow based on the evaluation of an expression.

For example, perhaps you have an automation that performs an action based on
whether it is nighttime. A condition node checks the time of day, then follows
the appropriate execution path based on that evaluation.
![Condition flow](https://developers.home.google.com/static/apis/images/apis-automation-flow-condition.svg) *Figure 3: Condition flow*


A **select flow** is useful when you want to have more than one
starter that can activate your automation. When you enclose two or more starters
in a `select` flow, any one of the starters can activate the automation.

For example, you could write an automation that lowers the blinds at sunset, if
the temperature rises above a certain threshold, or if the brightness exceeds a
threshold. Three separate starters handle each of these scenarios, and all three
would be wrapped in a `select` flow.
| **Important:** A `select` flow must be the first node in a `sequential` flow, and cannot be placed in a `parallel` flow or nested within another `select` flow.
![Select flow](https://developers.home.google.com/static/apis/images/apis-automation-flow-select.svg) *Figure 4: Select flow*

### Nested flows

In complex automations, execution flow nodes can also be nested. For example,
you may have a sequential flow that executes a parallel flow.
![Nested execution flows](https://developers.home.google.com/static/apis/images/apis-automation-flow-nested.svg) *Figure 5: Nested execution flows*

DSL nodes can be nested and combined in various ways to meet your specific
needs, according to constraints outlined in the following table. The Builder
column links to the Kotlin typesafe builder documentation, which details what is
allowed for use in each type of node.

| Node | May contain the following node type and data | Must be within one of the following node types |
|---|---|---|
| **Starter** | Expression | Select, Sequential |
| **ManualStarter** |   | Select, Sequential |
| **StateReader** | Expression (typically consisting of a trait attribute value) | Action, Condition |
| **Action** | Command, Entity, Expression | Parallel, Select, Sequential |
| **Sequential** | Parallel, Select, Sequential |   |
| **Parallel** | Action | Sequential |
| **Condition** | Expression | Parallel, Sequential |
| **Select** | Condition, Sequential, Starter, ManualStarter | Sequential, and must be the first node in the flow |
[*Table: How nodes may be combined*]

## Automation DSL

In the Home APIs, automations are defined using the Automation DSL
(Domain-Specific Language). The Automation DSL is implemented as a
[Kotlin DSL (domain-specific
language)](https://kotlinlang.org/docs/type-safe-builders.html),
using Kotlin type-safe builders and is specifically designed for defining
automation templates.

When an automation is compiled, Kotlin type-safe builders generate Kotlin data
classes that are then serialized to protocol buffer JSON, which is used to make
calls to Google's Automation Services.

The Automation DSL simplifies and streamlines the process of building
automations. It natively uses the same [data model](https://developers.home.google.com/apis/android/data-model) of
Matter standard traits and smart home traits
featured in the Device API.

The Automation DSL also defines the logic of an automation in terms of abstract
device types, as opposed to specific device instances located in a user's home.
It allows the developer to provide input parameters that may be used at runtime
to specify actual device instances, as well as other important parameter values.

The DSL syntax is similar to Kotlin's, and is equally type-safe, but an
automation written in the Automation DSL is simpler and more concise than the
same automation written in pure Kotlin.

### Example

The following is an example automation that turns on a device, written using the
Automation DSL:  

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

This automation is very basic: when `device1`, a light, turns on (the `onOff`
attribute changes to `true`), then sends the `on()` command to turn
`device2` on.

The automation uses a `sequential` node, which indicates that its nodes will run
in sequential order.

Within the `sequential` node are behavioral nodes such as `starter`,
`condition`, and `action`. The output of the `starter` node is assigned to a
variable for use in the `condition` node.