How to execute or stop a script from within a lambda?

I have a project where I need to start and stop a script from within a lambda. Has anyone found a clean way to do this? I’ve tried something like this but it fails to compile:

script:
  - id: script_timer
    mode: restart # Restarts the timer if called again while already running.
    then:
       ... do stuff...

text_sensor:
  - platform: template
    id: text_sensor_example
    ...
    lambda: |-
         ...other code...
         id(script_timer).execute;   // Start script_timer
         ...more code...

Fails to compile with error:

error: invalid use of non-static member function ‘virtual void esphome::script::RestartScript::execute()’

Looking at main.cpp it appears there are various global objects created under the hood to manage the starting and stopping of scripts so it doesn’t look like being a simple thing to do.

For the time being, as a work-around, I’ve created a dummy internal switch which proxies the the starting and stopping of the timer script:

script:
  - id: script_timer
    mode: restart # Restarts the timer if called again while already running.
    then:
       ... do stuff...

switch:
  # Dummy internal switch to control script_timer from lambda:
  - platform: template
    id: switch_timer
    internal: true # Not published to HA.
    turn_on_action:
      - script.execute: script_timer
    turn_off_action:
      - script.stop: script_timer

text_sensor:
  - platform: template
    id: text_sensor_example
    ...
    lambda: |-
         ...other code...
         id(switch_timer).turn_on();   // Start script_timer via dummy switch.
         ...more code...
         id(switch_timer).turn_off();   // Stop script_timer via dummy switch.

This works, but it’s not ideal. I’d prefer to start and stop the script directly from the lambda if any one knows how…? Thanks.

I have the same problem after 8 month. Have you found a solution other solution than the switch?

No. My preferred solution at the moment is still to use a dummy switch as I described above.

Oh boy… I have tried with all possible class calls. And finally the solution is so simple. You wont believe it. Put chambers at the end of the execute. I will suggest an extension to the documentation.

id(your_script_name).execute();
4 Likes

Calling a parameterised script inside a lambda

  • lambda: id(blink_light)->execute(1000);

Without parameters

  • lambda: id(blink_light)->execute;

Thanks, been searching for ages for that, but what if the script has multiple params, how do you call it then using the parameter IDs ?

also how do you wait for it to complete:

id(myscript).wait()

Does not work