Easy Wi-Fi configuration page via SoftAP


#1

Hi there,

I would love to see an example of an Wi-Fi configuration page for the ESP32 WROOM. I’ve seen this request several times on this forum, but not with a working example. I did try something myself, but without success yet.

My SoftAP webpage:
config_page

But how to manage that the scanned networks will be selectable from the combo? If someone can point me in the right direction with some examples?

BR


#2

Via the webpage I’m able to get and post data:

Incoming connection from (192.168.123.100, 52296)
POST /index.html HTTP/1.1
Host: 192.168.123.142
Connection: keep-alive
Content-Length: 27
lenght of data to be received: 27
Cache-Control: max-age=0
Origin: http://192.168.123.142
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://192.168.123.142/index.html
Accept-Encoding: gzip, deflate
Accept-Language: nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7
payload data: ssid=mercedes&password=test
HTTP request received!
end
Waiting for connection...


Incoming connection from (192.168.123.100, 52297)
GET /favicon.ico HTTP/1.1
Host: 192.168.123.142
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
Accept: image/webp,image/apng,image/*,*/*;q=0.8
Referer: http://192.168.123.142/index.html
Accept-Encoding: gzip, deflate
Accept-Language: nl-NL,nl;q=0.9,en-US;q=0.8,en;q=0.7
HTTP request received!
end
Waiting for connection...

My python code:

################################################################################
# Wifi SoftAP Example
#
# Created: 2016-07-27 11:00:55.020628
#
################################################################################

import streams
import socket

from wireless import wifi
from espressif.esp32net import esp32wifi as wifi_driver

streams.serial()
wifi_driver.auto_init()
new_resource("index.html")

def wifi_scan():
    # a list of security strings
    wifi_sec=["Open","WEP","WPA","WPA2"]
    try:
        print("Scanning for 15 seconds...")
        # start scanning for 15000 milliseconds
        res = wifi.scan(15000)
        
        # if everything goes well, res is a sequence of tuples
        # each tuple contains:
        # -ssid: the name of the network
        # -sec: the security type of the network, from 0 to 3
        # -rssi: the strength of the signal, from 0 to 127
        # -bssid: the mac address of the access point
        for ssid,sec,rssi,bssid in res:
            print(ssid,"::",wifi_sec[sec],":: strength ",rssi*100/127)

    except Exception as e:
        print(e)

print("Creating Access Point...")
try:
    print("Scan for available networks...")
    wifi_scan()    

    #wifi.softap_init("ESP32",wifi.WIFI_WPA2,"computer")
    #print("Access Point started!")
    
    #use normal connection instead of SoftAP for Dev
    for i in range(0,5):
        try:
            wifi.link("ssid",wifi.WIFI_WPA2,"pass")
            break
        except Exception as e:
                print("Can't link",e)
    else:
        print("Impossible to link!")
        while True:
            sleep(1000)    
    
    
    # Let's print our ip, it will be needed soon
    info = wifi.link_info()
    print("My IP is:",info[0])
    
    # Now let's create a socket and listen for incoming connections on port 80
    sock = socket.socket()
    sock.bind(80)
    sock.listen()

    while True:
        try:
            # Type in your browser the board ip!
            print("Waiting for connection...")
            # here we wait for a connection
            clientsock,addr = sock.accept()
            print("Incoming connection from",addr)
            
            # yes! a connection is ready to use
            # first let's create a SocketStream
            # it's like a serial stream, but with a socket underneath.
            # This way we can read and print to the socket
            client = streams.SocketStream(clientsock)
            
            # let's read all the HTTP headers from the browser
            # stop when a blank line is received
            line = client.readline()
            print(line) # here you can see the request method
        
            if "GET /" in line:
                # handle get request
                while line!="\n" and line!="\r\n":
                    line = client.readline()
                    print(line) # here you can see remaining body of the request
            elif "POST /" in line:
                # handle post request
                data_len = 0
                data_recv = ""
                while line!="\n" and line!="\r\n":
                    line = client.readline()
                    print(line) # here you can see remaining body of the request
                    # check lenght of payload data to be received
                    if "Content-Length:" in line:
                        data_len = int(line[16:-1])
                        print("lenght of data to be received:", data_len)
                    sleep(10)
                while data_len>0:
                    tmp = clientsock.recv(min(32,data_len))
                    data_len-=len(tmp)
                    if tmp:
                        data_recv += tmp
                    else:
                        break
                print("payload data:", data_recv)
        
            print("HTTP request received!")

            # start sending webpage
            f = open("resource://index.html",'rb')
        
            html_response = "HTTP/1.1 200 OK\r\n"
            html_response += "Content-Type: text/html\r\n"
            html_response += "Content-Length: "+str(f.size)+"\r\n"
            html_response += "Connection: close\r\n\r\n"
    
            clientsock.send(html_response)
            
            offset = 0
            chunk = 32
            while True:
                data = f.read(chunk)
                if data:
                    clientsock.send(data)
                    offset += chunk
                    f.seek(offset)
                else:
                    print("end")
                    break

            clientsock.close()

            # close connection and go waiting for another one
            client.close()
        except Exception as e:
            print("ooops, something wrong:",e)

except Exception as e:
    print("ooops, something :(", e)
    while True:
        sleep(1000)

My webpage:

<html lang="en">

  <head>
	<title>Wi-Fi configuration page</title>

    <style>
        .login-page {
          width: 100%;
          padding: 8% 0 0;
          margin: auto;
        }
        .form {
          position: relative;
          z-index: 1;
          background: #FFFFFF;
          max-width: 360px;
          margin: 0 auto 100px;
          padding: 45px;
          text-align: center;
          box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
        }
        .form input {
          font-family: "Roboto", sans-serif;
          outline: 0;
          background: #f2f2f2;
          width: 100%;
          border: 0;
          margin: 0 0 15px;
          padding: 15px;
          box-sizing: border-box;
          font-size: 14px;
        }
        .form select {
          font-family: "Roboto", sans-serif;
          outline: 0;
          background: #f2f2f2;
          width: 100%;
          border: 0;
          margin: 0 0 15px;
          padding: 15px;
          box-sizing: border-box;
          font-size: 14px;
        }		
        .form button {
          font-family: "Roboto", sans-serif;
          text-transform: uppercase;
          outline: 0;
          background: #4CAF50;
          width: 100%;
          border: 0;
          padding: 15px;
          color: #FFFFFF;
          font-size: 14px;
          -webkit-transition: all 0.3 ease;
          transition: all 0.3 ease;
          cursor: pointer;
        }
        .form button:hover,.form button:active,.form button:focus {
          background: #43A047;
        }
        .form .message {
          margin: 15px 0 0;
          color: #b3b3b3;
          font-size: 12px;
        }
        .form .message a {
          color: #4CAF50;
          text-decoration: none;
        }
        .form .register-form {
          display: none;
        }
        .container {
          position: relative;
          z-index: 1;
          max-width: 300px;
          margin: 0 auto;
        }
        .container:before, .container:after {
          content: "";
          display: block;
          clear: both;
        }
        .container .info {
          margin: 50px auto;
          text-align: center;
        }
        .container .info h1 {
          margin: 0 0 15px;
          padding: 0;
          font-size: 36px;
          font-weight: 300;
          color: #1a1a1a;
        }
        .container .info span {
          color: #4d4d4d;
          font-size: 12px;
        }
        .container .info span a {
          color: #000000;
          text-decoration: none;
        }
        .container .info span .fa {
          color: #EF3B3A;
        }
        body {
          background: #76b852; /* fallback for old browsers */
          background: -webkit-linear-gradient(right, #76b852, #8DC26F);
          background: -moz-linear-gradient(right, #76b852, #8DC26F);
          background: -o-linear-gradient(right, #76b852, #8DC26F);
          background: linear-gradient(to left, #76b852, #8DC26F);
          font-family: "Roboto", sans-serif;
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;      
        }
    </style>
    
    <script>
        function myFunction() {
        document.getElementById("connect_button").style.color = "red";
    	//alert("I am an alert box!");
    	$('form').animate({height: "toggle", opacity: "toggle"}, "slow");
        }
    </script>
    
  </head>
  
  <body>


<div class="login-page">
  <div class="form">
    <div><h1>Enter Wi-Fi settings</h1></div>
    <form method="get" action="index.html" class="login-form">
		<select name="ssid" id="ssid">
		  <option value="" selected disabled hidden>SSID</option>
		  <option value="volvo">Network 1</option>
		  <option value="saab">Network 2</option>
		  <option value="mercedes">Network 3</option>
		  <option value="audi">Network 4</option>
		</select>

		<input type="password" name="password" id="password" placeholder="password"/>
		<button type="submit" formmethod="post" onclick="myFunction()" id="connect_button">Connect to WiFi!</button>
    </form>

  </div>
</div>

</body>
</html>

#3

Hello @Marcel,

the easiest way it definitely to use the Zerynth App which allows you to simply open a bi directional communication.

Otherwise you would need for example some Javascript attached to a refresh button asking to the board for the updated list of networks and capable of handling the response editing the box accordingly.

Let me know