capture serial data with start and end marker question

I encounter the following problem. The library that I’m using needs a whole “telegram”. A telegram always starts with ‘/’ and ends with ‘!’ and is closed by a crc checksum of 4 characters.

This is what a telegram looks like:

/XMX5LGBBFG1012478418

1-3:0.2.8(42)
0-0:1.0.0(200329143717S)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009159.772kWh)
1-0:1.8.2(006069.669
kWh)
1-0:2.8.1(000000.000kWh)
1-0:2.8.2(000000.000
kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.409kW)
1-0:2.7.0(00.000
kW)
0-0:96.7.21(00001)
0-0:96.7.9(00000)
1-0:99.97.0(0)(0-0:96.7.19)
1-0:32.32.0(00000)
1-0:32.36.0(00000)
0-0:96.13.1()
0-0:96.13.0()
1-0:31.7.0(003A)
1-0:21.7.0(00.409
kW)
1-0:22.7.0(00.000kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303139333430323930303538323136)
0-1:24.2.1(200329140000S)(05387.414
m3)
!BE43

I adjusted my sketch to use a start marker ‘/’ and an end marker ‘!’ so I can catch the whole telegram. The start and end marker are also removed by the sketch but I don’t want them to be removed because the library needs them.

#include <WiFi.h>
#include <WiFiMulti.h>
#include "dsmr.h"

WiFiMulti wifiMulti;


using MyData = ParsedData<
  /* String */ identification,
  /* String */ p1_version,
  /* String */ timestamp,
  /* String */ equipment_id,
  /* FixedValue */ energy_delivered_tariff1,
  /* FixedValue */ energy_delivered_tariff2,
  /* FixedValue */ energy_returned_tariff1,
  /* FixedValue */ energy_returned_tariff2,
  /* String */ electricity_tariff,
  /* FixedValue */ power_delivered,
  /* FixedValue */ power_returned,
  /* FixedValue */ electricity_threshold,
  /* uint8_t */ electricity_switch_position,
  /* uint32_t */ electricity_failures,
  /* uint32_t */ electricity_long_failures,
  /* String */ electricity_failure_log,
  /* uint32_t */ electricity_sags_l1,
  /* uint32_t */ electricity_sags_l2,
  /* uint32_t */ electricity_sags_l3,
  /* uint32_t */ electricity_swells_l1,
  /* uint32_t */ electricity_swells_l2,
  /* uint32_t */ electricity_swells_l3,
  /* String */ message_short,
  /* String */ message_long,
  /* FixedValue */ voltage_l1,
  /* FixedValue */ voltage_l2,
  /* FixedValue */ voltage_l3,
  /* FixedValue */ current_l1,
  /* FixedValue */ current_l2,
  /* FixedValue */ current_l3,
  /* FixedValue */ power_delivered_l1,
  /* FixedValue */ power_delivered_l2,
  /* FixedValue */ power_delivered_l3,
  /* FixedValue */ power_returned_l1,
  /* FixedValue */ power_returned_l2,
  /* FixedValue */ power_returned_l3,
  /* uint16_t */ gas_device_type,
  /* String */ gas_equipment_id,
  /* uint8_t */ gas_valve_position,
  /* TimestampedFixedValue */ gas_delivered,
  /* uint16_t */ thermal_device_type,
  /* String */ thermal_equipment_id,
  /* uint8_t */ thermal_valve_position,
  /* TimestampedFixedValue */ thermal_delivered,
  /* uint16_t */ water_device_type,
  /* String */ water_equipment_id,
  /* uint8_t */ water_valve_position,
  /* TimestampedFixedValue */ water_delivered,
  /* uint16_t */ slave_device_type,
  /* String */ slave_equipment_id,
  /* uint8_t */ slave_valve_position,
  /* TimestampedFixedValue */ slave_delivered
>;

struct Printer {
  template<typename Item>
  void apply(Item &i) {
    if (i.present()) {
      Serial.print(Item::name);
      Serial.print(F(": "));
      Serial.print(i.val());
      Serial.print(Item::unit());
      Serial.println();
    }
  }
};

const byte numChars = 5000;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

//how many clients should be able to telnet to this ESP32
#define MAX_SRV_CLIENTS 10
const char* ssid = "xxxxx";
const char* password = "xxxxx";

WiFiServer server(23);
WiFiClient serverClients[MAX_SRV_CLIENTS];

HardwareSerial Serial_one(1);  // UART1/Serial1 pins 16,17



void setup() {
  Serial.begin(115200);
  Serial_one.begin(115200, SERIAL_8N1, 2, 3, true);
  Serial.println("\nConnecting");

  wifiMulti.addAP(ssid, password);
  wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
  wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");

  Serial.println("Connecting Wifi ");
  for (int loops = 10; loops > 0; loops--) {
    if (wifiMulti.run() == WL_CONNECTED) {
      Serial.println("");
      Serial.print("WiFi connected ");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      break;
    }
    else {
      Serial.println(loops);
      delay(1000);
    }
  }
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("WiFi connect failed");
    delay(1000);
    ESP.restart();
  }

  //start UART and the server
  server.begin();
  server.setNoDelay(true);

  Serial.print("Ready! Use 'telnet ");
  Serial.print(WiFi.localIP());
  Serial.println(" 23' to connect");
}



void loop() {
    recvWithStartEndMarkers();
    showNewData();

  uint8_t i;
  if (wifiMulti.run() == WL_CONNECTED) {
    //check if there are any new clients
    if (server.hasClient()){
      for(i = 0; i < MAX_SRV_CLIENTS; i++){
        //find free/disconnected spot
        if (!serverClients[i] || !serverClients[i].connected()){
          if(serverClients[i]) serverClients[i].stop();
          serverClients[i] = server.available();
          if (!serverClients[i]) Serial.println("available broken");
          Serial.print("New client: ");
          Serial.print(i); Serial.print(' ');
          Serial.println(serverClients[i].remoteIP());
          break;
        }
      }
      if (i >= MAX_SRV_CLIENTS) {
        //no free/disconnected spot so reject
        server.available().stop();
      }
    }
    //check clients for data
    for(i = 0; i < MAX_SRV_CLIENTS; i++){
      if (serverClients[i] && serverClients[i].connected()){
        if(serverClients[i].available()){
          //get data from the telnet client and push it to the UART
          while(serverClients[i].available()) Serial1.write(serverClients[i].read());
        }
      }
      else {
        if (serverClients[i]) {
          serverClients[i].stop();
        }
      }
    }
  }  
  else {
    Serial.println("WiFi not connected!");
    for(i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i]) serverClients[i].stop();
    }
    delay(1000);
  }
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '/';
    char endMarker = '!';
    char rc;
   
    while (Serial_one.available() > 0 && newData == false) {
        rc = Serial_one.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\n'; // terminate the line
                ++ndx;
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
  uint8_t i;
    if (newData == true) {
        Serial.print(receivedChars);

  MyData data;
  ParseResult<void> res = P1Parser::parse(&data, receivedChars, lengthof(receivedChars), true);
  if (res.err) {
    // Parsing error, show it
    Serial.println(res.fullError(receivedChars, receivedChars + lengthof(receivedChars)));
  } else {
    // Parsed succesfully, print all values
    data.applyEach(Printer()); 
    }

      //push UART data to all connected telnet clients
      for(i = 0; i < MAX_SRV_CLIENTS; i++){
        if (serverClients[i] && serverClients[i].connected()){
          serverClients[i].write(receivedChars);
        }
      }
    }
    newData = false;
 }

Is there another way to capture the whole telegram? If that’s not possible, can I insert the removed start and end marker which are needed by the library?

Well, I’m surprised that you’re asking about preserving the end marker, because I already showed you how to do that here:

You just have to add it before terminating the line:

            else {
                receivedChars[ndx] = endMarker; // terminate the telegram
                if (ndx < numChars - 1) ++ndx;
                receivedChars[ndx] = '\n'; // terminate the line
                if (ndx < numChars - 1) ++ndx;
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }

I added some crude protection to avoid overflowing the buffer. I leave it to you, to see how the start marker could be appended to the start of the telegram… you can see that things are starting to become awkward. Knowing in advance that the entire message is supposed to pass through, I would re-examine the serial logic to see if it can be slightly modified to accommodate it more “naturally”.

Another option is to capture without start and end markers, and use strcat() to concatenate them, since you know what their values are.

Thanks,

I added the startMarker and this part works. Now I think I am experiencing the buffer overflow problem you mentioned because every time the telegram gets cut-off at exactly the same point.

/MX5LGBBFG1012478418

1-3:0.2.8(42)
0-0:1.0.0(200329175030S)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009161.896*k!

So for that I added the adjusted part but now I only have this:

X!

I adjusted my sketch to use a start marker ‘/’ and an end marker ‘!’ so I can catch the whole telegram. The start and end marker are also removed by the sketch but I don’t want them to be removed because the library needs them.

This preserves the start and end markers and null terminates

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '/';
  char endMarker = '!';
  char rc;

  while (Serial.available() > 0 && newData == false) { // <<== NEW - get all bytes from buffer
    rc = Serial.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = endMarker;//preserve endmarker 
        receivedChars[ndx+1] = '\0';// terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      receivedChars[0] = startMarker;//preserve startMarker
      ndx++;
      recvInProgress = true;
    }
  } 
}

These are your globals

const byte numChars = 5000;
char receivedChars[numChars];

cattledog:
This preserves the start and end markers and null terminates

void recvWithStartEndMarkers() {

static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = ‘/’;
  char endMarker = ‘!’;
  char rc;

while (Serial.available() > 0 && newData == false) { // <<== NEW - get all bytes from buffer
    rc = Serial.read();

if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = endMarker;//preserve endmarker
        receivedChars[ndx+1] = ‘\0’;// terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

else if (rc == startMarker) {
      receivedChars[0] = startMarker;//preserve startMarker
      ndx++;
      recvInProgress = true;
    }
  }
}




These are your globals


const byte numChars = 5000;
char receivedChars[numChars];

I did this already and this works partially. The data read from the serial gets cut-off. I changed const byte numChars = 5000; to 5000 to get a biggur buffer but that does not help.

rwanrooy:
I changed const byte numChars = 5000; to 5000 to get a biggur buffer but that does not help.

A byte can hold a maximum value of 255. If you want to have a value of 5000 you must use an int

const int numChars = 5000;

...R

Good catch Robin2.

Change this as well

//static byte ndx = 0;
static int ndx = 0;

Sounds logical... so I changed the value to

const int numChars = 5000;
static int ndx = 0;

the output is unpredictable... When I get just below 255, i.a. 248, it gets cut off at exact the same place and gets predictable again. Above 255 it will be unpredictable. I think the serial buffer is just not bigger that 256? In that case, is there another way to deal with this?

You will have a major problem if you are receiving more than one “telegram” in rapid succession. You are printing out the received data, which will vastly exceed the capacity of the serial output buffer, and delay the code until nearly the entire telegram is sent. During that time the input buffer will not be read and could easily overflow.

And just what is this doing in a time-sensitive operation like reading input at 115200 baud?
    delay(1000); //<<< on line 117, in loop()

I'm not clear if you have input or output buffer issues, or if some of the wifi servicing is terminating the readings. Perhaps you could try a blocking reading to see if it gives a clue.

Does this read the entire message

void receiveMessage()
{
  while(Serial_one.available() > 0 && newData == false) 
  {
    //readBytes returns number read not zero referenced, blocking function with timeout
    int numberRead = Serial_one.readBytes(receivedChars, numChars);
    receivedChars[numberRead] = '\0';//null terminate
    Serial.println(receivedChars);
    newData = true;
  }
}

EDIT:
You can read until the end character with this variation

int numberRead = Serial_one.readBytesUntil('!', receivedChars, numChars);

Note that with readBytesUntil the terminating character is not placed in the buffer, and it will need to be added.

cattledog:
I'm not clear if you have input or output buffer issues, or if some of the wifi servicing is terminating the readings. Perhaps you could try a blocking reading to see if it gives a clue.

Does this read the entire message

void receiveMessage()

{
 while(Serial_one.available() > 0 && newData == false)
 {
   //readBytes returns number read not zero referenced, blocking function with timeout
   int numberRead = Serial_one.readBytes(receivedChars, numChars);
   receivedChars[numberRead] = '\0';//null terminate
   Serial.println(receivedChars);
   newData = true;
 }
}




The output stops at exactly the same point with your new code (also with the line you added later). What I notice is that when I use '\n' as the end marker and no start marker, I get all the lines except the first one that begins with '/'. I think this line does not end with a new line character.

When the sketch is processing the whole telegram at once, so with the start and end markers, the buffer gets full and it cut's off the rest. This is even the case when I make a clean sketch without the telnet and wifi stuff.

I also need the crc (the 4 bytes after the '!'), but that changes every telegram.

If one is not in control of what/how data is being sent, then one has to just deal as best as one can. If one is in control of what/how data is being sent, then one needs to focus on the sending side. If one is overflowing buffers and such, then the data sending may need to be evaluated. I doubt this controls a "fly by wire" fighter jet.

The output stops at exactly the same point with your new code (also with the line you added later). What I notice is that when I use '\n' as the end marker and no start marker, I get all the lines except the first one that begins with '/'. I think this line does not end with a new line character.

When the sketch is processing the whole telegram at once, so with the start and end markers, the buffer gets full and it cut's off the rest. This is even the case when I make a clean sketch without the telnet and wifi stuff.

Good idea on working without the telnet and wifi and just work on reading a long message.

MX5LGBBFG1012478418

1-3:0.2.8(42)
0-0:1.0.0(200329175030S)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009161.896*k!

Given your output, the first line would appear to end with a \n or \n\r or \r\n or else there would not be a gap to the second line.
I suggest printing out the byte value of every character received, to see what is there.

If you read each line individually instead of the entire message will that work for the application?

I don't know what I altered but now I can read all the data between the start and endmarker. The problem is the last 3 bytes after the endmarker. This is a crc checksum which is different in each telegram. So I need the 4 bytes after the endmarker.

Is there a way to do this?

Are you not in control of the telegram contents? Put the endmarker after the CRC.

I don't know what I altered but now I can read all the data between the start and endmarker.

Did you change anything in hardware?
Did you change anything in software?
Did you change anything on the sender side?
What is sending the message?

Please post the code which is reading the entire message.

I'm not in control of the telegram contents. The 4 byte crc is always after the endmarker wich is '!'. The crc changes every telegram. I have to capture the data 4 bytes beyond the endmarker.

rwanrooy:
I'm not in control of the telegram contents. The 4 byte crc is always after the endmarker wich is '!'. The crc changes every telegram. I have to capture the data 4 bytes beyond the endmarker.

Really? I'm surprised because your first program didn't use start and end markers. You could make a state machine with two states, MESSAGE and GETCRC. While in MESSAGE, what you already have, while in GETCRC, count and collect bytes, then go back to MESSAGE.

That's probably the cleanest way to do it.

OTOH, you can probably just read the required number of CRC bytes, at the time you encounter the end marker. Not as elegant but can be made to work. This is all pretty much common sense.

cattledog:
Did you change anything in hardware?
Did you change anything in software?
Did you change anything on the sender side?
What is sending the message?

Please post the code which is reading the entire message.

I did not change anything in the sketch. The only thing that was changed was powered off the esp32 in total. I just picked up where I left yesterday.
The esp32 gets the data from a smart meter which sends a “telegram” every 10 seconds. This is what a telegram looks like:

/XMX5LGBBFG1012478418

1-3:0.2.8(42)
0-0:1.0.0(200329143717S)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009159.772kWh)
1-0:1.8.2(006069.669
kWh)
1-0:2.8.1(000000.000kWh)
1-0:2.8.2(000000.000
kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.409kW)
1-0:2.7.0(00.000
kW)
0-0:96.7.21(00001)
0-0:96.7.9(00000)
1-0:99.97.0(0)(0-0:96.7.19)
1-0:32.32.0(00000)
1-0:32.36.0(00000)
0-0:96.13.1()
0-0:96.13.0()
1-0:31.7.0(003A)
1-0:21.7.0(00.409
kW)
1-0:22.7.0(00.000kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303139333430323930303538323136)
0-1:24.2.1(200329140000S)(05387.414
m3)
!BE43

The dsmr.h library puts the above values in variables which I need later. This library expects the whole telegram including the crc. The crc changes with every telegram so I can’t use it as an end marker. The ‘!’ never changes so if I can use n=4 and capture the telegram from ‘/’ till ‘!+4’ the dsmr library can read the values.

This is the sketch which I use now.

#include <WiFi.h>
#include <WiFiMulti.h>
#include "dsmr.h"

WiFiMulti wifiMulti;

using MyData = ParsedData<
  /* String */ identification,
  /* String */ p1_version,
  /* String */ timestamp,
  /* String */ equipment_id,
  /* FixedValue */ energy_delivered_tariff1,
  /* FixedValue */ energy_delivered_tariff2,
  /* FixedValue */ energy_returned_tariff1,
  /* FixedValue */ energy_returned_tariff2,
  /* String */ electricity_tariff,
  /* FixedValue */ power_delivered,
  /* FixedValue */ power_returned,
  /* FixedValue */ electricity_threshold,
  /* uint8_t */ electricity_switch_position,
  /* uint32_t */ electricity_failures,
  /* uint32_t */ electricity_long_failures,
  /* String */ electricity_failure_log,
  /* uint32_t */ electricity_sags_l1,
  /* uint32_t */ electricity_sags_l2,
  /* uint32_t */ electricity_sags_l3,
  /* uint32_t */ electricity_swells_l1,
  /* uint32_t */ electricity_swells_l2,
  /* uint32_t */ electricity_swells_l3,
  /* String */ message_short,
  /* String */ message_long,
  /* FixedValue */ voltage_l1,
  /* FixedValue */ voltage_l2,
  /* FixedValue */ voltage_l3,
  /* FixedValue */ current_l1,
  /* FixedValue */ current_l2,
  /* FixedValue */ current_l3,
  /* FixedValue */ power_delivered_l1,
  /* FixedValue */ power_delivered_l2,
  /* FixedValue */ power_delivered_l3,
  /* FixedValue */ power_returned_l1,
  /* FixedValue */ power_returned_l2,
  /* FixedValue */ power_returned_l3,
  /* uint16_t */ gas_device_type,
  /* String */ gas_equipment_id,
  /* uint8_t */ gas_valve_position,
  /* TimestampedFixedValue */ gas_delivered,
  /* uint16_t */ thermal_device_type,
  /* String */ thermal_equipment_id,
  /* uint8_t */ thermal_valve_position,
  /* TimestampedFixedValue */ thermal_delivered,
  /* uint16_t */ water_device_type,
  /* String */ water_equipment_id,
  /* uint8_t */ water_valve_position,
  /* TimestampedFixedValue */ water_delivered,
  /* uint16_t */ slave_device_type,
  /* String */ slave_equipment_id,
  /* uint8_t */ slave_valve_position,
  /* TimestampedFixedValue */ slave_delivered
>;

struct Printer {
  template<typename Item>
  void apply(Item &i) {
    if (i.present()) {
      Serial.print(Item::name);
      Serial.print(F(": "));
      Serial.print(i.val());
      Serial.print(Item::unit());
      Serial.println();
    }
  }
};



const int numChars = 2000;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

//how many clients should be able to telnet to this ESP32
#define MAX_SRV_CLIENTS 10
const char* ssid = "OUDE-MARKT";
const char* password = "jipenjanneke";

WiFiServer server(23);
WiFiClient serverClients[MAX_SRV_CLIENTS];

HardwareSerial Serial_one(1);  // UART1/Serial1 pins 16,17

void setup() {
  Serial.begin(115200);
  Serial_one.begin(115200, SERIAL_8N1, 2, 3, true);
  Serial.println("\nConnecting");

  wifiMulti.addAP(ssid, password);
  wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
  wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");

  Serial.println("Connecting Wifi ");
  for (int loops = 10; loops > 0; loops--) {
    if (wifiMulti.run() == WL_CONNECTED) {
      Serial.println("");
      Serial.print("WiFi connected ");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
      break;
    }
    else {
      Serial.println(loops);
      delay(1000);
    }
  }
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("WiFi connect failed");
    delay(1000);
    ESP.restart();
  }

  //start UART and the server
  server.begin();
  server.setNoDelay(true);

  Serial.print("Ready! Use 'telnet ");
  Serial.print(WiFi.localIP());
  Serial.println(" 23' to connect");
}

void loop() {
    recvWithStartEndMarkers();
    showNewData();
  uint8_t i;
  if (wifiMulti.run() == WL_CONNECTED) {
    //check if there are any new clients
    if (server.hasClient()){
      for(i = 0; i < MAX_SRV_CLIENTS; i++){
        //find free/disconnected spot
        if (!serverClients[i] || !serverClients[i].connected()){
          if(serverClients[i]) serverClients[i].stop();
          serverClients[i] = server.available();
          if (!serverClients[i]) Serial.println("available broken");
          Serial.print("New client: ");
          Serial.print(i); Serial.print(' ');
          Serial.println(serverClients[i].remoteIP());
          break;
        }
      }
      if (i >= MAX_SRV_CLIENTS) {
        //no free/disconnected spot so reject
        server.available().stop();
      }
    }
    //check clients for data
    for(i = 0; i < MAX_SRV_CLIENTS; i++){
      if (serverClients[i] && serverClients[i].connected()){
        if(serverClients[i].available()){
          //get data from the telnet client and push it to the UART
          while(serverClients[i].available()) Serial1.write(serverClients[i].read());
        }
      }
      else {
        if (serverClients[i]) {
          serverClients[i].stop();
        }
      }
    }
  }  
  else {
    Serial.println("WiFi not connected!");
    for(i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i]) serverClients[i].stop();
    }
    delay(1000);
  }
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static int ndx = 0;
    char startMarker = '/';
    char endMarker = '!';
    char rc;
   
    while (Serial_one.available() > 0 && newData == false) {
        rc = Serial_one.read();
                receivedChars[0] = startMarker; // place startMarker at begin of telegram

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = endMarker; // place endMarker at end of telegram
                ++ndx;
                receivedChars[ndx] = '\n'; // terminate the line
                ++ndx;
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
  uint8_t i;
    if (newData == true) {
        Serial.print(receivedChars);



  MyData data;
  ParseResult<void> res = P1Parser::parse(&data, receivedChars, lengthof(receivedChars), true);
  if (res.err) {
    // Parsing error, show it
    Serial.println(res.fullError(receivedChars, receivedChars + lengthof(receivedChars)));
  } else {
    // Parsed succesfully, print all values
    data.applyEach(Printer());
  }



      //push UART data to all connected telnet clients
      for(i = 0; i < MAX_SRV_CLIENTS; i++){
        if (serverClients[i] && serverClients[i].connected()){
          serverClients[i].write(receivedChars);
          newData = false;
        }
      }
    }
 }

“The esp32 gets the data from a smart meter which sends a “telegram” every 10 seconds”

Well, if the packet is sent every 10 seconds, then you may not need markers, and just capture based on timing knowing there won’t bee another packet for another 10 seconds. Below is very simple code that captures what is sent knowing there is a time separation between the packets.

//zoomkat 6-29-14 Simple serial echo test
//type or paste text in serial monitor and send

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("Simple serial echo test"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(3);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() > 0) {
    Serial.println(readString);  //so you can see the captured String
    readString = "";
  }
}