My TV Remote Stopped Working… So I Made My Own.

UPDATE

V2.1 of the YAML removes the battery monitor function. It appears that most of the LOLIN Boards don’t have voltage dividers on the module, which makes them incompatible with the battery monitor code.

 

Build Your Own Everything Remote

You’re in the right place — this page has everything you’ll need to build your own Everything Remote.

Here you'll find links to the 3D printable files (hosted on Printables), the PCB project listing (on PCBWay), plus the ESPHome configuration and automation examples to help you get started.

This isn’t a step-by-step guide — if you’re looking for that, check out the full build tutorial below. This page is your resource hub, with all the files and info you need to bring your own Everything Remote to life.


 

It seems the Aliexpress ESP Board links may be broken, use the search term ‘wemos lolin32 lite’ on aliexpress to find the right board. Be sure to get the USB C variant!


Pins -> Buttons

I swear this made sense at some point


My ESPHome YAML

V2.1

The Deep sleep version (1-2 week battery life with regular use. This version only wakes the remote when you tap the power button (GPIO0). It reboots and reconnects to wifi in about 2 seconds for me, so it has barely affected my use case.

The remote will go to sleep after no activity for 20 minutes (you can change this timeout if you’d like)

esphome:
  name: everything_remote
  friendly_name: Everything Remote
  on_boot:
    - priority: 250
      then:
        - lambda: |-
            id(last_active) = millis() / 1000;
            id(wake_button_processed) = false;

            auto cause = esp_sleep_get_wakeup_cause();
            if (cause == ESP_SLEEP_WAKEUP_EXT0) {
              ESP_LOGI("main", "Device woke up by EXT0");
            } else if (cause == ESP_SLEEP_WAKEUP_TIMER) {
              ESP_LOGD("main", "Device woke up by timer.");
            } else {
              ESP_LOGD("main", "Device woke up by other cause: %d", cause);
            }

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:

api:

ota:
  platform: esphome

wifi:
  ssid: "my_wifi"
  password: "my_password"
  fast_connect: true
  power_save_mode: LIGHT

globals:
  - id: last_active
    type: int
    restore_value: no
    initial_value: '0'
  - id: wake_button_processed
    type: bool
    restore_value: no
    initial_value: 'false'

script:
  - id: reset_idle_timer
    then:
      - lambda: |-
          id(last_active) = millis() / 1000;

deep_sleep:
  id: deep_sleep_ctrl
  sleep_duration: 2800 min
  wakeup_pin:
    number: GPIO0
    inverted: true
    allow_other_uses: true

interval:
  - interval: 60s
    then:
      - if:
          condition:
            lambda: return (millis() / 1000) - id(last_active) >= 1200;
          then:
            - deep_sleep.enter: deep_sleep_ctrl

# BUTTONS
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      mode:
        input: true
        pullup: true
      inverted: true
      allow_other_uses: true
    name: "Power"
    id: power
    internal: true
    on_press:
      then:
        - script.execute: reset_idle_timer
        - homeassistant.event:
            event: esphome.remote_button_pressed
            data: {button: "power", type: "single"}

  - platform: gpio
    pin:
      number: GPIO2
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Back"
    id: back
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "back", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "back", type: "long"}

  - platform: gpio
    pin:
      number: GPIO4
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Home"
    id: home
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "home", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "home", type: "long"}

  - platform: gpio
    pin:
      number: GPIO5
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Play Pause"
    id: play_pause
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "play_pause", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "play_pause", type: "long"}

  - platform: gpio
    pin:
      number: GPIO18
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Up"
    id: up
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "up", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "up", type: "long"}

  - platform: gpio
    pin:
      number: GPIO19
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Left"
    id: left
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "left", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "left", type: "long"}

  - platform: gpio
    pin:
      number: GPIO22
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Select"
    id: select_button 
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "select_button", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "select_button", type: "long"}

  - platform: gpio
    pin:
      number: GPIO23
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Right"
    id: right
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "right", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "right", type: "long"}

  - platform: gpio
    pin:
      number: GPIO25
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Down"
    id: down
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "down", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "down", type: "long"}

  - platform: gpio
    pin:
      number: GPIO12
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Volume Up"
    id: volume_up
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "volume_up", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "volume_up", type: "long"}

  - platform: gpio
    pin:
      number: GPIO13
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Mute"
    id: mute
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "mute", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "mute", type: "long"}

  - platform: gpio
    pin:
      number: GPIO14
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Channel Up"
    id: channel_up
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "channel_up", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "channel_up", type: "long"}

  - platform: gpio
    pin:
      number: GPIO15
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Volume Down"
    id: volume_down
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "volume_down", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "volume_down", type: "long"}

  - platform: gpio
    pin:
      number: GPIO16
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Settings"
    id: settings
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "settings", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "settings", type: "long"}

  - platform: gpio
    pin:
      number: GPIO17
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Channel Down"
    id: channel_down
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "channel_down", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "channel_down", type: "long"}

  - platform: gpio
    pin:
      number: GPIO32
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Shortcut 3"
    id: shortcut_3
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_3", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_3", type: "long"}

  - platform: gpio
    pin:
      number: GPIO33
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Shortcut 4"
    id: shortcut_4
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_4", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_4", type: "long"}

  - platform: gpio
    pin:
      number: GPIO26
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Brightness Down"
    id: brightness_down
    internal: false 
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "brightness_down", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "brightness_down", type: "long"}

  - platform: gpio
    pin:
      number: GPIO27
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Brightness Up"
    id: brightness_up
    internal: false 
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "brightness_up", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "brightness_up", type: "long"}

  - platform: gpio
    pin:
      number: GPIO34
      mode:
        input: true
      inverted: true
    name: "Shortcut 1"
    id: shortcut_1
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_1", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_1", type: "long"}

  - platform: gpio
    pin:
      number: GPIO35
      mode:
        input: true
      inverted: true
    name: "Shortcut 2"
    id: shortcut_2
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_2", type: "single"}
      - timing:
          - ON for at least 500ms
        then:
          - script.execute: reset_idle_timer
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data: {button: "shortcut_2", type: "long"}

V1.0

This is the Light Sleep version of the YAML, for instant responses, but 24 hour battery life.

esphome:
  name: everything-remote
  friendly_name: Everything Remote
  min_version: 2024.11.0
  name_add_mac_suffix: false

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
# logger:

# Enable Home Assistant API
api:

# Allow Over-The-Air updates
ota:
- platform: esphome

wifi:
  ssid: my_wifi
  password: my_password
  output_power: 10db
  fast_connect: True
  power_save_mode: LIGHT

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO0
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Power"
    id: power
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: power
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: power
                type: long
  - platform: gpio
    pin:
      number: GPIO2
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Back"
    id: back
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: back
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: back
                type: long
  - platform: gpio
    pin:
      number: GPIO4
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Home"
    id: home
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: home
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: home
                type: long
  - platform: gpio
    pin:
      number: GPIO5
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Play Pause"
    id: play_pause
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: play_pause
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: play_pause
                type: long
  - platform: gpio
    pin:
      number: GPIO18
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Up"
    id: up
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: up
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: up
                type: long
  - platform: gpio
    pin:
      number: GPIO19
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Left"
    id: left
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: left
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: left
                type: long
  - platform: gpio
    pin:
      number: GPIO22
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Select"
    id: select_button
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: select_button
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: select_button
                type: long
  - platform: gpio
    pin:
      number: GPIO23
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Right"
    id: right
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: right
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: right
                type: long
  - platform: gpio
    pin:
      number: GPIO25
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Down"
    id: down
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: down
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: down
                type: long
  - platform: gpio
    pin:
      number: GPIO12
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Volume Up"
    id: volume_up
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: volume_up
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: volume_up
                type: long
  - platform: gpio
    pin:
      number: GPIO13
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Mute"
    id: mute
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: mute
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: mute
                type: long
  - platform: gpio
    pin:
      number: GPIO14
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Channel Up"
    id: channel_up
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: channel_up
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: channel_up
                type: long
  - platform: gpio
    pin:
      number: GPIO15
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Volume Down"
    id: volume_down
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: volume_down
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: volume_down
                type: long
  - platform: gpio
    pin:
      number: GPIO16
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Settings"
    id: settings
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: settings
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: settings
                type: long
  - platform: gpio
    pin:
      number: GPIO17
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Channel Down"
    id: channel_down
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: channel_down
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: channel_down
                type: long
  - platform: gpio
    pin:
      number: GPIO32
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Shortcut 3"
    id: shortcut_3
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_3
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_3
                type: long
  - platform: gpio
    pin:
      number: GPIO33
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Shortcut 4"
    id: shortcut_4
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_4
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_4
                type: long
  - platform: gpio
    pin:
      number: GPIO26
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Brightness Down"
    id: brightness_down
    internal: false
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: brightness_down
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: brightness_down
                type: long
  - platform: gpio
    pin:
      number: GPIO27
      mode:
       input: true
       pullup: true
      inverted: true
    name: "Brightness Up"
    id: brightness_up
    internal: false
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: brightness_up
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: brightness_up
                type: long
  - platform: gpio
    pin:
      number: GPIO34
      mode:
       input: true
      inverted: true
    name: "Shortcut 1"
    id: shortcut_1
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_1
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_1
                type: long
  - platform: gpio
    pin:
      number: GPIO35
      mode:
       input: true
      inverted: true
    name: "Shortcut 2"
    id: shortcut_2
    internal: true
    on_multi_click:
      - timing:
          - ON for at most 350ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_2
                type: single
      - timing:
          - ON for at least 500ms
        then:
          - homeassistant.event:
              event: esphome.remote_button_pressed
              data:
                button: shortcut_2
                type: long

My Automation YAML

Here’s the YAML for my Samsung TV navigation automation

alias: Remote - Navigation
description: Maps ESPHome button events to Samsung TV Smart key commands
triggers:
  - event_type: esphome.remote_button_pressed
    trigger: event
conditions: []
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'up' and trigger.event.data.type
              == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_UP
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'down' and trigger.event.data.type
              == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_DOWN
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'left' and trigger.event.data.type
              == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_LEFT
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'right' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_RIGHT
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'select_button' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_ENTER
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'back' and trigger.event.data.type
              == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_RETURN
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'home' and trigger.event.data.type
              == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_HOME
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'settings' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_MENU
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'volume_up' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_VOLUP
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'volume_down' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_VOLDOWN
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'mute' and trigger.event.data.type
              == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_MUTE
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'channel_up' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_CHUP
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'channel_down' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_CHDOWN
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'power' and
              trigger.event.data.type == 'single' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            data:
              media_content_type: send_key
              media_content_id: KEY_POWER
            action: media_player.play_media
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'power' and
              trigger.event.data.type == 'long' }}
        sequence:
          - target:
              entity_id: "{{ tv_entity }}"
            action: media_player.turn_off
      - conditions:
          - condition: template
            value_template: >-
              {{ trigger.event.data.button == 'play_pause' and
              trigger.event.data.type == 'single' }}
        sequence:
          - choose:
              - conditions:
                  - condition: template
                    value_template: "{{ play_pause_toggle == 'pause' }}"
                sequence:
                  - target:
                      entity_id: "{{ tv_entity }}"
                    data:
                      media_content_type: send_key
                      media_content_id: KEY_PAUSE
                    action: media_player.play_media
            default:
              - target:
                  entity_id: "{{ tv_entity }}"
                data:
                  media_content_type: send_key
                  media_content_id: KEY_PLAY
                action: media_player.play_media
variables:
  tv_entity: media_player.living_room_tv
  play_pause_toggle: >
    {% set last = state_attr('automation.remote_navigation', 'last_triggered')
    %} {% if last and (now() - last).total_seconds() < 3 %}
      pause
    {% else %}
      play
    {% endif %}
mode: queued

Previous
Previous

A Quick Project That’ll Save Me Hours Every Week

Next
Next

Kmart Lied to Me, So I Hacked Their Lamp