TCPClient is acting really weird, I’m trying to send to a Socket Server my core’s id, sometimes it sends sometimes it doesn’t. I would say, it sends 75% of the time, the other 25% of the time the core restets and goes in Panic Mode and displays SOS 1 blink. But that’s not it, when the server sends data to the core via the socket connection using TCP, it goes panic, flahes red, and same, 1 blink. And I’m not even sending big data, I’m sending 6 bytes data, if I send this 6 bytes packet to the core a couple times really fast, it goes to panic and again 1 blink and the core resets. And I’m reading the data from the client, when it’s client.available(), so there is no bufferoverload…
I am seeing this kind of behavior too!!
@Cabada Could you please post your code that is causing the issues?
What language are you using? I’ve socketed to my Spark Core from a RPi and noticed that this doesn’t happen if you put tiny sleeps in between bytes on the rpi side(i used .015 seconds between bytes) using python
@lbruder I’m using Node.JS, and I already tried it with delays, and still seeing the same behavior.
@nitred Here is the code:
TCPClient client;
byte server[] = { 0, 0, 0, 0 }; //My real server ip goes here
unsigned long retry = 0;
unsigned long alive = 0;
int connected = 0;
int aliveStatus = 0;
char buf[25];
int data_index = 0;
char data_msg[50];
void setup()
{
firstconnection();
}
void firstconnection(){
String myID = Spark.deviceID();
myID.toCharArray(buf, 25);
connect();
}
void connect(){
client.stop();
if(client.connect(server,5100)){
alive = millis();
aliveStatus = 0;
connected = 1;
} else {
connected = 0;
retry = millis();
}
}
void analize_data(int size){
if(data_msg[0]==0x56){ //Reply to the server
client.write(0x07);
client.write('X');
client.write('O');
client.write('S');
client.write(0x08);
} else if(data_msg[0]=='L'){ //ASKS FOR LOGIN
//IT SOMETIMES CRASHES HERE WHILE TRYING TO SEND BUF
//BUF IS THE BUFFER THAT CONTAINS MY ID, I DON’T USE STRING CAUSE
//STRING CLASS TAKES LOTS OF RESOURCES
client.write(0x07);
client.write('S');
client.write('L');
client.write(buf);
client.write(0x08);
}
}
void readdata(){
//When receiveng lots of bytes it crashes (By lots, I mean even from 3 packets of 6 bytes)
//I tested it by removing the processing of the data, and just send bytes and same, crashes
if(client.available()>0){
char c = client.read();
if(c==0x02){
//Just used to keep the socket open
} else {
if(c==0x07){
//START BYTE
data_index = 0;
} else if(data_index>-1){
if(c==0x08){
//END BYTE
analize_data(data_index);
data_index = -1;
} else {
data_msg[data_index] = c;
data_index++;
}
}
}
alive = millis(); //got response, socket still alive
aliveStatus = 0;
}
}
void loop()
{
readdata();
keepalive();
}
void keepalive(){
if(!client.connected() && connected==1){
connected = 0;
retry = millis();
}
if(connected==0){
//Retrying to connect
if((long)(millis()-retry)>15000){
connect();
}
}
}
@Cabada Hi thanks for the code. The last time I tried to do a tcpClient.write(char buffer)
, my local compiler punched me in the face and told me I can’t do it. I’m not certain how the code is compiling for you (maybe there have been some changes recently that I don’t know of). If you look at the link below, you should be able to write uint8_t buffers
and you will also have to mention the size of buffer.
https://github.com/spark/core-firmware/blob/master/inc/spark_wiring_tcpclient.h#L40
So I’d suggest trying the following things :
-
Make your
char buf[25];
touint8_t buf[24];
-
Converting your void firstconnection() to:
void firstconnection(){
char temp_buf[25];
String myID = Spark.deviceID();
myID.toCharArray(temp_buf, 25);
memcpy(buf,temp_buf,24); // this could cause issues, but I’m certain in this case its fine
connect();
} -
Covert your
client.write(buf);
toclient.write(buf, 24);
-
If you want to take it a step further, since the tcpClient is not the most stable feature, calling
client.write
so many times invoid analize_data
is not such a great idea. You could have auint8_t temp_buffer[5]
, fill it up with the0x07, 'X', 'O', 'S', 0x08
and send it in one go likeclient.write(temp_buffer,5)
. Also your Node server will appreciate all the data coming in at one go.
I could be wrong about a lot things. Let me know if it works
Your red flashing SOS, one flash, SOS means hard fault. Often this is your code treating a pointer as data or vice-versa or other programming issue.
You got good advice from @nitred about client.write(buf). That writes one byte, not the whole buffer, but your example does not seem to be calling analize_data() right now.
You are writing your data_msg[] array without any bounds checking. I know your protocol has a terminating byte of 0x08, but it that is not working for some reason, you code will write all over memory. I would fix that first and see if it improves.
I think you should also start looking at the return codes from client.write(). It returns -1 when it cannot send to the socket. You can also check client.read() for -1 returns which means nothing is there. These are probably OK, but for debugging it is best to check them.
@bko Hey, sorry, my code var and function names were in spanish and I translated them to english so you understood, I’m calling analize_data whenever I receive the 0x08 byte, so calling that function should be there, I forgot to write it when I was tranlasting the code to post it here, just updated the code. I’ll try what @nitred says and I’ll let you know if I still have the same issue.
Apparently I fixed the problem with a couple technics, actually didn’t fix it but avoided it.
-
I am now sending every single packet all together, like you told me @nitred. Doing one single write.
-
I am avoiding sending and receiving packets at the same time, my server now awaits for an “ACK” packet so the server cannot sent a second packet if the Spark client hasn’t send an “ACK” back. I found out that I cannot be sending something while receiving it, at least that what I came to. Maybe it was just a coincidence, but now it’s working.
Thanks! I’ll keep monitoring it to see if I ever encounter that red LED.
Just so you know @Cabada, I have an app that uses TCPClient to read a Yahoo weather forecast page and pulls out the next five days and puts out on an LCD display, refreshing every 5 minutes. Runs for days and days and never seems to have a problem.