Best way to parse UDP data

Let me apologize to start as my C has gotten very rusty. I'm working on a project that will send commands from a PC to the Arduino via UDP to manage RGB LED strips. So far I've gotten the send data part to work fine. I can generate the command in the PC app, send to the arduino, and it receives the string.

The problem I'm dealing with is how best to parse the data on the Arduino side so I can act on it. The hurdle is in that at times on may want to set the device to a single color and at others have it fade through a couple different colors. I'd like to have an open ended number of colors but gave up on that a while ago. So now I've limited the number of commands to 10. Below is my code:

String databuffer;

String active[10];
String colorPause[10];
String fadeDelay[10];
String redValue[10];
String greenValue[10];
String blueValue[10];


void setup() {
// Simulate(Uno)

  Serial.begin(9600); // note the IO window autmatically opens
  databuffer = "<1:10:5:123:124:125~1:10:5:255:124:125~1:20:5:200:156:0~0:0:0:0:0:0~0:0:0:0:0:0~0:0:0:0:0:0~0:0:0:0:0:0~0:0:0:0:0:0~0:0:0:0:0:0~0:0:0:0:0:0~0:0:0:0:0:0>";
   

}

void loop() {
 
    // Serial.println(databuffer); 
    HandleData(databuffer );

}


void HandleData( String data) 
{
    int ampPosition = 0;
    int loopCount = 0;
    Serial.println(data); 

    data = data.substring(1, data.length()-1); // Strip the start and end char

    do
    {
        ampPosition= data.indexOf("~")
        if ( ampPosition!= -1) 
        {
            HandleValues(data.substring(0, ampPosition), loopCount);
            data= data.substring(ampPosition+1, data.length());
        }
        else
        {
        
            if( data.length() > 0 )
            {
               HandleValues(data, loopCount);
            }

        }
            loopCount ++;
    }
    while(ampPosition>= 0);

}


void HandleValues(String commands, int arrCount)
{
    int colonPosition;
    int commandcount = 0;

    do
    {
        colonPosition= commands.indexOf(":")
        if ( colonPosition!= -1) 
        {
                if (commandcount == 0) {
                    active[arrCount] = commands.substring(0, colonPosition).toint();
                } 
                if (commandcount == 1) {
                    colorPause[arrCount] = commands.substring(0, colonPosition);
                } 
                if (commandcount == 2) {
                    fadeDelay[arrCount] = commands.substring(0, colonPosition);
                } 
                if (commandcount == 3) {
                    redValue[arrCount] = commands.substring(0, colonPosition);
                } 
                if (commandcount == 4) {
                    greenValue[arrCount] = commands.substring(0, colonPosition);
                } 
            \\ Serial.println(commands.substring(0, colonPosition));
            commands = commands.substring(colonPosition+1, commands.length());
        }
        else
        {
    
            if( commands.length() > 0 )
            {
                blueValue[arrCount] = commands;
                Serial.println(commands);
                Serial.println(blueValue[arrCount]);

            }

        }
        commandcount ++;
    }
    while(colonPosition>= 0);

    Serial.println("active:" + active[arrCount]);
    Serial.println("pause:" +  colorPause[arrCount]);

}

databuffer simulates a full list of commands with each groups of commands separated by a ~ and each value in the command separated by a : This scheme works but is very slow and I imagine uses more memory than it should. Seems like there has to be a better way to do this. I'm willing to toss all of this if someone can point me to a way to send a groups of integer values ranging from 0-255 and break each value out once received.

Any help would be appreciated.

I'm willing to toss all of this if someone can point me a way to send a groups of integer values ranging from 0-255 and break each value of once received.

(1) Give up on Strings and use C style strings (arrays of chars terminated by a zero) instead.
(2) Use strtok to parse the received strings.
(3) Why not just send a series of bytes delimited by a colon between each byte and a tilde between groups of bytes ?

By the way, your program does not compile due to a multitude of errors, but I assume that you know this

I'm fine with any of the option and it seems like number 3 would be the least amount of overhead. I just haven't had any luck pulling it off. I used to do quite a bit of C++ programming in the days of DOS but it's been many moons now and I've forgotten most of it now it appears.

I've been very surprised to find very little in the way of examples where people are accepting commands from an outside source via UDP. Seems like that would be a fairly common task given the possibilities.

Would it be possible to use some sort of Start of command value and then just read the next 3 bytes as the values I need?

cmpenney:
Would it be possible to use some sort of Start of command value and then just read the next 3 bytes as the values I need?

Yes

Hi cmpenney

Have I understood your requirements right?

  • Each UDP packet contains 1 or more commands.
  • Each command consists of a command code and 1 or more arguments.
  • The command code is a 1-byte value.
  • Each argument is a 1-byte value.

If you treat the contents of the UDP packet as bytes rather than characters, then I think you can do without separator characters.

If the number of arguments for a given command code is fixed, you could send (for a three argument command): <command-code><argument-1><argument-2><argument-3>.

If the number of arguments can vary, then include a length byte: <command-code><length><argument-1><argument-2><argument-3>.

The code to parse the packet could use a state machine approach. The information on this page http://www.gammon.com.au/forum/?id=11425 may be useful - it is written about serial input but the ideas can be applied to other data sources.

Regards

Ray