TCPClient looks really buggy (red LED)

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 :

  1. Make your char buf[25]; to uint8_t buf[24];

  2. 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();
    }

  3. Covert your client.write(buf); to client.write(buf, 24);

  4. If you want to take it a step further, since the tcpClient is not the most stable feature, calling client.write so many times in void analize_data is not such a great idea. You could have a uint8_t temp_buffer[5], fill it up with the 0x07, 'X', 'O', 'S', 0x08 and send it in one go like client.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 :smile:

1 Like

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.

2 Likes

@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.

1 Like

Apparently I fixed the problem with a couple technics, actually didn’t fix it but avoided it.

  1. I am now sending every single packet all together, like you told me @nitred. Doing one single write.

  2. 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.

2 Likes

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.

1 Like