Compile error with sample file "uart_read_line_sensor.h"

Hi,

I want to read lines from the UART interface. I found the example of a custom uart text sensor:

I created the *.h-file and added the - include in the yaml-file.
Unfortunately I get a compiler error:

In file included from src/main.cpp:47:0:
src/uart_read_line_sensor.h:3:83: error: expected class-name before '{' token
 class UartReadLineSensor : public Component, public UARTDevice, public TextSensor {
                                                                                   ^
src/uart_read_line_sensor.h: In member function 'virtual void UartReadLineSensor::loop()':
src/uart_read_line_sensor.h:40:29: error: 'publish_state' was not declared in this scope
         publish_state(buffer);

It seems that the class name TextSensor is not recognized. What can I do?

I suspect you had a copy/paste error - the sample code compiles fine for me.

Please advise the version of ESPHome you are using and the install type (add-on or standalone). Also post your yaml and the .h file.

Thanks for your answer.

My environment (on Raspi 4B):

Home Assistant 2022.10.4
Supervisor 2022.10.0
Operating System 9.2
Frontend 20221010.0 - latest
ESPHome AddOn 2022.10.1

My yaml-file:

esphome:
  name: stromzaehler 
  includes:
    - uart_read_line_sensor.h

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  level: DEBUG

# Enable Home Assistant API
api:
  password: !secret api_password
ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_eg_ssid
  password: !secret wifi_eg_password

  manual_ip:
    static_ip: 192.168.2.86
    gateway: 192.168.2.1
    subnet: 255.255.255.0
    
  fast_connect: true

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "stromzaehler"
    password: !secret hotspot_password

captive_portal:

uart:
  - id: uart_bus1
    rx_pin: GPIO16
    tx_pin: GPIO17
    baud_rate: 9600
    data_bits: 8
    parity: NONE
    stop_bits: 1

  - id: uart_bus2
    rx_pin: GPIO18
    tx_pin: GPIO19
    baud_rate: 300
    data_bits: 7
    parity: EVEN
    stop_bits: 1
    debug:
      direction: BOTH
      dummy_receiver: true
      after:
        delimiter: "\n"
      sequence:
        - lambda: UARTDebug::log_string(direction, bytes);

sml:
  id: sml1
  uart_id: uart_bus1

sensor:
  - platform: sml
    name: "Strom Haushalt Zählerstand"
    sml_id: sml1
    server_id: "0a014150410105e05912"
    obis_code: "1-0:1.8.0"
    unit_of_measurement: kWh
    accuracy_decimals: 5
    device_class: energy
    state_class: total_increasing
    filters:
      - multiply: 0.0001  

  - platform: sml
    name: "Strom Haushalt Leistung"
    sml_id: sml1
    server_id: "0a014150410105e05912"
    obis_code: "1-0:16.7.0"
    unit_of_measurement: kW
    accuracy_decimals: 3
    device_class: power
    state_class: measurement
    filters:
      - multiply: 0.001

button:
  - platform: template
    name: "Pull Button"
    on_press:
      - then:
        - uart.write:
            id: uart_bus2
            data: [0x2F, 0x3F, 0x21, 0x0D, 0x0A]
        - delay: 2s
        - uart.write:
            id: uart_bus2
            data: [0x06, 0x30, 0x30, 0x30, 0x0D, 0x0A]        

My file /config/esphome/uart_read_line_sensor.h:

#include "esphome.h"

class UartReadLineSensor : public Component, public UARTDevice, public TextSensor {
 public:
  UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}

  void setup() override {
    // nothing to do here
  }

  int readline(int readch, char *buffer, int len)
  {
    static int pos = 0;
    int rpos;

    if (readch > 0) {
      switch (readch) {
        case '\n': // Ignore new-lines
          break;
        case '\r': // Return on CR
          rpos = pos;
          pos = 0;  // Reset position index ready for next time
          return rpos;
        default:
          if (pos < len-1) {
            buffer[pos++] = readch;
            buffer[pos] = 0;
          }
      }
    }
    // No end of line has been found, so return -1.
    return -1;
  }

  void loop() override {
    const int max_line_length = 80;
    static char buffer[max_line_length];
    while (available()) {
      if(readline(read(), buffer, max_line_length) > 0) {
        publish_state(buffer);
      }
    }
  }
};

Nevermind, I found the reason for the compilation error. I didn’t understand the magic of ESPHome concerning the compiling process.
As you can see in my yaml file, I included the *.h-file but didn’t define a text_sensor. This leads to a esphome.h-file without including the class definition of TextSensor. Probably to save memory. After defining a text_sensor in the yaml-file, as in the full example from above, the code compiles.

1 Like

I suspect that if you don’t have a matching text sensor, it doesn’t include the libraries needed to compile the custom component. Explains why mine worked as I included the example text sensor.