This is an overview of the fundamental concepts of the Automation DSL iOS.

## 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 for iOS also
contain metadata, such as **name** and **description**, which can be used to
identify them for developers and users.

## Nodes

In the Home APIs for iOS, 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 | Swift implementation | Description |
|---|:---:|:---:|---|
| **Starter** | Behavioral | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Protocols/Starter ` | Starts an automation when a trait's state (any attribute) changes. |
| **StateReader** | Behavioral | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/StateReader ` | Reads a trait attribute and lets you to capture its value for use in condition nodes. |
| **Action** | Behavioral | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/Action ` | Invokes trait command(s). |
| **Sequential** | Execution flow | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/SequentialFlow ` | Executes nested action nodes in sequence. This is the default execution behavior. |
| **Parallel** | Execution flow | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/ParallelFlow ` | Executes nested action nodes in parallel. |
| **Condition** | Execution flow | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/Condition ` | 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 | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/SelectFlow ` | Allows more than one starter to activate an automation. |
| **IfFlow** | Execution flow | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/IfFlow ` | Runs at most one action (or branch) based on which condition (if any) evaluates to true (similar to an if-then-else statement). |
| **Expression** | Value | ` https://developers.home.google.com/reference/swift/GoogleHomeSDK/Protocols/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]
> **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*

An **if-then-else flow** (`IfFlow`) allows branching conditional execution
within an automation. Unlike a `condition` node, which stops the entire
automation if the condition is `false`, an if-then-else flow conditionally
executes specific actions when a condition is true, and can fall back to
alternative conditions or fallback actions, or continue to subsequent nodes in
the automation. For more details, see
[Conditional execution](https://developers.home.google.com/apis/ios/automation/dsl/complex#conditional-execution).

### 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.

| 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) | IfFlow, Parallel, Sequential |
| **Action** | Command, Entity, Expression | IfFlow, Parallel, Select, Sequential |
| **Sequential** | IfFlow, Parallel, Select, Sequential |   |
| **Parallel** | Action | IfFlow, Sequential |
| **Condition** | Expression | IfFlow, Parallel, Sequential |
| **Select** | Condition, Sequential, Starter, ManualStarter | Sequential, and must be the first node in the flow |
| **IfFlow** | Action, Condition, Delay, IfFlow, Parallel, Sequential, StateReader, Suppression | Sequential |
[*Table: How nodes may be combined*]

## Automation DSL for iOS

In the Home APIs for iOS, automations are defined using the Automation DSL
(Domain-Specific Language). The Automation DSL for iOS is specifically designed
for defining automation templates and is implemented using type-safe builders,
some of which leverage
[Swift Result Builders](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/advancedoperators#Result-Builders)
for building such flows and parameters. For example,
[`FlowBuilder`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/FlowBuilder) is used to
build a list of nodes for a flow and
[`ParameterBuilder`](https://developers.home.google.com/reference/swift/GoogleHomeSDK/Structs/ParameterBuilder)
to build parameters.

The Automation DSL for iOS simplifies and streamlines the process of building
automations. It natively uses the same data model of
Matter standard traits and smart home traits
featured in the Device API.

The Automation DSL for iOS 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.

### Example

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

    typealias OnOffTrait = Matter.OnOffTrait

    let draftAutomation = automation(
        name: "MyFirstAutomation",
        description: "Turn on a device when another device is turned on."
      ) {
        let onOffStarter = starter(light1, OnOffLightDeviceType.self, OnOffTrait.self)
        onOffStarter
        condition {
          onOffStarter.onOff.equals(true)
        }
        action(light2, OnOffLightDeviceType.self) {
          OnOffTrait.on()
        }
      }

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

An automation by default uses a `sequential` node as the first node, which
indicates that its child nodes will run in sequential order. This node type
does not need to be specified for the first node.

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.

### Void assignment statements

Note that for flow result builders in the Automation DSL for iOS, statements
with a `void` result are ignored by the `FlowBuilder`. Since an assignment
statement is void, a separate statement of the assignment result is needed to
add it to the flow.

This is seen in the earlier example:

    {
      // Assignment not auto-added to the flow
      let onOffStarter = starter(light1, OnOffLightDeviceType.self, OnOffTrait.self)
      // Required to add onOffStarter to the flow
      onOffStarter

      // Auto-added to the flow
      condition {
        onOffStarter.onOff.equals(true)
      }

      // Auto-added to the flow
      action(light2, OnOffLightDeviceType.self) {
        OnOffTrait.on()
      }
    }

This pattern is required when building automations in Swift using the
Automation DSL.