Hello everyone,
I’m using ESPHome quite some time for various tasks and also created custom components. And I really like it so first of all thanks for this great tool.
However, now I have a problem I really don’t seem get solved by myself:
I want to access some DIY hardware via Modbus with the standard approach using a chain of uart, modbus, modbus_controller and e.g. a sensor component which works great.
Additionally I want to be able to do firmware updates of the DIY hardware via the same serial connection (RS485) used by the Modbus link, however in this case I need a direct tunnel to the uart component from my development machine which can be done nicely via the stream server (GitHub - oxan/esphome-stream-server: Stream server (serial-to-wifi bridge) for ESPHome).
However having both of them active in the same ESPHome configuration simultaneously is not possible out of the box I guess. So one solution could be to reprogram the ESPHome node every time I want to do an update with either the configuration uart + stream server or uart + modbus, however it would be much more convenient to have something like a merger or switch for the data streams going to and from the uart component to allow the Modbus and stream server components to be simultaneously active on the ESPHome node.
So I tried to create a custom component accessing the uart component and representing itself also as two uart components which can be accessed by Modbus and stream sever later. So the custom component would sit between uart and Modbus / Stream server and select which one can access the bus.
However I’m stuck on how to integrate this components into the yaml configuration.
The header file of the custom components looks like this:
class UARTSlv : public UARTComponent, public Component {
public:
void setup() override { };
float get_setup_priority() const override { return setup_priority::BUS; }
void write_array(const uint8_t *data, size_t len) override;
bool peek_byte(uint8_t *data) override;
bool read_array(uint8_t *data, size_t len) override;
int available() override;
void flush() override;
protected:
void check_logger_conflict() override {};
};
class UARTSwitch : public Component {
public:
UARTSlv *uart_slv_0;
UARTSlv *uart_slv_1;
UARTSwitch(UARTComponent *uart_master, int flow_control_pin);
~UARTSwitch();
protected:
UARTComponent *uart_mst;
int flow_pin;
};
And this is the relevant corresponding yaml configuration:
uart:
- id: mst_uart
tx_pin: 13
rx_pin: 14
baud_rate: 9600
stop_bits: 1
custom_component:
- lambda: |-
auto sw_uart = new UARTSwitch(id(mst_uart), 2);
App.register_component(sw_uart);
return { sw_uart->uart_slv_0, sw_uart->uart_slv_1 };
components:
- id: mb_uart
- id: net_uart
stream_server:
uart_id: net_uart
port: 6638
modbus:
id: mb
uart_id: mb_uart
However, I get an error while compiling:
ID ‘net_uart’ of type Component doesn’t inherit from uart::UARTComponent. Please double check your ID is pointing to the correct value.
ID ‘mb_uart’ of type Component doesn’t inherit from uart::UARTComponent. Please double check your ID is pointing to the correct value.
Seems like the type of the slave uart is removed when I assign an id to them in the custom_component section.
So maybe someone has an idea what I can do to make this thing compile or maybe has an even better idea to realize this uart switch function.
Many thanks,
Michael