Control HA switch from ESPHome, in lambda

Hi, all.

I am using an M5stack, and I want to update a HomeAssistant switch inside a GPIO button lambda.

Here is some code I am trying to use:

  - platform: gpio
    id: M5_BtnB
    pin:
      number: 38
      inverted: true
    on_click:
      then:
        lambda: |-
          if(id(screen_type) == 1 or id(screen_type) == 2) {
            if(id(screen_show_all) == 1) {
              id(screen_show_all) = 0;
            } else {
              id(screen_show_all) = 1;
            }
          } else if(id(screen_type) == 3) {
            id(mbr_bedside_lamp).toggle();
          }

I am using the M5stack Button C to cycle between several screen types (screen types are Weather, Temp/Humidity, and Lights). Basically, the M5stack will show me weather data, or ESPHome sensor temp/humidity data, or light data depending on which screen type is being shown.

M5stack button A cycles through the various pieces of data for each screen type: for weather, button A cycles between the days in the forecast; for temp/humidity data, button A cycles between the different temp/humidity sensors in my house; for lights, button A cycles between the various lights in the house.

Button B toggles between “all” and “one” (i.e., all of the weather data, or just one day’s weather data; or all of the temp/humidity sensor data, or just one sensor’s data). For lights, I want button B to toggle the indicated light on or off.

I tried using this in my ESPHome code, but it fails to compile:

switch:
  - platform: homeassistant
    id: mbr_bedside_lamp
    entity_id: switch.mbr_bedside_lamp

I get an error indicating that there is no HomeAssistant switch in ESPHome.

I have searched the web and the forums, and I have found references to controlling a HomeAssistant switch from ESPHome inside a trigger. But I am not using triggers – I am using lambda here. Is it possible to control a HomeAssistant switch from inside a lambda inside ESPHome, or is it only possible inside a trigger? If this only works in a trigger, is it possible to call a trigger from inside a lambda?

Thanks.

I did see this post: Calling HA services from within esphome lambda functions – and I tried the code, but I don’t have this working yet.

The exact code:

            api::HomeAssistantServiceCallAction<> *ha_service;
            ha_service = new api::HomeAssistantServiceCallAction<>(&*api_apiserver, true);
            ha_service->add_data("entity_id", "switch.mbr_bedside_lamp.toggle");
            ha_service->play();

I have tried various things in the add_data line, but so far I don’t have this working.

Did you read down further in that thread where it seems some of the code has changed? The example that may now be relevant is this post:

Also - have you enabled the API for the particular ESPHome device in the ESPHome integration? It is off by default.

image

I did read the thread, and I tried all of the code in the thread.

I’m sure the problem is probably that this option is not set, since I never knew about it and didn’t know to set it. I searched a while and finally found it, and will test soon. Thanks!

Well, the issue is more than simply enabling API access. I have again unsuccessfully tried all the code in that thread. Any ideas on where I should go now?

One specific issue is that api_id is not set, and I don’t know how to set it. I have done web and forum searches, and I don’t see where/how this is set. I tried setting api_id as a global variable (a char[50]) to my API key, but that didn’t work either.

Why don’t you simply put the standard service call inside a script, then call the script from lambda. That is well documented:

script:
  - id: toggle_switch
    then:
      - homeassistant.service:
          service: switch.toggle
          data:
            entity_id: switch.mbr_bedside_lamp

...
          } else if(id(screen_type) == 3) {
            id(toggle_switch).execute();
          }
...

Thanks, I will try that. I did not know this was possible.

thanks zoogara, thats great with the script. I spent some hours trying different ways in Lambda, but was not succesful. With the script it works fine.