Calling custom functions

I’m trying to figure out how to call a custom function in a switch.
I have a custom uart polling component where I pass some sensor values that it reads. I also want to be able to send some uart commands that are implemented in a function in the custom component.
I can’t figure out how to do this. Now I’m a hardware guy and know enough software to be dangerous! :slight_smile:
My switch is define like this:

switch:
  - platform: gpio
    pin: GPIO26
    id: generic_switch
    name: 'on_off_mppt'
    on_turn_on:
    - logger.log: "Switch on"
    - lambda: "id(mppt_jb).send_CC_ON()"
    on_turn_off:
    - logger.log: "Switch off"

it’s complaining about no send_CC_ON being defined.
my custom component is instantiated here:

custom_component:

- id: mppt_jb
  lambda: |-
    auto my_mppt2 = new BlueSkyWiFi(id(uart3),id(Bvol),id(PVvol),id(Bcur),id(Bwatts));
    App.register_component(my_mppt2);
    return {my_mppt2};

My customer component looks like this:

class BlueSkyWiFi : public PollingComponent, public UARTDevice
{
  Sensor *xsensor1{nullptr};
  Sensor *xsensor2{nullptr};
  Sensor *xsensor3{nullptr};
  Sensor *xsensor4{nullptr};
  Switch *xsw1{nullptr};
  mppt_controller myMppt;
  int count;
  int last_milli;
  int new_milli;

public:
  BlueSkyWiFi(UARTComponent *parent, Sensor *sensor1, Sensor *sensor2, Sensor *sensor3, Sensor *sensor4) : UARTDevice(parent), xsensor1(sensor1), xsensor2(sensor2), xsensor3(sensor3), xsensor4(sensor4) {}

  byte buf[32];
  void init_count() {
    this->count=0;
    this->last_milli = 0;
  }

  void send_CC_ON(){
      write_byte(0xAA);
      write_byte(0xCC);
      write_byte(0x02);
      write_byte(0x00);
      write_byte(0x00);
      write_byte(0xCE);

  }

How do I get it call a function from like a switch action. I’m either missing something simple or I’m going about it the wrong way!

Thanks,

Jim

I’m no ESPHome wizard, but I believe you might have to define send_CC_ON as an ESPHome service in your YAML file, and possibly in your C++ code.

Clearly I’m not a wizard either! I would have thought that because the custom component is already registered and the function is a public function, it would know about that function.

I’m going to bump this as I still haven’t figured it out yet and I just went back to revisit this!, Any help/examples would be appreciated… :slight_smile:

Try using this as your on_turn_on function:

 - lambda: |-
 static_cast< BlueSkyWiFi*> (id(mppt_jb).get_component(0))->send_CC_ON();
2 Likes

Thanks! That did work. I probably should dive down deep to figure out why that works and would I have any chance of finding that on my own!! :grinning_face_with_smiling_eyes:

You have to look at the API docs to see what backend functions you have available.

https://esphome.io/api/custom__component_8h_source.html
https://esphome.io/api/classesphome_1_1custom__component_1_1_custom_component_constructor.html

Since there is only one component for that ID, you use component 0. You then have to cast it to whatever custom component Class is assigned to that component.

Another thing you can do is have a look at the generated build files that esphome creates from the yaml, specifically main.cpp. Those files show up in the directory

 /config/esphome/.esphome/build/<your project name>/src

You will see how custom components are instantiated there. Looking at this file will give you a better understanding of the inner workings of esphome.

I was playing around and found another maybe simpler way of accomplishing this by setting up your class variable my_mppt2 as global instead of localized under the custom component instantiation.

What you do is add this line after your class definition in your header file:

BlueSkyWiFi * my_mppt2;

Then when you assign the class in the custom component, you simply remove the “auto” definition from the instantiation, which will assign to the previously globally defined my_mppt2 variable above.

my_mppt2 = new BlueSkyWiFi …

So what that means then, is in your other lambda functions you are able to access your class functions using:
my_mppt2->send_CC_ON();

I don’t see any minuses from doing it this way so far. Works fine in my testing.

3 Likes

I just want to say that this is the only clean solution I’ve found to have a global custom class on which you can call methods.