/*
Serial Parse Data
<command:value>
example:
<distance:42>
<length:100>
https://forum.arduino.cc/t/bluetoothdaten-lesen-und-parsen/1230830/8
2024-03-02 by noiasca
*/
class Receiver {
protected:
static const byte numChars = 20; // receiver buffer size
char receivedChars[numChars]; // an array to store the received data
byte ndx = 0; // length of received message
boolean newData = false; // flag to indicate when new data is complete
Stream &stream; // a reference to the serial interface
void (*cbOnNewData)(); // gets called after we received a full message
// payload data
int distance = 0;
int length = 0;
void delBuffer() {
memcpy(receivedChars, "", sizeof(receivedChars));
ndx = 0;
}
// parse data and if according to specification store to internal variable
//<test:1234> <distance:42> <length:100>
void parseData() {
char * ptr = strchr(receivedChars, ':');
if (ptr) {
char tag[numChars] {};
char value[numChars] {};
size_t pos = ptr - receivedChars;
strncpy(tag, receivedChars, pos);
strncpy(value, receivedChars + pos + 1, numChars);
Serial.println(tag);
Serial.println(value);
// take over values into member variables
if (!strcmp(tag, "distance")) distance = atoi(value);
else if (!strcmp(tag, "length")) length = atoi(value);
}
delBuffer();
}
// validate if checksum of telegram is correct - only dummy in this version
bool validateChecksum() {
return true;
}
void parseLine() { // process a telegram
Serial.print(F("I53: This is just in ... ")); Serial.println(receivedChars); // output all
if (validateChecksum()) {
parseData();
if (cbOnNewData) cbOnNewData();
}
}
public:
Receiver (Stream &stream) : stream(stream) {
delBuffer();
}
// set a callback function. Gets called when new data was received
void setOnNewData(void (*cbOnNewData)()) {
(*this).cbOnNewData = cbOnNewData;
}
// run this member function in loop()
void update() {
// start flag, fix length
constexpr char startMarker = '<';
constexpr char endMarker = '>';
if (stream.available() > 0) {
char rc = stream.read();
if (rc == startMarker) {
delBuffer();
}
else if (rc == endMarker) {
parseLine();
}
else { // for all we accept any value (including the startMarker
receivedChars[ndx] = rc;
if (ndx < numChars) {
ndx++;
}
}
}
}
// getter to return payload
int getDistance() {
return distance;
}
int getLength() {
return length;
}
};
//#include <SoftSerial.h>
//SoftwareSerial mySerial(2, 3); // RX, TX
//Receiver receiver(mySerial); // on an UNO you will need SoftSerial get a second serial
// create the sensor object and hand over the Serial interface to use:
Receiver receiver(Serial); // use Hardware Serial (for example for testing with the PC)
void output() { // simple output of data
Serial.print("D:"); Serial.print(receiver.getDistance());
Serial.print("\tL:"); Serial.print(receiver.getLength());
Serial.println();
}
// a timer to output data to serial
void timerOutput() {
static uint32_t previousMillis = 0; // time management
const uint16_t interval = 3000; // interval to display data
if (millis() - previousMillis >= interval) {
previousMillis = millis();
output();
}
}
void setup() {
Serial.begin(9600);
Serial.println("Serial Parse Data");
//mySerial.begin(9600);
//receiver.setOnNewData(output); // register a callback function which gets called when a new telegram was received
}
void loop() {
receiver.update(); // you must call the .update() method in your loop()
timerOutput();
}