Sunday, September 29, 2024

ESP8266 Captive Portal, Static Serve, and Websockets

While working on a toy for my dog, I wanted to set up an AP with captive portal. This took a little bit because a lot of examples out there were a bit out of date and did not work properly. The main issue was that the CaptiveRequestHandler class was not specifically handling Android and iOS captive handler endpoints. 

I changed the class like this and it worked fine: 

class CaptiveRequestHandler : public AsyncWebHandler {
public:
  CaptiveRequestHandler() {}
  virtual ~CaptiveRequestHandler() {}

  bool canHandle(AsyncWebServerRequest *request){
    String url = request->url();
    return (url == "/generate_204" || url == "/hotspot-detect.html");
  }

    void handleRequest(AsyncWebServerRequest *request) {
        if (!request) {
            Serial.println("Received null request");
            return; // Return early if the request is null
        }

        // Check for specific requests (e.g., Android's `/generate_204`)
        if (request->url() == "/generate_204" || request->url() == "/hotspot-detect.html") {
            // Redirect to the captive portal (ESP8266’s IP)
            request->redirect("http://192.168.4.1/index.html");
        }
    }
};


The canHandle was modified to only handle these methods, otherwise to return false. This is important because later we want to handle requests with other handlers. 

That said, I also added a static serve handler:

WiFi.softAP(SSID);
dnsServer.start(53, "*", WiFi.softAPIP());
server.addHandler(new CaptiveRequestHandler()).setFilter(ON_AP_FILTER);//only when requested from AP
server.serveStatic("/", LittleFS, "/").setDefaultFile("index.html");

This meant my index.html page would request other assets (images, css, js) and they would be served. One thing to note is that in order for this to work on a platformio project, you need to update your platform.io config with your (filesystemboard_build.filesystem = littlefs)

Finally because we are allowing handlers, we can setup the web sockets. 

// Set up WebSocket
ws.onEvent(onEvent);
server.addHandler(&ws);  // Add WebSocket handler to the server

// Start the server
server.begin();



Friday, September 13, 2024

Slightly Painful - Painless Mesh for ESP32

While working on a mesh networking project, I decided to give Painless Mesh a try. 

I ran into whole bunch of issues in PlatformIO for some reason, so I resorted to using ArduinoIDE 2. 

The first weird thing was that I got a message saying: 

Failed to install library: 'PubSubClient:2.8.0'.

Error: 2 UNKNOWN: destination dir C:\Users\CorrLabs\Documents\Arduino\libraries\PubSubClient already exists, cannot install

The solution to this was just to manually delete the folder and reinstall the library. For some reason there was a library already downloaded, but Arduino IDE could not utilize it.


Then I ran into this one:

wifi.hpp:49:14: error: 'class WiFiClass' has no member named 'setAutoConnect'; did you mean 'setAutoReconnect'?

Fortunately, I found a comment by a person named luckymatt who had the answer to this. Basically the problem is just with compatibility changes between versions. 


At this point, I was able to compile and flash my ESP32-WROOM32 dev board with the Painless Mesh MQTT example.


References:

https://forum.arduino.cc/t/error-with-wifi-hpp-when-compiling-painless-mesh-code/1248608/13