Data from home assistant to ESP32 (Esphome)

Tags: #<Tag:0x00007fc409f553f0>

Hi all,
I’m trying to pass data from home assistant to esphome, so I’ve done the following step

  1. defined a sensor in home assistant as the following
sensor:
 - platform: template
   sensors:
     test:
       entity_id: sensor.test
       value_template: '10'

The I got the id from home assistant and defined a sensor in esphome in this way:

api:

#   MQTT                         
mqtt:
  broker: 192.168.1.190
  port: 1883
  username: mqtt_user
  password: passwordmqtt

# SENSOR   
sensor:
  - platform: homeassistant
    name: "test Sensor From Home Assistant"
    entity_id: sensor.test 

But the value of the sensor is not showed in the webserver and also if I update the sensor in home assistant nothing happen in esphome

Could you help me? What I made worng?
This is the log form esphome

INFO Reading configuration /config/esphome/test.yaml... 
INFO Starting log output from 192.168.1.30 using esphome API 
INFO Connecting to 192.168.1.30:6053 (192.168.1.30) 
INFO Successfully connected to 192.168.1.30 
[19:47:29][I][app:105]: ESPHome version 1.17.2 compiled on May 17 2021, 00:25:26 [19:47:29][C][wifi:443]: WiFi: 
[19:47:29][C][wifi:303]: SSID: 'FASTWEB CAPASSO'[redacted] 
[19:47:29][C][wifi:304]: IP Address: 192.168.1.30 
[19:47:29][C][wifi:306]: BSSID: 78:B4:6A:FD:A1:D0[redacted] 
[19:47:29][C][wifi:307]: Hostname: 'test' 
[19:47:29][C][wifi:311]: Signal strength: -62 dB ▂▄▆█
 [19:47:29][C][wifi:315]: Channel: 11 
[19:47:29][C][wifi:316]: Subnet: 255.255.255.0 
[19:47:29][C][wifi:317]: Gateway: 192.168.1.1
 [19:47:29][C][wifi:318]: DNS1: 0.0.0.0 
[19:47:29][C][wifi:319]: DNS2: 0.0.0.0 
[19:47:29][C][logger:185]: Logger: 
[19:47:29][C][logger:186]: Level: DEBUG 
[19:47:29][C][logger:187]: Log Baud Rate: 115200 
[19:47:29][C][logger:188]: Hardware UART: UART0 
[19:47:29][C][captive_portal:169]: Captive Portal: 
[19:47:29][C][web_server:136]: Web Server: 
[19:47:29][C][web_server:137]: Address: 192.168.1.30:80 
[19:47:29][C][ota:029]: Over-The-Air Updates: 
[19:47:29][C][ota:030]: Address: 192.168.1.30:3232 
[19:47:29][C][api:095]: API Server: 
[19:47:29][C][api:096]: Address: 192.168.1.30:6053 
[19:47:29][C][mqtt:051]: MQTT: 
[19:47:29][C][mqtt:053]: Server Address: 192.168.1.190:1883 (192.168.1.190) [19:47:29][C][mqtt:054]: Username: 'mqtt_user'[redacted] 
[19:47:29][C][mqtt:055]: Client ID: 'test-3c61051d8fc0'[redacted] 
[19:47:29][C][mqtt:057]: Discovery prefix: 'homeassistant' 
[19:47:29][C][mqtt:058]: Discovery retain: YES 
[19:47:29][C][mqtt:060]: Topic Prefix: 'test' 
[19:47:29][C][mqtt:062]: Log Topic: 'test/debug' 
[19:47:29][C][mqtt:065]: Availability: 'test/status' 
[19:47:29][C][homeassistant.sensor:024]: Homeassistant Sensor 'test Sensor From Home Assistant' 
[19:47:29][C][homeassistant.sensor:024]: Unit of Measurement: '' 
[19:47:29][C][homeassistant.sensor:024]: Accuracy Decimals: 1 
[19:47:29][C][homeassistant.sensor:025]: Entity ID: 'sensor.test' 
[19:47:29][C][mqtt.sensor:024]: MQTT Sensor 'test Sensor From Home Assistant': 
[19:47:29][C][mqtt.sensor:028]: State Topic: 'test/sensor/test_sensor_from_home_assistant/state'

Not sure why you are setting MQTT in the esphome.

Also

When enabling MQTT and you do not use the “native API” for Home Assistant, you must remove the api: line from your ESPHome configuration, otherwise the ESP will reboot every 5 minutes because no client connected to the native API.

I’m using mqtt to manage the OTAP when the device is in deep sleep, but also if I remove the mqtt and I use just the native API the sensor value is not updated in esphome when I change it in home assistant

Try a text sensor instead

Solved, I was making a silly error, I was mixing sensors created by mqtt integration and sensors created by esphome integration.
In fact removing sensors created by mqtt I’ve been able to recognize the sensors created by esphome integration, and changing their value in home assistant they are immediately updated in esphome

Luca_Garofalo
Can You please post the Yaml file. I am dealing with a similar problem and have the Idea that your solution may provide me with the golden tip.

I’m not sure about what do you need.
My error wasn’t in the yaml file but in the incorrect use of the interactions.
You can use

  • or the native api (ESPHome Integration)
  • or the MQTT integration
  • or both of them at the same time

example.: If you have a sensor declared in esphome like this:


sensor:
  - platform: homeassistant
    name: "sleeptime"
    entity_id: sensor.sleeptime 
    id: sleeptime

and

  • you have enabled both integrations(ESPhome and MQTT) in your home assistant
  • you have enabled both integrations also in the yaml of your esphome device with a code like this:
# Enable Home Assistant API
api:
mqtt:
  broker: 192.168.1.xxx
  port: 1883
  username: mqtt_user
  password: mqtt_password

As result you will have 2 sensors in home assistant, one created by ESPhome Integration and another one created by MQTT integration (obviously with similar but different id)
In this case please pay attention to use the sensor created by ESPhome integration if you want to update your sensor via native api (easiest way)
or in case you want update the sensor via MQTT you have to pass through MQTT services and in this case, please, pay attention to use the sensor created by the MQTT integration.

If I wasn’t enough clear (sorry, I’m not english mother tongue), please let me know, and I’ll try to be more clear using images or other examples

Thanks for the reply. This is my first HA/esp8266 project, have a little bit programming experience but more into hardware.
I am trying to build a system for monitoring and homogenizing temperature in cold-rooms. The native PWM in the esp8266 is to slow, so I build a custom polling component for the EMC2301

#include <esphome.h>
#include <Wire.h>
#include <stdint.h>

class emc2301 : public PollingComponent, public Sensor {
 public:
  emc2301() : PollingComponent(6000) {}
  uint8_t PWMDrive;
  float get_setup_priority() const override {return esphome::setup_priority::BUS;}
  void SetPWM(uint8_t drive);
  void setup() override{
      Wire.begin();
      Serial.begin(115200);
      delay(10);
      // set fan configuration
      Wire.beginTransmission(0x2F);
      Wire.write(0x32);
      Wire.write(0x1B);
      Wire.endTransmission();
      //PWMDrive = 0;
  }
  void update() override{
      uint16_t TachoCount = (0x00);
      // set pwm 
      Wire.beginTransmission(0x2F);
      Wire.write(0x30);
      Wire.write(0x30);
      Wire.endTransmission();

      // point to tacho msb
      Wire.beginTransmission(0x2F);
      Wire.write(0x3E);      
      Wire.endTransmission();
      delay(5);
      //read tacho msb
      Wire.requestFrom(0x2F, 1);
      while (Wire.available()) { 
        TachoCount = Wire.read();
      }
      TachoCount = TachoCount << 8;    
      //point to tacho lsb
      Wire.beginTransmission(0x2F);
      Wire.write(0x3F);
      Wire.endTransmission();
      delay(5);
      //read tacho lsb
      Wire.requestFrom(0x2F, 1);
      while (Wire.available()) { 
        TachoCount |= Wire.read();    
      }
      TachoCount = TachoCount >> 3;
      int rot = TachoCount / 4;
      publish_state(rot);
      ESP_LOGD("custom", "drive value: %u", PWMDrive);
      //SetPWM(9);
  }
 };

 void emc2301::SetPWM(uint8_t dr) {
   PWMDrive = dr;
   ESP_LOGD("custom", "dr: %u", dr);
   ESP_LOGD("custom", "SetPWM: %u", PWMDrive);
 }

The driver is simple and does the job The line //SetPWM(9); was for diagnostics, uncommenting it nicely calls SetPWM and shows up in the logs
The tacho is captured by ESPHome and send to home assistant. Here is the esp yaml:

esphome:
  name: f1
  platform: ESP8266
  board: huzzah
  includes:
   custom_emc2301.h
wifi:
  ssid: "********"
  password: "**********"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "F1 Fallback Hotspot"
    password: "*******"

captive_portal:

# Enable logging
logger:
  level: debug
  esp8266_store_log_strings_in_flash: False
  
# Enable Home Assistant API
api:
  password: "******"

ota:
  password: "****"
  
dallas:
  - pin: GPIO14
i2c:
    sda: 4
    scl: 5
    scan: True
    id: bus_a
sensor:
  - platform: homeassistant
    entity_id: input_number.fan_drive
    id : id_fan_drive
#   on_value:
#     then:
#      lambda: |-
#         fan -> PWMDrive = int(id(id_fan_drive).state);

  - platform: dallas
    address: 0x85000009137A4028
    name: "Temperature #1"
  - platform: dallas
    address: 0x4600000912A9E028
    name: "Temperature #2"
  - platform: custom
    lambda: |-
     auto fan = new emc2301();
     App.register_component(fan);
     fan -> PWMDrive = int(id(id_fan_drive).state);
     return {fan};
     
     
     
    sensors:
     name: "fan data"

I managed to send a PWMDrive value to the emc2301 with
fan → PWMDrive = 123; but int(id(id_fan_drive).state); doesn’t work the log reports 255 for PWM whatever the value for id_fan_drive is, I don’t understand why.
If this works it would be a lousy solution because it is called in every loop. I tried to write an on_value approach so a modification of input_number.fan_drive in the HA frontend would trigger a PWM update (see the # lines) but the yaml was invalid.

As this is still a data from HA to ESP I appended it to this post. Hope this is OK

Wow, for sure your knowledge about C language is better then mine.
Try with this:

fan -> PWMDrive = id(id_fan_drive).state;

but I’m not sure it will works

Luca_Garofalo
have been playing around with your suggestion (Pwmdrive is changed to Uint_16), here are the results:
The log is preseded with#, my comments with ##

lambda: |-
     auto fan = new emc2301();
     App.register_component(fan);
     
     ESP_LOGD("custom", "transfer before SetPWM: %u", id(transfer));
     fan -> SetPWM(id(id_fan_drive).state);
     return {fan};
#[11:56:05][D][custom:248]: transfer before on_value: 136
#[11:56:05][D][custom:251]: transfer after on_value : 177
#[11:56:07][D][sensor:092]: 'fan data': Sending state 2047.00000  with 0 decimals of accuracy
#[11:56:07][D][custom:055]: drive value: 255

##drive value remains 255 (max for uint_8 SetPWM()); ESP_LOGD in lambda not executed

lambda: |-
     auto fan = new emc2301();
     App.register_component(fan);
     
     ESP_LOGD("custom", "transfer before SetPWM: %u", id(transfer));
     fan -> PWMDrive = id(id_fan_drive).state;
     return {fan};


#[12:03:29][D][custom:055]: drive value: 65535
#[12:03:35][D][homeassistant.sensor:019]: 'input_number.fan_drive': Got state 147.00
#[12:03:35][D][sensor:092]: 'id_fan_drive': Sending state 147.00000  with 0 decimals of accuracy
#[12:03:35][D][custom:248]: transfer before on_value: 177
#[12:03:35][D][custom:251]: transfer after on_value : 147
#[12:03:35][D][sensor:092]: 'fan data': Sending state 2047.00000  with 0 decimals of accuracy
#[12:03:35][D][custom:055]: drive value: 65535

##drive value remains 65535 (max for uint_16 PWMDrive); ESP_LOGD in lambda not executed

No error was generated but the addressed variables went to there maximum value this feels like nothing is passed.Maybe a scope issue so lets try with a global and let the slider update the global

##added globals 
globals:
  - id: transfer
    type: int
    initial_value: '100'
    

##update global transfer with slider value   
sensor:
  - platform: homeassistant
    entity_id: input_number.fan_drive
    id : id_fan_drive
    accuracy_decimals: 0
    on_value:
      then:
        - lambda: |-
           ESP_LOGD("custom", "transfer before on_value: %u", id(transfer));
           id(transfer) = id(id_fan_drive).state;
           
           ESP_LOGD("custom", "transfer after on_value : %u", id(transfer));

Repeat the first two experiments put now with the “transfer” global

##try with PWMDrive
lambda: |-
   auto fan = new emc2301();
   App.register_component(fan);
     
   ESP_LOGD("custom", "transfer before SetPWM: %u", id(transfer));
     fan -> PWMDrive = id(transfer);
   return {fan};[12:11:17][D][custom:055]: drive value: 100#[12:11:19][D][homeassistant.sensor:019]: 'input_number.fan_drive': Got state 177.00
#[12:11:19][D][sensor:092]: 'id_fan_drive': Sending state 177.00000  with 0 decimals of accuracy
#[12:11:19][D][custom:248]: transfer before on_value: 147
#[12:11:19][D][custom:251]: transfer after on_value : 177
#[12:11:23][D][sensor:092]: 'fan data': Sending state 2047.00000  with 0 decimals of accuracy
#[12:11:23][D][custom:055]: drive value: 100

#The initial value of the global is transferred to 'drive value' but the updates of the global not

##Try with SetPWM()
lambda: |-
     auto fan = new emc2301();
     App.register_component(fan);
     
     ESP_LOGD("custom", "transfer before SetPWM: %u", id(transfer));
     fan -> SetPWM(id(transfer));;
     return {fan}; 
     
    
#[12:22:04][D][custom:055]: drive value: 100
#[12:22:08][D][homeassistant.sensor:019]: 'input_number.fan_drive': Got state 134.00
#[12:22:08][D][sensor:092]: 'id_fan_drive': Sending state 134.00000  with 0 decimals of accuracy
#[12:22:08][D][custom:248]: transfer before on_value: 116
#[12:22:08][D][custom:251]: transfer after on_value : 134
#[12:22:10][D][custom:055]: drive value: 100   

#The initial value of the global is transferred to 'drive value' but the updates of the global not

From these tests I understand that the syntaxis you proposed is correct -the initial global variable is transferred to the class instance- but this happens only by the creation of the fan object. The update should be done somewhere else I guess. The On_value block from id_fan_drive seems the logic place. This is what I could come up with:

on_value:
      then:
        - lambda: |-
           ESP_LOGD("custom", "transfer before on_value: %u", id(transfer));
           id(transfer) = id(id_fan_drive).state;
           fan -> SetPWM(id(transfer));
           ESP_LOGD("custom", "transfer after on_value : %u", id(transfer));
#
# src/main.cpp: In lambda function:
# src/main.cpp:250:7: error: 'fan' was not declared in this scope
#        fan -> SetPWM(transfer->value());
#        ^

then:
        - lambda: |-
           ESP_LOGD("custom", "transfer before on_value: %u", id(transfer));
           id(transfer) = id(id_fan_drive).state;
           id(fan) -> SetPWM(id(transfer));
           ESP_LOGD("custom", "transfer after on_value : %u", id(transfer));
#
# Yaml : cold'nt find id 'fan'

then:
        - lambda: |-
           ESP_LOGD("custom", "transfer before on_value: %u", id(transfer));
           id(transfer) = id(id_fan_drive).state;
           fan.PWMDrive -> SetPWM(id(transfer));
#
#src/main.cpp:250:7: error: 'fan' was not declared in this scope
#       fan.PWMDrive -> SetPWM(transfer->value());
#       ^

## references to id(fan) result in yaml error, references to fan. rises c++ scope error

But as you see it always turns out in a scope error from yaml or c++. I tried to solve this by adding an id to the fan component:

- platform: custom
    id: fr
    lambda: |-
     auto fan = new emc2301();
##try to access fr in on_value block

but without success, fr is treated as a member of the constants class as far as i understand.
OK, I learned a lot but at this point suggestions are more then welcome!!!