AboutBlogContact
ProductsESP DimmerESP Dimmer gen2Software Setup

Internal Automations

Prepare some internal automations!

What are Internal Automations?

Internal automations are a powerful way to create simple, core automations that run directly on your boneIO ESP controller. This means they will work even if your main smart home hub (like Home Assistant) is offline. They are perfect for critical functions, like turning on a light with a wall switch.

Basic Automation: Toggling a Light

Let's start with a default configuration that links a button press to a light.

binary_sensor:
  - platform: gpio
    name: 'IN_01'
    id: in_01
    pin:
      pcf8574: pcf_inputs
      number: 0
      mode:
        input: true
      inverted: true
    on_press: # This is our automation trigger
      then:
        - light.toggle: chl_01 # This is the action to perform

light:
  - platform: monochromatic
    output: chl01
    name: 'CHL 01'
    id: chl_01
    default_transition_length: 2s
    gamma_correct: 0

In the on_press: section, we define what happens when the button is pressed.
The action - light.toggle: chl_01 will toggle the state of the light with the ID chl_01.

Advanced Automation: Multi-Click

ESPHome allows you to define multiple actions for a single button based on how it's pressed (single, double, or long press). This is done using the on_multi_click component.

Let's configure one button (in_01) to control three different lights.

1. The Goal

  • Single Click: Toggle chl_01.
  • Double Click: Toggle chl_02.
  • Long Press: Toggle chl_03.

2. The Configuration

First, ensure you have your lights defined. Then, in your binary_sensor configuration, replace on_press with on_multi_click.

# Ensure these lights are defined elsewhere in your config
light:
  - platform: monochromatic
    output: chl01
    name: 'CHL 01'
    id: chl_01
    default_transition_length: 2s
    gamma_correct: 0
  - platform: monochromatic
    output: chl02
    name: 'CHL 02'
    id: chl_02
    default_transition_length: 2s
    gamma_correct: 0
  - platform: monochromatic
    output: chl03
    name: 'CHL 03'
    id: chl_03
    default_transition_length: 2s
    gamma_correct: 0

# Now, configure the multi-click automation
binary_sensor:
 - platform: gpio
    name: 'IN_01'
    id: in_01
    pin:
      pcf8574: pcf_inputs
      number: 0
      mode:
        input: true
      inverted: true
    on_multi_click:
      # Note: The order matters! ESPHome checks from top to bottom.
      # It's best to define the most complex patterns (longest clicks) first.

      # 1. Long Click Action
      - timing:
          - ON for at least 1.4s
        then:
          - logger.log: 'Long Click Detected, toggling Light 1'
          - light.toggle: chl_01

      # 2. Double Click Action
      - timing:
          - ON for at most 1s
          - OFF for at most 0.5s
          - ON for at most 1s
          - OFF for at least 0.2s
        then:
          - logger.log: 'Double Click Detected, toggling Light 2'
          - light.toggle: chl_02

      # 3. Single Click Action
      - timing:
          - ON for at most 1s
          - OFF for at least 0.5s
        then:
          - logger.log: 'Single Click Detected, toggling Light 3'
          - light.toggle: chl_03

3. How It Works

The on_multi_click automation checks a sequence of timing blocks from top to bottom. The first one that matches the user's button press pattern is executed.

  • timing: This defines the pattern of ON (pressed) and OFF (released) states. You can adjust the time values (e.g., at most 1s, at least 0.5s) to fine-tune the responsiveness, but the defaults are usually a good starting point.

  • then: This block contains the actions to be performed when the timing pattern is matched. We've included a logger.log action, which is very helpful for debugging your automations in the device logs.

By arranging the clicks from most complex (long press) to least complex (single press), you ensure that a long press doesn't also trigger the single press action.

Brightening lights with a button hold

binary_sensor:
  - platform: gpio
    name: 'IN_01'
    id: in_01
    pin:
      pcf8574: pcf_inputs
      number: 1
      mode:
        input: true
      inverted: true
    on_press:
      then:
        - while:
            condition:
              binary_sensor.is_on: in_01
            then:
              - if:
                  condition:
                    lambda: 'return id(chl_01).current_values.get_brightness() >= 0.90f;'
                  then:
                    - light.control:
                        id: chl_01
                        brightness: 0%
                    - light.turn_off:
                        id: chl_01
                  else:
                    - light.dim_relative:
                        id: chl_01
                        relative_brightness: 5%
                        transition_length: 0.2s
              - delay: 200ms

How it works

  • on_press trigger: Starts the automation when the button is pressed and immediately enters a while loop.
  • while with condition: binary_sensor.is_on: in_01 keeps looping for as long as the button remains physically pressed.
  • Brightness threshold: lambda: 'return id(chl_01).current_values.get_brightness() >= 0.90f;' reads the current brightness of chl_01 (0.0–1.0). Once it reaches ≥ 90%, it executes a shutdown sequence:
    • light.control: brightness: 0% sets brightness to 0 without a transition,
    • light.turn_off ensures the light is OFF.
  • Step brightening: If the threshold is not reached, light.dim_relative: relative_brightness: 5% increases brightness by 5% with a short 0.2s transition.
  • Update cadence: delay: 200ms sets the step frequency (every 200 ms) until the button is released or the threshold is reached.

Tips

  • Ensure a light with id: chl_01 exists in your light: configuration (see examples above).
  • Want to dim instead of brighten? Use a negative value, e.g. relative_brightness: -5%.
  • Adjust 5%, 0.2s, and 200ms to change step size, smoothness, and responsiveness.

Multi-Click: Single click — toggle, short hold — dimming

Warning

This code hasn't been tested in real life — it may not work without additional fixes.

binary_sensor:
  - platform: gpio
    name: 'IN_01_MultiClick_Dim'
    id: in_01
    pin:
      pcf8574: pcf_inputs
      number: 1
      mode:
        input: true
      inverted: true
    on_multi_click:
      # 1. Short hold: dim while holding
      - timing:
          - ON for at least 0.6s
        then:
          - while:
              condition:
                binary_sensor.is_on: in_01
              then:
                - light.dim_relative:
                    id: chl_01
                    relative_brightness: -5%
                    transition_length: 0.2s
                - delay: 200ms
      
      # 2. Single click: toggle the light
      - timing:
          - ON for at most 0.5s
          - OFF for at least 0.2s
        then:
          - light.toggle: chl_01

How it works

  • Pattern order: The shorter single-click pattern is placed last so it doesn't intercept the hold gesture.
  • Dim while holding: After ON for at least 0.6s, a loop reduces brightness by 5% every 200ms until release.
  • Tuning thresholds: Adjust 0.6s, 0.5s, and 0.2s to fine-tune gesture detection based on your button hardware and responsiveness needs.

Change RGBW color on click

Warning

This code hasn't been tested in real life — it may not work without additional fixes.

This example cycles through a predictable color palette on each click, so it's easy to reach common presets and return to white.

# Color palette exposed as a select (visible in Home Assistant)
select:
  - platform: template
    name: "RGBW Color Preset"
    id: rgbw_palette
    optimistic: true
    options:
      - White
      - Red
      - Green
      - Blue
      - Cyan
      - Magenta
      - Yellow
      - Amber
      - Purple
    set_action:
      # White (uses W channel)
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "White";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                white: 100%
                red: 0%
                green: 0%
                blue: 0%
      # Red
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Red";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 100%
                green: 0%
                blue: 0%
                white: 0%
      # Green
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Green";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 0%
                green: 100%
                blue: 0%
                white: 0%
      # Blue
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Blue";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 0%
                green: 0%
                blue: 100%
                white: 0%
      # Cyan
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Cyan";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 0%
                green: 100%
                blue: 100%
                white: 0%
      # Magenta
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Magenta";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 100%
                green: 0%
                blue: 100%
                white: 0%
      # Yellow
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Yellow";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 100%
                green: 100%
                blue: 0%
                white: 0%
      # Amber
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Amber";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 100%
                green: 60%
                blue: 0%
                white: 0%
      # Purple
      - if:
          condition:
            lambda: 'return id(rgbw_palette).state == "Purple";'
          then:
            - light.turn_on:
                id: rgbw_l
                brightness: 80%
                red: 60%
                green: 0%
                blue: 100%
                white: 0%

# Click = next color in the palette
binary_sensor:
  - platform: gpio
    id: in_01
    name: "IN_01_Color_Next"
    pin:
      pcf8574: pcf_inputs
      number: 1
      mode:
        input: true
      inverted: true
    on_press:
      then:
        - select.next: rgbw_palette

How it works

  • Palette as select: Lets you view and choose the current color from Home Assistant as well.
  • select.next on click: Each press advances to the next preset and applies it to rgbw_l.
  • Predictable set: A fixed list (White, Red, Green, …) makes operation simple and returning to White easy.

Tips

  • Make sure a rgbw_l RGBW light is defined in your light: configuration.
  • Optionally add double-click to jump to White, or a hold to dim/brighten.