You implemented a 2-byte checksum correctly. However, calculating the checksum of the packet does not result in 0xF7D8. Are you sure the checksum method is simply subtracting all bytes from 0xFFFF? Also, for the packet to appear in the logs, the entire format must be correct. How did you construct your packet?
Ha, you are indeed correct. the packet I was sending for testing the CRC wasn’t correctly formed, as I used it in an example from a few years ago when we didnt know how to calculate the CRC correctly, and had sliped my mind
I will get that ammended and tested now
The checksum is working perfectly. Thank you for bringing it to my attention.
Is it possible for the Lambda to fetch the value of the Header? If not I can get a PR drafted to create a Subtract Checksum if that would be OK
The serial packet contains 2 lines of data for an LCD screen. Im struggling to get any data pushed into a Text_sensor. Can you advise how I can extract data from the array into a Text_sensor, for characters 7-23 and 24-40 and display them as ASCII text?
Edit: Is there a cleaner way to get the strings than this:
text_sensor:
- platform: uartex
name: "Line1"
id: "line1"
lambda: |-
std::string s;
for (int i = 4; i < 20; i++) {
s += static_cast<char>(data[i]);
}
return s.c_str();
- platform: uartex
name: "Line2"
id: "line2"
lambda: |-
std::string s;
for (int i = 21; i < 36; i++) {
s += static_cast<char>(data[i]);
}
return s.c_str();
The question after that will be are there any examples using this component to send a serial message and calculate the CRC? edit: yep switches are great for this
In a Lambda function, you can’t retrieve the header values directly, but specifying a header means the value is fixed. So, in this case, it’s fine to simply use the fixed header value within the Lambda function.
Since only lambda functions can be used in text_sensor
at the moment, I’ve simplified the code a bit.
text_sensor:
- platform: uartex
name: "Line1"
id: "line1"
lambda: |-
return std::string(reinterpret_cast<const char*>(data + 4), 16);
- platform: uartex
name: "Line2"
id: "line2"
lambda: |-
return std::string(reinterpret_cast<const char*>(data + 21), 15);
Its all working really nicely. Thank you once again for this component
I have a couple of questions now im onto the next stage:
I need to extract sensor values on the presence of a string. for example Line 1 reads "Diagnostic 02 " and Line 2 reads " 20 039 % 1070 "
I would like to read that out as 3 sensors, on the condition that the first 14 characters are “Diagnostic 02” so I guess a check like std::string(reinterpret_cast<const char*>(data + 4), 14) == "Diagnostic 02"
would be needed
Im struggling to get my head around the previous examples to see if there is any that would be suitable for this need
edit:
This works, but feels like it could be a lot cleaner
text_sensor:
- platform: uartex
name: "Diagnostic 04 Internal RH"
lambda: 'return std::string(reinterpret_cast<const char*>(data + 5), 33);'
filters:
- lambda: |-
if (x.substr(0, 14) == "Diagnostic 04") {
return x.substr(17, 2);
} else {
return {};
}
- platform: uartex
name: "Diagnostic 04 Internal RH unit"
lambda: 'return std::string(reinterpret_cast<const char*>(data + 5), 33);'
filters:
- lambda: |-
if (x.substr(0, 14) == "Diagnostic 04") {
return x.substr(20, 1);
} else {
return {};
}
- platform: uartex
name: "Diagnostic 04 Internal Temperature"
lambda: 'return std::string(reinterpret_cast<const char*>(data + 5), 33);'
filters:
- lambda: |-
if (x.substr(0, 14) == "Diagnostic 04") {
return x.substr(22, 2);
} else {
return {};
}
- platform: uartex
name: "Diagnostic 04 Internal Temperature unit"
lambda: 'return std::string(reinterpret_cast<const char*>(data + 5), 33);'
filters:
- lambda: |-
if (x.substr(0, 14) == "Diagnostic 04") {
return x.substr(25, 1);
} else {
return {};
}
- platform: uartex
name: "Diagnostic 04 Average RH 5 mins ago"
lambda: 'return std::string(reinterpret_cast<const char*>(data + 5), 33);'
filters:
- lambda: |-
if (x.substr(0, 14) == "Diagnostic 04") {
return x.substr(27, 2);
} else {
return {};
}
- platform: uartex
name: "Diagnostic 04 Sensor ID"
lambda: 'return std::string(reinterpret_cast<const char*>(data + 5), 33);'
filters:
- lambda: |-
if (x.substr(0, 14) == "Diagnostic 04") {
return x.substr(30, 3);
} else {
return {};
}
You can add the state:
option to filter only the packets that match the specified state.
text_sensor:
- platform: uartex
name: "Diagnostic Internal RH"
state:
data: "Diagnostic 04". #If the data starting from index 0 matches 'Diagnostic 04'
offset: 0
lambda: |-
return std::string(reinterpret_cast<const char*>(data + 17), 2);
- platform: uartex
name: "Diagnostic 02 somedata"
state:
data: "Diagnostic 02" #If the data starting from index 4 matches 'Diagnostic 02'
offset: 4
lambda: |-
return std::string(reinterpret_cast<const char*>(data + 17), 2);