Lambda service call light.turn_on

I’m trying to get a ESP device do a service call from lambda.
If it can be done without lambda then that is fine too.

But from searching I found some code that is rather old but I can’t get it to work.
It first complained about servicecall not existing, should it be action, and even with that change it does not work.

sensor:
  - platform: homeassistant
    id: david_brightness
    entity_id: light.davids_lampa
    attribute: brightness

  - platform: rotary_encoder
    name: "Brightness Encoder"
    id: brightness_encoder
    pin_a: GPIO5
    pin_b: GPIO6
    internal: true
    on_value:
      - lambda: |-
          HomeassistantServiceResponse resp;
          resp.service = "light.turn_on";
          HomeassistantServiceMap entity_id_kv;
          entity_id_kv.key = "entity_id";
          entity_id_kv.value = "light.davids_lampa";
          resp.data.push_back(entity_id_kv);
          entity_id_kv.key = "brightness";

          // Calculate change from last position
          int current = (int)x;
          int delta = current - id(last_encoder_value);
          id(last_encoder_value) = current;
          

          float new_brightness = id(david_brightness).state + (delta * 5.0);
          
          // Clamp to valid range
          if (new_brightness < 0) new_brightness = 0;
          if (new_brightness > 255) new_brightness = 255;
          
          if (new_brightness != id(david_brightness).state) {
            entity_id_kv.value = to_string(new_brightness));
            resp.data.push_back(entity_id_kv);
            id(api_id).send_homeassistant_action(resp);
            ESP_LOGI("encoder", "Brightness adjusted to %.0f", new_brightness);
          }

The rotary encoding part of the code works but it’s the action part that is the issue. It pretty much gives an error on every line of the code.
I can’t find any documentation or other posts about lamda actions.

Summary
/config/esphome/david-sang.yaml: In lambda function:
/config/esphome/david-sang.yaml:114:7: error: 'HomeassistantServiceResponse' was not declared in this scope
  114 |           HomeassistantServiceResponse resp;
      |       ^   ~~~~~~~~~~~~~~~~~~~~~~~~
/config/esphome/david-sang.yaml:115:7: error: 'resp' was not declared in this scope
  115 |           resp.service = "light.turn_on";
      |       ^   
/config/esphome/david-sang.yaml:117:26: error: no match for 'operator=' (operand types are 'esphome::StringRef' and 'const char [10]')
  117 |           entity_id_kv.key = "entity_id";
      |                          ^~~~~~~~~~~
In file included from src/esphome/core/application.h:17,
                 from src/esphome/components/api/api_frame_helper.h:13,
                 from src/esphome/components/api/api_connection.h:5,
                 from src/esphome.h:3,
                 from src/main.cpp:3:
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(const esphome::StringRef&)'
   26 | class StringRef {
      |       ^~~~~~~~~
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'const char [10]' to 'const esphome::StringRef&'
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(esphome::StringRef&&)'
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'const char [10]' to 'esphome::StringRef&&'
/config/esphome/david-sang.yaml:118:28: error: no match for 'operator=' (operand types are 'esphome::StringRef' and 'const char [19]')
  118 |           entity_id_kv.value = "light.davids_lampa";
      |                            ^~~~~~~~~~~~~~~~~~~~
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(const esphome::StringRef&)'
   26 | class StringRef {
      |       ^~~~~~~~~
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'const char [19]' to 'const esphome::StringRef&'
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(esphome::StringRef&&)'
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'const char [19]' to 'esphome::StringRef&&'
/config/esphome/david-sang.yaml:120:26: error: no match for 'operator=' (operand types are 'esphome::StringRef' and 'const char [11]')
  120 |           entity_id_kv.key = "brightness";
      |                          ^~~~~~~~~~~~
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(const esphome::StringRef&)'
   26 | class StringRef {
      |       ^~~~~~~~~
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'const char [11]' to 'const esphome::StringRef&'
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(esphome::StringRef&&)'
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'const char [11]' to 'esphome::StringRef&&'
/config/esphome/david-sang.yaml:145:54: error: no match for 'operator=' (operand types are 'esphome::StringRef' and 'std::string' {aka 'std::__cxx11::basic_string<char>'})
  145 |             entity_id_kv.value = to_string(new_brightness));
      |                                                      ^
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(const esphome::StringRef&)'
   26 | class StringRef {
      |       ^~~~~~~~~
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'std::string' {aka 'std::__cxx11::basic_string<char>'} to 'const esphome::StringRef&'
src/esphome/core/string_ref.h:26:7: note: candidate: 'constexpr esphome::StringRef& esphome::StringRef::operator=(esphome::StringRef&&)'
src/esphome/core/string_ref.h:26:7: note:   no known conversion for argument 1 from 'std::string' {aka 'std::__cxx11::basic_string<char>'} to 'esphome::StringRef&&'
/config/esphome/david-sang.yaml: In lambda function:
/config/esphome/david-sang.yaml:517:3: warning: control reaches end of non-void function [-Wreturn-type]
  517 | 
      |   ^
*** [.pioenvs/david-sang/src/main.cpp.o] Error 1
========================= [FAILED] Took 48.75 seconds =========================

Here’s an example from something of mine.

sensor:
  - platform: rotary_encoder
    name: "Living Room Dimmer"
    id: livingroom_dimmner
    min_value: 0.0
    max_value: 100
    filters:
      - or:
        - debounce: 0.1s
        - delta: 10
      - lambda: |-
          if (x < 0.0) return 0.0;
          if (x > 100.0) return 100.0;
          return x;
    on_value:
      then:
        - homeassistant.service:
            service: light.turn_on
            data_template:
              entity_id: light.living_room_light
              brightness_pct: "{{ brightness_1 | int }}"
            variables:
              brightness_1: 'return id(livingroom_dimmner).state;'   
         
                  
                  
    pin_a: 
      number: D6
      inverted: true
      mode:
        input: true
        pullup: true     

    pin_b: 
      number: D7
      inverted: true
      mode:
        input: true
        pullup: true

Interesting.
I’ll have a look at that method also.

But I asked a friend, let’s call him Al. He gave me this code.
And it works for a fixed brightness, so I guess I just have to make it work with the rotary also.
Shouldn’t be too hard…

      - lambda: |-
            HomeassistantActionRequest svc;
            svc.service = StringRef("light.turn_on");

            svc.data.init(2); 

            auto &kv1 = svc.data.emplace_back();
            kv1.key = StringRef("entity_id");
            kv1.value = StringRef("light.davids_lampa");

            auto &kv2 = svc.data.emplace_back();
            kv2.key = StringRef("brightness");
            kv2.value = StringRef("128"); 

            global_api_server->send_homeassistant_action(svc);

I’d avoid using HomeassistantActionRequest directly as its not a public API and isn’t stable between version.

Use custom_api_device.h instead

Ya, well your friend “AI” will really screw you up and ultimately just make things more difficult for you if you never bother trying to actually learn how to do thsse already supported actions like this. There is a whole section in the official Esphome documentation that covers API/Service calls/Events and provides lots of detailed explanations and examples so that it’s easier to understand. Using service calls is already a supported festure and therfore shouldn’t require you to use any custom code like your “friend” gave you. This is why i say that using AI will ultimately cause you more trouble than its worth. Just read the documentation.

bdraco & Jimmy
I can’t say that is very well documented.
Where do you find documentations about this? The native API page has mentions of it at best but no proper explanations or examples

You probably aren’t looking or trying hard enough because using AI is always essier and faster for people but, in the long run this method will pay far more dividends!

Service

Keep in mind that there are both options for “event” and “action/service” that could be used.

See, its all there.

This is not lambda.
I know it can be done without lambda but that isn’t the main goal.
It would complicate things if i was not using lambda.

And the second post is at best a mention, not a documentation.

Ya, no kidding! Lambda is for whenever you need to write custom code for something that isnt supported already by the current Esphome syntax. All of what you are trying to do is already supported and can very easily be setup without needing to make any of it through lambdas.

It’s fine one minute and the next minute its causing hissy fits… For such small things your doing and trying to send some homeassistant.actions based on the state of a rotary encoder, you’re really making this way more complicated and difficult than it ever needed to be and that it is. If you elaborated more on what it is you’re trying to do then maybe people could steer you in the best direction for example, I am nealy certain that whatever it is you’re trying to do here you dont even need to be messing with homeassistant.action or homeassistant.service etc. There are very specific scenarios where you might need to use those and for practically everything else there are far better ways to accomplish the same thing.

Well then! What exactly isn’t mentioned in it and is something you need? They give you a list of all the different api actions along with every single one of those actions configuration options that can be used so… unless you recently learned some cheat codes that enable hidden features then at best you’re just overlookeding details or at worse, you dont fully understand how the documentation is organized and how to use it correctly but, in all honesty everyone has that problem starting out and even myself struggled at first with it untill i figured it out and then things started falling into place with little difficulty afterwards.

I’m trying to get a rotary encoder to control a light independent from other controls.
So if I turn on the light in HA at 50% and I then twist the rotary encoder then it should base it on the 50% and make it for instance 45%.

The code you posted before does not work independently as I see it.
It will always use the rotary encoder value and not the lights brightness value.

As I see it the documentations is very poor in this case.
And if you Google for solutions to use lambda and Home Assistant actions then you will see threads just like the one I posted in the first post where everyone just throws stuff at the wall in hope something sticks.
Perhaps we are all clueless idiots, or the documentations is not enough. If you find it so easy to use lambda with actions then just post the code. I’m sure there is a lot of people who want to see it given the amount of posts that is unsolved with this problem.