Automations and Scenes

Create automations triggered by ESP32 sensors and control ESP32 actuators from Home Assistant

A smart home without automations is just a collection of sensors and switches with a fancy dashboard. Automations are what make it smart -- they let your home react to conditions without you lifting a finger. In this article, you will learn how to create Home Assistant automations that use your ESP32 sensor data as triggers and control your ESP32 actuators as actions.

🔗The Trigger-Condition-Action Model

Every Home Assistant automation follows a three-part structure:

graph LR
    T[Trigger] --> C{Condition}
    C -->|passes| A[Action]
    C -->|fails| N[Nothing happens]
  • Trigger -- what starts the automation. "Temperature rises above 28 degrees," "motion detected," "time is 7:00 AM."
  • Condition (optional) -- additional checks that must pass. "Only if it is a weekday," "only between sunset and sunrise."
  • Action -- what happens. "Turn on the fan," "send a notification," "turn off the lights."

An automation can have multiple triggers (any one of them can start it), multiple conditions (all must be true), and multiple actions (they run in sequence).

🔗Creating Automations: UI vs. YAML

Home Assistant offers two ways to create automations:

🔗The Visual Editor (UI)

  1. Go to Settings > Automations & Scenes > Create Automation.
  2. Click Create new automation.
  3. Use the visual editor to select triggers, conditions, and actions from dropdown menus.

The UI editor is excellent for getting started. It shows all available options and validates your configuration as you build it.

🔗YAML

You can also write automations directly in YAML, either in the automation editor (click the three-dot menu and select Edit in YAML) or in your automations.yaml file.

YAML gives you more control and is easier to copy, share, and version-control. All the examples in this article show both approaches where practical.

🔗Example 1: Turn On Fan When Temperature Is High

This automation turns on a relay-controlled fan when the temperature from your ESP32 BME280 sensor exceeds $28\,\text{°C}$, and turns it off when it drops below $25\,\text{°C}$.

🔗UI Steps

  1. Trigger: Select Numeric state > Entity: sensor.office_sensor_temperature > Above: 28
  2. Action: Select Call service > Service: switch.turn_on > Entity: switch.office_relay

Then create a second automation for turning it off:

  1. Trigger: Numeric state > Entity: sensor.office_sensor_temperature > Below: 25
  2. Action: Call service > switch.turn_off > Entity: switch.office_relay

🔗YAML

- alias: "Turn on fan when temperature is high"
  description: "Activates the fan relay when office temperature exceeds 28°C"
  trigger:
    - platform: numeric_state
      entity_id: sensor.office_sensor_temperature
      above: 28
  action:
    - service: switch.turn_on
      target:
        entity_id: switch.office_relay

- alias: "Turn off fan when temperature drops"
  description: "Deactivates the fan relay when office temperature drops below 25°C"
  trigger:
    - platform: numeric_state
      entity_id: sensor.office_sensor_temperature
      below: 25
  action:
    - service: switch.turn_off
      target:
        entity_id: switch.office_relay

Why different thresholds (28 on, 25 off)? This creates a $3\,\text{°C}$ hysteresis band that prevents the fan from rapidly switching on and off when the temperature hovers around a single threshold. Without hysteresis, you would get annoying on-off-on-off cycling.

🔗Example 2: Motion-Activated Lights

This automation turns on a light when a PIR motion sensor detects movement, and turns it off 5 minutes after the last motion event.

🔗YAML

- alias: "Motion-activated hallway light"
  description: "Turns on the hallway light on motion, off after 5 minutes of no motion"
  trigger:
    - platform: state
      entity_id: binary_sensor.hallway_motion
      to: "on"
  condition:
    - condition: sun
      after: sunset
      before: sunrise
  action:
    - service: light.turn_on
      target:
        entity_id: light.hallway_light
      data:
        brightness_pct: 80
    - wait_for_trigger:
        - platform: state
          entity_id: binary_sensor.hallway_motion
          to: "off"
          for:
            minutes: 5
    - service: light.turn_off
      target:
        entity_id: light.hallway_light

This automation uses several important concepts:

  • Sun condition: The light only activates between sunset and sunrise. During the day, motion is ignored.
  • wait_for_trigger: Instead of a fixed timer, the automation waits for the motion sensor to stay "off" for 5 minutes. Every new motion event resets the timer.
  • Brightness: The brightness_pct parameter sets the light to 80% brightness.

🔗Example 3: Soil Moisture Notification

Send a push notification to your phone when the garden soil moisture drops below 20%:

🔗YAML

- alias: "Low soil moisture alert"
  description: "Sends a notification when garden soil is too dry"
  trigger:
    - platform: numeric_state
      entity_id: sensor.garden_sensor_node_soil_moisture
      below: 20
      for:
        minutes: 30
  condition:
    - condition: time
      after: "08:00:00"
      before: "22:00:00"
  action:
    - service: notify.mobile_app_your_phone
      data:
        title: "Garden needs water"
        message: >
          Soil moisture is {{ states('sensor.garden_sensor_node_soil_moisture') }}%.
          Time to water the plants!
        data:
          tag: "soil-moisture"

Key details:

  • for: minutes: 30 -- the soil moisture must stay below 20% for 30 minutes before the automation triggers. This prevents false alerts from a single bad reading.
  • Time condition -- notifications are only sent between 8 AM and 10 PM. Nobody wants a plant watering alert at 3 AM.
  • tag -- the notification tag ensures that repeated alerts replace each other instead of stacking up on your phone.
  • Templates -- the {{ states(...) }} syntax inserts the current sensor value into the message. Home Assistant uses Jinja2 templates for dynamic content.

🔗Example 4: Lights at Sunset

Turn on outdoor lights at sunset and off at sunrise:

🔗YAML

- alias: "Outdoor lights at sunset"
  description: "Turns on garden lights at sunset"
  trigger:
    - platform: sun
      event: sunset
      offset: "-00:15:00"
  action:
    - service: switch.turn_on
      target:
        entity_id: switch.garden_lights

- alias: "Outdoor lights off at sunrise"
  description: "Turns off garden lights at sunrise"
  trigger:
    - platform: sun
      event: sunrise
      offset: "00:15:00"
  action:
    - service: switch.turn_off
      target:
        entity_id: switch.garden_lights

The offset field adjusts the trigger time relative to the sun event. "-00:15:00" means 15 minutes before sunset (so lights come on while it is still getting dark), and "00:15:00" means 15 minutes after sunrise (so lights stay on until it is fully light).

🔗Example 5: Time-Based Automation with Multiple Actions

Run a morning routine at 7:00 AM on weekdays:

🔗YAML

- alias: "Weekday morning routine"
  description: "Activates morning settings on weekday mornings"
  trigger:
    - platform: time
      at: "07:00:00"
  condition:
    - condition: time
      weekday:
        - mon
        - tue
        - wed
        - thu
        - fri
  action:
    - service: light.turn_on
      target:
        entity_id: light.kitchen_light
      data:
        brightness_pct: 100
        color_temp_kelvin: 5000
    - service: switch.turn_on
      target:
        entity_id: switch.coffee_maker
    - delay:
        minutes: 30
    - service: switch.turn_off
      target:
        entity_id: switch.coffee_maker

This shows multiple sequential actions: turn on the kitchen light at full brightness (cool white for alertness), start the coffee maker, wait 30 minutes, then turn off the coffee maker.

🔗Scenes

A scene captures the state of multiple devices and lets you activate them all at once. Think of it as a snapshot of how you want things to look.

🔗Creating a Scene in the UI

  1. Go to Settings > Automations & Scenes > Scenes.
  2. Click Add Scene.
  3. Give it a name (e.g., "Movie Night").
  4. Add entities and set their desired states.

🔗Scene YAML Example

- name: "Movie Night"
  entities:
    light.living_room:
      state: "on"
      brightness: 30
      color_temp_kelvin: 2700
    light.kitchen_light:
      state: "off"
    switch.tv_backlight:
      state: "on"

- name: "All Lights Off"
  entities:
    light.living_room:
      state: "off"
    light.kitchen_light:
      state: "off"
    light.bedroom:
      state: "off"
    switch.garden_lights:
      state: "off"

Activate a scene from an automation:

action:
  - service: scene.turn_on
    target:
      entity_id: scene.movie_night

Scenes are useful for creating presets that you can trigger manually from the dashboard, from an automation, or via voice commands.

🔗Notification Actions

Home Assistant can send notifications through several channels:

🔗Mobile Push Notifications

Requires the Home Assistant Companion App on your phone:

action:
  - service: notify.mobile_app_your_phone
    data:
      title: "Alert Title"
      message: "Alert message body"

🔗Actionable Notifications

Push notifications with buttons that trigger automations:

action:
  - service: notify.mobile_app_your_phone
    data:
      title: "Garden is dry"
      message: "Soil moisture is low. Water the garden?"
      data:
        actions:
          - action: "WATER_GARDEN"
            title: "Water Now"
          - action: "DISMISS"
            title: "Dismiss"

Then create a separate automation to handle the button press:

- alias: "Handle water garden notification action"
  trigger:
    - platform: event
      event_type: mobile_app_notification_action
      event_data:
        action: "WATER_GARDEN"
  action:
    - service: switch.turn_on
      target:
        entity_id: switch.garden_pump
    - delay:
        minutes: 10
    - service: switch.turn_off
      target:
        entity_id: switch.garden_pump

🔗Telegram Notifications

For a free, self-hosted alternative to push notifications, you can use Telegram:

  1. Create a Telegram bot via @BotFather.
  2. Add the Telegram integration in Home Assistant.
  3. Use the notify.telegram service:
action:
  - service: notify.telegram
    data:
      title: "Home Alert"
      message: "Motion detected in the garden at {{ now().strftime('%H:%M') }}"

🔗Debugging Automations

When an automation does not work as expected, Home Assistant provides tools to figure out why.

🔗Automation Traces

Every time an automation runs (or attempts to run), Home Assistant records a trace:

  1. Go to Settings > Automations & Scenes.
  2. Click on the automation.
  3. Click Traces (top right).

The trace shows:

  • Whether the automation was triggered
  • Which trigger fired
  • Whether each condition passed or failed
  • What actions were executed
  • Any errors that occurred

This is the most valuable debugging tool. If a condition failed, the trace shows exactly which one and why.

🔗Developer Tools

Use Developer Tools > States to check the current state of any entity. This helps verify that your trigger entity has the value you expect.

Use Developer Tools > Services to test actions manually. You can call switch.turn_on on a specific entity to verify it works before putting it in an automation.

🔗Logbook

The Logbook (in the sidebar) shows a chronological list of all state changes and automation executions. Useful for verifying that events happened in the expected order.

🔗Common Debugging Issues

ProblemCauseSolution
Automation never triggersEntity ID is wrongCheck the exact entity ID in Developer Tools > States
Automation triggers but action failsService name wrong or entity unavailableTest the action manually in Developer Tools > Services
Numeric state trigger does not fireValue type mismatch (string vs number)Ensure the sensor reports a numeric value, not a string
Automation runs at wrong timeTime zone misconfiguredCheck Settings > System > General for the correct time zone
Automation runs multiple timesTrigger fires repeatedlyAdd a for duration to the trigger, or use a condition to check current state

🔗Template Automations

For more advanced logic, Home Assistant supports Jinja2 templates in automations. Templates let you do calculations, format strings, and make conditional decisions.

🔗Temperature Difference Alert

Alert when the difference between indoor and outdoor temperature exceeds $10\,\text{°C}$:

- alias: "Large temperature difference alert"
  trigger:
    - platform: template
      value_template: >
        {{ (states('sensor.indoor_temperature') | float -
            states('sensor.outdoor_temperature') | float) | abs > 10 }}
  action:
    - service: notify.mobile_app_your_phone
      data:
        message: >
          Big temperature difference!
          Indoor: {{ states('sensor.indoor_temperature') }}°C,
          Outdoor: {{ states('sensor.outdoor_temperature') }}°C

The | float filter converts the string state to a number, and | abs takes the absolute value so the alert works regardless of which side is warmer.

🔗Best Practices

Start simple. Create basic automations first and add complexity gradually. A working automation with one trigger and one action is better than a complex one that does not work.

Use meaningful names. Name your automations descriptively: "Turn on fan when office temperature exceeds 28°C" is much more useful than "Automation 1" when you have 30 automations.

Add descriptions. The description field is optional but helpful for remembering why you created an automation six months later.

Use hysteresis for threshold-based triggers. If you turn something on at 28 degrees, turn it off at 25 degrees. This prevents rapid cycling.

Test with Developer Tools before automating. Make sure the action works manually before putting it in an automation.

Group related automations. Use labels or naming conventions (prefix with room name or function) to keep your automation list organized.

🔗What is Next?

Your ESP32 sensors are now triggering automations in Home Assistant. The final article in this section shows you how to add voice control -- ask Alexa or Google Home about your sensor readings and control your ESP32 relays with voice commands.