Sorry, that’s the one using struct I was looking at.
It’s funny because I first got started in MCU’s last year by using MicroPython. It was never the most reliable for me and then I found HA + ESPHome which has been great.
I think I’ll take baby steps. Get full OS + Python a go with that module. Then see if that repo can be massaged to work in MicroPython.
Massaged the python library into CircuitPython on an ESP32-S2 sending data to WLED via UDP Sync. Maybe one day I’ll know enough C++ to get it working in ESPHome.
Thanks for the suggestion. The sensor in question does not use line/carriage returns of any sort. After further testing I can confirm that fixed size byte arrays are indeed what are used. Got it working with MicroPython and have yet to loop back to decipher the hex data in cpp. Thx!
At this point I’m trying to understand how to actually consume the data that is coming in over UART/Modbus. It’s being written into the log just fine but exactly how do I get to it in a usable form? Been reading up on C++ a bit to try to understand stuff on the documentation pages but I think I need a little more advice. Thanks!
I’d presume that the external component publishes something to be used. Haven’t checked the git repo. Are there examples?
I’ll try and take a look when I can, perhaps it could help me as well. I’ve been playing with Arduino Serial examples. Suspect theses are two different issues as I am guessing the component you have found does the parsing.
I’ve gotten to the point where I can send hex data from my PC to the ESPHome node via RS485 and have that data logged by ESPHome as raw hex as well as ASCII characters. I can also send either predefined raw hex bytes via UART/RS485 or predefined hex commands (with automatically generated CRC bytes) via Modbus/RS485. So I just need to be able to read and filter incoming hex so I can pass it out again over the second physical UART/RS485 interface, substituting my custom commands for the filtered-out commands.
OK, some things are slowly coming to me, so I’m going to try to get them down here before I lose them.
It now seems to me that your data resides in the “bytes” variable in that lambda line that’s logging the data. The “sequence” action publishes “bytes” to the log . The logging helper that you left uncommented is showing the data a string with some characters escaped, hence the backslashes. So, I’m thinking that if you use that lambda to assign a value of “bytes” to your text sensor, your text sensor’s state would be the string of data you received. That could then be manipulated as necessary.
I’m a newbie to this stuff, but I sensed when getting help on something a little similar, that this is the level/complexity where advanced users kind of recommend moving from a ESPHome config solution to a custom component solution in C++.
You could look over this and the GitHub project if you’re interested.
I would head over to Discord and see what the guru’s reckon.
Yes that looks accurate. While I don’t know much C++ (aside from basic concepts and formatting). I can read through that well enough. The struggle is typically types and converting between them. Especially hex strings to vectors!
Not sure if you’re still working on this… maybe you’d rather me help you with some other c++ when I’m a bit bored on a weekday.
But… I don’t think you even need to bother with a custom component since it’s fairly simple. 15 lines or so of your lambda will do the trick
You’ve got the bytes variable inside a lambda which is a string so you’re off to the races. You check to make sure its the message you want by checking the length or by checking if it starts with an “r” for resp.
Then take a substring to get the last 4x4 bytes. (str.substr). Then just use index operators on your string to get your bytes also known as characters.
You can do some char array (also known as byte array) to float conversion then just go id(my_sensor).publish_state(my_value) for each of the 4 sensors inside the lambda
You can convert an array of 4 bytes to a float using a memcpy or just by casting from a 4 byte array → int → float
Hopefully that nails it down and I could happily provide some more concrete code
Ultimately the goal was to have it HA configurable/updateable while having local UDP “send” ala custom_component somehow got working but don’t know how to combine yet…
#include "WiFiUdp.h"
class MyCustomSensor : public PollingComponent, public Sensor {
public:
// constructor
MyCustomSensor() : PollingComponent(15000) {}
WiFiUDP UDP;
void setup() override {
// This will be called by App.setup()
}
void update() override {
// This will be called every "update_interval" milliseconds.
unsigned int remotePort = 21324;
IPAddress ip(192, 168, 0, 119);
uint8_t wledsync[7];
wledsync[0] = 4; //DNRGB
wledsync[1] = 1; //RTN
wledsync[2] = 0; //High
wledsync[3] = 0; //Low
wledsync[4] = 255;
wledsync[5] = 5;
wledsync[6] = 255;
for (int i = 0; i <= 255; i++) {
ESP_LOGD("custom", "Sending UDP ", i);
wledsync[3] = i; //Low
// Send return packet
UDP.beginPacket(ip, remotePort);
UDP.write(wledsync,7);
UDP.endPacket();
}
}
};
This is where I last left off, not working yet as the whole ESPHome custom serial bit is still mysterious to me (and types and whatever << is supposed to do!).
#include "esphome.h"
class kld7 : public Component, public UARTDevice {
public:
kld7(UARTComponent *parent) : UARTDevice(parent) {}
void setup() override {
// nothing to do here
}
void loop() override {
// Use Arduino API to read data, for example
const int BUFFER_SIZE = 25;
byte TDAT[BUFFER_SIZE];
int i = 0;
while (available() >= BUFFER_SIZE) {
// read the incoming bytes:
TDAT[i] = read();
i++;
}
if (sizeof(TDAT) == 25) {
uint16_t kld7_distance = uint16_t(TDAT[18]) | (uint16_t(TDAT[19]) << 8);
uint16_t kld7_speed = uint16_t(TDAT[20]) | (uint16_t(TDAT[21]) << 8);
uint16_t kld7_angle = uint16_t(TDAT[22]) | (uint16_t(TDAT[23]) << 8);
id(distance).publish_state(kld7_distance);
id(speed).publish_state(kld7_speed);
id(angle).publish_state(kld7_angle);
ESP_LOGD("kld7", "TDAT is: %s", TDAT);
}
while (available() > 0) {
// read the incoming bytes:
read();
}
}
};