Access Globals from update() function of custom component?

How might I expose a variable in a custom component .h file to lambdas and/or expose esphome globals to the .h code. Obviously, I’m not competent at C++ coding.

For those who are still trying to figure this out:

A global in an ESPHome configuration YAML file translates to an instance of the GlobalsComponent class in the C++ code, declared in your <NODE_NAME>/src/main.cpp. You can access it in a custom component .h file as follows:

my_global->value() = something;
something = my_global->value();

where something and my_global should be of the same or compatible type.

So by defining one or more globals in the YAML file, data can be exchanged between (custom) components, from YAML to C++ and back.

1 Like

Hi @clemo , thanks for the suggestion. I was looking for a way to share data between a custom component and esphome but when I use it the way you defined, I get an error that the global variable isnt defined which is obvious as the custom component does not include the file which includes this definition. How can we solve that?

Do you include your custom component header file in ESPHome’s YAML file? Like this:

esphome:
  name: "relay4"
  platform: ESP8266
  board: esp01_1m
  includes:
    - relay4.h

ESPHome parses the YAML file and includes your header file right below the definitions of the globals in main.cpp so your code is aware of the declarations:

globals::GlobalsComponent<uint8_t> *relay4_state;
#include "relay4.h"
// ========== AUTO GENERATED INCLUDE BLOCK END ==========="

The global variable is defined in the YAML file:

globals:
  - id: relay4_state
    type: uint8_t
    restore_value: no
    initial_value: '0'

Hope this helps.

Thanks for the explanation, that makes sense. I tried again and it worked, maybe I was doing something wrong yday.

Hello,

Is there any way to “pass” the name of a global variable to a custom light component?
Following what suggested in this thread I have managed to access a global variable from a custom light component. However, I would like to avoid hardcoding in he custom light component the name of the global variable and instead pass the name of the global variable when defining the custom light in the .yaml file.

For example:

esphome:
  includes:
    - kessil.h

globals:
  - id: reef_tank_light_brightness_value
    type: float
  - id: reef_tank_light_color_value
    type: float

light:
  - platform: custom
    id: reef_tank_light
    lambda: |-
      auto kessil_light = new KessilLight(id(reef_tank_light_brightness_pwm), id(reef_tank_light_color_pwm), id(reef_tank_light_brightness_value), id(reef_tank_light_color_value));
      App.register_component(kessil_light);
      return {kessil_light};

How can I then access the global variables (in this case reef_tank_light_brightness_value and reef_tank_light_color_value) from the custom light component?

Hello all,

I noticed in the main.cpp file the global variable are defined as follow:

globals::GlobalsComponent<float> *reef_tank_light_brightness_value;
globals::GlobalsComponent<float> *reef_tank_light_color_value;

I have so edit the custom light class to take as two globals::GlobalsComponent pointers as arguments:

#pragma once

#include "esphome.h"

class KessilLight : public Component, public LightOutput, public LightColorValues {
    public:
    KessilLight(FloatOutput *brightness_output, FloatOutput *color_output, globals::GlobalsComponent<float>  *brightness_value, globals::GlobalsComponent<float>  *color_value)
    {
        brightness_output_ = brightness_output;
        color_output_ = color_output;
        brightness_value_ = brightness_value;
        color_value_ = color_value;
    }

    LightTraits get_traits() override {
        auto traits = LightTraits();
        traits.set_supports_brightness(true);
        traits.set_supports_color_temperature(false);
        traits.set_supports_rgb(false);
        traits.set_supports_rgb_white_value(true);
        return traits;
    }

    void write_state(LightState *state) override {
        float red, green, blue;
        state->current_values_as_rgbw(&red, &green, &blue, &white, this->color_interlock_);
        state->current_values_as_brightness (&brightness);
        white = white / brightness;
        if (brightness == 0)
                {
            this->brightness_output_->set_level(0);
            this->color_output_->set_level(0);
            this->brightness_value_->value() = 0;
            this->color_value_->value() = 0;
        }
        else
        {
            this->brightness_output_->set_level(brightness);
            this->color_output_->set_level(white);
            this->brightness_value_->value() = brightness * 100;
            this->color_value_->value() = white * 100;
        }
        
    }

    protected:
    FloatOutput *brightness_output_;
    FloatOutput *color_output_;
    globals::GlobalsComponent<float>  *brightness_value_;
    globals::GlobalsComponent<float>  *color_value_;
    float brightness;
    float white;
    bool color_interlock_;
};

An in the .yaml file I pass the two global variables when defining the custom light:

light:
  - platform: custom
    id: reef_tank_light
    lambda: |-
      auto kessil_light = new KessilLight(id(reef_tank_light_brightness_pwm, reef_tank_light_brightness_value, reef_tank_light_color_value), id(reef_tank_light_color_pwm));
      App.register_component(kessil_light);
      return {kessil_light};
    lights:
      - name: "Reef Tank - Light"

Now this code compiles without errors and gets uploaded to the ESP8266. However, ESPHome fails to start up. After this code has been uploaded to the ESP8266 via OTA upload I can ping the device… but HA fails to connect to through the API. I have the impression this setup causes some sort of runtime error…

Any suggestion or advice?

I know this is an old question but going to the original question asked here, it is possible to directly expose variables in custom component .h files to lambdas.

I gave an example of how to do it here: esphome::custom::CustomLightOutputConstructor' has no member named 'current_values' - #4 by stefan-sh