Errors while trying to put code into classes (Webserver AP)

Hello everyone,

i want to use the base of this tutorial and put it in classes for a little bit more tidiness.
Yesterday i had one error which i couldnt solve, so i redid the whole thing.
Now i have 20 errors and i dont know whats different... :fearful:

There are 4 different types of errors which i will post some examples. In the end i will post the whole .cpp / .ino / .h

webserver.h:35:39: error: initializer-string for array of chars is too long [-fpermissive]
     const char index_html[] PROGMEM = R"rawliteral(

webserver.cpp:13:39: error: 'this' was not captured for this lambda function
     request->send_P(200, "text/html", index_html);

webserver.cpp:20:27: error: invalid use of non-static data member 'webserver::PARAM_INPUT_1'
In file included from C:\Users\...\webserver.cpp:2:0:
C:\Users\...\webserver.h:16:33: note: declared here
     const char* PARAM_INPUT_1 = "input1";

In member function 'void webserver::setup_server(AsyncWebServer)':
webserver.cpp:10:22: error: declaration of 'AsyncWebServer server' shadows a parameter
 AsyncWebServer server(80);

Honestly im floored on what to do. Searching for similar problems didnt do much, besides confuse me more.
Any and all help is very appreciated

main.ino

#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#else
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>
#include "webserver.h"

webserver webserver;
AsyncWebServer server(80);
const char* ssid = "blabla";
const char* password = "blabla";

void setup() {
  Serial.begin(115200);

  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();

  Serial.println();
  Serial.print("IP Address: ");
  Serial.println(IP);

  webserver.setup_server(server);
}
void loop() {
}

webserver.cpp

#include "Arduino.h"
#include "webserver.h"

webserver::webserver() {
}

void webserver::setup_server(AsyncWebServer server) {
  // Send web page with input fields to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/html", index_html);
  });

  // Send a GET request to <ESP_IP>/get?input1=<inputMessage>
  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest * request) {

    // GET input1 value on <ESP_IP>/get?input1=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
    }
    // GET input2 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_2)) {
      inputMessage = request->getParam(PARAM_INPUT_2)->value();
      inputParam = PARAM_INPUT_2;
    }
    // GET input3 value on <ESP_IP>/get?input3=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_3)) {
      inputMessage = request->getParam(PARAM_INPUT_3)->value();
      inputParam = PARAM_INPUT_3;
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field ("
                  + inputParam + ") with value: " + inputMessage +
                  "
<a href=\"/\">Return to Home Page</a>");
  });
  server.onNotFound(webserver.notFound());
  server.begin();
}

void webserver::notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

webserver.h

#ifndef webserver_h
#define webserver_h

#include "Arduino.h"
#include "ESPAsyncWebServer.h"
#include "AsyncTCP.h"
#include <WiFi.h>

class webserver {

  private:
    // REPLACE WITH YOUR NETWORK CREDENTIALS
    const char* PARAM_INPUT_1 = "input1";
    const char* PARAM_INPUT_2 = "input2";
    const char* PARAM_INPUT_3 = "input3";

  public:
    //Insert Public Variables and Functions
    webserver();
    AsyncWebServer server(int port);

    String music_state;
    IPAddress IP;

    String inputMessage;
    String inputParam;

    // HTML web page to handle 3 input fields (input1, input2, input3)
    const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
  <title>ESP Input Form</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  </head><body>
  <form action="/get">
    input1: <input type="text" name="input1">
    <input type="submit" value="Submit">
  </form>

  <form action="/get">
    input2: <input type="text" name="input2">
    <input type="submit" value="Submit">
  </form>

  <form action="/get">
    input3: <input type="text" name="input3">
    <input type="submit" value="Submit">
  </form>
</body></html>)rawliteral";

    void setup_server(AsyncWebServer server);
    void notFound(AsyncWebServerRequest *request);

};

#endif

there is no reason to create a class to just separate functions which would be using globals from your main code... just forget about that idea, it's not the right way. You can just use multiple files if you want to keep each tab small...

Hm thats kinda sad... Since i do this thing with some friends of mine there is gonna be alot more added to my code. Thats why i wanted to keep it tidy.

What i could do is just use a header file without the class and just put all my variables in there and include it into the main.io, right?

"Tidy" does not mean creating a class if you don't require a class and instances of that thing. Here it seems you just want to separate things to make it easier to read / maintain.

you could indeed separate things apart in files and use a .h to describe what's available to your main program

for example (with 1 variable and one function) you could have your main ino file as

test.ino

#include "myStuff.h"

void setup() {
  Serial.begin(115200);
  Serial.print(F("value is = ")); Serial.println(value);
  Serial.print(F("computed result is = ")); Serial.println(computedResult(10));
}

void loop() {}

in myStuff.h you list stuff that needs to be known outside your .cpp file

#ifndef MYSTUFF_H
#define MYSTUFF_H
extern int value;
int computedResult(int v);
#endif

and in myStuff.cpp

#include "myStuff.h"

int value = 12;

// this function is not advertised outside this file.
int superSecretFunction(int v)
{
  return v * 2;
}

int computedResult(int v)
{
  return superSecretFunction(v) * 10;
}

your main .ino file will know that a value variable exists as well as a computedResult() function but it does not know about the superSecretFunction()

it should compile without any warning and in the Serial Monitor (@ 115200 bauds) you should see

[color=purple]
value is = 12
computed result is = 200
[/color]

Thanks for the explaination and the very descriptive example.

I will be sure to put your advice to good use

Hey just a quick update. I used your advice and deleted the class and shifted some variables around, but
i still get some errors.

C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.data.PARAM_INPUT_1+0x0): multiple definition of `PARAM_INPUT_1'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.data.PARAM_INPUT_1+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.bss.inputMessage+0x0): multiple definition of `inputMessage'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.bss.inputMessage+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.bss.inputParam+0x0): multiple definition of `inputParam'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.bss.inputParam+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.data.PARAM_INPUT_2+0x0): multiple definition of `PARAM_INPUT_2'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.data.PARAM_INPUT_2+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.data.PARAM_INPUT_3+0x0): multiple definition of `PARAM_INPUT_3'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.data.PARAM_INPUT_3+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.bss.server+0x0): multiple definition of `server'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.bss.server+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.bss.music_state+0x0): multiple definition of `music_state'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.bss.music_state+0x0): first defined here
C:\...\Temp\arduino_build_431459\sketch\webserver.cpp.o:(.bss.IP+0x0): multiple definition of `IP'
C:\...\Temp\arduino_build_431459\sketch\main.ino.cpp.o:(.bss.IP+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
Multiple librarys for "WiFi.h" found
 used: C:\Users\...\Arduino15\packages\firebeetle32\hardware\esp32\0.1.1\libraries\WiFi
 not used: C:\Program Files (x86)\Arduino\libraries\WiFi
Bibliothek ESPAsyncWebServer-master in Version 1.2.3 im Ordner: C:\Users\...\Arduino\libraries\ESPAsyncWebServer-master  wird verwendet
Bibliothek FS in Version 1.0 im Ordner: C:\Users\...\Arduino15\packages\firebeetle32\hardware\esp32\0.1.1\libraries\FS  wird verwendet
Bibliothek WiFi in Version 1.0 im Ordner: C:\Users\...\Arduino15\packages\firebeetle32\hardware\esp32\0.1.1\libraries\WiFi  wird verwendet
Bibliothek AsyncTCP-master in Version 1.1.1 im Ordner: C:\Users\...\Arduino\libraries\AsyncTCP-master  wird verwendet
exit status 1
Error while compiling for the Board FireBeetle-ESP32.

The first ones are pretty selfexplainatory, some variables are more than once defined.

The last one with

collect2.exe: error: ld returned 1 exit statu

i dont know what to think about this error. It seems like a very gerneral error.
Could you please give me some more info about that?

the last error is the compiler (linker) giving up because it is fed up with all the mistakes :slight_smile:

fix all the other stuff and you should get going

Ok thanks again :smiley: :smiley: