4

I would like to test the contents of data received over a serial connection. In my loop() I store the data in bffr; and afterwards I would like to test to see if there are some predefined words in it.

#define BFFSZ 90
char bffr[BFFSZ];
char bffridx; 

void loop()
{
   readline();

   //- Test the bffr
       if(strstr(bffr, "CLOSED")){ //- WORKS
          Serial.println("> conn. closed");
          digitalWrite(A1, HIGH); 
       }else if(strstr(bffr, "RING")){ //- WORKS
          Serial.println("> Someone is ringing");
          digitalWrite(A2, HIGH);
       }else if(strstr(bffr, "0,7,j,BLINK")){ //- Doesn't work
          Serial.println("> Blink");
          digitalWrite(A2, HIGH);
          delay(300);
          digitalWrite(A2, LOW);
       }
}


void readline()
{
   memset(bffr,0,sizeof(bffr));
   char c;
   int i =0;
   bffridx = 0; // start at beginning


   long previousMillis = millis();
   while (1) {
     unsigned long currentMillis = millis();
     if(currentMillis - previousMillis > 20000) {
       Serial.println("TIMEOUT");
       return;
     }
     delay(2);

     c=gsm.SimpleRead2();
     //- debug only, to see if there is something received.     
     Serial.write(c);

     if (c == -1)
       continue;
     if (c == '\n')
       continue;
     if ((bffridx == BFFSZ-1) || (c == '\r')) {
       bffr[bffridx] = 0;
       return;
     }

     bffr[bffridx++]= c;
     delay(2);
   }
}

The debug-line makes that I can see the data flowing, eg when I phone the SIM.

But it looks like the buffer isn't tested properly. The first two will work, but the last test fails. It is part of a larger string: $0,7,j,BLINK,567^ But I thought the strstr(1,2) searches for 2 in 1. And as 0,7,j,BLINK, is within the haystack I assume it wil return true. But apparently not...

The gsm.SimpleRead2() comes from GSMlib and is my altered version of gsm.SimpleRead(). Instead of printing the char, I just return it so we can buffer it in the readline function.

void SIMCOM900::SimpleRead()
{

 char datain;
 if(_cell.available()>0){
   datain=_cell.read();
   if(datain>0){
     Serial.print(datain);
   }
 }
}
char SIMCOM900::SimpleRead2()
{

 char datain;
 if(_cell.available()>0){
   datain=_cell.read();
   if(datain>0){
     return datain;
   }
 }
}

Does anyone know the answer to this?

stUrb
  • 341
  • 2
  • 5
  • 9
  • Did you check that `gsm.SimpleRead2()` never returns non-printable characters (ASCII 0x00-0x1F)? That could explain why you don't see anything in the debug with Serial and the searched string can then not be found. – jfpoilpret Apr 25 '14 at 05:30
  • By the way, where does this GSM library `SimpleRead2` come from? Could you provide a link? – jfpoilpret Apr 25 '14 at 05:31
  • @jfpoilpret I've added the simpleread functions and a link to the library. – stUrb Apr 25 '14 at 09:13
  • So there might be some strange characters in the `bffr` which causes the test to fail. How can I strip a string with non-printable characters? – stUrb Apr 25 '14 at 09:13
  • 1
    If there are strange characters in the GSM output, then it is quite easy to check and skip: you can use `isPrintable(c)` to check it and add `c` to `bffr` only in that case. This is part of standard C library, there are many other `isXxxx(c)` functions defined in `WCharacter.h`. – jfpoilpret Apr 26 '14 at 08:48

1 Answers1

1

After a serial.read();, the data [as far as I can tell] is pretty much destroyed. You have two main options to accomplish this:

  • Store the data in a string when read and then reference this later. I'd do this with a global variable, that is declared outside of a method and accessible throughout your whole sketch.
  • I haven't read throughout your whole code, but, if you only need to read one character, you can use serial.peek();. This only works if you need the first character of the buffer.

Most likely, your only option would be the first bullet. I'd implement this by adding a method something like this:

String buffer_string_serial;

void setup() { //code here }

void loop() { //code here }

int serial_read_buffer() {
  while(serial.avaliable() > 0) {
    buffer_string_serial = buffer_string_serial + serial.peek();
    return serial.read();
  }
}

Then, just use serial_read_buffer();. That will act similar to serial.read();. The only difference is it will fill up the buffer_string_serial string. You'll have to clear that out after you used all the data so it doesn't get full.

Anonymous Penguin
  • 6,155
  • 9
  • 31
  • 62
  • That's what I've done with the `readline()` It stores everything in a global `bffr`. And afterwards I try to test it; but the testing doesn't work. – stUrb Apr 24 '14 at 21:43
  • @stUrb Test it with expressions? I'd recommend verifying the string is exactly what you want and revisiting your testing code. Maybe print the string before testing to the serial window? – Anonymous Penguin Apr 24 '14 at 21:48
  • Checking for an exact match is not easy. The protocol consists of an unique integer at the end, describing a job id: `$0,7,j,JOB,ID^` so everything except the ID is know and can be tested. Does Arduino/C has some kind of regular expression test/match? – stUrb Apr 24 '14 at 22:26
  • @stUrb I can't find built in support in the Arduino core libraries for regex, but [this library here for Arduino](http://forum.arduino.cc/index.php?topic=59917) (with pretty good documentation) might help you. – Anonymous Penguin Apr 24 '14 at 22:47