convert uint8_t to char

I want to convert serial data to char.

    if(Serial_one.available()){
      size_t len = Serial_one.available();
      uint8_t sbuf[len];
      Serial_one.readBytes(sbuf, len);

I tried it with char raw[len] = (char) sbuf, len; but I get the following error:
error: cast from 'uint8_t* {aka unsigned char*}' to 'char' loses precision [-fpermissive]

what am I doing wrong?

The serial input basics tutorial shows how to receive serial data into a null termnated character array (string) using a non blocking method.

I tried this:

uint8_t raw[len];
raw[len] = sbuf[len];
Serial.println(raw[len]);

in the telnet session I get the right output which is:

0-0:96.13.1()
0-0:96.13.0()
1-0:31.7.0(006A)
1-0:21.7.0(01.099
kW)
1-0:22.7.0(00.000kW)
0-1:24.1.0(003)
F-1:96.1.0(4730303139333430323930303538323136)
0-1:24.2.1(200327220000W)(05379.570
m3)
!52A6

In the serial monitor I only see integers like this:

22:48:24.807 -> 176
22:48:24.842 -> 176
22:48:24.878 -> 0
22:48:24.922 -> 0
22:48:24.922 -> 128
22:48:24.969 -> 63
22:48:24.969 -> 63
22:48:25.016 -> 139
22:48:25.016 -> 70

How can I copy it exactly like the original?

Please post your entire sketch so we can see how the error is generated.

This is not C syntax:
char raw[len] = (char) sbuf, len;It's so wrong, that to explain what is wrong with it requires knowing what you think it means...

This is the whole sketch:

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

WiFiMulti wifiMulti;

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

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() {
  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();
        }
      }
    }
    //check UART for data
    if(Serial_one.available()){
      size_t len = Serial_one.available();
      uint8_t sbuf[len];
      Serial_one.readBytes(sbuf, len);

uint8_t raw[len];
raw[len] = sbuf[len];
Serial.println(raw[len]);
      
      //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(sbuf, len);
          delay(1);
        }
      }
    }
  }
  else {
    Serial.println("WiFi not connected!");
    for(i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i]) serverClients[i].stop();
    }
    delay(1000);
  }
}
uint8_t raw[len];
raw[len] = sbuf[len];

An array of length “len” has no element with the index “len”, because arrays typically index from zero.

Ok, I did some more adjustments and I am getting more to a solution. I used the following to copy the serial data for later use:

delay(300);
char raw[len];
memcpy(raw, sbuf, sizeof(sbuf));
Serial.println(raw);

The when I use the telnet session and the console output I see that the output is almost ok but just some characters.

Console:
⸮?
1-3:0.2.8(42)
0-0:1.0.0(200328132739W)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009144.268kWh)
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.469kW)
1-0:2.7.0(00.000
k1-3:0.2.8(42)
0-0:1.0.0(200328132739W)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009144.268kWh)
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.469kW)
1-0:2.7.0(00.000
k⸮⸮?
1-0:21.7.0(00.469kW)
1-0:22.7.0(00.000
kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303139333430323930303538323136)
0-1:24.2.1(200328130000W)(05382.411*m3)
!0F91

The red part is where it is always going wrong. I copied the above output to notepad++ and see the following:

NAK-?
1-3:0.2.8(42)
0-0:1.0.0(200328132739W)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009144.268kWh)
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.469kW)
1-0:2.7.0(00.000
k1-3:0.2.8(42)
0-0:1.0.0(200328132739W)
0-0:96.1.1(4530303331303033323531323636363136)
1-0:1.8.1(009144.268kWh)
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.469kW)
1-0:2.7.0(00.000
kSYN?
1-0:21.7.0(00.469kW)
1-0:22.7.0(00.000
kW)
0-1:24.1.0(003)
0-1:96.1.0(4730303139333430323930303538323136)
0-1:24.2.1(200328130000W)(05382.411*m3)
!0F91

What is happening here? The first time the packet is copied like the above, the more packets arrive, the more corrupt the copies get.

How can we know what is wrong without seeing your "adjustments"? Please re-post the modified sketch.

This is the new sketch with adjustments.

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

WiFiMulti wifiMulti;

//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() {
  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();
        }
      }
    }
    //check UART for data
    if(Serial_one.available()){
      size_t len = Serial_one.available();
      uint8_t sbuf[len];
      Serial_one.readBytes(sbuf, len);

      //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(sbuf, len);

delay(300)
char raw[len];
memcpy(raw, sbuf, sizeof(sbuf));
Serial.println(raw);

        }
      }
    }
  }  
  else {
    Serial.println("WiFi not connected!");
    for(i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i]) serverClients[i].stop();
    }
    delay(1000);
  }
}

So the memcpy works but the red lines in the previous post are wrong copied. Do you notice the NAK and SYN when viewed in notepad?

You don’t check for line terminator, just available characters. I assume you are depending on some delay in the code to guarantee that the input buffer has a complete line waiting for your read to take place. That is not reliable under all circumstances. For one thing, the buffer might overflow. Also why do you need raw? Can’t you just print sbuf directly?

  //check UART for data
    if (Serial_one.available()) {
      size_t len = Serial_one.available();
      uint8_t sbuf[len];
      Serial_one.readBytes(sbuf, len);

      //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(sbuf, len);

          delay(300)
          char raw[len];
          memcpy(raw, sbuf, sizeof(sbuf));
          Serial.println(raw);

        }
      }
    }
  }

aarg:
You don’t check for line terminator, just available characters. I assume you are depending on some delay in the code to guarantee that the input buffer has a complete line waiting for your read to take place. That is not reliable under all circumstances. For one thing, the buffer might overflow. Also why do you need raw? Can’t you just print sbuf directly?

  //check UART for data

if (Serial_one.available()) {
     size_t len = Serial_one.available();
     uint8_t sbuf[len];
     Serial_one.readBytes(sbuf, len);

//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(sbuf, len);

delay(300)
         char raw[len];
         memcpy(raw, sbuf, sizeof(sbuf));
         Serial.println(raw);

}
     }
   }
 }

Thanks for your answer. I read the https://forum.arduino.cc/index.php?topic=396450.0 so I know what you mean. Like you said. I played with changing the delay in time and place in the sketch, that altered the behaviour.

In the meantime I am rewriting the sketch like explained in the article. This goes (almost) well and I can print the output of the comport to the console. Now I am trying to print the output in the telnet session but it doesn’t add carriage returns to the telnet output. I am using the /n as an endmarker.

This is the new code.

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

WiFiMulti wifiMulti;

const byte numChars = 32;
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() {
    recvWithEndMarker();
    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 recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    while (Serial_one.available() > 0 && newData == false) {
        rc = Serial_one.read();

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

void showNewData() {
  uint8_t i;
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println(receivedChars);

      //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 reading of the Serial_one is optimized and I can successfully show the Serial_one output on the console. When I write the same output to the telnet session each line gets overwritten. The difference is that I use Serial.println(receivedChars); for the console session and serverClients*.write(receivedChars); for the telnet session.*
I searched for some sort of serverClients*.writeln(receivedChars); wich I hoped to print each line seperate but I don’t think that exists.*
Is there a way to insert a ‘/n’ at each line printed in the telnet session?

Is there a way to insert a '/n' at each line printed in the telnet session?

You could just insert a '\n' in the received line...

        else {
            receivedChars[ndx] = '\n'; // terminate the line
            ++ndx;
            receivedChars[ndx] = '\0'; // terminate the string
           ndx = 0;
            newData = true;
        }

That did the trick, thanks! :slight_smile: