Serial2MQTT

Hello.
I know it is a little off topic, but I have seen, that several people want to control a simple unit ( Heater, Solar Charger, … ) that has a serial port.

I think, the best solution is, that one could use ESPhome with a simple serial2mqtt interface. That way, you can easily integrate the hardware into almost everything and still use the ESPhome goodness for other stuff.

Since I am stuck with that UART interface in ESPhome, I have created a ticket for a solution. Perhaps you guys can take a look at it an help. This would open up a whole lot of new sensors for Home Assistant!

Thanks
Oliver

That is not a bug report it is a feature request, or support request. You should close that issue and ask here instead:

1 Like

Also doesn’t this cover it? https://esphome.io/components/text_sensor/uart.html

Yes, but AquaMCU was asking about a simpler way than having to use lambdas.

Thank you guys for the fast reply.
I will change the ticket to features …

Yes, it should be really easy. I mean, basically, you need to pipe the mqtt topic on the serial port (should work in the code I put in the ticket) AND pipe the serial output to the mqtt topic. Since there is no on_receive or similar, that is not possible just using yaml.

Yes. Somehow with a custom component it should work, but since there is now howto or sample code, it will scare a lot of people away ( like me :wink: )

Oliver

Created a feature ticket :slight_smile:

Well this should do what you want according to the link Nick posted above.:

Save this config:

#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];
    if (available() && readline(read(), buffer, max_line_length) > 0) {
      publish_state(buffer);
    }
  }
};

As a file called uart_read_line_sensor.h in your configuration directory.

In addition to your wifi, mqtt/api, etc… setup, include this in your esphome device config:

esphome:
  includes:
    - uart_read_line_sensor.h

logger:
  level: VERBOSE #makes uart stream available in esphome logstream
  baud_rate: 0 #disable logging over uart

uart:
  id: uart_bus
  tx_pin: D0
  rx_pin: D1
  baud_rate: 9600

text_sensor:
- platform: custom
  lambda: |-
    auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
    App.register_component(my_custom_sensor);
    return {my_custom_sensor};
  text_sensors:
    id: "uart_readline"
    on_value:
      then:
        - mqtt.publish:
            topic: YOUR_TOPIC_HERE
            payload: !lambda |-
              return id(uart_readline).state;

This should work for any received UART string up to 80 characters in length that is terminated by a carriage return and sent as 9600/8/n/1.

Completely untested. I’ve never actually done this.

Can we get this as like a component into ESPhome?