I’m working on a home automation project using several ESP8266 modules together with an ESP32 as a central hub.
Here’s the basic setup:
There are 8 ESP8266 devices installed in my house.
Three of them include a rotary encoder to control the general light brightness.
When an encoder is rotated, that ESP8266 should send a WebSocket message to the other devices so they can adjust their brightness accordingly.
At first, I tried having one ESP8266 act as a “master”, sending WebSocket messages directly to the other 7 devices.
However, it became very slow and was unable to handle encoder pulses properly.
To improve performance, I replaced the master with an ESP32 “central” node, intended to relay messages between the ESP8266 devices.
The ESP32’s only task is to receive a message from one ESP8266 and immediately forward it to the others, without any processing or interpretation.
The architecture looks like this:
Code: Select all
Encoder (ESP8266_1) ---> WebSocket ---> ESP32 (central)
ESP32 (central) ---> WS1 ---> ESP8266_1
---> WS2 ---> ESP8266_2
---> WS3 ---> ESP8266_3
---> ...
---> WS8 ---> ESP8266_8Unfortunately, I’m still experiencing significant latency.
When I open more than 3 WebSocket connections on the ESP32 and call .loop() for each client, the system becomes almost unresponsive.
My questions:
Is there a better way to manage multiple WebSocket connections efficiently on the ESP32?
Would it be smarter to use a different communication method (like MQTT, UDP broadcast, or something else)?
Any known examples or best practices for this kind of setup?
Any help or suggestions would be greatly appreciated.
Thanks in advance!
The ESP32 code is this, its the bare minimun. With one ws it works good, with 2 its ok, more than that it cant handle it,
Code: Select all
#include <WiFiManager.h>
#include <DNSServer.h>
#include <WebSocketsServer.h>
#include <WebSocketsClient.h>
// ---------------- CONFIGURACIÓN WIFI ----------------
const char ssid[] = "xxxx";
const char pass[] = "xxx";
// ---------------- CLIENTES (otros módulos) ----------------
WebSocketsClient wsRGB;
WebSocketsClient wsCUADRO;
WebSocketsClient wsPC;
WebSocketsClient wsBARRA;
WebSocketsClient wsPIXEL;
WebSocketsClient wsFISCHER;
WebSocketsClient wsCENTRAL;
WebSocketsClient wsCAMA;
// ---------------- IPs y PUERTOS ----------------
const char* wsRGB_ip = "192.168.0.7";
const uint16_t wsRGB_port = 81;
const char* wsCUADRO_ip = "192.168.0.21";
const uint16_t wsCUADRO_port = 82;
const char* wsCAMA_ip = "192.168.0.9";
const uint16_t wsCAMA_port = 83;
const char* wsPC_ip = "192.168.0.10";
const uint16_t wsPC_port = 84;
const char* wsBARRA_ip = "192.168.0.4";
const uint16_t wsBARRA_port = 85;
const char* wsPIXEL_ip = "192.168.0.6";
const uint16_t wsPIXEL_port = 86;
const char* wsFISCHER_ip = "192.168.0.8";
const uint16_t wsFISCHER_port = 87;
const char* wsCENTRAL_ip = "192.168.0.2";
const uint16_t wsCENTRAL_port = 88;
// ---------------- SERVIDOR WEBSOCKET ----------------
const uint16_t wsNUEVACENTRAL_port = 89;
WebSocketsServer wsServer(wsNUEVACENTRAL_port);
// ---------------- PROTOTIPOS ----------------
void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length);
String nombrePorIP(IPAddress ip);
// ---------------- SETUP ----------------
void setup() {
Serial.begin(115200);
delay(500);
Serial.println("\n=== Conectando al WiFi ===");
WiFi.begin(ssid, pass);
unsigned long startAttemptTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 10000) {
Serial.print(".");
delay(500);
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\nNo se pudo conectar, abriendo WiFiManager...");
WiFiManager wifiManager;
wifiManager.autoConnect("Domo LEDS", "tucocapo");
}
// Inicializo servidor WebSocket
wsServer.begin();
wsServer.onEvent(webSocketEvent);
Serial.printf("Servidor WebSocket iniciado en puerto %u\n", wsNUEVACENTRAL_port);
// Inicializo clientes WebSocket
wsRGB.begin(wsRGB_ip, wsRGB_port, "/");
wsCUADRO.begin(wsCUADRO_ip, wsCUADRO_port, "/");
wsBARRA.begin(wsBARRA_ip, wsBARRA_port, "/");
wsPIXEL.begin(wsPIXEL_ip, wsPIXEL_port, "/");
/*
wsFISCHER.begin(wsFISCHER_ip, wsFISCHER_port, "/");
wsCENTRAL.begin(wsCENTRAL_ip, wsCENTRAL_port, "/");
wsCAMA.begin(wsCAMA_ip, wsCAMA_port, "/");
wsPC.begin(wsPC_ip, wsPC_port, "/");
*/
}
unsigned long lastLoopCall = 0;
const unsigned long loopInterval = 200; // 1 segundo
// ---------------- LOOP ----------------
void loop() {
wsServer.loop();
//if (millis() - lastLoopCall >= loopInterval) {
wsRGB.loop();
lastLoopCall = millis();
wsCUADRO.loop();
wsBARRA.loop();
wsPIXEL.loop();
// wsFISCHER.loop();
//wsCENTRAL.loop();
//wsCAMA.loop();
//wsPC.loop();
yield();
}
}
// ---------------- EVENTOS WEBSOCKET ----------------
void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length) {
switch (type) {
case WStype_TEXT:
// Serial.printf("%s (%s): ", nombre.c_str(), ip.toString().c_str());
// for (size_t i = 0; i < length; i++) Serial.print((char)payload[i]);
// Serial.println();
String mensaje = String((char*)payload);
wsRGB.sendTXT(mensaje);
break;
}
}