Hello,
The code that manages the (ws-data (resource)) is creating a memory corruption. The data passed from the webpage and transmitted on the socket is randomly corrupted in the process.
Here is a simple test… Use code/webpage BELOW and monitor the output from WS_EVT_DATA (*data) on the serial monitor. You will see the random corruptions, randomly. Sometimes is starts after the first few transmissions, other times it takes 100’s of transmits to show itself. Press “AUTO DATA”, the page simply pulls strings from an array and sends it on the socket.
The library is unusable as it is.
Thank you,
Chris Loubier
CODE:
// Import required libraries #include <Arduino.h> #include <WiFi.h> #include <AsyncTCP.h> #include <ESPAsyncWebServer.h> #include <SPIFFS.h> // Replace with your network credentials const char* ssid = "ISQE_ESP32"; const char* password = ""; bool ledState = 0; const int ledPin = 2; // Create AsyncWebServer object on port 80 AsyncWebServer server(80); AsyncWebSocket ws("/ws"); void notifyClients() { ws.textAll(String(ledState)); } void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) { AwsFrameInfo *info = (AwsFrameInfo*)arg; //Serial.printf("data= %s\n", data); if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { data[len] = 0; if (strcmp((char*)data, "toggle") == 0) { ledState = !ledState; notifyClients(); } } } void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) { switch (type) { case WS_EVT_CONNECT: Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str()); break; case WS_EVT_DISCONNECT: Serial.printf("WebSocket client #%u disconnected\n", client->id()); break; case WS_EVT_DATA: Serial.printf("WS_EVT_DATA_0 = %s\n", (char*)data); handleWebSocketMessage(arg, data, len); break; case WS_EVT_PONG: case WS_EVT_ERROR: break; } } void initWebSocket() { ws.onEvent(onEvent); server.addHandler(&ws); } String processor(const String& var){ Serial.println(var); if(var == "STATE"){ if (ledState){ return "ON"; } else{ return "OFF"; } } } void setup(){ // Serial port for debugging purposes Serial.begin(115200); if(!SPIFFS.begin()){ Serial.println("An Error has occurred while mounting SPIFFS"); return; } pinMode(ledPin, OUTPUT); digitalWrite(ledPin, LOW); // You can remove the password parameter if you want the AP to be open. WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); Serial.println("Wait 100 ms for AP_START..."); delay(100); Serial.println("Set softAPConfig"); IPAddress Ip(10,0,0,1); IPAddress NMask(255, 0, 0, 0); WiFi.softAPConfig(Ip, Ip, NMask); IPAddress myIP = WiFi.softAPIP(); Serial.print("AP IP address: "); Serial.println(myIP); initWebSocket(); // Route for root / web page server.on("/html", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/index.html", "text/html"); }); server.on("/jquery-3.3.1.min.js", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/jquery-3.6.0.min.js", "text/javascript"); }); server.begin(); // Route for root / web page //server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // request->send_P(200, "text/html", index_html, processor); //}); // Start server //server.begin(); } void loop() { ws.cleanupClients(); digitalWrite(ledPin, ledState); } WEB PAGE: <!DOCTYPE HTML><html> <head> <title>ESP Web Server</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="data:,"> <script> var counter = 0; var autoSend = false; var autoDate = ['P0F0,1231', 'P0F0,1232','P0F0,1234','P0F0,1235','P0F0,1236','P0F0,1237', 'P0F0,1238','P0F0,1239','P0F0,1230','P0F0,0000',] </script> <style> html { font-family: Arial, Helvetica, sans-serif; text-align: center; } h1 { font-size: 1.8rem; color: white; } h2{ font-size: 1.5rem; font-weight: bold; color: #143642; } .topnav { overflow: hidden; background-color: #143642; } body { margin: 0; } .content { padding: 30px; max-width: 600px; margin: 0 auto; } .card { background-color: #F8F7F9;; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); padding-top:10px; padding-bottom:20px; } .button { padding: 15px 50px; font-size: 24px; text-align: center; outline: none; color: #fff; background-color: #0f8b8d; border: none; border-radius: 5px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); } /*.button:hover {background-color: #0f8b8d}*/ .button:active { background-color: #0f8b8d; box-shadow: 2 2px #CDCDCD; transform: translateY(2px); } .state { font-size: 1.5rem; color:#8c8c8c; font-weight: bold; } </style> <title>ESP Web Server</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="data:,"> </head> <body> <script> var myVar = setInterval(myTimer, 250); function myTimer() { if(autoSend == true) { counter ++; if(counter >9) { counter = 0; } document.getElementById('autoData').value = autoDate[counter]; websocket.send(document.getElementById('autoData').value); } } </script> <div class="topnav"> <h1>ESP WebSocket Server</h1> </div> <div class="content"> <div class="card"> <h2>Web Socket Data Test</h2> <p><input id="autoData"> <input id="dataIn"></p> <p><button id="setAutoSend" onClick="toggleAutoState()" class="button">Auto Data</button> <button id="button" class="button">Send Data</button></p> </div> </div> <script> var gateway = `ws://${window.location.hostname}/ws`; var websocket; window.addEventListener('load', onLoad); function initWebSocket() { console.log('Trying to open a WebSocket connection...'); websocket = new WebSocket(gateway); websocket.onopen = onOpen; websocket.onclose = onClose; websocket.onmessage = onMessage; // <-- add this line } function onOpen(event) { console.log('Connection opened'); } function onClose(event) { console.log('Connection closed'); setTimeout(initWebSocket, 2000); } function onMessage(event) { var state = event.data; } function onLoad(event) { initWebSocket(); initButton(); } function toggleAutoState(){ autoSend = !autoSend; } function initButton() { document.getElementById('button').addEventListener('click', toggle); } function toggle(){ websocket.send(document.getElementById('dataIn').value); } </script> </body> </html>
My thought is that if you’ve found a bug in a library you should report it on the library’s GitHub page.
Hi Chris.
Thanks for letting us know. I wasn’t aware of that issue.
As Steve suggested, I think it might be a good idea to report a bug in the library github page.
I’m out of the office at the moment, but when I get back I can test your code and see what I get.
Regards,
Sara
Hi Sara,
I am unable to find this library on other than Platform-IO. I did post on their forum, but the post has not appeared yet. As you see the server is running as an AP with a fixed IP address. The corruptions that we see are really bizarre..! Sometimes just random chars, but sometimes its paragraphs of text about Chrome, of Microsoft or some random ,com url, it’s just crazy. If it was not an AP maybe I could see some of what I am seeing, but as an AP it is its own world as far as I know. I am going to try disabling all of the other WiFi sources in our lab and see if that changes anything.
Thank you,
Chris
Hi Sara,
Here is a message I just got off of the serial monitor from ws.data:
dhcps: send_nak>>udp_sendto results 0
what was sent to the socket was:
P0F0,1238
Hi Chris.
Indeed, that’s very weird. This is the library GitHub issues page: https://github.com/me-no-dev/ESPAsyncWebServer/issues
Send me a link to your issue when it is published.
Regards,
Sara
That message looks normal to me. “dhcps” is almost certainly the DHCP Server (In your router). The ESP32 was trying to renew its DHCP lease and sent a request to do so. The send was not acknowledged (“send_nak”); The “udp_sendto” got zero results (UDP (User Datagram Protocol) is an alternative communications protocol to Transmission Control Protocol (TCP)).
If that is the kind of “Data corruption” you are seeing then I don’t believe that is correct. It’s just protocol messages.
Hi Chris.
After testing your code, I can better understand what is going on.
After Steve’s clarification, the following message that you receive seems normal.
dhcps: send_nak>>udp_sendto results 0 P0F0,1238
What is not “normal” is the garbage that you receive after the data sent via WebSocket. I think that issue is related to the problem addressed in this discussion (although this is for a python server, the issue is the same):
Stating that discussion:
The Websocket protocol mandates that the client sends all its data using a mask. This is why you see ‘garbage’ – it’s the masked text.
So, that’s the issue with your project. At the moment, I haven’t searched enough to understand how to solve it. However, now you know what you need to search for to try to solve the issue
I hope this helps.
Regards,
Sara