Parsing Problem

Hello,

My project involves having a Parallax Propeller control my well system for my house. That part I have sorted out and working well, and having learned a little about the Photon, I’ve got one connected to my Propeller, with the intent of having the Prop send a string to the Photon: <255,324,155,200> \0. The four ints are numbers from my well I’d like to port over to Adafruit IO and see on a dashboard trend.

The Prop is a 3.3V device, and I have it sending a serial string to the Photon’s RX terminal, and a common ground between the two of course. It’s just a straight connection.

Unfortunately, I’m having no luck getting the parsing accomplished, the below code is me trying to see if I can get the string parsed and into variables so I can see them on my iphone Particle App, or the console. Can anyone tell me what I’m doing wrong?

Thanks!

// Example 5 - Receive with start- and end-markers combined with parsing

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
int Height, WellGallons, TankGallons, WaterUsed; 


boolean newData = false;

//============

void setup() {
   
    Particle.variable("Height", &Height, INT);
    Particle.variable("WellGallons", &WellGallons, INT);
    Particle.variable("TankGallons", &TankGallons, INT);
    Particle.variable("WaterUsed", &WaterUsed, INT);
    Serial1.begin(9600, SERIAL_8N1);
 
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() used in parseData() replaces the commas with \0
        parseData();
     
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    Height = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    WellGallons = atoi(strtokIndx);     // convert this part to an int

    strtokIndx = strtok(NULL, ",");
    TankGallons = atoi(strtokIndx);     // convert this part to an int
    
    strtokIndx = strtok(NULL, ",");
    WaterUsed = atoi(strtokIndx);     // convert this part to an int
}

The first call to strtok() must have the source string as first parameter, only after that you can use NULL to continue on the same string. But without actually knowing which string to work on it’s impossible to continue.

You even state that fact in your comment // this continues where the previous call left off.
No previous call left off anywhere AFAICT:

BTW, you can use the Stream functions like readBytesUntil() to read your string with much less effort and sscanf() to parse the data more concisely.

You are also using outdated syntax for Particle.variable()
For quite some time now your variables would simply be registered like this

    Particle.variable("Height", Height);
    Particle.variable("WellGallons", WellGallons);
    Particle.variable("TankGallons", TankGallons);
    Particle.variable("WaterUsed", WaterUsed);

Hey thanks for your reply. I’ve ammended the Particle variable calls, and put in recievedChars in place of the NULL for the first Parsing call.

I copied that code largely from an Arduino tutorial of course, and didn’t delete out the comment.

I flashed it, but still no joy. Tomorrows a new day and I’ll try to figure out those better ways you mentioned. Thanks.

Got it! I had a couple ‘Serial’ calls in there, not ‘Serial1’, also I had to add in a couple Particle.process() calls to keep it from breathing green. It’s my first real project that made it to IoT stage, and it’s awesome! Thanks for your help!

2 Likes