I have the following serial message that I'm receiving from an ESP32 running GRBL:
<Idle|MPos:158.500,0.000,0.000|FS:0,0|Pn:H|Ov:100,100,100|SD:0.21,/instruction.nc>
I want to check the value after SD:
which in this case would be 0.21
.
It is a value that represents the percentage of a file being read, so values between 100.00 and 0.00 are being sent.
My guess is to look for the SD:
in the string and then read all characters until the ,
but I can't really find a way to realize that.
I found the startsWith()
and the substring()
function that are able to look for a set of characters in a string, but it seems like they can only check a set amount of characters which in this case doesn't work as 0.00
is 4 characters and 100.00
is 6 characters.
Any help is much appreciated!!
1 Answer 1
Firstly you should really be working with a C string (char *
) instead of a String
object, otherwise you will be massively fragmenting your heap with the string manipulations to come.
Once you have your data in a C string (char array) you can use strtok_r
to split the string on the |
character, then for each substring further split it on the :
. You need the _r
variant of strtok
to make it "re-entrant" so you can have two tokenizations at once nested.
For example (untested):
char *data = "<Idle|MPos:158.500,0.000,0.000|FS:0,0|Pn:H|Ov:100,100,100|SD:0.21,/instruction.nc>";
char *pair; // Pointer to a K/V pair
char *pairptr = data; // Pointer for outer strtok
// Split the string on the first |
pair = strtok_r(data, "|", &pairptr);
// While we have a K/V pair
while (pair) {
char *kvptr = pair;
// Split the substring into two parts on the colon
char *key = strtok_r(pair, ":", &kvptr);
char *val = strtok_r(NULL, ":", &kvptr);
if (val) { // If we split the data correctly:
if (strcmp(key, "SD") == 0) { // If the key is "SD" then
Serial.print("SD data: ");
Serial.println(val);
}
}
// Get the next string portion
pair = strtok_r(NULL, "|", &pairptr);
}
Once you have your val
you can further split that down on commas in the same way as it's been split on the colon.
|
then for each substring split it on:
. You then have key/value pairs that are easy to compare and work with. Use a C string not aString
object andstrtok_r
andstrcmp
to do the job with minimal memory outlay. I'll write a proper answer later, I'm on my phone at the moment.