External ESP8266 Configuration

There are a few different methods I’ve seen for external input of local WiFi credentials to the ESP8266, and having them saved to the EEPROM. However, for me, none of them worked quite as advertised. It also turns out that the ESP8266 saves the most recent SSID and Password internally (even after a reflash), so using EEPROM was actually unnecessary.

Much of the code for setting up a local server / access point was borrowed from Tzapu and chriscook8. Any suggestions for improvement are welcome, as I’m very much a novice at Arduino coding.

    //A simplified version of work begun by Tzapu and chriscook8
    //for saving local WiFi SSID and Passwords to the ESP8266.
    //Uses ESP8266 internal memory instead of the problematic EEPROM.
    //To input local SSID and Password, connect to WiFi "ESP8266",
    //and point your browser to "192.168.4.1".
    
    #include "ESP8266WiFi.h"
    #include <ESP8266mDNS.h>
    #include <WiFiClient.h>
    #include <BlynkSimpleEsp8266.h>
    
    MDNSResponder mdns;
    WiFiServer server(80);
    
    char auth[] = "YourAuthToken"; // Blynk token
    const char* APssid = "ESP8266"; // Name of access point
    
    String st;
    String rsid;
    String rpass;
    boolean newSSID = false;
    
    
    void setup() {
      Serial.begin(115200);
      delay(10);
      Serial.println("Startup");
    
      // if the stored SSID and password connected successfully, exit setup
      if ( testWifi()) {
              Blynk.config(auth);
              return;
          }
      // otherwise, set up an access point to input SSID and password     
      else
          Serial.println("");
          Serial.println("Connect timed out, opening AP"); 
          setupAP();
    }
    
    int testWifi(void) {
      int c = 0;
      Serial.println("Waiting for Wifi to connect");  
      while ( c < 20 ) {
        if (WiFi.status() == WL_CONNECTED) {
          Serial.println("WiFi connected.");
          return(1); 
          }      
        delay(500);
        Serial.print(WiFi.status());    
        c++;
      }
      return(0);
    } 
    
    void launchWeb(int webtype) {
        Serial.println("");
        Serial.println("WiFi connected");
        Serial.println(WiFi.localIP());
        Serial.println(WiFi.softAPIP());
        if (!mdns.begin("esp8266", WiFi.localIP())) {
          Serial.println("Error setting up MDNS responder!");
          while(1) { 
            delay(1000);
          }
        }
        Serial.println("mDNS responder started");
        // Start the server
        server.begin();
        Serial.println("Server started");   
        int b = 20;
        int c = 0;
        while(b == 20) { 
           b = mdns1(webtype);
    
           //If a new SSID and Password were sent, close the AP, and connect to local WIFI
           if (newSSID == true){
              newSSID = false;
    
              //convert SSID and Password sting to char
              char ssid[rsid.length()];
              rsid.toCharArray(ssid, rsid.length());         
              char pass[rpass.length()];
              rpass.toCharArray(pass, rpass.length());
    
              Serial.println("Connecting to local Wifi");
              WiFi.disconnect();
              delay(500);
        
              WiFi.begin(ssid,pass);
              delay(1000);
              if ( testWifi()) {
                Blynk.config(auth);
                return;
              }
    
             else{
                Serial.println("");
                Serial.println("New SSID or Password failed. Reconnect to server, and try again.");
                setupAP();
                return;
             }
           }
         }
    }
    
    
    void setupAP(void) {
      
      WiFi.mode(WIFI_STA);
      WiFi.disconnect();
      delay(100);
      int n = WiFi.scanNetworks();
      Serial.println("scan done");
      if (n == 0)
        Serial.println("no networks found");
      else
      {
        Serial.print(n);
        Serial.println(" networks found");
      }
      Serial.println(""); 
      st = "<ul>";
      for (int i = 0; i < n; ++i)
        {
          // Print SSID and RSSI for each network found
          st += "<li>";
          st +=i + 1;
          st += ": ";
          st += WiFi.SSID(i);
          st += " (";
          st += WiFi.RSSI(i);
          st += ")";
          st += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
          st += "</li>";
        }
      st += "</ul>";
      delay(100);
      WiFi.softAP(APssid);
      Serial.println("softAP");
      Serial.println("");
      launchWeb(1);
    }
    
    
    String urldecode(const char *src){ //fix encoding
      String decoded = "";
        char a, b;
        
      while (*src) {     
        if ((*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {      
          if (a >= 'a')
            a -= 'a'-'A';       
          if (a >= 'A')                
            a -= ('A' - 10);                   
          else               
            a -= '0';                  
          if (b >= 'a')                
            b -= 'a'-'A';           
          if (b >= 'A')                
            b -= ('A' - 10);            
          else                
            b -= '0';                        
          decoded += char(16*a+b);            
          src+=3;        
        } 
        else if (*src == '+') {
          decoded += ' ';           
          *src++;       
        }  
        else {
          decoded += *src;           
          *src++;        
        }    
      }
      decoded += '\0';        
      return decoded;
    }
    
    
    int mdns1(int webtype){
      // Check for any mDNS queries and send responses
      mdns.update();
      
      // Check if a client has connected
      WiFiClient client = server.available();
      if (!client) {
        return(20);
      }
      Serial.println("");
      Serial.println("New client");
    
      // Wait for data from client to become available
      while(client.connected() && !client.available()){
        delay(1);
       }
      
      // Read the first line of HTTP request
      String req = client.readStringUntil('\r');
      
      // First line of HTTP request looks like "GET /path HTTP/1.1"
      // Retrieve the "/path" part by finding the spaces
      int addr_start = req.indexOf(' ');
      int addr_end = req.indexOf(' ', addr_start + 1);
      if (addr_start == -1 || addr_end == -1) {
        Serial.print("Invalid request: ");
        Serial.println(req);
        return(20);
       }
      req = req.substring(addr_start + 1, addr_end);
      Serial.print("Request: ");
      Serial.println(req);
      client.flush(); 
      String s;
      if ( webtype == 1 ) {
          if (req == "/")
          {
            IPAddress ip = WiFi.softAPIP();
            String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
            s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
            s += ipStr;
            s += "<p>";
            s += st;
            s += "<form method='get' action='a'><label>SSID: </label><input name='ssid' length=32><input name='pass' length=64><input type='submit'></form>";
            s += "</html>\r\n\r\n";
            Serial.println("Sending 200");
          }
          else if ( req.startsWith("/a?ssid=") ) {
    
            newSSID = true;
            String qsid; //WiFi SSID 
            qsid = urldecode(req.substring(8,req.indexOf('&')).c_str()); //correct coding for spaces as "+"
            Serial.println(qsid);
            Serial.println("");
            rsid = qsid;
            
            String qpass; //Wifi Password
            qpass = urldecode(req.substring(req.lastIndexOf('=')+1).c_str());//correct for coding spaces as "+"
            Serial.println(qpass);
            Serial.println("");
            rpass = qpass;
     
            s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 ";
            s += "<p> New SSID and Password accepted</html>\r\n\r\n"; 
          }
          else
          {
            s = "HTTP/1.1 404 Not Found\r\n\r\n";
            Serial.println("Sending 404");
          }
      } 
      else
      {
          if (req == "/")
          {
            s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266";
            s += "<p>";
            s += "</html>\r\n\r\n";
            Serial.println("Sending 200");
          }
          else
          {
            s = "HTTP/1.1 404 Not Found\r\n\r\n";
            Serial.println("Sending 404");
          }       
      }
      client.print(s);
      Serial.println("Done with client");
      return(20);
    }
    
    
    void loop() {
      // put your main code here, to run repeatedly:
    
      Blynk.run();
    }

I’m continuing to tweak this code, and have run into a problem: Is there a command to close the softAP?

When a new SSID and Password are accepted, and the ESP8266 restarts, it continues to broadcast the softAP SSID. I’d like to close the softAP, so that whatever device was used to feed it the local credentials (usually my cell phone) reverts back to the local wifi. Instead, it’s remaining connected to the softAP, so that I have to manually go into my phone’s settings, and disconnect it from the ESP8266.

I’ve tried “WiFi.disconnect()”. Doesn’t seem to have any effect. I’ve tried creating a new softAP wit a different name. My phone remains connected to the original softAP, but now, BOTH softAPs are available.

Any thoughts? How does one shut down a softAP, once created?

i tried the code and i get only the error below , also after connecting to the access point 192.168.4.1 not showing any thing only error

666666666666666
Connect timed out, opening AP
scan done
3networks found

softAP


WiFi connected
0.0.0.0
192.168.4.1
Error setting up MDNS responder!

@Chrome1000

Does doing a

 WiFi.mode(WIFI_OFF); 

followed by a

Wifi.mode(WIFI_STA);
WiFi.begin(ssid,pass);

Workk??

@scropion86

Comment out this:

if (!mdns.begin("esp8266", WiFi.localIP())) {
      Serial.println("Error setting up MDNS responder!");
      while(1) { 
        delay(1000);
      }
}
    Serial.println("mDNS responder started");

And this:

 mdsn.update();

And it should work fine, I think something broke the mdns in a recent update.

i will try and let you know.

i also tried to test https://github.com/tzapu/WiFiManager
and same error

@Chrome1000

Here is some stuff I dug up but haven’t had a chance to check because I don’t need the functionality right now.

To summarize what I think I read, certain flags in the original code became true and don’t get changed.

For instance, if you have called WiFi.softAP() once, the flag will be true, and WiFi.begin() will consider it and set the mode to WIFI_AP_STA (as opposed to WIFI_AP if the flag wasn’t set, which happens to be the default).

From the second link:

Links2004 commented on Aug 9
yes WiFi.mode(WIFI_STA); goes to STA mode only.
what version do you use. this behavior is changed 27 days ago.
see 6233977 and #529
WiFi.softAPdisconnect(true); shut work too, the difference to WiFi.mode(WIFI_STA); is its delete the AP config complete form the espressif config memory.

WiFi.softAPdisconnect(true) seems like a good possible option. If you are using a library from prior to middle of July this functionality won’t work.

https://github.com/esp8266/Arduino/issues/529

https://github.com/esp8266/Arduino/issues/676

@Chrome1000

Got curious and updating to the staging package in the arduino IDE board manager then redownloading will compile the WiFi.softAPdisconnect function. This function does just what you want. I inserted it where I would have put it in the code below(Copied from above and edited)

//A simplified version of work begun by Tzapu and chriscook8
//for saving local WiFi SSID and Passwords to the ESP8266.
//Uses ESP8266 internal memory instead of the problematic EEPROM.
//To input local SSID and Password, connect to WiFi "ESP8266",
//and point your browser to "192.168.4.1".

#include "ESP8266WiFi.h"
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp8266.h>

MDNSResponder mdns;
WiFiServer server(80);

char auth[] = "YourAuthToken"; // Blynk token
const char* APssid = "ESP8266"; // Name of access point

String st;
String rsid;
String rpass;
boolean newSSID = false;


void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println("Startup");

  // if the stored SSID and password connected successfully, exit setup
  if ( testWifi()) {
          Blynk.config(auth);
          return;
      }
  // otherwise, set up an access point to input SSID and password     
  else
      Serial.println("");
      Serial.println("Connect timed out, opening AP"); 
      setupAP();
}

int testWifi(void) {
  int c = 0;
  Serial.println("Waiting for Wifi to connect");  
  while ( c < 20 ) {
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("WiFi connected.");
      return(1); 
      }      
    delay(500);
    Serial.print(WiFi.status());    
    c++;
  }
  return(0);
} 

void launchWeb(int webtype) {
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.softAPIP());
   /* if (!mdns.begin("esp8266", WiFi.localIP())) {
      Serial.println("Error setting up MDNS responder!");
      while(1) { 
        delay(1000);
      }
    }
    Serial.println("mDNS responder started");
    */
    // Start the server
    server.begin();
    Serial.println("Server started");   
    int b = 20;
    int c = 0;
    while(b == 20) { 
       b = mdns1(webtype);

       //If a new SSID and Password were sent, close the AP, and connect to local WIFI
       if (newSSID == true){
          newSSID = false;

          //convert SSID and Password sting to char
          char ssid[rsid.length()];
          rsid.toCharArray(ssid, rsid.length());         
          char pass[rpass.length()];
          rpass.toCharArray(pass, rpass.length());

          Serial.println("Connecting to local Wifi");
          delay(500);
          WiFi.softAPdisconnect(true);
          delay(500);
          WiFi.mode(WIFI_STA);
          WiFi.begin(ssid,pass);
          delay(1000);
          if ( testWifi()) {
            Blynk.config(auth);
            return;
          }

         else{
            Serial.println("");
            Serial.println("New SSID or Password failed. Reconnect to server, and try again.");
            setupAP();
            return;
         }
       }
     }
}


void setupAP(void) {
  
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0)
    Serial.println("no networks found");
  else
  {
    Serial.print(n);
    Serial.println(" networks found");
  }
  Serial.println(""); 
  st = "<ul>";
  for (int i = 0; i < n; ++i)
    {
      // Print SSID and RSSI for each network found
      st += "<li>";
      st +=i + 1;
      st += ": ";
      st += WiFi.SSID(i);
      st += " (";
      st += WiFi.RSSI(i);
      st += ")";
      st += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
      st += "</li>";
    }
  st += "</ul>";
  delay(100);
  WiFi.softAP(APssid);
  Serial.println("softAP");
  Serial.println("");
  launchWeb(1);
}


String urldecode(const char *src){ //fix encoding
  String decoded = "";
    char a, b;
    
  while (*src) {     
    if ((*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {      
      if (a >= 'a')
        a -= 'a'-'A';       
      if (a >= 'A')                
        a -= ('A' - 10);                   
      else               
        a -= '0';                  
      if (b >= 'a')                
        b -= 'a'-'A';           
      if (b >= 'A')                
        b -= ('A' - 10);            
      else                
        b -= '0';                        
      decoded += char(16*a+b);            
      src+=3;        
    } 
    else if (*src == '+') {
      decoded += ' ';           
      *src++;       
    }  
    else {
      decoded += *src;           
      *src++;        
    }    
  }
  decoded += '\0';        
  return decoded;
}


int mdns1(int webtype){
  // Check for any mDNS queries and send responses
  //mdns.update();
  
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return(20);
  }
  Serial.println("");
  Serial.println("New client");

  // Wait for data from client to become available
  while(client.connected() && !client.available()){
    delay(1);
   }
  
  // Read the first line of HTTP request
  String req = client.readStringUntil('\r');
  
  // First line of HTTP request looks like "GET /path HTTP/1.1"
  // Retrieve the "/path" part by finding the spaces
  int addr_start = req.indexOf(' ');
  int addr_end = req.indexOf(' ', addr_start + 1);
  if (addr_start == -1 || addr_end == -1) {
    Serial.print("Invalid request: ");
    Serial.println(req);
    return(20);
   }
  req = req.substring(addr_start + 1, addr_end);
  Serial.print("Request: ");
  Serial.println(req);
  client.flush(); 
  String s;
  if ( webtype == 1 ) {
      if (req == "/")
      {
        IPAddress ip = WiFi.softAPIP();
        String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
        s += ipStr;
        s += "<p>";
        s += st;
        s += "<form method='get' action='a'><label>SSID: </label><input name='ssid' length=32><input name='pass' length=64><input type='submit'></form>";
        s += "</html>\r\n\r\n";
        Serial.println("Sending 200");
      }
      else if ( req.startsWith("/a?ssid=") ) {

        newSSID = true;
        String qsid; //WiFi SSID 
        qsid = urldecode(req.substring(8,req.indexOf('&')).c_str()); //correct coding for spaces as "+"
        Serial.println(qsid);
        Serial.println("");
        rsid = qsid;
        
        String qpass; //Wifi Password
        qpass = urldecode(req.substring(req.lastIndexOf('=')+1).c_str());//correct for coding spaces as "+"
        Serial.println(qpass);
        Serial.println("");
        rpass = qpass;
 
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 ";
        s += "<p> New SSID and Password accepted</html>\r\n\r\n"; 
      }
      else
      {
        s = "HTTP/1.1 404 Not Found\r\n\r\n";
        Serial.println("Sending 404");
      }
  } 
  else
  {
      if (req == "/")
      {
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266";
        s += "<p>";
        s += "</html>\r\n\r\n";
        Serial.println("Sending 200");
      }
      else
      {
        s = "HTTP/1.1 404 Not Found\r\n\r\n";
        Serial.println("Sending 404");
      }       
  }
  client.print(s);
  Serial.println("Done with client");
  return(20);
}


void loop() {
  // put your main code here, to run repeatedly:

  Blynk.run();
}

Thank you so much @Schmorrison! :+1:

You should note that moving the softAPdisconnect function to the following position will help in the case the module doesn’t connect to the Wifi you input.

Completely over looked that. Its likely you will want to change WiFi.mode(WIFI_STA); to WiFi.mode(WIFI_STA_AP); so you don’t get thrown off the AP before the credential are accepted.

 //convert SSID and Password sting to char
      char ssid[rsid.length()];
      rsid.toCharArray(ssid, rsid.length());         
      char pass[rpass.length()];
      rpass.toCharArray(pass, rpass.length());

      Serial.println("Connecting to local Wifi");
      delay(500);
      WiFi.mode(WIFI_AP_STA);
      WiFi.begin(ssid,pass);
      delay(1000);
      if ( testWifi()) {
        Blynk.config(auth);
        WiFi.softAPdisconnect(true);
        delay(500);
        return;
      }

     else{
        Serial.println("");
        Serial.println("New SSID or Password failed. Reconnect to server, and try again.");
        setupAP();
        return;
     }

Don’t copy that code, I ran into issues, don’t know where.

When I figure out what when wrong I’ll upload it to my github and paste a link here.

Pretty certain the issue I am running into is multiple favicon request being sent to the module before it can handle the main request. Not sure why it was working fine a few days ago.

New client
Request: /favicon.ico
Sending 404
Done with client

I’ve tried client.stop(); and specifically sending a null header for if (req == "/favicon.ico") however neither of these seem to be the silver bullet.

I am sure sending a 404 doesn’t help because it has to do with getting requests while responding at the same time.

I’ve found code Github Weather sensor webserver Which has a busy flag which prevents the esp from receiving a new request until its done responding. I am going to look at it, but not really sure where to start for implementing it in this code. They seem to be using the client.stop(); function but it feels like that function could also terminate the desired connection if client.stop(); is related to the host and not the request.

I’ve made a few more changes, including reformatting the login page. This is working very well for me with the staging package, as suggested by @schmorrison. Also, I don’t know if it’s the Blynk library update or the addition of the yield(); statement in the loop (or a combination of the two), but my ESP8266 boards have been running rock stable for weeks.

/****************************************************************************
* A simplified version of work begun by Tzapu and chriscook8
*for saving local WiFi SSID and Passwords to the ESP8266.
*Uses ESP8266 flash memory instead of the problematic EEPROM.
*To input local SSID and Password, connect to WiFi "ESP8266",
*and point your browser to "192.168.4.1".
*
*Added option to erase current credentials by setting virtual pin 30 high in
*the Blynk app.
*****************************************************************************
*/

#include "ESP8266WiFi.h"
#include <ESP8266mDNS.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp8266.h>

MDNSResponder mdns;
WiFiServer server(80);

char auth[] = "xxxxxxxxxxxxxxxx"; // Blynk token "YourAuthToken"
const char* APssid = "ESP8266"; // Name of access point

String st;
String rsid;
String rpass;
boolean newSSID = false;


void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println("Startup");

  // if the stored SSID and password connected successfully, exit setup
  if ( testWifi()) {
          Blynk.config(auth);
          return;
      }
  // otherwise, set up an access point to input SSID and password     
  else
      Serial.println("");
      Serial.println("Connect timed out, opening AP"); 
      setupAP();
}

int testWifi(void) {
  long Timeout = (millis() + 10000);
  
  Serial.print("Waiting for Wifi to connect. ");  
  while (millis() < Timeout){
    delay(500);
    Serial.print(".");
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("");
      Serial.println("WiFi connected.");
      return(1); 
    }
  }      
  return(0);
} 

void launchWeb(int webtype) {
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println(WiFi.localIP());
    Serial.println(WiFi.softAPIP());
    
    // Start the server
    server.begin();
    Serial.println("Server started");   
    int b = 20;
    int c = 0;
    while(b == 20) { 
       b = mdns1(webtype);

       //If a new SSID and Password were sent, close the AP, and connect to local WIFI
       if (newSSID == true){
          newSSID = false;

          //convert SSID and Password sting to char
          char ssid[rsid.length()];
          rsid.toCharArray(ssid, rsid.length());         
          char pass[rpass.length()];
          rpass.toCharArray(pass, rpass.length());

          Serial.println("Connecting to local Wifi"); //Close the AP and connect with new SSID and P/W
          WiFi.softAPdisconnect(true);
          delay(500);
          WiFi.begin(ssid,pass);
          delay(1000);
          
          if ( testWifi()) {
            Blynk.config(auth);
            return;
          }

         else{
            Serial.println("");
            Serial.println("New SSID or Password failed. Reconnect to server, and try again.");
            setupAP();
            return;
         }
       }
     }
}


void setupAP(void) {
  
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  int n = WiFi.scanNetworks();
  Serial.println("scan done");
  if (n == 0)
    Serial.println("no networks found");
  else
  {
    Serial.print(n);
    Serial.println(" networks found");
  }
  Serial.println(""); 
  st = "<ul>";
  for (int i = 0; i < n; ++i)
    {
      // Print SSID and RSSI for each network found
      st += "<li>";
      st += WiFi.SSID(i);
      st += " (";
      st += WiFi.RSSI(i);
      st += ")";
      st += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
      st += "</li>";
    }
  st += "</ul>";
  delay(100);
  WiFi.softAP(APssid);
  Serial.println("softAP");
  Serial.println("");
  launchWeb(1);
}


String urldecode(const char *src){ //fix encoding
  String decoded = "";
    char a, b;
    
  while (*src) {     
    if ((*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {      
      if (a >= 'a')
        a -= 'a'-'A';       
      if (a >= 'A')                
        a -= ('A' - 10);                   
      else               
        a -= '0';                  
      if (b >= 'a')                
        b -= 'a'-'A';           
      if (b >= 'A')                
        b -= ('A' - 10);            
      else                
        b -= '0';                        
      decoded += char(16*a+b);            
      src+=3;        
    } 
    else if (*src == '+') {
      decoded += ' ';           
      *src++;       
    }  
    else {
      decoded += *src;           
      *src++;        
    }    
  }
  decoded += '\0';        
  return decoded;
}


int mdns1(int webtype){
  
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return(20);
  }
  Serial.println("");
  Serial.println("New client");

  // Wait for data from client to become available
  while(client.connected() && !client.available()){
    delay(1);
   }
  
  // Read the first line of HTTP request
  String req = client.readStringUntil('\r');
  
  // First line of HTTP request looks like "GET /path HTTP/1.1"
  // Retrieve the "/path" part by finding the spaces
  int addr_start = req.indexOf(' ');
  int addr_end = req.indexOf(' ', addr_start + 1);
  if (addr_start == -1 || addr_end == -1) {
    Serial.print("Invalid request: ");
    Serial.println(req);
    return(20);
   }
  req = req.substring(addr_start + 1, addr_end);
  Serial.print("Request: ");
  Serial.println(req);
  client.flush(); 
  String s;
  if ( webtype == 1 ) {
      if (req == "/")
      {
        IPAddress ip = WiFi.softAPIP();
        String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>";
        s += "<font face='arial,helvetica' size='7'>";
        s += "<b><label>Hello from ESP8266 at ";
        s += ipStr;
        s += "</label></b><p>";
        s += st;
        s += "<form method='get' action='a'><label>SSID: </label><input name='ssid' style='width:200px; height:60px; font-size:50px;'>   ";
        s += "<label>Password: </label><input name='pass' style='width:200px; height:60px; font-size:50px;'>";
        s += "<p><input type='submit' style='font-size:60px'></form>";
        s += "</html>\r\n\r\n";
        Serial.println("Sending 200");
      }
      else if ( req.startsWith("/a?ssid=") ) {

        newSSID = true;
        String qsid; //WiFi SSID 
        qsid = urldecode(req.substring(8,req.indexOf('&')).c_str()); //correct coding for spaces as "+"
        Serial.println(qsid);
        Serial.println("");
        rsid = qsid;
        
        String qpass; //Wifi Password
        qpass = urldecode(req.substring(req.lastIndexOf('=')+1).c_str());//correct for coding spaces as "+"
        Serial.println(qpass);
        Serial.println("");
        rpass = qpass;
 
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 ";
        s += "<p> New SSID and Password accepted</html>\r\n\r\n"; 
      }
      else
      {
        s = "HTTP/1.1 404 Not Found\r\n\r\n";
        Serial.println("Sending 404");
      }
  } 
  else
  {
      if (req == "/")
      {
        s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266";
        s += "<p>";
        s += "</html>\r\n\r\n";
        Serial.println("Sending 200");
      }
      else
      {
        s = "HTTP/1.1 404 Not Found\r\n\r\n";
        Serial.println("Sending 404");
      }       
  }
  client.print(s);
  Serial.println("Done with client");
  return(20);
}

//Use virtual pin 30 to overwrite wifi credentials in flash
BLYNK_WRITE(30){
  if (param.asInt()){
    Serial.println("Erasing SSID and restarting.");
    delay(100);
    WiFi.begin("FakeSSID","FakePW"); //replace current WiFi credentials with fake ones
    setupAP();   
   }
}


void loop() {
  // put your main code here, to run repeatedly:

  Blynk.run();
  yield();
}
1 Like

hi guys,

just wanted to let you know that i ve updated the WiFiManager library quite a lot and it sorts the mdns error now, together with stuff like captive portal to make everything faster to configure, also new webserver code that seems more reliable. should be “drag and drop” with blynk

@chrome1000 really good job. i know how flaky the esp’s can be from the weirdest reasons.

2 Likes

Love the improvements @tzapulica- especially the captive portal .

Just curious… why use the EEPROM, when the ESP already stores SSID and P/W to flash? Also, may I suggest eliminating the reset? WiFiManager’s software reset still fails on my ESP-01. It might be a quirk of that particular board, but it’s the reason I avoided using software resets. Those two minor details aside, this is really awesome work!

hi,

there s actually a big discussion about this stuff here https://github.com/esp8266/Arduino/issues/849

i used EEPROM and was planning on moving forward to FS in order to provide other fields, like blynk auth token for instance to be added.

It seems it will be a choice between simplicity and flexibility, and I might go down the route of simplicity for this and drop FS and EEPROM.

I will look into dropping the reset, maybe as a flag. I think I added it mostly because there are some issues between STA and AP modes and switching between them would leave the ESP’s in some noncommunicating state. Maybe that’s fixed.

Yeah, I found some quirkiness with mode switching, too. Thankfully, the way I resolved it doesn’t leave the ESP in a noncommunicating state, but That’s probably more a case of beginner’s luck than brilliant programming skills. :smile:

@chrome1000 Hi Eric,
I ve just commited a new test build of WiFiManager that does not need EEPROM or reset after configuring anymore.

give it a spin if you want and let me know
cheers

1 Like

For external config of the esp I also borrowed from Tzapu and chriscook8.
I didn’t want to have to re prog the esp if I changed from local to cloud etc or changed local ports etc.
I added auth code and port entries, using a port add of 1.1.1.1 to indicate cloud use.
The auth code can be copied and pasted into the field for easy use.
I also added a delay at start up, so if port 2 was pulled down just after start up, all data would be cleared and the ap started again.
That way I have the freedom of attaching the esp to where I want to work on it.
I have had no problems at all, and it is very convenient.
As to the use of ‘eeprom’ with the esp, I don’t understand what the issues are. Documentation appears to indicate that the same area in flash memory is used as in the esp config?
Sure, maybe a reset is required after the new config is made, but that is not really a problem?

Several months of use hasn’t given rise to any problems yet.

1 Like

See my code below: Reading and writing EEPROM en my simple webpage

void ReadEEPROM() {
  // read esid from EEPROM

  EEPROM.begin(512);
  
  esid = "";
  for (int i = 0; i < 20; ++i)
  {
    if(char(EEPROM.read(Start_address_SSID + i)) != '\0') {
    esid += char(EEPROM.read(Start_address_SSID + i));
    Serial.print("Read SSID: ");
    Serial.println(char(EEPROM.read(Start_address_SSID + i)));
    }
    }
  
   Serial.print("ESID_R: ");
   Serial.println(esid);
   ssid = "";
ssid = esid;
Serial.print("SSID_R: ");
Serial.println(ssid);

  // read epwd from EEPROM
  epwd = "";
  for (int i = 0; i < 30; ++i)
  {
    if(char(EEPROM.read(Start_address_PWD + i)) != '\0') {
    epwd += char(EEPROM.read(Start_address_PWD + i));
    Serial.print("Read SPWD: ");
    Serial.println(char(EEPROM.read(Start_address_PWD + i)));
  }
  }
   Serial.print("PWD: ");
   Serial.println(epwd);

  // read sauth from EEPROM
  eauth = "";
  for (int i = 0; i < sizeof(auth); ++i)
  {
    if(char(EEPROM.read(Start_address_AUTH + i)) != '\0') {
    eauth += char(EEPROM.read(Start_address_AUTH + i));
    Serial.print("Read SAUTH: ");
    Serial.println(char(EEPROM.read(Start_address_AUTH + i)));
  }
  } 
   Serial.print("AUTH: ");
  Serial.println(eauth);
 // Serial.println(auth);
   sauth = eauth;
  eauth.toCharArray(auth, eauth.length()+1);  // convert this string to char array
Serial.print("AUTH: (array)  ");
  Serial.println(auth);
}

void WriteEEPROM() {
 EEPROM.begin(512);
    
      // EEPROM clear
        Serial.println("clearing eeprom");
      for (int i = 0; i < 100; ++i) {
        EEPROM.write(i, 0);
      }
      //write ssid in EEPROM
      for (int i = 0; i < nssid.length(); ++i)  
      {
        EEPROM.write(Start_address_SSID + i, nssid[i]);
        Serial.print("Wrote SSID: ");
        Serial.println(nssid[i]);
      }
      Serial.println(nssid);
      //write passwd in EEPROM
      for (int i = 0; i < npwd.length(); ++i)
      {
        EEPROM.write(Start_address_PWD + i, npwd[i]);
        Serial.print("Wrote PWD: ");
        Serial.println(npwd[i]);
      }
        
      //write auth in EEPROM
      for (int i = 0; i < nauth.length(); ++i)
      {
        EEPROM.write(Start_address_AUTH + i, nauth[i]);
        Serial.print("Wrote AUTH ");
        Serial.println(nauth[i]);
      }
      EEPROM.commit();
}


void Runupdate () {    // de afhandeling van de update van de toegangsgegevens

  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  String req = client.readStringUntil('\r');
  Serial.println(req);
  int start = req.indexOf("favicon");  // to avoid a situation where only favicon is returned
  Serial.println(start);
  if (start == -1) {
  int start = req.indexOf("T1");
  int end = req.indexOf("T2");
  String result = req.substring(start + 3, end - 1);
  if (result != 0) nssid = result;
  start = req.indexOf("T2");
  end = req.indexOf("T3");
  result = req.substring(start + 3, end - 1);
  if (result != 0) npwd = result;
  start = req.indexOf("T3");
  end = req.indexOf("EEPROMMEN");
  result = req.substring(start + 3, end - 1);
  if (result != 0) nauth = result;
  start = req.indexOf("EEPROMMEN=ja");  // expliciete test op ja!!
  
  if (start>0) { Serial.println("write update in eeprom");WriteEEPROM();ReadEEPROM();}
  }
  client.flush();


  // Prepare the response. Start with the common header:
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Content-Type: text/html\r\n\r\n";
  s += "<!DOCTYPE HTML>\r\n<html>\r\n";
  s += "<head> <style> table, th, td { border: 1px solid black; padding: 5px;} table { border-spacing: 5px; }";
  s += "table#t01 {background-color: #f1f1c1;}  </style>";
  s += "<meta http-equiv content='2'>  </head>";
  s += "<body>";
  s += "<h1>";
  s += "<table id='t01'><caption> Overzicht van toegangsgegevens</caption>  ";
  s += "<tr><td> Waarde   </td><td> EEPROM </td> <td>NIEUW</td></tr>";
  s += "<tr><td> SSID     </td> <td>" + esid + "</td><td>" + nssid + "</td></tr>";
  s += "<tr><td> Password </td> <td>" + epwd + "</td><td>" + npwd + "</td></tr>";
  s += "<tr><td> AUTH     </td> <td>" + sauth + "</td><td>" + nauth + "</td></tr>";
  s += "</tabel>";
  s += "</h1>";
  s += "Voer de nieuwe gegevens hier in<br><br>";
  s += "<form>SSID_NIEUW_____: <input type='text' name='T1' value=''><br>" ;
  s += "PASSW_NIEUW__: <input type='text' name='T2' value=''><br>";
  s += "AUTH_NIEUW____: <input type='text' name='T3' value=''><br><br> ";
  s += "<h3> De gegevens worden in het EEPROM geplaatst zodra in onderstaand menu JA gekozen is </h2>";
  s += "<select name='EEPROMMEN'> <option value='nee' selected>NEE</option>  <option value='ja'>JA</option>  </select> <br><br>";
  s += "BEVESTIG : <input type='submit' value='Submit'> </form><br><br>";
  s += "</body>";
  s += "</html>\n";

  // Send the response to the client
  client.print(s);
  Serial.println("Client disonnected");

  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed
}

Please edit your post. Code should be formatted.

This is how to do that:

 ``` <--- insert this 
 Paste your code here
 ``` <--- insert this 

This makes your code beautiful with highlighted syntax, like this:

//comment goes here 
void helloWorld() { 
   String message =  "hello" + "world"; 
}

You can also select the code and press </> button in the top menu: