ESPHome Help Request - passing references to entities in scripts

Trying to create a reasonably tricky config for ESPHome (on ESP32) & keep running into brick walls. Been struggling with this all day & am hoping some big-brain out there can help please.

Scenario as follows:

  • Have a number, say 8-10, template switches (number is fixed at build) which can be turned on/off via HAss
    • consistent naming convention, eg:
    id: switch_01
    id: switch_02
  • Each switch is exclusively associated with one or two GPIOs
  • When a switch is turned on, the GPIO(s) need to toggle in specific patterns
    • Each pattern is easily realised by a relatively simple script
    • Some patterns run once & then stop
    • Other patterns run in a loop for as long as that specific switch is turned on, ie:
      - while:
             switch.is_on: switch_01
  • The specific pattern required should be user-selectable via HAss UI
    • Using one select component per switch
    • If the user selects a different pattern for a switch, then that pattern should run the next time the switch is turned on

So, in configuration I have defined:

  • multiple outputs (GPIOs)
  • multiple template switches
  • corresponding select entities - one per template switch
  • multiple scripts, one per pattern

What I’m trying to achieve when a template switch is turned on is:

  • Determine the pattern selected by the user for that switch, eg:
!lambda 'return id(config_switch_01).state;'
  • Determine & invoke the corresponding script with references to the GPIOs & the affected switch
  • The script runs, toggling the appropriate GPIO(s), either once or for long as the relevant switch is kept turned on

All of this works nicely if I hard-code everything, but where I’m struggling is to make the scripts generic by getting & passing to them references to the respective GPIOs & calling switch.

I can do this sort of thing in HAss config, but not having much luck with ESPHome.

I’m starting to dive into the world of complex lambdas & suspect I’m getting closer, but could really do with a hand.

Is anybody able to provide any hints please?

Maybe making some progress, but feels 2 steps forward & 1 step back…

Basically just trying to create pointers to various entities & pass those pointers around.

Works, for instance, with a lambda in a script:

  - id: toggle_light
      light_id: int
      - lambda: |-
          static std::map<int, light::LightState*> light_map {
            { 1, id(led1) },
            { 2, id(led2) }
          auto it = light_map.find(light_id);
          if (it != light_map.end()) 

Which I can then invoke:

  - id: control_01
    platform: template
    name: "Control 1"
    optimistic: True
        - script.execute: 
            id: toggle_light
            light_id: 1

This works, in that I can find & invoke a reference to an entity (light in this case), but this becomes a real pain with complex scripts, multiple entities, etc as you’re constantly redefining the lookup map.

So, I thought, I could make it a global with something like:

  - id: lightEntity
    type: 'light::LightState*'
    restore_value: no
    initial_value: id(led1)

…but this just fails compilation with a bunch of cryptic errors:

/config/ref-test.yaml: In function 'void setup()':
/config/ref-test.yaml:281:75: error: no matching function for call to 'esphome::globals::GlobalsComponent<esphome::light::LightState*>::GlobalsComponent(esphome::light::LightState&)'
       energised: bool
In file included from src/esphome.h:22,
                 from src/main.cpp:3:
src/esphome/components/globals/globals_component.h:16:12: note: candidate: 'esphome::globals::GlobalsComponent<T>::GlobalsComponent(std::array<typename std::remove_extent<_Up>::type, std::extent<_Tp>::value>) [with T = esphome::light::LightState*; typename std::remove_extent<_Up>::type = esphome::light::LightState*]'
   explicit GlobalsComponent(std::array<typename std::remove_extent<T>::type, std::extent<T>::value> initial_value) {
src/esphome/components/globals/globals_component.h:16:12: note:   no known conversion for argument 1 from 'esphome::light::LightState' to 'std::array<esphome::light::LightState*, 0>'
src/esphome/components/globals/globals_component.h:15:12: note: candidate: 'esphome::globals::GlobalsComponent<T>::GlobalsComponent(T) [with T = esphome::light::LightState*]'
   explicit GlobalsComponent(T initial_value) : value_(initial_value) {}
src/esphome/components/globals/globals_component.h:15:12: note:   no known conversion for argument 1 from 'esphome::light::LightState' to 'esphome::light::LightState*'
src/esphome/components/globals/globals_component.h:14:12: note: candidate: 'constexpr esphome::globals::GlobalsComponent<T>::GlobalsComponent() [with T = esphome::light::LightState*]'
   explicit GlobalsComponent() = default;
src/esphome/components/globals/globals_component.h:14:12: note:   candidate expects 0 arguments, 1 provided
src/esphome/components/globals/globals_component.h:11:28: note: candidate: 'constexpr esphome::globals::GlobalsComponent<esphome::light::LightState*>::GlobalsComponent(const esphome::globals::GlobalsComponent<esphome::light::LightState*>&)'
 template<typename T> class GlobalsComponent : public Component {
src/esphome/components/globals/globals_component.h:11:28: note:   no known conversion for argument 1 from 'esphome::light::LightState' to 'const esphome::globals::GlobalsComponent<esphome::light::LightState*>&'
src/esphome/components/globals/globals_component.h:11:28: note: candidate: 'constexpr esphome::globals::GlobalsComponent<esphome::light::LightState*>::GlobalsComponent(esphome::globals::GlobalsComponent<esphome::light::LightState*>&&)'
src/esphome/components/globals/globals_component.h:11:28: note:   no known conversion for argument 1 from 'esphome::light::LightState' to 'esphome::globals::GlobalsComponent<esphome::light::LightState*>&&'
*** [.pioenvs/ref-test/src/main.cpp.o] Error 1
========================= [FAILED] Took 12.98 seconds =========================

All hints & guidance appreciated!!

Where did you find this? I don’t see it listed as a valid type. If the state is on/off use bool for type