I'm having trouble linking a number entity to a custom output

Hi all,

I want to make an ESP in ESPhome that functions both as a sensor and as an output. It’s communication with my car charger via RS485, and I’ve got the sensor part working (simulated through an arduino for now) but I’m having a lot of trouble with the output part.
In short, I want a number entity which I will control in a Node-RED flow. This number should be sent to the ESP and the ESP will construct a message via its UART. The number entity is working, so there’s that. But I can’t find a working way to send its value to my custom output.

The yaml below is what I’ve got so far:

esphome:
  name: esp-cp
  includes:
  - protocolMAXreceiver.h
  - protocolMAXcontroller.h

esp8266:
  board: esp01_1m

# Enable logging
logger:
  level: VERBOSE
  baud_rate: 0

# 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: "***************"
    password: "****************"

captive_portal:

uart:
  id: uart_bus
  rx_pin:
    number: 3
    inverted: false
  baud_rate: 38400

sensor:
- platform: custom
  lambda: |-
    auto chargepoint_sensor = new ProtocolMAXReader(id(uart_bus));
    App.register_component(chargepoint_sensor);
    return {
      chargepoint_sensor->allowableInterval,
      chargepoint_sensor->minimalCurrent,
      chargepoint_sensor->currentL1,
      chargepoint_sensor->cosPhiL1,
      chargepoint_sensor->cumulativePowerConsumption
    };

  sensors:
  - name: "CP Allowable time interval for setpoint"
    unit_of_measurement: s
    accuracy_decimals: 0
  - name: "CP Minimal Current"
    unit_of_measurement: A
    accuracy_decimals: 1
  - name: "CP Momentary Current"
    unit_of_measurement: A
    accuracy_decimals: 1
  - name: "CP Momentary Cos Phi"
    accuracy_decimals: 3
  - name: "CP Total Power Consumption"
    unit_of_measurement: kWh
    device_class: "energy"
    state_class: total_increasing

output:
- platform: custom
  type: float
  lambda: |-
    auto chargepoint_output = new ProtocolMAXController(id(uart_bus));
    App.register_component(chargepoint_output);
    return {chargepoint_output};
  outputs:
    id: CP_setpoint

number:
- platform: template
  name: "CP Maximum Current Setpoint"
  id: CP_current_setpoint
  min_value: 0
  max_value: 32
  step: 0.1
  set_action:
    then:
    - lambda: 
        id(CP_setpoint).write_state(x);

but that gives me an error

.\esp-cp.yaml:97:33: error: 'virtual void esphome::output::FloatOutput::write_state(float)' is protected within this context

Let’s say the method write_state() just prints the value as text on the UART for now…

I’ve tried 100 different combinations so far but I haven’t had it working yet.

Thanks for any advice!

Regards,

Tars

Taking a crack at it.
The error indicates to me the method isn’t accessible outside of it’s class. If it were public you’d be able to access it, or if your code was part of it’s class.

Looking at: ESPHome: /opt/build/esphome/esphome/components/output/float_output.cpp Source File

the write_state method is defined like:

 void FloatOutput::write_state(bool state) { this->set_level(state != this->inverted_ ? 1.0f : 0.0f); }

Any chance FloatOutput::set_level(float [state]) might be what you’re really looking for?

IE:

id(CP_setpoint).set_level(x);

All right, I’ll try that!
The ESPHome docs about the custom output does use the write_state function to override in the .h file but there is no call of it so you might be right:

# Example configuration entry
esphome:
  includes:
    - my_output.h

output:
- platform: custom
  type: float
  lambda: |-
    auto my_custom_float_output = new MyCustomFloatOutput();
    App.register_component(my_custom_float_output);
    return {my_custom_float_output};

  outputs:
    id: custom_float

Thank you a lot for your willingness to help!

You were right, but it has been a whole excercise getting the syntax right. Here’s what eventually worked:


output:
- platform: custom
  type: float
  lambda: |-
     auto chargepoint_output = new ProtocolMAXController(id(uart_bus));
     App.register_component(chargepoint_output);
     return {chargepoint_output};
  outputs:
    id: custom_setpoint


number:
- platform: template
  name: "CP Maximum Current Setpoint"
  id: CP_current_setpoint
  min_value: 0
  max_value: 32
  step: 0.1
  optimistic: true
  on_value:
    lambda: |-
      auto out = id(custom_setpoint);
      out->set_level(x);
1 Like

Glad you got it sorted. Home Assistant has a pretty steep learning curve, but that can make it fun if you’re into puzzles.