0

I am splitting a string (with weather information):

1:7.34:7.54:87.62:1012.33

Which is: message type, temperature, inside temperature, humidity and barometric pressure

  if (rf69.available()) {
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);
  if (rf69.recv(buf, &len)) {

  if (!len) return;
  buf[len] = 0;

  Serial.print("Received [");
  Serial.print(len);
  Serial.print("]: ");
  Serial.println((char*)buf);
  Serial.print("RSSI: ");
  Serial.println(rf69.lastRssi(), DEC);

  char* data;
  data = (char*)buf;
  char separator[] = ":";
  char *array[4]; //4
  int i=0;
  array[i] = strtok(data,separator);
  if( array[i][0] == '1' && array[i][1] == 0 ) {
    while( i < sizeof(array) / sizeof(*array) && array[i] != NULL)  { 
      array[i] = strtok(NULL,separator);
      Serial.println(array[i]);
      i++ ;
    }
  }

  char* t1 = array[0];
  char* t2 = array[1];
  char* h = array[2];
  char* p = array[3];
  Serial.print("Temperature Outside= "); Serial.print(t1);
  Serial.print(" Temperature Enclosure= "); Serial.print(t2);
  Serial.print(" Rel. Humidity =  "); Serial.print(h);
  Serial.print(" Pressure = "); Serial.println(p);
}

}

The correct result is:

Received [25]: 1:7.33:7.51:87.53:1012.32
RSSI: -60
7.33
7.51
87.53
1012.32 
Temperature Outside= 7.33 Temperature Enclosure= 7.51 Rel. Humidity =  87.53 Pressure = 1012.32

But at random times i seem to get this:

Received [25]: 1:7.33:7.50:87.60:1012.33
RSSI: -60
7.33
Temperature Outside= 7.33 Temperature Enclosure=  Rel. Humidity =   Pressure =  ⸮

As you can see the original date seems fine, but it fails processing at random times.
I don't see anything obvious, but i am also not a C expert.

HyperDevil
  • 2,519
  • 9
  • 38
  • 52
  • What is `buf`? Why do you do `data = (char*)buf`? Can't you use `buf` directly (well you still do since you don't copy the contents of `buf`, whatever it is)? – Some programmer dude Jan 26 '20 at 18:32
  • hi, i thought it wasnt important, but i have added it now :) it is an input from an RF69 radio. @Someprogrammerdude – HyperDevil Jan 26 '20 at 18:36
  • On an unrelated note, `sizeof(array) / sizeof(*array)` will *always* be equal to `4`. – Some programmer dude Jan 26 '20 at 18:43
  • What prints `Received [25]: 1:7.33:7.51:87.53:1012.32`? – KamilCuk Jan 26 '20 at 18:50
  • The code presented in the question does not appear capable of producing the output attributed to it. I don't see anything in it that would print the "Received" line, and that's definitely relevant to the question. – John Bollinger Jan 26 '20 at 18:50
  • sorry guys i missed a part on my last edit :) @JohnBollinger – HyperDevil Jan 26 '20 at 18:53
  • 2
    Now the code presented ought to print stuff that does not appear in the output presented. What we're looking for in an MRE is not code and output that merely happen to be aligned. Rather, it is code that reproduces the problem and output produced *by that code*. Otherwise, the example output is worthless. – John Bollinger Jan 26 '20 at 18:56
  • @JohnBollinger the code above should be correct now. The received part is what is the input from the strtok (initially buf), the output is printed below the code, what is should be and what i get. As i stated earlier the output fails about 1 out of 20 times. all of these times the buf data that is printed is OK, but not the processed data from strtok. (last example) – HyperDevil Jan 26 '20 at 21:11
  • `buf[len] = 0;` could be beyond. (len can be `sizeof buff` here) – wildplasser Jan 26 '20 at 21:58
  • To make it fail consistently, change `char *array[4];` to `char *array[4] = {NULL, NULL, NULL, NULL};` – user3386109 Jan 27 '20 at 05:58
  • could you explain what you mean @wildplasser? – HyperDevil Jan 27 '20 at 06:16
  • @user3386109 i want it to work all the time, why do i want to always make it fail? – HyperDevil Jan 27 '20 at 06:16
  • 2
    When dealing with an intermittent bug (that occurs 1 in 20 times according to your comment), 95% of the work is to figure out what triggers the bug. I've done that 95% for you. Now you just need to do the 5% to figure out how to fix it. – user3386109 Jan 27 '20 at 06:21
  • @user3386109 i tried your NULL NULL approach, now only the first 2 values are processed, not the last 3. – HyperDevil Jan 27 '20 at 17:39

1 Answers1

1

I changed my loop to this:

  char *array[4];
  char separator[] = ":";
  char *segmentPointer = strtok((char*)buf, separator);
  int i = 0;
  if ((segmentPointer[0] == '1') && (segmentPointer[1] == '\0')) {
    segmentPointer = strtok(NULL, separator);
    while (segmentPointer != NULL) {
      array[i] = segmentPointer;
      i++;
      segmentPointer = strtok(NULL, separator);
    }
  }

The loop now works as expected reliably!

HyperDevil
  • 2,519
  • 9
  • 38
  • 52