Performance issue with Adruino Yun code that is parsing content of a web page

We wrote code that changes the color of led lights based on the content of text file that is hosted on our web server.

Here are the contents of the txt file:

/rgb/255/0/255/

We have a web application that changes the values of this text file based on a clicked link. We have eliminated that app as the problem and isolated to our Arduino code.

Our issue:
The code is working but response time is slow and inconsistent. It takes 5 to 20 seconds to change the color. I think it's something in the loop. I posted all the code but I think the loop is where the issue is. Can anyone see anything that might help to optimize this? Thanks in advance.

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <String.h>
#include <Adafruit_NeoPixel.h>
#include <HttpClient.h>

#define PIN1 5
#define PIN2 6

#define pixelLength 59
#define pixelLength1 59
#define pixelLength2 59
String ledValues;

String redString; 
String greenString; 
String blueString; 

int redValue;
int greenValue;
int blueValue;

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(pixelLength1, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(pixelLength2, PIN2, NEO_GRB + NEO_KHZ800);

// Listen on default port 5555, the webserver on the Yun
// will forward there all the HTTP requests for us.
YunServer server;

void setup() {
  // Bridge startup
  Bridge.begin();
  Serial.begin(9600);
  // Listen for incoming connection only from localhost
  // (no one from the external network could connect)
  server.listenOnLocalhost();
  server.begin();
  
  strip1.begin();
  strip2.begin();
  
   int i;
   
   for (i=0; i<=pixelLength; i++)
     {
       strip1.setPixelColor(i, 0, 255, 0); 
       strip2.setPixelColor(i, 0, 255, 0); 
       strip1.show();    
       strip2.show();  
       delay(10);
     }
}

void loop() {
  // Get clients coming from server
  // Initialize the client library
  HttpClient client;
  // There is a new client?
  // Make a HTTP request:
// NOTE: I omitted server name when posting this code 
  client.get("http://[server-name]/lights/led-color.txt");
  
    while (client.available()) {
       process(client);
   char ledValues = client.read();
  }
  

  //Serial.flush();
  delay(1000); // Poll every 1sec
}

void process(HttpClient client) {
  
  // read the command in the URL
  String command = client.readStringUntil('/'); 
  
  // read the full URL (everything AFTER /arudino/)
  String fullUrl = client.readString();
  
   // separate color values from URL using getValue command (see code at bottom of page)
      redString = (getValue(fullUrl, '/', 0));
      greenString = (getValue(fullUrl, '/', 1));
      blueString = (getValue(fullUrl, '/', 2));

      // getValue stores it as a string. use this function to convert it over to an interger so we can pass to the Arduino
      int redValue = redString.toInt(); 
      int greenValue = greenString.toInt(); 
      int blueValue = blueString.toInt(); 
 
// looks for rgb
// could later use this command to make the lights do other stuff like OFF and ON, etc. 
  if (command == "rgb") {
     
    int i;
  
    for (i=0; i<=pixelLength; i++)
     {
       strip1.setPixelColor(i, redValue, greenValue, blueValue); 
       strip2.setPixelColor(i, redValue, greenValue, blueValue);
       strip1.show();    
       strip2.show();  
       delay(25);
     }
 
 

     

  }
  
  // PARTY MODE DUDE!
  if (command == "party") {
    
    theaterChaseRainbow(38);
   
   int i; 
   for (i=0; i<=strip1.numPixels(); i++)
     {
       strip1.setPixelColor(i, redValue, greenValue, blueValue); 
     }
 
     strip1.show(); 
     
     
    for (i=0; i<=strip2.numPixels(); i++)
     {
       strip2.setPixelColor(i, redValue, greenValue, blueValue); 
     }
 
     strip2.show(); 
 
  }
  

}

// getValue function that parses and separates URL value
String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}




//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < strip1.numPixels(); i=i+3) {
          strip1.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
        }
        for (int i=0; i < strip2.numPixels(); i=i+3) {
          strip2.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
        }
        strip1.show();
        strip2.show();
       
        delay(wait);
       
        for (int i=0; i < strip1.numPixels(); i=i+3) {
          strip1.setPixelColor(i+q, 0);        //turn every third pixel off
        }
        for (int i=0; i < strip2.numPixels(); i=i+3) {
          strip2.setPixelColor(i+q, 0);        //turn every third pixel off
        }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip1.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
   return strip2.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip1.Color(255 - WheelPos * 3, 0, WheelPos * 3);
   return strip2.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip1.Color(0, WheelPos * 3, 255 - WheelPos * 3);
   return strip2.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

I would use readStringUntil for reading led values as well, and get rid of getValue function

@fourgrant, you did not tell us what is your goal? It is couple hundred of ms or couple of ms or couple hundred of ns or even faster?

Thanks for the response Federico.

We couldn't get it to work without the getValue function. The problem is that we need the entire string and readStringUntil is only giving us the first part up to the first slash. We may have missed something in your suggestion.

We tried a different way and were able improve response times quite a bit. (would appreciate your opinion on it if you don't mind).

We removed the string parsing from the function and put it into the loop.

Specifically added this to the loop:

    String fullUrl = client.readString();
   
     command = (getValue(fullUrl, '/', 1));
     redString = (getValue(fullUrl, '/', 2));
     greenString = (getValue(fullUrl, '/', 3));
     blueString = (getValue(fullUrl, '/', 4));
     
     process();

@sonnyyu our initial code was taking anywhere from 15 to 30 seconds to complete. The new code (posted below) is much faster. Around 2-4 seconds. This is acceptable but ideally it would match the delay set in the loop. Would love to have it as close to 1 second as possible.

Here's the full updated code for reference (or if you want to do a diff on what we posted originally):

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <String.h>
#include <Adafruit_NeoPixel.h>
#include <HttpClient.h>

#define PIN1 5
#define PIN2 6

#define pixelLength 59
#define pixelLength1 59
#define pixelLength2 59
String ledValues;

String redString; 
String greenString; 
String blueString; 

int redValue;
int greenValue;
int blueValue;

String command;

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(pixelLength1, PIN1, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(pixelLength2, PIN2, NEO_GRB + NEO_KHZ800);

// Listen on default port 5555, the webserver on the Yun
// will forward there all the HTTP requests for us.
YunServer server;

void setup() {
  // Bridge startup
  Bridge.begin();
  Serial.begin(9600);
  // Listen for incoming connection only from localhost
  // (no one from the external network could connect)
  server.listenOnLocalhost();
  server.begin();
  
  strip1.begin();
  strip2.begin();
  
   int i;
   
   for (i=0; i<=pixelLength; i++)
     {
       strip1.setPixelColor(i, 0, 255, 0); 
       strip2.setPixelColor(i, 0, 255, 0); 
       strip1.show();    
       strip2.show();  
       delay(10);
     }
}

void loop() {
  // Get clients coming from server
  // Initialize the client library
  HttpClient client;
  // There is a new client?
  // Make a HTTP request:
// NOTE: I omitted server name when posting this code 
    client.get("http://[servername]/lights/led-color.txt");
    
    String fullUrl = client.readString();
   
     command = (getValue(fullUrl, '/', 1));
     redString = (getValue(fullUrl, '/', 2));
     greenString = (getValue(fullUrl, '/', 3));
     blueString = (getValue(fullUrl, '/', 4));
     
     process();

  delay(500); // Poll every .5 sec
}

void process() {

      // getValue stores it as a string. use this function to convert it over to an interger so we can pass to the Arduino
      int redValue = redString.toInt(); 
      int greenValue = greenString.toInt(); 
      int blueValue = blueString.toInt(); 
 
// looks for rgb
  if (command == "rgb") {
     
    int i;
    for (i=0; i<=pixelLength; i++)
     {
       strip1.setPixelColor(i, redValue, greenValue, blueValue); 
       strip2.setPixelColor(i, redValue, greenValue, blueValue);
       strip1.show();    
       strip2.show();  
       delay(10);
     }
  }
  
  // PARTY MODE DUDE!
  if (command == "party") {
    theaterChaseRainbow(38);
  }
  
}

// getValue function that parses and separates URL value
String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < strip1.numPixels(); i=i+3) {
          strip1.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
        }
        for (int i=0; i < strip2.numPixels(); i=i+3) {
          strip2.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
        }
        strip1.show();
        strip2.show();
       
        delay(wait);
       
        for (int i=0; i < strip1.numPixels(); i=i+3) {
          strip1.setPixelColor(i+q, 0);        //turn every third pixel off
        }
        for (int i=0; i < strip2.numPixels(); i=i+3) {
          strip2.setPixelColor(i+q, 0);        //turn every third pixel off
        }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
   return strip1.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
   return strip2.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip1.Color(255 - WheelPos * 3, 0, WheelPos * 3);
   return strip2.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip1.Color(0, WheelPos * 3, 255 - WheelPos * 3);
   return strip2.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}