Go Down

Topic: Parse received String from Ethernet Server (client) (Read 333 times) previous topic - next topic

Markuss

Hi,

I'm working on my Arduino project and I'm stuck on how to parse received string from Ethernet Server respectively connected client.
Syntax of received string: "CD01,CM01,CT01,CS03,BR255" where comma is a delimiter.
I need to parse this string into chunks without letter(int cd = 1; int cm = 1, int ct = 1; int cs = 1; int br = 255;) store them like int variables into array and then use each one variable  to execute specific operation like analogWrite(cs, br);. Does anybody know how to parse string this way?

All I've done until now is when I receive string separated into "<val>" then set LED on currnet val.

Code: [Select]
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress serverIP(192,168,1,10);
int serverPort=8888;
int index;
int led = 3;
int inInt;
char analogVal;
char inData[10];
boolean started = false;
boolean ended = false;
String str ="";
String stringBuffer;
EthernetServer server(serverPort);

void setup(){
  Ethernet.begin(mac, serverIP);
  server.begin();
  Serial.begin(9600);
  pinMode(led, OUTPUT);
}

void loop(){
  EthernetClient client = server.available(); 
    if(client){
      while(client.connected()){
        if(client.available()){
       
          char c = client.read();       
         
       if (stringBuffer.length() < 100) {
          stringBuffer += c;
       }
     
           
       if(c == '<'){
           started = true;
           index = 0;
           inData[index] = '\0';         
       }
       else if(c == '>')
       {
           ended = true;
       }
       else if(started)
       {
           inData[index] = c;
           index++;
           inData[index] = '\0';   
       }
   }
}
if(started && ended)
   {
       inInt = atoi(inData);

       analogWrite(led, inInt);
       Serial.println("Set LED on value: ");
       Serial.println(inInt);
       started = false;
       ended = false;
       index = 0;
       inData[index] = '\0';
}
    }
    client.stop();
  }



I'm out of ideas how to solve this problem. If anyone could help me or point me to some example code on how to do this I'd really appreciate it.

Thanks!

Marek


zoomkat

Below is some simple code that does stuff with the contents of a comma delineated data string. You should be able to do something similar with the data string received from the server.

Code: [Select]

//zoomkat 3-5-12 simple delimited ',' string 
//from serial port input (via serial monitor)
//and print result out serial port

String readString, substring;
//String servo1;
int loc;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like AA BB01/10/2014 CC12:23:25 DD32.2 EE5432 FF54.35,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    //if (c == '\n') {  //looks for end of data packet marker

    if (c == ',') {
      Serial.println(readString); //prints string to serial port out
      //do stuff     
      loc = readString.indexOf("BB");
      //Serial.println(loc);
      substring = readString.substring(loc+2, loc+12);
      Serial.print("date is: ");
      Serial.println(substring);

      loc = readString.indexOf("CC");
      //Serial.println(loc);
      substring = readString.substring(loc+2, loc+11);
      Serial.print("time is: ");
      Serial.println(substring);

      loc = readString.indexOf("DD");
      //Serial.println(loc);
      substring = readString.substring(loc+2, loc+6);
      Serial.print("DD is: ");
      Serial.println(substring);

      loc = readString.indexOf("EE");
      //Serial.println(loc);
      substring = readString.substring(loc+2, loc+6);
      Serial.print("date is: ");
      Serial.println(substring);

      loc = readString.indexOf("FF");
      //Serial.println(loc);
      substring = readString.substring(loc+2);
      Serial.print("FF is: ");
      Serial.println(substring);     

      readString=""; //clears variable for new input
      substring="";

    } 
    else {     
      readString += c; //makes the string readString
    }
  }
}

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)

PaulS

Quote
Syntax of received string: "CD01,CM01,CT01,CS03,BR255" where comma is a delimiter.

I hardly think that is going to fit in the 10 element array you have defined.

If you make inData large enough, the strtok function will then parse the string, returning tokens like "CD01", "CM01", etc.

Making sense of them is going to be challenging. If the string being received looked more like "CD=01,CM=01,..." then you could get tokens like "CD", "01", "CM", etc. and deal with names and values easily.

Markuss

#3
Jan 28, 2014, 01:44 am Last Edit: Jan 28, 2014, 02:11 am by Markuss Reason: 1
First at all I'd like to thank you both for advices and an example. I really appreciate it!!!

I've left an idea of Ehernet Server and I'm testing my parse function using Serial Monitor. I'm trying to parse and store each int value into array of integers. Strtok function was really helpful! But again I have few troubles.
Code: [Select]
#include <String.h>

String stringBuffer;

void setup(){
 Serial.begin(9600);
}

void loop(){
     
if(Serial.available()){
       int isTrue= 1;
       
       while(isTrue == 1){
               char c = Serial.read();
               if(c == 21)
                       isTrue = 0;
               else
                       if (stringBuffer.length() < 100) {
                               stringBuffer += c;
                       }  
       }
       Serial.print("Stored string: ");
       Serial.println(stringBuffer);
   
     }

int *data = parsed(stringBuffer);

       int i = 0;
        for(i = 0; i<5; i++){
        Serial.println(data[i]);
   }
 }

int *parsed(String stringBuffered){

int inParse[5];
String stringBuffer;
char pars[40];

  stringBuffer.toCharArray(pars, 20);
   
    char *pch;
      int count = 0;
      pch = strtok(pars, "CD CM CT CS BR :");

      while(pch != NULL){
        inParse[count] = atoi(pch);
        count++;
        Serial.print("Parsed value: ");
        Serial.println(pch);
        pch = strtok(NULL, "CD CM CT CS BR :");
      }
return inParse;
}


When I start Serial Monitor uncontrollably heap of values are written down in loop. At which point I'm wrong?

zoomkat

Some simple code that might do what you need. Each data packet needs to have a comma , delimiter at the end of the packet.

Code: [Select]

//zoomkat 3-5-12 simple delimited ',' string 
//from serial port input (via serial monitor)
//and print result out serial port

String readString, data;
//String servo1;
int CD, CM, CT, CS, BR;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like CD01,CM01,CT01,CS03,BR255,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
   
    if (c == ',') {
      Serial.println(readString); //prints string to serial port out
     
      if(readString.indexOf("CD") >=0) {
        data=readString.substring(2);
        Serial.print("CD is: ");
        Serial.println(data);
        CD = data.toInt();
        Serial.println(CD);
        Serial.println();
      }
      if(readString.indexOf("CM") >=0) {
        readString=readString.substring(2);
        Serial.print("CM is: ");
        Serial.println(readString);
        CM = readString.toInt();
        Serial.println(CM);
        Serial.println();
      }
      if(readString.indexOf("CT") >=0) {
        readString=readString.substring(2);
        Serial.print("CT is: ");
        Serial.println(readString);
        CT = readString.toInt();
        Serial.println(CT);
        Serial.println();
      }
       if(readString.indexOf("CS") >=0) {
        readString=readString.substring(2);
        Serial.print("CS is: ");
        Serial.println(readString);
        CS = readString.toInt();
        Serial.println(CS);
        Serial.println();
      }
       if(readString.indexOf("BR") >=0) {
        readString=readString.substring(2);
        Serial.print("BR is: ");
        Serial.println(readString);
        BR = readString.toInt();
        Serial.println(BR);
        Serial.println();
      }
     
      //do some stuff

      readString=""; //clears variable for new input
      data="";

    } 
    else {     
      readString += c; //makes the string readString
    }
  }
}
Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)

PaulS

Code: [Select]
                if(c == 21)
How are you sending a 21 from the Serial Monitor? A 21 is a NAK, which can't be sent from the Serial Monitor.

Code: [Select]
        while(isTrue == 1){
                char c = Serial.read();
                if(c == 21)
                        isTrue = 0;
                else
                        if (stringBuffer.length() < 100) {
                                stringBuffer += c;
                        } 
        }

The while loop is entered when there is at least one character available to read. This code then loops, reading mostly nothing from the serial port until the String instance is full of crap.

Quote
At which point I'm wrong?

Just about every point, starting with the String instance.

Go Up