I am currently working on creating a network of multisensors (measuring temp, humidity ect). There will be tens or in some buildings even hundreds of sensors measuring at the same time. All these sensors send their data via a http GET request to a local esp32 server that processes the data and converts it into whatever the building's contol system can work with (KNX, BACnet, MODbus). Now I stress tested this server and found out that it can process around 1400 requests per minute before the sender gets no response anymore. This seems like a high amount but if a sensor sends its data every 2 seconds it means there will be a limit of around 45 sensors. I need to find a way how to process such a request quicker, this is the code I currently use:
server.on("/get-data", HTTP_GET, [](AsyncWebServerRequest *request)
{handle_get_data(request); request->send(200); });
void handle_get_data(AsyncWebServerRequest *request)
{
packetval ;
sensorData.humidity = request->arg("humidity").toFloat();
sensorData.temperature = request->arg("temperature").toFloat();
sensorData.isMovement = request->arg("isMovement");
sensorData.isSound = request->arg("isSound");
sensorData.luxValue = request->arg("luxValue").toDouble();
sensorData.RSSI = request->arg("signalValue").toInt();
sensorData.deviceID = request->arg("deviceID");
sensorData.btList = request->arg("btList");
if (deviceList.indexOf(sensorData.deviceID) == -1)
{
deviceList = sensorData.deviceID;
activeSensors ;
}
if (sensorData.isMovement || sensorData.isSound)
{
sendDataFlag = true;
}
}
I use the AsyncTCP library.
Now I measured the execution time of the function handle_get_data()
and it turns out it is only ~175uS which is very quick. However the time between two calls of handle_get_data()
is around 6ms which is really slow but it still doesnt explain why I can only process 1400 per minute or 24 per second (6ms = 155Hz why is my limit 24Hz?). Other than that I do not use any other code during the processing of a request, is it perhaps a limitation in the library? Is there another way to process such a request?
A request looks like this: http://192.168.6.51:80/get-data?humidity=32.0&temperature=32.0&isMovement=1&isSound=1&luxValue=123&RSSI=32&deviceID=XX:XX:XX:XX:XX:XX&btList=d1d2d3d4d5d6d7
If there is really nothing I can do I can always switch to a raspberry pi to process everything but I would rather stick to esp32 since I want to easily create an own PCB.
Thanks for all the help!
CodePudding user response:
Creating a websocket instead of using http requests solved the issue for me:
AsyncWebSocket ws("/ws");
void setup()
{
ws.onEvent(onWsEvent);
server.addHandler(&ws);
}
AsyncWebSocketClient *wsClient;
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
{
if (type == WS_EVT_DATA)
{
AwsFrameInfo *info = (AwsFrameInfo *)arg;
String msg = "";
packetval ;
if (info->final && info->index == 0 && info->len == len)
{
if (info->opcode == WS_TEXT)
{
for (size_t i = 0; i < info->len; i )
{
msg = (char)data[i];
}
}
}
sensorData.humidity = msg.substring(msg.indexOf("<hum>") 5, msg.indexOf("</hum>")).toFloat();
sensorData.temperature = msg.substring(msg.indexOf("<tem>") 5, msg.indexOf("</tem>")).toFloat();
sensorData.isMovement = (msg.substring(msg.indexOf("<isMov>") 7, msg.indexOf("</isMov>")) == "1");
sensorData.isSound = (msg.substring(msg.indexOf("<isSnd>") 7, msg.indexOf("</isSnd>")) == "1");
sensorData.luxValue = msg.substring(msg.indexOf("<lux>") 5, msg.indexOf("</lux>")).toDouble();
sensorData.RSSI = msg.substring(msg.indexOf("<RSSI>") 6, msg.indexOf("</RSSI>")).toInt();
sensorData.deviceID = msg.substring(msg.indexOf("<dID>") 5, msg.indexOf("</dID>"));
sensorData.btList = msg.substring(msg.indexOf("<bt>") 4, msg.indexOf("</bt>"));
if (deviceList.indexOf(sensorData.deviceID) == -1)
{
deviceList = sensorData.deviceID;
activeSensors ;
}
if (sensorData.isMovement || sensorData.isSound)
{
sendDataFlag = true;
}
}
}
This will process more than 11000 packets per minute (200kb/s). The execution time of void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
takes ~500uS now which means there is definitly optimising to do in this function but the time between two calls is reduced all the way to 1ms.