Webserver for ssid,pass,server ip + auth code. ESP standalone

I wanted to be able to input the above data without having to re prog the chip, and choose between local or cloud servers, so I have cobbled together a working prog utilising the clever work by others and added what I needed.

I used a pull down on pin2 (just after reset, but within a second) to erase the flash, and put the esp into ap mode. With a pull down operated led on pin two, and a 1K switch to ground, allows the led to blink on a correct reset into flash erase mode.

Then into the Esp ap at 192.168.4.1 to enter the required details. Auth can be copied and pasted from a project (local and server auth for the same project will be different).
A server ip of 1.1.1.1 will force a Cloud connection else connection is local.
Reset after changing … the pull down led connected to pin 2 will indicate connection to a server.

Might be of use for someone?

I’m not sure what the correct procedure is to include code here, so I will await instructions before doing so, should it be desired.

1 Like

Sounds interesting! thanks for sharing.

You can paste code as a regular text. just follow these rules:

Wrap your code by pressing this magic button (Backtick`) 3 times (before the code and after it):

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:


//* A simplified version of work begun by Tzapu and chriscook8
//*for saving local WiFi SSID and Passwords to the ESP8266.
//*This is further adaption of this to include server and auth code input.


// ok... working from start reading flash.
// need a pin pull down at startup to set into ap mode for new variables input.
// pull pin2 low just after a reset (not at same time but within one second to clear ssid etc and start ap)
// entering server ip on ap webpage as 1.1.1.1 will connect to Blynk cloud.
// ap address is standard 192.168.4.1
// any other will be a local server connection.
// copy and paste auth code from Blynk project.
// reset after done to re-connect
// 

// working now that data is pulled from flash rather than relying on global variables.
// following just for info.
//IPAddress server_ip (10, 0, 0, 10);

// ///Mac address should be different for each device in your LAN
//byte arduino_mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
//IPAddress arduino_ip ( 10,   0,   0,  20);
//IPAddress dns_ip     (  8,   8,   8,   8);
//IPAddress gateway_ip ( 10,   0,   0,   1);
//IPAddress subnet_mask(255, 255, 255,   0);

//void setup()
//{
//  Serial.begin(9600);
//  Blynk.begin(auth, server_ip, 8442, arduino_ip, dns_ip, gateway_ip, subnet_mask, arduino_mac);
  // Or like this:
  //Blynk.begin(auth, "cloud.blynk.cc", 8442, arduino_ip, dns_ip, gateway_ip, subnet_mask, arduino_mac);

// problem with parsing server ip overcome using the above method


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

MDNSResponder mdns;
WiFiServer server(80);
//char auth[] = "47e420915db74a2a90439a60b71a7cf8"; // local server token 
//char auth[] = "88b810d70d8444b080666ee1928bc955"; // Blynk token "YourAuthToken"
const char* APssid = "ESP8266"; // Name of access point
const char* servAuth; 
const char* servi ;
const char* mypass;
const char* mysid;
//const char* mysid1;
String st;
String rsid;
String rpass;
String rserv;
String rkey;
String epsid;
 String eppass;
 String epserv;
 String epauth;
boolean newSSID = false;

String key;
int checkV0= 0;
WidgetLED led1(0);
WidgetLCD lcd(6);
int pos = 0;




IPAddress server_ip (0, 0, 0, 0);

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println("Startup");
   EEPROM.begin(512);
  
  delay(1000);
  if (digitalRead(2)==0){eepromClearSid();}  
 
  eepromRead();

  int count=0;

  
  WiFi.begin(mysid,mypass);     // gets from eeprom read.
  
  Serial.println(" trying wifi begin");
  
  //*****************************************************************
  
   pinMode(5,OUTPUT);
  pinMode(2,OUTPUT);
  digitalWrite(2,HIGH);
  if ( testWifi()) { 
      
   //****************************************
    // string epserv in the form of xxx#xxx$xxx%xxx*
          //need to extract each number string, convert to value, and put into server_ip
          String ip_one;
          String ip_two;
          String ip_three;
          String ip_four;
           
           ip_one=epserv.substring(0,epserv.indexOf('#'));
           ip_two=epserv.substring(epserv.indexOf('#')+1,epserv.indexOf('$'));
           ip_three=epserv.substring(epserv.indexOf('$')+1,epserv.indexOf('%'));
           ip_four=epserv.substring(epserv.indexOf('%')+1,epserv.indexOf('*'));
          
          Serial.println(ip_one);
          Serial.println(ip_two);
          Serial.println(ip_three);
          Serial.println(ip_four);
          
          server_ip[0]= ip_one.toInt();
          server_ip[1]= ip_two.toInt();
          server_ip[2]= ip_three.toInt();
          server_ip[3]= ip_four.toInt();
           
                           
         
           Serial.println ("Blynk begin?");
          
          
           if (server_ip[0]==1 && server_ip[1]==1 && server_ip[2]==1 && server_ip[3]==1) 
           {
           Serial.print("going Cloud");
           Blynk.config(servAuth);
           bool result = Blynk.connected();
          Serial.print(result);
          if (!result){digitalWrite(2,LOW);}
               }
           else
          {
           Serial.println("going local");
           Serial.println(server_ip);
           Blynk.begin(servAuth,mysid,mypass,server_ip); 
          bool result = Blynk.connected();
          Serial.print(result);
          if (!result){digitalWrite(2,LOW);}
          } 
           
           
          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());
    
   digitalWrite(2,LOW);
   delay(1000);
   digitalWrite(2,HIGH);
    
    
    
    // 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;

          Serial.println ("reading eeprom");
          eepromRead();
          
          Serial.println("Connecting to local Wifi"); //Close the AP and connect with new SSID and P/W
          WiFi.softAPdisconnect(true);
          delay(500);
                 
          Serial.println(epsid);
          Serial.println(eppass);
          Serial.println(epauth); 
          Serial.println(epserv);
          mysid = epsid.c_str();
          mypass =eppass.c_str();
          servi = epserv.c_str();
          servAuth = epauth.c_str();
          
          WiFi.begin(mysid,mypass);
       
          delay(3000);
           
          // string epserv in the form of xxx#xxx$xxx%xxx*
          //need to extract each number string, convert to value, and put into server_ip
          String ip_one;
          String ip_two;
          String ip_three;
          String ip_four;
           
           ip_one=epserv.substring(0,epserv.indexOf('#'));
           ip_two=epserv.substring(epserv.indexOf('#')+1,epserv.indexOf('$'));
           ip_three=epserv.substring(epserv.indexOf('$')+1,epserv.indexOf('%'));
           ip_four=epserv.substring(epserv.indexOf('%')+1,epserv.indexOf('*'));
          
          Serial.println(ip_one);
          Serial.println(ip_two);
          Serial.println(ip_three);
          Serial.println(ip_four);
          
          server_ip[0]= ip_one.toInt();
          server_ip[1]= ip_two.toInt();
          server_ip[2]= ip_three.toInt();
          server_ip[3]= ip_four.toInt();
           
          if ( testWifi()) {
                     
         
           Serial.println ("Blynk begin?");
          
          
           if (server_ip[0]==1 && server_ip[1]==1 && server_ip[2]==1 && server_ip[3]==1) 
           {
           Serial.print("going Cloud");
           Blynk.config(servAuth);}
           bool result = Blynk.connected();
          Serial.print(result);
          if (!result){digitalWrite(2,LOW);}
           else
          {
           Serial.println("going local");
           Serial.println(server_ip);
           Blynk.begin(servAuth,mysid,mypass,server_ip); 
           bool result = Blynk.connected();
          Serial.print(result);
          if (!result){digitalWrite(2,LOW);}
           }
            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><label>Server: </label><input name='serv+' style='width:200px; height:60px; font-size:50px;'>";
        s += "<p><label>Token: </label><input name='key' style='width:300px;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.indexOf('*')+2,req.lastIndexOf('%')-5).c_str());//correct for coding spaces as "+"
        Serial.println(qpass);
        Serial.println("");
        rpass = qpass;
  
      
        String qserv; //Wifi server port
        
        qserv = urldecode(req.substring(req.lastIndexOf('%')+4,req.lastIndexOf('&')).c_str());//correct for coding spaces as "+"
        Serial.println(qserv);
        Serial.println("");
        rserv = qserv;

         String qkey; //Wifi auth 
        qkey = urldecode(req.substring(req.lastIndexOf('=')+1).c_str());//correct for coding spaces as "+"
        Serial.println(qkey);
        Serial.println("");
        rkey = qkey;
       
       // conversion allocation of string to const char
       // const char* conv_my_str = my_str.c_str();
        
        mysid=qsid.c_str();
        mypass=qpass.c_str();
        servi=qserv.c_str();
        servAuth = qkey.c_str();
        Serial.print("at eeprom write stage");
        Serial.println ( mysid);
        Serial.println ( mypass);
        Serial.println ( servi);
        Serial.println ( servAuth);



        String allintoEP;
         allintoEP += qsid;
         allintoEP += qpass;
         allintoEP += qserv;
         allintoEP += qkey;
               
         char epssid[allintoEP.length()];
          allintoEP.toCharArray(epssid, allintoEP.length());

         int epcount=0;
         while (epcount < allintoEP.length()){
        if (allintoEP[epcount] == 0) {allintoEP[epcount]=42;}  // puts a "*" between variables
        
         EEPROM.write(epcount,allintoEP[epcount]); 
          epcount ++;
          }
         EEPROM.commit();
     
      
      // const char* conv_my_str = my_str.c_str();
      //  servi= rserv.c_str();
        
        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 eepromClearSid(){
  byte value=0;
  int count=0;  
  int len = 61;
  int addr;
  while (addr < len){
  value= 65;
  if (count ==15 || count ==30 || count == 45 || count == 60){ value=42;}
  EEPROM.write(addr,value);
  addr++;
  count++;
  }
  EEPROM.commit();
 
 }

void eepromRead() {


 epsid="";
 eppass="";
 epserv="";
 epauth="";
 String llit;
 int len = 200;
 int addr=0;
 int count=0;
 byte value; 
 byte marker=35; // "#"
 while (count < len) {
 value= EEPROM.read(addr);
 if (value != 42){ 
 epsid += char(value);} 
 count++;
 addr++;
 if (value == 42){ break; }
 }
Serial.print("epsid =");
 Serial.println(epsid);
while (count < len) {
 value= EEPROM.read(addr);
 if (value != 42){ 
 eppass += char (value);}
 count++;
 addr++;
 if (value == 42){ break; }
 }
 Serial.print("eppass =");
 Serial.println(eppass);
 
 //epserv = char(34);  //"
 while (count < len) {
 value= EEPROM.read(addr);
 if (value != 42){                  //  *
 if (value == 46){ value = marker;marker++;}     //46 = .  marker starts with # then $ then %
 epserv += char(value);}
  count++;
 addr++;
if (value == 42){ break; }
 }
  epserv += char(42);   //*
 
 
 Serial.print("epserv =");
 Serial.println(epserv);
 while (count < len) {
 value= EEPROM.read(addr);
 if (value != 42){ 
 epauth += char(value);}
  count++;
 addr++;
 if (value == 42){ break; }
 }
Serial.print("epauth =");
 Serial.println(epauth);


// mysid= fill.c_str(); assign string to const char
// const char* conv_my_str = my_str.c_str();
  mysid = epsid.c_str();
  mypass =eppass.c_str();
  servi = epserv.c_str();
  servAuth = epauth.c_str();
Serial.print("mysid=");
Serial.println(mysid);
Serial.print("mypass=");
Serial.println(mypass);
Serial.print("servi=");
Serial.println(servi);
Serial.print("servAuth=");
Serial.println(servAuth);
  
}

BLYNK_WRITE(V1) 
{
  lcd.clear();
  int pinData = param.asInt(); 
  Blynk.virtualWrite(5,millis()/1000);
  digitalWrite(5,pinData);
  Blynk.virtualWrite(V0,pinData);
  Serial.print("Virtualport = ");
  Serial.println(pinData);
  if (pinData == 0)
  { 
    led1.off();
    }
    else
  {
  led1.on() ;
  }
lcd.print(pos,1,"uptime");
 +pos;
 Blynk.notify("switch has been used");
} 
   
   BLYNK_WRITE(V5)
   {
   lcd.print(4,1,"uptime");
   
   
   }
void loop() {
  // put your main code here, to run repeatedly:

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

is this code working on ESP-01 or it’s only working on ESP-12 ?
as you mention that pin2 need to pulled down in start to activate the AP mode

Well, there is a pin 2 on the ESP-01, so there is no reason why it should not work.
Provided that pin is not pulled down within a second after start up, it can then be used as a pull down output port etc.

ESP SDK offers Smart Config im not sure why you are reinventing it.

@conkerkh I think we’d all prefer something simpler. Could you demonstrate how to implement Smart Config? I’m not finding a lot of useful information about it with the Google machine.

@conkerkh
Let me start by saying that this was no attempt at reinventing anything at all.
I have used the Windows espressif configuration for a year or so, making use of the esp as I want, but I am not a C person (assembly for last 20 years), so it doesn’t come that easy to me, particularly the endless searching for how to get around issues along with the two hundred ways of doing it more efficiently!

I know what I want for my projects, but just how to achieve it can be very frustrating at times.

Along comes Blynk and the Arduino environment … all becomes much cleaner, simpler and with so many experienced contributors, goals can be very much easier to achieve.

Blynk, for me, makes projects professional and enjoyable… sure, frustrating at times, but that is the nature of progression and learning.

I wanted the ability to input and store various data, and at the same time learn and understand more. I used what had been readily available, written by those I consider to be advanced and helpful contributors as a basis for what I actually wanted.
So, a quick paste, adaptions as needed, and very quickly all was combined along with Blynk facilities.
Since it worked quickly, I could go through it, understanding more along the way, and more importantly, move on with the project.

These processes often make that project you really would like to make far easier to actually achieve.

I would be very interested in seeing the integration of Smart Config within the Blynk environment along with extended facilities. Simple is good. Blynk is good :smile: always learning.

2 Likes

@Roffey

Thanks! I’ve been looking for a simple way to add AP config mode to my project and can confirm this works on my Nodemcu(essentially a esp-12).

And I fully agree, I would love to see the integration of smart config with the blynk app. Im currently working on a project for a friend who has zero coding skills but with the smart config I can give him the project and he can easily add his ssid, pass and token without my help.

Oh, that’s good to hear. Something positive! Just trying to get my Arduino ide back working after the latest upgrade won’t recognise esp boards even though they are loaded! Back to 1.6.5 after fixing what the upgrade took out.

Is this the latest of this code? I am going to play with it but want the latest :slight_smile:

I must admit I haven’t done any work on this since posting it. It just does what I want it to do and allows me to get on with any project that requires it. No doubt it could be made more efficient.
It was merely a slight adaption to work written by guys way out of my league.
There is another topic thread on here relating to the same facilities, but I am not aware of the advances that were made there.
Maybe worth a look … have fun!

Hi Roffey, Thanks for the code. I’ve implemented it to control my sliding gate. But recently I find out that the AP (SSID: ESP8266) is always on, I’ve tried to restart the esp but the AP is still on without the webserver.

Is there anyone have the same experience with this code?

Thanks

Yes, I did find this happening, but moving on to other projects I never did actually resolve it. Searching gives the possibility of using WiFi.softAPdisconnect(true); which apparently works in more recent arduino versions. There is an ap flag which gets raised once used, and would not get reset.
I cannot vouch for this function, but it would be worth looking at.

@Roffey Yes, I also read about using WiFi.softAPdisconnect(true);, I’ve tried to flash one of my project by adding that line. I put it in void setup(), after checking that the button was not pressed and before WiFi.begin. I put there because I read that WiFi.begin will trigger the softAP on. Please advice whether it is the right place to put that line. Thanks

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

delay(1000);
if (digitalRead(2)==0) {eepromClearSid();} 

else {WiFi.softAPdisconnect(true);} //added this line

eepromRead();
int count=0;
WiFi.begin(mysid,mypass);  
Serial.println(" trying wifi begin");
...

Hi, without trying it myself, I’m afraid I can’t give you a definitive answer on that, and I do not have a device set up to test it on.
It does seem a good place to start out. When there is a lack of absolute understanding as to what mechanisms are in play, sometimes trial and error is the only way.
Maybe there is more recent and relevant data within the 8266 community?