Perform some actions with physical buttons NodeMCU

Hello!

Let me explain what I need to do:
From several physical push buttons connected to a NodeMcu I want to control several led’s (Milight) and blinds (Shelly).

The idea for the same button is:
-1st When I press the button, the milight light turns off and when I press it again it turns on.

-2nd When I press the button for more than 2 seconds, it works as a dimmer in the Milight.

  - platform: gpio
    pin: D6
    id: light_0_touch
    on_click:
      then:
        - if:
            condition:
              light.is_off: light_0
            then:
              light.turn_on: 
                id: light_0
                brightness: 1.0
            else:
              light.turn_off: light_0
    on_press:
      then:
      - if:
          condition: 
            light.is_off: light_0
          then:
          - delay: 0.5s
          - while:
              condition:
                binary_sensor.is_on: light_0_touch
              then:
                - light.dim_relative:
                    id: light_0
                    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: light_0
              then:
                - light.dim_relative:
                    id: light_0
                    relative_brightness: -5%
                    transition_length: 0.1s
                - delay: 0.1s

-When double clicked, to raise a blind and when double clicked again, to stop raising the blind.

 on_double_click:
      min_length: 1s
      max_length: 1500ms
      then:
        - switch.toggle: persiana_dormitorio

In other projects I have programmed the NodeMcu independently, i.e. the pushbuttons act on the arduino’s own outputs and not on external entities.

I understand that I have to do it through MQTT but I would say that the bridges I have (https://www.diodhuset.com/wifi-bridge-for-mi-light) do not allow to receive MQTT, besides if I configure MQTT in Shelly I would lose the onCloud service.

Could I perform these button actions directly in Hassio, without having to call MQTT from the nodemcu?

What do you recommend?

Thanks for your patience.

Load “”

Is the milight and shelly also running esphome?

same same but different would be :point_down:

    on_click:
      then:
        light.toggle: light_0

Probably not. You can connect esphome via the native api to HA :point_down:

Yes, that’s possible but one step further is to trigger it directly from/in esphome (the nodemcu) :muscle:

on_...:
  - homeassistant.service:
      service: switch.toggle
      data:
        entity_id: switch.persiana_dormitorio # HA entity

Hi ferbulous,

Nope in Esphome I have some other arduino, Shelly in running with his own integration and Milight is connected through limitlessled

Hi orange-assistant,

Thanks for your recomendations! Sure I prefer to do it directly through the nodemcu .

I tried to do it with the command -Homeassistant.service: … but it doesn’t work for me, I mean it doesn’t change the status.

Let me put the code here with some comments


captive_portal:

logger:

api:

ota:

# ********** Pulsadores ********** #

binary_sensor:
  - platform: gpio
    pin:
      number: D4
      inverted: true 
      mode: INPUT_PULLUP
    name: "Boton_1_de_4_cabecera"
    on_click:
      then:
        - homeassistant.service:
            service: switch.toggle
            data:
              entity_id: switch.light.led_sup_dorm_1 # HA entity


    on_double_click: 
      then:
        - homeassistant.service:
            service: switch.toggle
            data:
              entity_id: switch.cover.shellyswitch25_dorm1 # Here I'd like to start moving up the curtain and once double click it again stop the movement. How can I define moving up or moving it down? becouse I'd use it to go down on another button


    on_press: # Here I don't know how can I put it with the entity "light.led_sup_dorm_1" :( Below I have a previous code that I used to config an arduino mosfet directly in another nodemcu basically the idea is  dimmering the light


# ********** LED Terraza  *********** #

light:
  - platform: monochromatic
    name: "Led Terraza"
    id: light_0
    output: light_0_out

output:
  - platform: esp8266_pwm
    id: light_0_out
    pin: D0

# *********** LED Terraza Dimmer *********** #

  - platform: gpio
    pin: D6
    id: light_0_touch
    on_click:
      then:
        - if:
            condition:
              light.is_off: light_0
            then:
              light.turn_on: 
                id: light_0
                brightness: 1.0
            else:
              light.turn_off: light_0
    on_press:
      then:
      - if:
          condition: 
            light.is_off: light_0
          then:
          - delay: 0.5s
          - while:
              condition:
                binary_sensor.is_on: light_0_touch
              then:
                - light.dim_relative:
                    id: light_0
                    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: light_0
              then:
                - light.dim_relative:
                    id: light_0
                    relative_brightness: -5%
                    transition_length: 0.1s
                - delay: 0.1s


Is the function activated in HA for that particular esphome node? :point_down:

Home Assistant service calls

ESPHome devices can make service calls to any Home Assistant service. This functionality is not enabled by default for newly configured device, but can be turned on the options flow on a per device basis.

Hi again orange-assistant,

Yes it’s activated

this is the error that I get from Hassio Log

> Logger: homeassistant
> Source: core.py:1978
> First occurred: 21:55:03 (1 occurrences)
> Last logged: 21:55:03
> 
> Error doing job: Task exception was never retrieved
> Traceback (most recent call last):
>   File "/usr/src/homeassistant/homeassistant/core.py", line 1978, in async_call
>     processed_data: dict[str, Any] = handler.schema(service_data)
>                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
>     return self._compiled([], data)
>            ^^^^^^^^^^^^^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 229, in _run
>     return self._exec(self._compiled, value, path)
>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 355, in _exec
>     raise e if self.msg is None else AllInvalid(self.msg, path=path)
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/validators.py", line 353, in _exec
>     v = func(path, v)
>         ^^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
>     return schema(data)
>            ^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 272, in __call__
>     return self._compiled([], data)
>            ^^^^^^^^^^^^^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
>     return base_validate(path, iteritems(data), out)
>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   File "/usr/local/lib/python3.11/site-packages/voluptuous/schema_builder.py", line 433, in validate_mapping
>     raise er.MultipleInvalid(errors)
> voluptuous.error.MultipleInvalid: not a valid value for dictionary value @ data['entity_id']

thanks in advance

Ok at the end I found another solution becaouse I couldn’t find the solution to do it directly in the Nodemcu.

esphome:
  name: dormitorio_cabecera
  platform: ESP8266 
  board: nodemcuv2

wifi:
  ssid: "your_ssid"
  password: "your_password"
  manual_ip:
    static_ip: 192.168.1.99
    gateway: 192.168.1.1
    subnet: 255.255.255.0

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Cabecera_Fallback_Hotspot"
    password: "password"


captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

# ********** Pulsadores ********** #

text_sensor:
  - platform: template
    name: Scene Button 1
    id: scene_button_1
    lambda: |-
      return {"Released"};
  - platform: template
    name: Scene Button 2
    id: scene_button_2
    lambda: |-
      return {"Released"};
  - platform: template
    name: Scene Button 3
    id: scene_button_3
    lambda: |-
      return {"Released"};
  - platform: template
    name: Scene Button 4
    id: scene_button_4
    lambda: |-
      return {"Released"};

### Botón 1 ###      
 
binary_sensor:
  - platform: gpio
    pin:
     number: D4
     mode: INPUT_PULLUP
     inverted: true
    name: "Scene Button 1"
    internal: true
   
    filters:
     delayed_on_off: 50 ms

    on_multi_click:
    
    - timing:
        - ON for at least 1s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_1
            state: "Hold"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_1
            state: "Released"
       
    - timing:
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
        - text_sensor.template.publish:
            id: scene_button_1
            state: "Clicked"
        -  delay: 2 s
        - text_sensor.template.publish:
            id: scene_button_1
            state: "Released"
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_1
            state: "Double Clicked"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_1
            state: "Released"     
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
       - text_sensor.template.publish:
            id: scene_button_1
            state: "Tripple Clicked"
       -  delay: 2 s
       - text_sensor.template.publish:
            id: scene_button_1
            state: "Released"
        
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
         - text_sensor.template.publish:
            id: scene_button_1
            state: "Fourth Clicked"
         -  delay: 2 s
         - text_sensor.template.publish:
            id: scene_button_1
            state: "Released"

### Botón 2 ###

  - platform: gpio
    pin:
     number: D2
     mode: INPUT_PULLUP
     inverted: true
    name: "Scene Button 2"
    internal: true
   
    filters:
     delayed_on_off: 50 ms

    on_multi_click:
    
    - timing:
        - ON for at least 1s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_2
            state: "Hold"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_2
            state: "Released"
       
    - timing:
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
        - text_sensor.template.publish:
            id: scene_button_2
            state: "Clicked"
        -  delay: 2 s
        - text_sensor.template.publish:
            id: scene_button_2
            state: "Released"
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_2
            state: "Double Clicked"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_2
            state: "Released"     
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
       - text_sensor.template.publish:
            id: scene_button_2
            state: "Tripple Clicked"
       -  delay: 2 s
       - text_sensor.template.publish:
            id: scene_button_2
            state: "Released"
        
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
         - text_sensor.template.publish:
            id: scene_button_2
            state: "Fourth Clicked"
         -  delay: 2 s
         - text_sensor.template.publish:
            id: scene_button_2
            state: "Released"


### Botón 3 ###

  - platform: gpio
    pin:
     number: D3
     mode: INPUT_PULLUP
     inverted: true
    name: "Scene Button 3"
    internal: true
   
    filters:
     delayed_on_off: 50 ms

    on_multi_click:
    
    - timing:
        - ON for at least 1s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_3
            state: "Hold"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_3
            state: "Released"
       
    - timing:
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
        - text_sensor.template.publish:
            id: scene_button_3
            state: "Clicked"
        -  delay: 2 s
        - text_sensor.template.publish:
            id: scene_button_3
            state: "Released"
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_3
            state: "Double Clicked"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_3
            state: "Released"     
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
       - text_sensor.template.publish:
            id: scene_button_3
            state: "Tripple Clicked"
       -  delay: 2 s
       - text_sensor.template.publish:
            id: scene_button_3
            state: "Released"
        
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
         - text_sensor.template.publish:
            id: scene_button_3
            state: "Fourth Clicked"
         -  delay: 2 s
         - text_sensor.template.publish:
            id: scene_button_3
            state: "Released"


### Botón 4 ###

  - platform: gpio
    pin:
     number: D1
     mode: INPUT_PULLUP
     inverted: true
    name: "Scene Button 4"
    internal: true
   
    filters:
     delayed_on_off: 50 ms

    on_multi_click:
    
    - timing:
        - ON for at least 1s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_4
            state: "Hold"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_4
            state: "Released"
       
    - timing:
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
        - text_sensor.template.publish:
            id: scene_button_4
            state: "Clicked"
        -  delay: 2 s
        - text_sensor.template.publish:
            id: scene_button_4
            state: "Released"
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
      - text_sensor.template.publish:
            id: scene_button_4
            state: "Double Clicked"
      -  delay: 2 s
      - text_sensor.template.publish:
            id: scene_button_4
            state: "Released"     
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
       - text_sensor.template.publish:
            id: scene_button_4
            state: "Tripple Clicked"
       -  delay: 2 s
       - text_sensor.template.publish:
            id: scene_button_4
            state: "Released"
        
    - timing:
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at most 0.5s
        - ON for at most 0.5s
        - OFF for at least 1s
      then:
         - text_sensor.template.publish:
            id: scene_button_4
            state: "Fourth Clicked"
         -  delay: 2 s
         - text_sensor.template.publish:
            id: scene_button_4
            state: "Released"


So once I charged the code in the Node I can interact with Hassio throught an automatizations in this way:

I hope It can be usefull for someone (extracted from youtuber [kian.smarthome] )

Problem cames when you want to use the same state to alternate different actions ( for example: You want to use doble click to open the blind and the same double click to stop the blind. It seems it’s not possible because once you perform the “action” after 2 s of delay the state return to “Released” .

To perform different actions with the same button is solved in this post → Shelly 2.5 Roller mode get the buttons state as cover entities - #5 by retrup

About the dimmer light I tried to do it trought an automation but it doesn’t work well (there is a big delay
since when I push the button to start dimming…

alias: Test Dimmer con Hold
trigger:
  - platform: state
    entity_id: sensor.scene_button_1
    from: "released"
    to: "hold"
action:
  - repeat:
      sequence:
        - service: light.turn_on
          data_template:
            entity_id: light.led_cocina  
            brightness: "{{ (repeat.index / 10 * 255) | int }}"
        - delay: "00:00:00.5"  
      until:
        - condition: state
          entity_id: sensor.scene_button_1
          state: "released"

:frowning:

Hi Again,

I’ve noticed that if I create automations in Hassio it takes at least 1,5 seconds to repond…

I’m trying to do it directly in the initial code of the board but it doesn’t work for me.
I’ve asked for it to ChatGpt and Bard but the only that I get from both are errors…

To do some tests, I just need a code to toogle the entity: “light.led_cocina_x3” when I press the button is conected to the pin D4

Could you help me please?