How do I increase brightness while button held with ESPHome via MQTT

I have a H801 LED controller with ESPHome and a button attached. Pressing the button, turns the light on/off, holding it dims the light - I need an additional button at a place where physical wiring is impossible - and it needs to work without direct connection to HA (hence api disabled). I have made a configuration that works to turn the light on/off, but I can not figure out how to recreate the dimming while holding the button (both code pieces below). I guess I need some sort of while loop that increments a number from 0 to 255 (brightness), before publishing the MQTT topic - but I can not figure it out. Some advise would be appreciated. It works on the H801 because I can use the relative_brightness function there - but that’s not an option on the remote ESPHome device.

Here’s the configuration for the H801 LED controller with the physical button attached:


esphome:
  name: esp28
  platform: ESP8266
  board: esp01_1m

wifi:
  use_address: 192.168.2.108
  networks:
  - ssid: "SEL_Wifi"
    password: "xxx"
  - ssid: "Boatnet"
    password: "xxx"
    manual_ip:
      static_ip: 192.168.2.108
      gateway: 192.168.2.1
      subnet: 255.255.255.0
      dns1: 192.168.2.1
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp28 Fallback Hotspot"
    password: "XX"

captive_portal:

# Enable logging
logger:

# Enable MQTT
mqtt:
  broker: xxx
  username: xxx
  password: xxx
  port: xxx
  

# Enable Home Assistant API
#api:

ota:
sensor:
  - platform: wifi_signal
    name: "WiFi Signal ESP28 h801"
    update_interval: 60s
#RGBWarm
output:
  - platform: esp8266_pwm
    pin: 12
    frequency: 1000 Hz
    id: pwm_b
  - platform: esp8266_pwm
    pin: 13
    frequency: 1000 Hz
    id: pwm_g
  - platform: esp8266_pwm
    pin: 15
    frequency: 1000 Hz
    id: pwm_r
  - platform: esp8266_pwm
    pin: 14
    frequency: 1000 Hz
    id: pwm_w
  - platform: esp8266_pwm
    pin: 16
    frequency: 1000 Hz
    id: pwm_cw
light:
  - platform: rgb
    name: "H801 RGB"
    id: h801_rgb
    red: pwm_r
    green: pwm_g
    blue: pwm_b
    #white: pwm_w
  - platform: cwww
    name: "H801 white"
    id: h801_ww
    #red: pwm_r
    #green: pwm_g
    #blue: pwm_b
    cold_white: pwm_cw
    warm_white: pwm_w
    cold_white_color_temperature: 153 mireds
    warm_white_color_temperature: 500 mireds
binary_sensor:
  - platform: gpio
    pin: GPIO03
    id: light_0_touch
    on_click:
      then:
        - if:
            condition:
              light.is_off: h801_ww
            then:
              light.turn_on: 
                id: h801_ww
                brightness: 1.0
                color_temperature: 500 mireds
            else:
              - light.turn_off: h801_ww
              - light.turn_off: h801_rgb
    on_press:
      then:
      - if:
          condition: 
            light.is_off: h801_ww
          then:
          - delay: 0.5s
          - while:
              condition:
                binary_sensor.is_on: light_0_touch
              then:
                - light.dim_relative:
                    id: h801_ww
                    relative_brightness: 5%
                    transition_length: 0.1s
                - delay: 0.1s
          else:
          - delay: 0.5s
          - while:
              condition:
                and:
                  - binary_sensor.is_on: light_0_touch
                  - light.is_on: h801_ww
              then:
                - light.dim_relative:
                    id: h801_ww
                    relative_brightness: -5%
                    transition_length: 0.1s
                - delay: 0.1s

Heres the code on the remote ESPHome, it currently works fine for on/off functionality, but this is where I need some way of increasing the brightness while holding the button.

esphome:
  name: esp41
  platform: ESP8266
  board: nodemcuv2

wifi:
  use_address: 192.168.2.109
  networks:
  - ssid: "Boatnet"
    password: "xxx"
    manual_ip:
      static_ip: 192.168.2.109
      gateway: 192.168.2.1
      subnet: 255.255.255.0
      dns1: 192.168.2.1
  - ssid: "SEL_Wifi"
    password: "xxx"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp41 Fallback Hotspot"
    password: "xxx"

captive_portal:

# Enable logging
logger:

# Define virtual sensor to store state of light
text_sensor:
  - platform: template
    name: "ESP28 light state"
    id: light_state
    internal: true

# Enable MQTT
mqtt:
  broker: xxx
  username: xxx
  password: xxx
  port: xxx
  
  on_json_message:
    topic: esp28/light/h801_white/state
    then:
      - logger.log: "JSON payload received"
      - text_sensor.template.publish:
          id: light_state
          state: !lambda 'return x["state"];'
      
# Enable Home Assistant API
#api:

ota:

sensor:
  - platform: wifi_signal
    name: "WiFi Signal ESP41"
    update_interval: 60s
binary_sensor:
  - platform: gpio
    pin: 
      number: D2
      mode: INPUT_PULLUP
    id: touch
    
    on_press:
      then:
        - logger.log: "Press registered"
        - if:
            condition:
              text_sensor.state:
                id: light_state
                state: 'OFF'
            then:
              - logger.log: "Publishing ON command"
              - mqtt.publish_json:
                  topic: esp28/light/h801_white/command
                  payload: |-
                    root["state"] = "ON";
                    root["brightness"] = "255";
                    root["color_temp"] = "500";
        - if:
            condition:
              text_sensor.state:
                id: light_state
                state: 'ON'
            then:
              - logger.log: "Publishing OFF command"
              - mqtt.publish_json:
                  topic: esp28/light/h801_white/command
                  payload: |-
                    root["state"] = "OFF";

Dos you ever get this to work ?
I’m trying to do the same thing but I have the remote button publish its state to MQTT and using that as a binary input on the ESP that controls the light. This work ok but it doesn’t always register a click (guessing it’s not fast enough to read the MQTT server)

Unfortunately not. Have the same expierence as you - it’s not reliable to start dimming on press and stopping on release. But I’m still searching for a reliable way to do it.

Have you tried “on_click” with your GPIO button?

It accepts a bunch of time intervals and then you can perform some action (like publish a MQTT event with a specific value) fthat is different for each time interval.

binary_sensor:
  - platform: gpio
    # ...
    on_click:
    - min_length: 50ms
      max_length: 350ms
      then:
        ... do first thing
    - min_length: 500ms
      max_length: 1000ms
      then:
        ... do second thing
   - min_length: etc...

Another idea:

in the on_click trigger save the result of “millis()” in a variable. in the on_release() trigger calculated the time it was pressed down like (mllils()-click_millis) and then multiply it by some factor (lets say 0.5) and substract that from the current brightness.

It would be great if the on_release trigger would provide info about for how long the button was pressed.

For me, it would be optimal if it was possible to execute a function that would reduce brightness by XX% or by a fixed value every X ms. for as long as the button was pressed until a min. value was reached and then increase the brightness by XX% or a fixed value every X ms. until a max. brightness was reached all until the button was released. This is what I can achieve on the device, physically connected to the light because I can use the light.dim_relative function.

@DebugBug, how did you wire the switch? did you have to add a resistor?

I used a touch button that basically just puts ground to the input pin when it is touched.

some how my code does not work as expected.
i would like to add just a simple emergency pushbutton.
at the minute i try this:

binary_sensor:
  - platform: gpio
    pin: GPIO03
    name: "led-button"
    on_state:
      - light.toggle: button_w
    internal: true

before i used something like this:

binary_sensor:
  - platform: gpio
    pin: GPIO03
    id: light_0_touch
    on_click:
      then:
        - if:
            condition:
              light.is_off: button_w
            then:
              light.turn_on: 
                id: button_w
                brightness: 1.0
            else:
              - light.turn_off: button_w
              - light.turn_off: button_rgbw

I don’t use ESPHome enough to be able to guide you, but one thing i know is that if you define internal: true, then the state will not be visible to Home Assistant (outside the ESPHome device).