Coding help needed: TCP sending and recieving on cores

Hi guys,
I’ve been working on this for a while now and can now send a char array from one core to the other and print it out on the other end. The spec for the software I’m writing requires there to be a header with a Unique ID (UUID) and a zigbee type, which will eventually tell the server what type of controller iit is recieving data from then a variable sized data packet.

As I previously mentioned I have managed to send one char array and I now want to send two which would be inputted seperately on the clientside and split up into two seperate strings or arrays on the server side. My current issue is that in wiring certain things can’t be done. I can’t send a String using the “Client.write()” command, only bytes and chars. I can’t do the string.length() command either, which I will need later, because it doesn’t seem to output a varible but it’s alot easier to add the char arrays together if they are strings. On the server side I have a similar problem as the char arrays refuse to split or print. Basically I have been writing incredibly “hacky” ways around using the wiring experience I have and I have hit a dead end. I hope someone can help. Sorry for how messy the code is.

Clientside code:

byte serv[] = { 172, 16, 0, 222 }; //dos
//SYSTEM_MODE(MANUAL);<
//TCPServer server = TCPServer(23);
TCPClient client;
#include <string.h>
#include <stdio.h>
void setup()
{
    Serial.begin(9600);
  // start listening for clients
    while(!Serial.available()) SPARK_WLAN_Loop();
  //  client.connect(serv,23);
    if (client.connect(serv, 80))
    {
        Serial.println("connected");
        client.println("We are all connected");
    }
    else
    {
        Serial.println("connection failed");
    }
}

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void loop()
{
    if (client.connected())
    {
        delay(1000);
        Serial.print("Here");
        int length = client.read();
        Serial.println(length);
        client.flush();
        String s4 = "";  
        
        for (int i=1; i <= length; i++){
            char be = client.read();
            s4 += be;
            Serial.println(s4);
            delay(1000);
            }
    Serial.println("Post for loop");
    

    String word1 = getValue(s4, ' ', 0);
    String word2 = getValue(s4, ' ', 1);
    Serial.println(word1);
    Serial.println(word2);
    
    /*char packet[13];
    char UUID[7];
    char ZigBeeType[6];
    //int z;
    //String UUID =  "";
    //String ZigBeeType =  "";
    
    s4.toCharArray(packet, 13);
        
    char* z = packet;
        
    strncpy(UUID, z, 7);
    z += 7;
    
    strncpy(ZigBeeType, z, 6);
    z += 6;
    
   /* char * pch;
    //printf ("Splitting string \"%s\" into tokens:\n",str);
    pchar str[] ="- This, a sample string.";
    char * pch;
    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," ,.-");
    while (pch != NULL)
    {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
    }
    
    /*strncpy(UUID, UUIDC, 7);
    UUID[7] = '\0';
    strncpy(ZigBeeType, ZigBeeTypeC, 6);
    ZigBeeType[6] = '\0';
    
    Serial.println("");
    Serial.println("The Unique ID of this packet is: ", UUID);
    Serial.println("");
    Serial.println("The ZigBeeType of this packet is: ", ZigBeeType);
    */
    
    }else{
        Serial.println();
        Serial.println("disconnecting.");

    } 
}

Server side code:

#include <string.h>
TCPServer server = TCPServer(80);
TCPClient client; 

void setup()
{
    Serial.begin(9600);
  // start listening for clients
    server.begin();
    while(!Serial.available()) SPARK_WLAN_Loop();
  // Make sure your Serial Terminal app is closed before powering your Core

  // Now open your Serial Terminal, and hit any key to continue!

}

void loop()
{
   // char packet[10] = "packet";
    char UUID[8] = {'1', '2', '3', '4', '5', '6', '7', ' '};   // int length;
    char ZigBeeType[6] = {'0', 'x', '0', '6', '0', '0'};
    char packet [14];
    
    memcpy(packet, UUID, 8);
    memcpy(&packet[20], ZigBeeType, 6);
    
   
    
    //String UUIDs = "1234567";
    //String ZigBeeTypes = "0x0600";
    //String packets = "";
    
    //packetS += UUIDS;
    //packetS += ZigBeeTypeS;
    
    //int length = 20;
    int length = arraySize(packet);
    client.write(length);
    
    if (client.connected()) {
        while (client.available()) {
            Serial.print("It's working, promise:  ");
            client.write(packet);
            Serial.println(packet);
            client.flush();
            delay(30000);
            
    }
    } else {
    // if no client is yet connected, check for a new connection
        Serial.print(" No connection here ");
        client = server.available();
    } 
    //Serial.print(c);
    delay (2000);
    
}

Client side output:

Here14
▒
▒1
▒12
▒123
▒1234
▒12345
▒123456
▒1234567
▒1234567
▒1234567 ▒
▒1234567 ▒O
▒1234567 ▒O▒
▒1234567 ▒O▒▒
▒1234567 ▒O▒▒▒
Post for loop
▒1234567
▒O▒▒▒
Here-1
Post for loop

Server side output:

 No connection here  No connection here It's working, promise:  1234567 ▒O

With char arrays you'd use strlen() to get the string length.

Have you tried Client.print()? Since you got a propper string (no binary data with '\0' chars and such stuff), print should work. Another way would be to Client.write() each byte one by one in a loop.

Sorry, but I don't quite get the meaning of this complete sentence

And how would you like to "split" the char array? If I knew how you mean this, I might be able to come up with something.
And how does the char array refuse to be printed?

One thing you don't seem to know about strings and strings in char arrays is, that you need a final '\0' character (aka zero terminator) at the end of a string to denote its end. Without this e.g. print() would spit out every byte between the actual end of your string and the first \0 byte that happens to lay around in memory.

2 Likes

Hi, thanks for the response. Would I be able to use the information from client.print() on the client side or would it simply print out in serial? I need to be able to use the data at a later date not just print it.

Sorry for my terrible wording, what I’m trying to say is I’ve been unable to send a string using client.write() and client.read() so I’ve had to send over the data as a char array (sending char by char then looping) but on the client side, as you mentioned, I don’t know how to split the array without pulling it out char by char which, again, is pretty hacky. So I decided to change it back to a string on the client side so I could split it into two strings. I’d rather either use a char array OR a string. Preferably a string if there is a way to send that over TCP.

fixed the char array not printing thing. I’m going to add in zero terminators now and I’m also going to strlen(). Thanks alot for your help so far.

client.print() does “print” (=send) the data to the client. The client then can decide what it does with it.
And yes once you have a char array, you should even be able to client.write(array, strlen(array));.

For your way of reading char by char, that’s not hacky, but that’s the way it’s usually done.

But you can also use an overload of read that might look like the one of TCPClient.read()

int TCPClient::read(uint8_t *buffer, size_t size)
{
        int read = -1;
        if (bufferCount() || available())
        {
          read = (size > (size_t) bufferCount()) ? bufferCount() : size;
          memcpy(buffer, &_buffer[_offset], read);
          _offset += read;
        }
        return read;
}
1 Like

I think I’ll try and use your first suggestion once I’ve got it working this way. Any idea’s why I’m getting:

▒1234567

Rather than 1234567? I know it’s sending 1234567 without the "▒"so it’s likely clientside.

I guess there is a problem with an index somewhere along the line.
Either you are sending data from the position one before your actual beginning of the string or you are printing from an invalid position.

But a more dangerous problem with your code is here.

Maybe you can find the problem and repost a current version of the complete codes of either side.

Current code:
Server side

#include <string.h>
TCPServer server = TCPServer(80);
TCPClient client; 

void setup()
{
    Serial.begin(9600);
  // start listening for clients
    server.begin();
    while(!Serial.available()) SPARK_WLAN_Loop();
  // Make sure your Serial Terminal app is closed before powering your Core

  // Now open your Serial Terminal, and hit any key to continue!

}

void loop()
{
   // char packet[10] = "packet";
    char UUID[8] = {'1', '2', '3', '4', '5', '6', '7', ' '};   // int length;
    char ZigBeeType[6] = {'0', 'x', '0', '6', '0', '0'};
    char packet [14];
    
    memcpy(packet, UUID, 8);
    memcpy(&packet[14], ZigBeeType, 6);

    int length = arraySize(packet);
    client.write(length);
    
    if (client.connected()) {
        while (client.available()) {
            Serial.print("It's working, promise:  ");
            client.write(packet);
            Serial.println(packet);
            client.flush();
            delay(30000);
            
    }
    } else {
    // if no client is yet connected, check for a new connection
        Serial.print(" No connection here ");
        client = server.available();
    } 
    //Serial.print(c);
    delay (2000);
    
}

Client side

byte serv[] = { 172, 16, 0, 222 }; //dos
//SYSTEM_MODE(MANUAL);<
//TCPServer server = TCPServer(23);
TCPClient client;
#include <string.h>
#include <stdio.h>
void setup()
{
    Serial.begin(9600);
  // start listening for clients
    while(!Serial.available()) SPARK_WLAN_Loop();
  //  client.connect(serv,23);
    if (client.connect(serv, 80))
    {
        Serial.println("connected");
        client.println("We are all connected");
    }
    else
    {
        Serial.println("connection failed");
    }
}

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void loop()
{
    if (client.connected())
    {
        delay(1000);
        Serial.print("Here");
        int length = client.read();
        Serial.println(length);
        client.flush();
        String s4 = "";
        
        for (int i=0; i <= length; i++){
            char be = client.read();
            s4 += be;
            Serial.println(s4);
            delay(1000);
            }
    Serial.println("Post for loop");
    
    s4 += "\0";
    String word1 = getValue(s4, ' ', 0);
    String word2 = getValue(s4, ' ', 1);

    Serial.println("");
    Serial.println("The Unique ID of this packet is: ");
    Serial.print(word1);
    Serial.println("");
    Serial.println("The ZigBeeType of this packet is: ");
    Serial.println(word2);
    
    
    }else{
        Serial.println();
        Serial.println("disconnecting.");

    } 
}

Hi @OddieCAT

The part above looks to me like it is writing to memory beyond the packet array since you are starting the second memcpy at the end of the packet array.

I didn't look at the client side after finding this.

Right, great so my output is now:

▒1234567 0x0600
Unique ID: ▒1234567
Zigbee Type: 0x0600

So it’s splitting them fine! Thanks guys.

Anyone got any idea on the “▒”?

@bko, that was my finding at the post above

1 Like

Hi @OddieCAT

@ScruffR and I are saying that your server code is wrong and needs to be fixed. I am not sure what you wanted to do but what you are doing is over-writting other variables in memory, so your program will eventually crash.

If you meant to pack the 8-bytes of UUID and 6-bytes ZigBeeType into one 14-byte array, here is how:

char UUID[8] = {'1', '2', '3', '4', '5', '6', '7', ' '}; // int length;
char ZigBeeType[6] = {'0', 'x', '0', '6', '0', '0'};
char packet [14];

memcpy(packet, UUID, 8);
memcpy(&packet[8], ZigBeeType, 6);

This explains why it would only run one iteration before not working! Thanks again. I’m going to keep this thread relatively active because you guys are great! next step is fix some timings then implement the packet standard I want and hopefully input some real data.

Thanks again!

1 Like

Another thing you might consider doing instead of what you already have

char UUID[9] = "1234567 ";    // 9 to account for the '\0' terminator
char ZigBeeType[] = "0x0600"; // or let the compiler fill that in for you

If you do hardcode strings, always make sure to zero terminate them propperly. By use of string literals (using “…”) this will be done automatically.

2 Likes