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.099kW)
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.570m3)
!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.669kWh)
1-0:2.8.1(000000.000kWh)
1-0:2.8.2(000000.000kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.469kW)
1-0:2.7.0(00.000k1-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.669kWh)
1-0:2.8.1(000000.000kWh)
1-0:2.8.2(000000.000kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.469kW)
1-0:2.7.0(00.000k⸮⸮?
1-0:21.7.0(00.469kW)
1-0:22.7.0(00.000kW)
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.669kWh)
1-0:2.8.1(000000.000kWh)
1-0:2.8.2(000000.000kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.469kW)
1-0:2.7.0(00.000k1-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.669kWh)
1-0:2.8.1(000000.000kWh)
1-0:2.8.2(000000.000kWh)
0-0:96.14.0(0001)
1-0:1.7.0(00.469kW)
1-0:2.7.0(00.000kSYN?
1-0:21.7.0(00.469kW)
1-0:22.7.0(00.000kW)
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 Serial Input Basics - updated - Introductory Tutorials - Arduino Forum 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! 