Description
Hello,
I am using ESP8266WiFi in station mode to connect to my AP at home. It is controlling 3 RGB leds sets via the GPIO (9 channels for 3 sets). There is an situation where the server that controls them all polls the ESP8266WiFi server for the status of the lights with many concurrent http requests, e.g.
- /rgb1/status
- /rgb1/colour
- /rgb1/brightness
- /rgb2/status
- /rgb2/colour
- /rgb2/brightness
- /rgb3/status
- /rgb3/colour
- /rgb3/brightness
My code is below and as new connections are created on the server, I add them to the array clients
, once I have received a whole request and attempt to write back to that client, the line clients[i]->println("HTTP/1.1 200 OK");
takes a long time to execute and return 0, as I do not believe it still has that connection open and therefore cannot respond to the client? Is this because I am hitting a concurrent connection limit?
Is there a maximum number of connections in Station mode?
Can I increase this?
Thanks,
Daniel
#include <ESP8266WiFi.h>
const char* location = "tv room LED controller";
const int locationID = 2;
int whiteLedPin[3] = {5,14,3}; // Pin 8
int redLedPin[3] = {4,12,1}; // Pin 6
int greenLedPin[3] = {0,13,9}; // Pin 7
int blueLedPin[3] = {2,15,10}; // Pin 8
int rgbLedStatus[3] = {0,0,0};
String rgbColour[3] = {"FFFFFF","FFFFFF","FFFFFF"};
int WWLedStatus[3] = {0,0,0};
int ledWWBrightness[3] = {100,100,100};
#define MAX_CLIENTS 10
#define MAX_LINE_LENGTH 50
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);
WiFiClient *clients[MAX_CLIENTS] = { NULL };
String st[MAX_CLIENTS];
void printJsonForTemperatureAndHumidityToClient(WiFiClient client,int locationID) {
client.print("{\"room\": \"");
client.print(location);
client.print("\",\"id\": ");
client.print(locationID);
client.print(", \"led status\": ");
client.print(rgbLedStatus[0]);
client.print(", \"rgb colour\": \"");
client.print(rgbColour[0]);
client.print("\"}");
}
unsigned int hexToDec(String hexString) {
unsigned int decValue = 0;
int nextInt;
for (int i = 0; i < hexString.length(); i++) {
nextInt = int(hexString.charAt(i));
if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
nextInt = constrain(nextInt, 0, 15);
decValue = (decValue * 16) + nextInt;
}
return decValue;
}
void setRGBLightState(int lightIndex){
if (rgbLedStatus[lightIndex] == 0) {
analogWrite(redLedPin[lightIndex], 0);
analogWrite(greenLedPin[lightIndex], 0);
analogWrite(blueLedPin[lightIndex], 0);
} else {
int redBrightness = hexToDec(rgbColour[lightIndex].substring(0,2));
int greenBrightness = hexToDec(rgbColour[lightIndex].substring(2,4));
int blueBrightness = hexToDec(rgbColour[lightIndex].substring(4,6));
redBrightness = map(redBrightness, 0, 255, 0, 1023);
greenBrightness = map(greenBrightness, 0, 255, 0, 1023);
blueBrightness = map(blueBrightness, 0, 255, 0, 1023);
analogWrite(redLedPin[lightIndex], redBrightness);
analogWrite(greenLedPin[lightIndex], greenBrightness);
analogWrite(blueLedPin[lightIndex], blueBrightness);
}
}
void setWWLightState(int lightIndex){
if (WWLedStatus[lightIndex] == 0) {
analogWrite(whiteLedPin[lightIndex], 0);
} else {
analogWrite(whiteLedPin[lightIndex], map(ledWWBrightness[lightIndex], 0,100,0,1023));
}
}
void setup() {
Serial.begin(115200);
delay(10);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
for (int lightIdx = 1; lightIdx < 2; lightIdx++) {
Serial.print("initialising pins for light: ");
Serial.println(lightIdx);
pinMode(redLedPin[lightIdx], OUTPUT);
pinMode(greenLedPin[lightIdx], OUTPUT);
pinMode(blueLedPin[lightIdx], OUTPUT);
pinMode(whiteLedPin[lightIdx], OUTPUT);
}
}
void loop() {
// Check if a new client has connected
WiFiClient newClient = server.available();
if (newClient) {
Serial.println("");
Serial.println("new client");
// Find the first unused space
for (int i=0 ; i<MAX_CLIENTS ; ++i) {
if (NULL == clients[i]) {
clients[i] = new WiFiClient(newClient);
Serial.print("new client created with index: ");
Serial.println(i);
break;
}
}
}
// Check whether each client has some data
for (int i=0 ; i<MAX_CLIENTS ; ++i) {
// If the client is in use, and has some data...
if (NULL != clients[i] && clients[i]->available() ) {
// Read the data
char newChar = clients[i]->read();
// If we have the end of a string
// (Using the test your code uses)
if ('\r' == newChar) {
// Blah blah, do whatever you want with inputs[i]
Serial.print("request complete for client:");
Serial.print(i);
Serial.print(":");
Serial.println(st[i]);
Serial.print("clients[");
Serial.print(i);
Serial.print("]->available()");
Serial.println(clients[i]->available());
delay(200);
Serial.println(clients[i]->println("HTTP/1.1 200 OK"));
Serial.println(clients[i]->println("Content-Type: text/html"));
Serial.println(clients[i]->println("")); // do not forget this one
Serial.println("header done");
// Read the first line of the request
String request = st[i];
if (request.indexOf("/api/rgb") != -1) {
// contains /api in request
int lightIndex = request.substring(request.indexOf("/api/rgb")+8,request.indexOf("/api/rgb")+9).toInt();
if (request.indexOf("/status") != -1) {
clients[i]->println(rgbLedStatus[lightIndex]);
} else if (request.indexOf("/brightness") != -1) {
int r = hexToDec(rgbColour[lightIndex].substring(0,2));
int g = hexToDec(rgbColour[lightIndex].substring(2,4));
int b = hexToDec(rgbColour[lightIndex].substring(4,6));
int maxrg = _max(r,g);
int maxrgb = _max (maxrg,b);
float ratio = (float)maxrgb / 255.0;
float brightness = ratio * 100;
clients[i]->println(brightness);
} else if (request.indexOf("/colour") != -1) {
clients[i]->println(rgbColour[lightIndex]);
} else if (request.indexOf("/setcolour") != -1) {
rgbColour[lightIndex] = request.substring(request.indexOf("/setcolour")+11,request.indexOf("/setcolour")+17);
setRGBLightState(lightIndex);
} else if (request.indexOf("/on") != -1) {
rgbLedStatus[lightIndex] = 1;
setRGBLightState(lightIndex);
} else if (request.indexOf("/off") != -1) {
rgbLedStatus[lightIndex] = 0;
setRGBLightState(lightIndex);
}
} else if (request.indexOf("/api/ww") != -1) {
// contains /api in request
Serial.println("ww");
int lightIndex = request.substring(request.indexOf("/api/ww")+7,request.indexOf("/api/ww")+8).toInt();
if (request.indexOf("/status") != -1) {
Serial.println("ww status");
clients[i]->println(WWLedStatus[lightIndex]);
} else if (request.indexOf("/brightness") != -1) {
Serial.println("ww brightness");
if(request.length() > 33){
ledWWBrightness[lightIndex] = request.substring(24,24+request.length()-33).toInt();
}
clients[i]->println(ledWWBrightness[lightIndex]);
} else if (request.indexOf("/on") != -1) {
Serial.println("ww on");
WWLedStatus[lightIndex] = 1;
setWWLightState(lightIndex);
} else if (request.indexOf("/off") != -1) {
Serial.println("ww off");
WWLedStatus[lightIndex] = 0;
setWWLightState(lightIndex);
}
} else {
// no command
// printJsonForTemperatureAndHumidityToClient(clients[i],locationID);
}
// Empty the string for next time
st[i] = "";
// The flush that you had in your code - I'm not sure
// why you want this, but here it is
// clients[i]->flush();
// If you want to disconnect the client here, then do this:
clients[i]->stop();
delete clients[i];
clients[i] = NULL;
delay(1);
Serial.println("Client disconnected");
Serial.println("");
} else {
Serial.print("Building request for client:");
Serial.print(i);
Serial.print(":");
Serial.println(st[i]);
// Add it to the string
st[i].concat(newChar);
// IMPORTANT: Nothing stops this from overrunning the string and
// trashing your memory. You SHOULD guard against this.
// But I'm not going to do all your work for you :-)
}
}
}
}