Search code examples
c++carduinoiotesp8266

ESP8266WebServer - Refactoring class, problems with std::bind and handleRoot


I'm having some trouble while putting my ESP8266WebServer standard connection procedure to its own class. I'm not able to pass the object server to my handleRoot function via bind::std.... I have tried multiple approaches, but right now, nothing succeeds. So maybe you could help me. Right now, the code compiles, I have commented out the corresponding lines. But in order to peform some actions on a client request, I need to have access to the server class methods in the functions handleRoot and handleForm. Here are the corresponding sketches. Thank you for your help.

Arduino sketch:

#include "WiFiHandler.h"
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);
WiFiHandler myWiFiHandler;


void setup(){
  Serial.begin(115200);
  myWiFiHandler.setupWiFi(server); // Setup WiFi
}

void loop(){     
  myWiFiHandler.clientHandler(server); //Handle client requests
}

Header file:

#ifndef WiFiHandler_h
#define WiFiHandler_h

#include <WiFiSetup.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "handleHTML.h"

class WiFiHandler
{
private:
  WiFiSetup myWiFiSetup; // Create object myWiFiSetup
  handleHTML myHTMLhandler; // Create object myHTMLHandler
  char* _ssid;
  char* _password;
  void handleRoot();
  void handleForm();
public:
  WiFiHandler();
  ~WiFiHandler();
  void setupWiFi(ESP8266WebServer&);
  void clientHandler(ESP8266WebServer&);
};

#endif

Source file:

#include <WiFiSetup.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "handleHTML.h"
#include "Arduino.h"
#include "WiFiHandler.h"

WiFiHandler::WiFiHandler() 
  : _ssid(myWiFiSetup.ssid()), _password(myWiFiSetup.passcode())
{
}

WiFiHandler::~WiFiHandler(){/*Nothing to destruct*/}

void WiFiHandler::setupWiFi(ESP8266WebServer& server_)
{
  WiFi.begin(_ssid, _password);

    // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print("Status: \n");
    Serial.println(WiFi.status());
  }

  //If connection successful show IP address in serial monitor
  Serial.print("Connected to ");
  Serial.println(_ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //IP address assigned to your ESP

  server_.on("/", std::bind(&WiFiHandler::handleRoot, this)); // Which routine to handle at root location
  server_.on("/", std::bind(&WiFiHandler::handleForm, this));  // Form action is handled here

  server_.begin(); //Start server
  Serial.println("HTTP server started");
}

void WiFiHandler::handleRoot()
{
  Serial.print("WiFi-Request received");
  // server_.send(200, "text/html", myHTMLhandler.getHTML());  //Send web page
}

void WiFiHandler::handleForm()
{
  // String buttonState = server.arg("State");
  Serial.print("State: ");
  // Serial.println(buttonState);

  String s = "<a href='/'> Go Back </a>";
  // server_.send(200, "text/html", s); //Send web page 
}

void WiFiHandler::clientHandler(ESP8266WebServer& server_)
{
  server_.handleClient();
}

Solution

  • I do it the following way, the principle works by the way also with async webserver:

    class MY_WebServer : public WebServer  { // inherit from the lib class
      public:
        MY_WebServer();
        void begin() {
           MDNS.addService("http", "tcp", 80);
           WebServer::begin();
        }
        void startWebServer(); // this function initializes wifi, all handlers and params
    
     private:
        void handleFileList();
     //.... some 30 handlers ...
    
     }
    

    Works in a quite complex application stable for months.