How to pass a variable from Home Assistant to ESPHome custom component?

Hello,
I’m struggling to fetch data from HomeAssistant using this method : Home Assistant Sensor

I am also using a custom Custom component like this : Custom Sensor Component

I want to send a brightness data of a lamp from HomeAssistant to my ESP32.
(I will later use this data to control a motorized fader!)

Here is the yaml for my esphome node

esphome:
  name: light-control-ui
  includes:
  - my_custom_sensor.h

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "☓☓☓☓☓☓☓☓☓☓"

ota:
  password: "☓☓☓☓☓☓☓☓☓☓"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Light-Control-Ui"
    password: "☓☓☓☓☓☓☓☓☓☓"

captive_portal:



sensor:
- platform: homeassistant
  id: light_bureau
  entity_id: light.bureau
  attribute: brightness
  internal: true


- platform: custom
  lambda: |-
    auto my_sensor = new MyCustomSensor();
    float value = id(light_bureau).state;
    my_sensor->custom_value = value;
    my_sensor->test_value = 25.4;
    App.register_component(my_sensor);
    return {my_sensor->brightness_sensor};
    

  sensors:
  - name: "My Brightness Sensor"
    unit_of_measurement: "%"
    accuracy_decimals: 2

Here is the .h of the custom sensor component :

#include "esphome.h"
#include <iostream>
class MyCustomSensor : public PollingComponent {
 public:

  float custom_value;
  float test_value;
  float another_value;

  Sensor *brightness_sensor = new Sensor();

  MyCustomSensor() : PollingComponent(500) { }
  
  float get_setup_priority() const override { return esphome::setup_priority::DATA; }
  
  
///////////////////////////////////////////////////////////////////////////////////
  void setup() override {
 
  }
  
///////////////////////////////////////////////////////////////////////////////////
  void update() override {
  
  brightness_sensor->publish_state(custom_value);
  ESP_LOGD("custom", "custom_value = %.1f", custom_value);
  ESP_LOGD("custom", "test_value = %.1f", test_value);
  }
};

Here are the logs :

INFO Reading configuration /config/esphome/light-control-ui.yaml...
INFO Starting log output from light-control-ui.local using esphome API
INFO Successfully connected to light-control-ui.local
[19:26:50][I][app:102]: ESPHome version 2022.11.0 compiled on Dec 12 2022, 19:10:51
[19:26:50][C][wifi:504]: WiFi:
[19:26:50][C][wifi:362]:   Local MAC: ▮▮▮▮▮▮▮▮
[19:26:50][C][wifi:363]:   SSID: [redacted]
[19:26:50][C][wifi:364]:   IP Address: ▮▮▮▮▮
[19:26:50][C][wifi:366]:   BSSID: [redacted]
[19:26:50][C][wifi:367]:   Hostname: 'light-control-ui'
[19:26:50][C][wifi:369]:   Signal strength: -59 dB ▂▄▆█
[19:26:50][C][wifi:373]:   Channel: 6
[19:26:50][C][wifi:374]:   Subnet: ▮▮▮▮▮
[19:26:50][C][wifi:375]:   Gateway: ▮▮▮▮
[19:26:50][C][wifi:376]:   DNS1: ▮▮▮▮
[19:26:50][C][wifi:377]:   DNS2: ▮▮▮▮▮▮
[19:26:50][C][logger:293]: Logger:
[19:26:50][C][logger:294]:   Level: DEBUG
[19:26:50][C][logger:295]:   Log Baud Rate: 115200
[19:26:50][C][logger:296]:   Hardware UART: UART0
[19:26:50][C][captive_portal:088]: Captive Portal:
[19:26:50][C][mdns:103]: mDNS:
[19:26:50][C][mdns:104]:   Hostname: light-control-ui
[19:26:50][C][ota:093]: Over-The-Air Updates:
[19:26:50][C][ota:094]:   Address: light-control-ui.local:3232
[19:26:50][C][ota:097]:   Using Password.
[19:26:50][C][api:138]: API Server:
[19:26:50][C][api:139]:   Address: light-control-ui.local:6053
[19:26:50][C][api:141]:   Using noise encryption: YES
[19:26:50][C][homeassistant.sensor:030]: Homeassistant Sensor 'light_bureau'
[19:26:50][C][homeassistant.sensor:030]:   State Class: ''
[19:26:50][C][homeassistant.sensor:030]:   Unit of Measurement: ''
[19:26:50][C][homeassistant.sensor:030]:   Accuracy Decimals: 1
[19:26:50][C][homeassistant.sensor:031]:   Entity ID: 'light.bureau'
[19:26:50][C][homeassistant.sensor:033]:   Attribute: 'brightness'
[19:26:50][D][sensor:127]: 'My Brightness Sensor': Sending state nan % with 2 decimals of accuracy
[19:26:50][D][custom:026]: custom_value = nan
[19:26:50][D][custom:027]: test_value = 25.4
[19:26:51][D][sensor:127]: 'My Brightness Sensor': Sending state nan % with 2 decimals of accuracy
[19:26:51][D][custom:026]: custom_value = nan
[19:26:51][D][custom:027]: test_value = 25.4

Some details about the lamp/entity from which I want to get the brightness/data :

Here are some other ressources I used :
https://esphome.io/custom/custom_component.html
https://community.home-assistant.io/t/fetch-data-from-api-and-present-it-on-a-display-fails/359663
https://esphome.io/cookbook/display_time_temp_oled.html
https://community.home-assistant.io/t/how-to-pass-a-variable-from-home-assistant-front-end-to-esphome/183845/2
https://community.home-assistant.io/t/send-data-to-esp32/289095

Have I missed something in the code?
Please let me know what I’m doing wrong ?
Are there any other ways to achieve this (ie. getting the brightness level from a lamp in HA to an esp32 via esphome to then move a motorized fader)?

Thanks!

Your posted logs don’t show HA establishing a connection to the ESP. Make sure this device is added correctly to HA, the brightness value from HA should then be shown in the logs for the homeassistant sensor.

I think the lambda for the custom component only gets executed once when the sensor is setup. To pass the updated value to the sensor, try setting up the homeassistant sensor on_value: automation to set the new value. Untested changes below:

  attribute: brightness
  internal: true
  on_value:
    - lambda: |-
      id(customSlider)->custom_value = id(light_bureau).state;


- platform: custom
  id: customSlider
  lambda: |-
    auto my_sensor = new MyCustomSensor();
    App.register_component(my_sensor);
    return {my_sensor->brightness_sensor};

@mulcmu Thank you for your response. As you pointed out I did not add the device correctly to HA.
After doing so I got the logs for established connection and the brightness values.

[15:10:13][D][custom:028]: test_value = 2.0
[15:10:14][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:10:14][D][custom:027]: custom_value = 0.0
[15:10:14][D][custom:028]: test_value = 2.0
[15:10:14][D][homeassistant.sensor:022]: 'light.bureau::brightness': Got attribute state 206.55
[15:10:14][D][sensor:127]: 'light_bureau': Sending state 206.55000  with 1 decimals of accuracy
[15:10:14][D][homeassistant.sensor:022]: 'light.bureau::brightness': Got attribute state 183.60
[15:10:14][D][sensor:127]: 'light_bureau': Sending state 183.60001  with 1 decimals of accuracy
[15:10:14][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:10:14][D][custom:027]: custom_value = 0.0
[15:10:14][D][custom:028]: test_value = 2.0
[15:10:15][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:10:16][D][custom:027]: custom_value = 0.0
[15:10:16][D][custom:028]: test_value = 2.0
[15:10:16][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:10:16][D][custom:027]: custom_value = 0.0
[15:10:16][D][custom:028]: test_value = 2.0

HOWEVER I’m still struggling to send the data to the esp32 device. I tried these changes based on @mulcmu 's suggestions :

sensor:
- platform: homeassistant
  id: light_bureau
  entity_id: light.bureau
  attribute: brightness
  internal: true
  on_value:
    lambda: |-
      id(customSlider)->custom_value = id(light_bureau).state;
      
- platform: custom
  id: customSlider
  lambda: |-
    auto my_sensor = new MyCustomSensor();
    App.register_component(my_sensor);
    return {my_sensor->brightness_sensor};
  sensors:
  - name: "My Brightness Sensor"
    unit_of_measurement: "%"
    accuracy_decimals: 2

But I got this error :

Compiling /data/light-control-ui/.pioenvs/light-control-ui/src/main.cpp.o
/config/esphome/light-control-ui.yaml: In lambda function:
/config/esphome/light-control-ui.yaml:48:19: error: base operand of '->' has non-pointer type 'const esphome::custom::CustomSensorConstructor'
       id(customSlider)->custom_value = id(light_bureau).state;
                   ^
*** [/data/light-control-ui/.pioenvs/light-control-ui/src/main.cpp.o] Error 1
========================= [FAILED] Took 31.14 seconds =========================

So I tried with a Global Variable like this :

captive_portal:

globals:
- id: my_global_float
  type: float
  restore_value: no
  initial_value: '0'

sensor:
- platform: homeassistant
  id: light_bureau
  entity_id: light.bureau
  attribute: brightness
  internal: true
  on_value:
    lambda: |-
      id(my_global_float) = id(light_bureau).state;
      //id(customSlider)->custom_value = id(light_bureau).state;
      
- platform: custom
  id: customSlider
  lambda: |-
    auto my_sensor = new MyCustomSensor();
    my_sensor->custom_value = id(my_global_float);
    App.register_component(my_sensor);
    return {my_sensor->brightness_sensor};
  sensors:
  - name: "My Brightness Sensor"
    unit_of_measurement: "%"
    accuracy_decimals: 2

It got compilled sucessfully but still no data being transferred to the variable custom value in my .h file.

[15:38:05][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:38:05][D][custom:027]: custom_value = 0.0
[15:38:05][D][custom:028]: test_value = 2.0
[15:38:05][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:38:05][D][custom:027]: custom_value = 0.0
[15:38:05][D][custom:028]: test_value = 2.0
[15:38:05][D][homeassistant.sensor:022]: 'light.bureau::brightness': Got attribute state 206.55
[15:38:05][D][sensor:127]: 'light_bureau': Sending state 206.55000  with 1 decimals of accuracy
[15:38:06][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:38:06][D][custom:027]: custom_value = 0.0
[15:38:06][D][custom:028]: test_value = 2.0
[15:38:06][D][sensor:127]: 'My Brightness Sensor': Sending state 0.00000 % with 2 decimals of accuracy
[15:38:06][D][custom:027]: custom_value = 0.0
[15:38:06][D][custom:028]: test_value = 2.0

I am still missing something…any ideas ?

Thanks!

I know it is a bit late, but looking at the generated code it is clear the lambda gets the contructor component instead of your component. So all you need to do is cast it to your class in the lambda

 on_value:
    lambda: |-
      static_cast<MyCustomSensor*>(id(customSlider))->custom_value = id(light_bureau).state;

then you id must be the returned component

- platform: custom
  lambda: |-
    auto my_sensor = new MyCustomSensor();
    my_sensor->custom_value = id(my_global_float);
    App.register_component(my_sensor);
    return {my_sensor->brightness_sensor};
  sensors:
  - name: "My Brightness Sensor"
    id: customSlider
    unit_of_measurement: "%"
    accuracy_decimals: 2
1 Like