was not declared in this scope

Hallo zusammen,

ich versuche schon seit mehreren Stunden meinen Fehler zu beheben, bekomme es aber nicht hin.
Der Fehler ist fas ganz am Ende bei "server.send(200, "text/html", content());"
Hier bekomme beim Kompilieren die Meldung: "'content' was not declared in this scope"

Der Sketch läuft auf einem ESP8266 01, der als Webserver dient, um seine GPIOs zu schalten, davor muss man sich aber anmelden.

Der Plan ist der, wenn ich auf einen Button klick, dann wird die IP des ESP aufgerufen und /output1 dahinter gehängt. Im Sketch wird dann geschaut ob der "output1_state" true oder false ist und wird dann eben entweder ein oder ausgeschaltet.

Ich hoffe man versteht was ich meine.

Ich wäre froh, wenn mir jemand sagen kann, was ich falsch mache....Das Programm sonst läuft einwandfrei. Es hängt nur an der einen Zeile....

Schonmal Vielen Dank!!

und hier der Code:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const char* ssid = "Banane";
const char* password = "19ihetc57g";

const char* host = "webcontrol";

// define GPIO pins:
const int output1 = 0;
const int output2 = 2;

// output status variables:
boolean output1_state = true;
boolean output2_state = true;

ESP8266WebServer server(80);

//Check if header is present and correct
bool is_authentified(){
  Serial.println("Enter is_authentified");
  if (server.hasHeader("Cookie")){   
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
    if (cookie.indexOf("ESPSESSIONID=1") != -1) {
      Serial.println("Authentification Successful");
      return true;
    }
  }
  Serial.println("Authentification Failed");
  return false;  
}

//login page, also called for disconnect
void handleLogin(){
  String msg;
  if (server.hasHeader("Cookie")){   
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
  }
  if (server.hasArg("DISCONNECT")){
    Serial.println("Disconnection");
    String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
    if (server.arg("USERNAME") == "admin" &&  server.arg("PASSWORD") == "admin" ){
      String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=1\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n";
      server.sendContent(header);
      Serial.println("Log in Successful");
      return;
    }
  msg = "Wrong username/password! try again.";
  Serial.println("Log in Failed");
  }
  String content = "<html><body><form action='/login' method='POST'>To log in, please use : admin/admin
";
  content += "User:<input type='text' name='USERNAME' placeholder='user name'>
";
  content += "Password:<input type='password' name='PASSWORD' placeholder='password'>
";
  content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "
";
  server.send(200, "text/html", content);
}


//root page can be accessed only if authentification is ok
void handleRoot(){
  Serial.println("Enter handleRoot");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2>
";
  if (server.hasHeader("User-Agent")){
    content += "the user agent used is : " + server.header("User-Agent") + "

";
    
  if (output1_state)
  {
    content += "Output1: <a href=\"output1\"><button>ON</button></a>
";
  }
  else
  {
    content += "Output1: <a href=\"output1\"><button>OFF</button></a>
";
  }

  if (output2_state)
  {
    content += "Output2: <a href=\"output2\"><button>ON</button></a>
";
  }
  else
  {
    content += "Output2: <a href=\"output2\"><button>OFF</button></a>
";
  }

  }
  content += "You can access this page until you <a href=\"/login?DISCONNECT=YES\">disconnect</a></body></html>";
  server.send(200, "text/html", content);
}


void setup(void){

    // configure GPIO 0 and GPIO 2 as outputs:
  pinMode(output1, OUTPUT);
  pinMode(output2, OUTPUT);

  // set outputs to low:
  digitalWrite(output1, LOW);
  digitalWrite(output2, LOW);


  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

if (MDNS.begin(host))
  {
    Serial.println("mDNS responder started");
  }
  MDNS.addService("http", "tcp", 80);

  

  //here the list of headers to be recorded
  const char * headerkeys[] = {"User-Agent","Cookie"} ;
  size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
  //ask server to track these headers
  server.collectHeaders(headerkeys, headerkeyssize );
  server.begin();
  Serial.println("HTTP server started");

  
  server.on("/", handleRoot);
  server.on("/login", handleLogin);
  server.on("/output1", [](){
       if (output1_state)
    {
      Serial.println("LED1 aus");
      Serial.println(output1_state);
      digitalWrite(output1, LOW);
      output1_state = false;

    }
    else
    {
      Serial.println("LED1 an");
      digitalWrite(output1, HIGH);
      Serial.println(output1_state);
      output1_state = true;
    }
    server.send(200, "text/html", content()); 
    delay(1000);
  });


 
}

void loop(void){
  server.handleClient();
}

Ich vermute die Klammer "()" ist zu viel.
Es sollte nur "content" heißen.

Wenn nicht, poste mal die komplette Fehlermeldung

Habe ich auch schon probiert. Der kompiler will trotzdem nicht....

Zum einen sind die Klammern zuviel.
Zum anderen ist 'content' in den Funktionen handleLogin() und handleRoot() jeweils lokal als String definiert. Ausserhalb der Funktionen kann man deshalb darauf nicht zugreifen.

Hast du mir dann evtl. einen Tipp, wie ich das lösen kann?

Wobei, was willst Du denn da überhaupt senden? Selbst wenn Du 'content' nun definierst, muss ja auch irgendwo ein Inhalt reingeschrieben werden ( so wie in den beiden anderen Funktionen auch ).

Ich möchte wieder auf die Seite, wo ich die GPOIs anschalten kann. Im Prinzip, will ich die Ip aufrufen und dahinter /output1 setzten und danach wieder auf die Startseite, wo ich die GPIOs schalten kann, mich aber nicht immer neu anmelden muss.

Ok, ich habe mit dem ESP8266 noch nciht viel gemacht. Aber so wie ich das sehe, gibst Du mit server.send die Webseite aus, deren Inhalt in 'content' stehen muss. D.h., Wenn Du wieder das gleiche anzeigen willst wie in handleRoot, dann musst Du da auch das gleiche ausgeben. Nur darfst Du es eben nicht vom Login abhängig machen. Ich hab' mal auf die Schnelle den Webseitenanteil von handleRoot in eine eigene Funktion gepackt, und dann auch in /output1 ausgegeben:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

const char* ssid = "Banane";
const char* password = "19ihetc57g";

const char* host = "webcontrol";

// define GPIO pins:
const int output1 = 0;
const int output2 = 2;

// output status variables:
boolean output1_state = true;
boolean output2_state = true;

ESP8266WebServer server(80);

//Check if header is present and correct
bool is_authentified(){
  Serial.println("Enter is_authentified");
  if (server.hasHeader("Cookie")){   
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
    if (cookie.indexOf("ESPSESSIONID=1") != -1) {
      Serial.println("Authentification Successful");
      return true;
    }
  }
  Serial.println("Authentification Failed");
  return false; 
}

//login page, also called for disconnect
void handleLogin(){
  String msg;
  if (server.hasHeader("Cookie")){   
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
  }
  if (server.hasArg("DISCONNECT")){
    Serial.println("Disconnection");
    String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){
    if (server.arg("USERNAME") == "admin" &&  server.arg("PASSWORD") == "admin" ){
      String header = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=1\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n";
      server.sendContent(header);
      Serial.println("Log in Successful");
      return;
    }
  msg = "Wrong username/password! try again.";
  Serial.println("Log in Failed");
  }
  String content = "<html><body><form action='/login' method='POST'>To log in, please use : admin/admin
";
  content += "User:<input type='text' name='USERNAME' placeholder='user name'>
";
  content += "Password:<input type='password' name='PASSWORD' placeholder='password'>
";
  content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "
";
  server.send(200, "text/html", content);
}


//root page can be accessed only if authentification is ok
void handleRoot(){
  Serial.println("Enter handleRoot");
  String header;
  if (!is_authentified()){
    String header = "HTTP/1.1 301 OK\r\nLocation: /login\r\nCache-Control: no-cache\r\n\r\n";
    server.sendContent(header);
    return;
  }
  sendMain();
}

void sendMain() {
  String content = "<html><body><H2>hello, you successfully connected to esp8266!</H2>
";
  if (server.hasHeader("User-Agent")){
    content += "the user agent used is : " + server.header("User-Agent") + "

";
   
  if (output1_state)
  {
    content += "Output1: <a href=\"output1\"><button>ON</button></a>
";
  }
  else
  {
    content += "Output1: <a href=\"output1\"><button>OFF</button></a>
";
  }

  if (output2_state)
  {
    content += "Output2: <a href=\"output2\"><button>ON</button></a>
";
  }
  else
  {
    content += "Output2: <a href=\"output2\"><button>OFF</button></a>
";
  }

  }
  content += "You can access this page until you <a href=\"/login?DISCONNECT=YES\">disconnect</a></body></html>";
  server.send(200, "text/html", content);
}

void setup(void){

    // configure GPIO 0 and GPIO 2 as outputs:
  pinMode(output1, OUTPUT);
  pinMode(output2, OUTPUT);

  // set outputs to low:
  digitalWrite(output1, LOW);
  digitalWrite(output2, LOW);


  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

if (MDNS.begin(host))
  {
    Serial.println("mDNS responder started");
  }
  MDNS.addService("http", "tcp", 80);

 

  //here the list of headers to be recorded
  const char * headerkeys[] = {"User-Agent","Cookie"} ;
  size_t headerkeyssize = sizeof(headerkeys)/sizeof(char*);
  //ask server to track these headers
  server.collectHeaders(headerkeys, headerkeyssize );
  server.begin();
  Serial.println("HTTP server started");

 
  server.on("/", handleRoot);
  server.on("/login", handleLogin);
  server.on("/output1", [](){
       if (output1_state)
    {
      Serial.println("LED1 aus");
      Serial.println(output1_state);
      digitalWrite(output1, LOW);
      output1_state = false;

    }
    else
    {
      Serial.println("LED1 an");
      digitalWrite(output1, HIGH);
      Serial.println(output1_state);
      output1_state = true;
    }
    //server.send(200, "text/html", content());
    sendMain();
    delay(1000);
  });


 
}

void loop(void){
  server.handleClient();
}

P.S. Ich find's übersichtlicher, auch die Funktion für output1 ( und weitere ) als getrennte Funktionen zu definieren - z.B. handleOutput1() - , und in server.on den Funktionsnamen zu übergeben.

P.P.S Da er sich merkt, ob er angemeldet ist, könntest Du da doch anstelle des server.send auch einfach wieder handleRoot() aufrufen.

Also für das, das du noch nicht viel mit dem ESP gemacht hast, funktioniert es einwandfrei. Genau das, was ich wollte.

Vielen Dank Franz-Peter!!

Bitte schön :slight_smile:

und eine solide Grundlage hilft eigentlich überall :wink:

wollte mich hier nur mal bedanken und sagen, dass mir der Code von Franz-Peter super weitergeholfen hat. MERCI :slight_smile: