Wifimgr lib with blynk_token field

Hi,

Not sure if someone has already modified the wifimanager library for ESP found here to incorporate the blynk_token field in the html form. If not, here’s a version to add the blink token along with the ssid/password credentials:

#original version: https://github.com/tayfunulu/WiFiManager

import network
import socket
import ure
import time

ap_ssid = "WifiManager"
ap_password = "12345678"
ap_authmode = 3  # WPA2
blynk_token = "token"

NETWORK_PROFILES = 'wifi.dat'

wlan_ap = network.WLAN(network.AP_IF)
wlan_sta = network.WLAN(network.STA_IF)

server_socket = None


def get_connection():
    """return a working WLAN(STA_IF) instance or None"""

    # First check if there already is any connection:
    if wlan_sta.isconnected():
        return wlan_sta

    connected = False
    try:
        # ESP connecting to WiFi takes time, wait a bit and try again:
        time.sleep(3)
        if wlan_sta.isconnected():
            return wlan_sta

        # Read known network profiles from file
        profiles = read_profiles()

        # Search WiFis in range
        wlan_sta.active(True)
        networks = wlan_sta.scan()

        AUTHMODE = {0: "open", 1: "WEP", 2: "WPA-PSK", 3: "WPA2-PSK", 4: "WPA/WPA2-PSK"}
        for ssid, bssid, channel, rssi, authmode, hidden in sorted(networks, key=lambda x: x[3], reverse=True):
            ssid = ssid.decode('utf-8')
            encrypted = authmode > 0
            print("ssid: %s chan: %d rssi: %d authmode: %s" % (ssid, channel, rssi, AUTHMODE.get(authmode, '?')))
            if encrypted:
                if ssid in profiles:
                    password = profiles[ssid]
                    connected = do_connect(ssid, password)
                else:
                    print("skipping unknown encrypted network")
            else:  # open
                connected = do_connect(ssid, None)
            if connected:
                break

    except OSError as e:
        print("exception", str(e))

    # start web server for connection manager:
    if not connected:
        connected = start()

    return wlan_sta if connected else None

def read_profiles():
    global blynk_token
    with open(NETWORK_PROFILES) as f:
        lines = f.readlines()
    profiles = {}
    for line in lines:
        ssid, password, blynk_token = line.strip("\n").split(";")
        profiles[ssid] = password
    return profiles

def write_profiles(profiles):
    lines = []
    for ssid, _ in profiles.items():
        password = _[0]
        token = _[1]
        lines.append("%s;%s;%s\n" % (ssid, password, token))
    with open(NETWORK_PROFILES, "w") as f:
        f.write(''.join(lines))
        
def get_token():
    global blynk_token
    with open(NETWORK_PROFILES) as f:
        lines = f.readlines()
    profiles = {}
    for line in lines:
        ssid, password, blynk_token = line.strip("\n").split(";")
        #profiles[ssid] = (password, blynk_token)
    return blynk_token

def do_connect(ssid, password):
    wlan_sta.active(True)
    if wlan_sta.isconnected():
        return None
    print('Trying to connect to %s...' % ssid)
    wlan_sta.connect(ssid, password)
    for retry in range(100):
        connected = wlan_sta.isconnected()
        if connected:
            break
        time.sleep(0.1)
        print('.', end='')
    if connected:
        print('\nConnected. Network config: ', wlan_sta.ifconfig())
    else:
        print('\nFailed. Not Connected to: ' + ssid)
    return connected

def send_header(client, status_code=200, content_length=None ):
    client.sendall("HTTP/1.0 {} OK\r\n".format(status_code))
    client.sendall("Content-Type: text/html\r\n")
    if content_length is not None:
      client.sendall("Content-Length: {}\r\n".format(content_length))
    client.sendall("\r\n")


def send_response(client, payload, status_code=200):
    content_length = len(payload)
    send_header(client, status_code, content_length)
    if content_length > 0:
        client.sendall(payload)
    client.close()


def handle_root(client):
    wlan_sta.active(True)
    ssids = sorted(ssid.decode('utf-8') for ssid, *_ in wlan_sta.scan())
    send_header(client)
    client.sendall("""\
        <html>
            <h1 style="color: #5e9ca0; text-align: center;">
                <span style="color: #ff0000;">
                    Wi-Fi Client Setup
                </span>
            </h1>
            <form action="configure" method="post">
                <table style="margin-left: auto; margin-right: auto;">
                    <tbody>
    """)
    while len(ssids):
        ssid = ssids.pop(0)
        client.sendall("""\
                        <tr>
                            <td colspan="2">
                                <input type="radio" name="ssid" value="{0}" />{0}
                            </td>
                        </tr>
        """.format(ssid))
    client.sendall("""\
                        <tr>
                            <td>Password:</td>
                            <td><input name="password" type="password" /></td>
                        </tr>
                        <tr>
                            <td>Blynk_Token:</td>
                            <td><input name="blynk_token" type="text" /></td>
                        </tr>
                    </tbody>
                </table>
                <p style="text-align: center;">
                    <input type="submit" value="Submit" />
                </p>
            </form>
            <p>&nbsp;</p>
            <hr />
            <h5>
                <span style="color: #ff0000;">
                    Your ssid and password information will be saved into the
                    "%(filename)s" file in your ESP module for future usage.
                    Be careful about security!
                </span>
            </h5>
            <hr />
            <h2 style="color: #2e6c80;">
                Some useful infos:
            </h2>
            <ul>
                <li>
                    Original code from <a href="https://github.com/cpopp/MicroPythonSamples"
                        target="_blank" rel="noopener">cpopp/MicroPythonSamples</a>.
                </li>
                <li>
                    This code available at <a href="https://github.com/tayfunulu/WiFiManager"
                        target="_blank" rel="noopener">tayfunulu/WiFiManager</a>.
                </li>
            </ul>
        </html>
    """ % dict(filename=NETWORK_PROFILES))
    client.close()


def handle_configure(client, request):
    match = ure.search("ssid=([^&]*)&password=(.*)&blynk_token=(.*)", request)
    if match is None:
        send_response(client, "Parameters not found", status_code=400)
        return False
    # version 1.9 compatibility
    global blynk_token
    try:
        ssid = match.group(1).decode("utf-8").replace("%3F", "?").replace("%21", "!")
        print(ssid)
        password = match.group(2).decode("utf-8").replace("%3F", "?").replace("%21", "!")
        print(password)
        blynk_token = match.group(3).decode("utf-8").replace("%3F", "?").replace("%21", "!")
        print(blynk_token)
    except Exception:
        ssid = match.group(1).replace("%3F", "?").replace("%21", "!")
        password = match.group(2).replace("%3F", "?").replace("%21", "!")
        blynk_token = match.group(3).replace("%3F", "?").replace("%21", "!")
    if len(ssid) == 0:
        send_response(client, "SSID must be provided", status_code=400)
        return False

    if do_connect(ssid, password):
        response = """\
            <html>
                <center>
                    <br><br>
                    <h1 style="color: #5e9ca0; text-align: center;">
                        <span style="color: #ff0000;">
                            ESP successfully connected to WiFi network %(ssid)s.
                        </span>
                    </h1>
                    <br><br>
                </center>
            </html>
        """ % dict(ssid=ssid)
        send_response(client, response)
        try:
            profiles = read_profiles()
        except OSError:
            profiles = {}
        profiles[ssid] = (password, blynk_token)
        write_profiles(profiles)

        time.sleep(5)

        return True
    else:
        response = """\
            <html>
                <center>
                    <h1 style="color: #5e9ca0; text-align: center;">
                        <span style="color: #ff0000;">
                            ESP could not connect to WiFi network %(ssid)s.
                        </span>
                    </h1>
                    <br><br>
                    <form>
                        <input type="button" value="Go back!" onclick="history.back()"></input>
                    </form>
                </center>
            </html>
        """ % dict(ssid=ssid)
        send_response(client, response)
        return False


def handle_not_found(client, url):
    send_response(client, "Path not found: {}".format(url), status_code=404)


def stop():
    global server_socket

    if server_socket:
        server_socket.close()
        server_socket = None


def start(port=80):
    global server_socket

    addr = socket.getaddrinfo('0.0.0.0', port)[0][-1]

    stop()

    wlan_sta.active(True)
    wlan_ap.active(True)

    wlan_ap.config(essid=ap_ssid, password=ap_password, authmode=ap_authmode)

    server_socket = socket.socket()
    server_socket.bind(addr)
    server_socket.listen(1)

    print('Connect to WiFi ssid ' + ap_ssid + ', default password: ' + ap_password)
    print('and access the ESP via your favorite web browser at 192.168.4.1.')
    print('Listening on:', addr)

    while True:
        if wlan_sta.isconnected():
            return True

        client, addr = server_socket.accept()
        print('client connected from', addr)
        print()
        try:
            client.settimeout(5.0)

            request = b""
            try:
                while "\r\n\r\n" not in request:
                    request += client.recv(512)
            except OSError:
                pass

            print("Request is: {}".format(request))
            if "HTTP" not in request:  # skip invalid requests
                continue

            # version 1.9 compatibility
            try:
                url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/")
            except Exception:
                url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/")
            print("URL is {}".format(url))

            if url == "":
                handle_root(client)
            elif url == "configure":
                handle_configure(client, request)
            else:
                handle_not_found(client, url)

        finally:
            client.close()

main.py code:

import wifimgr_blynk as wm

wlan = wm.get_connection()

if wlan is None:
    print("Could not initialize the network connection.")
    while True:
        pass  # you shall not pass :D

blynk_token = wm.get_token()
print(blynk_token)

# Main Code goes here, wlan is a working network.WLAN(STA_IF) instance.
print("ESP OK")

Results:

[0;32mI (21185) network: CONNECTEDe[0m
… [0;32mI (22425) event: sta ip: 192.168.0.54, mask: 255.255.255.0, gw: 192.168.0.1 [0m
[0;32mI (22425) network: GOT_IPe[0m
.
Connected. Network config: (‘192.168.0.54’, ‘255.255.255.0’, ‘192.168.0.1’, ‘192.168.0.1’)
c604d040123456789faa3ed291cf6ff4
ESP OK
MicroPython v1.10-98-g4daee3170 on 2019-02-14; ESP32 module with ESP32
Type “help()” for more information.

I used the above codes for my ESP32_OLED and ESP8266-12 and worked fine.
Any improvements to the code are always welcome.

1 Like

This code shows how to use the above wifimgr_blynk lib on an ESP32_OLED.

import BlynkLib
from BlynkTimer import BlynkTimer
import machine, ssd1306, gc
from machine import Pin, I2C
import wifimgr_blynk as wm
import urequests
#from time import sleep
import socket, errno
import esp
esp.osdebug(None)

wlan = wm.get_connection()

if wlan is None:
    print("Could not initialize the network connection.")
    while True:
        pass  # you shall not pass :D

# Create BlynkTimer Instance
timer = BlynkTimer()

#oled connections
i2c = I2C(scl=machine.Pin(4), sda=machine.Pin(5))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)

blynk_token = wm.get_token()
ext_ip = ''
my_ip = wlan.ifconfig()[0]

def display_txt():
    gc.collect() #clear memory
    oled.fill(0)
    oled.text('MicroPython on', 0, 0)
    oled.text('an ESP32 with an', 0, 10)
    oled.text('attached SSD1306', 0, 20)
    oled.text(my_ip, 0, 30)
    oled.show()
   
def display_ips():
    gc.collect() #clear memory
    oled.fill(0)
    #ip = 'ip: {}'.format(ip_txt)
    oled.text('my ip:', 0, 0)
    oled.text(my_ip, 0, 10)
    oled.text('my ext ip:', 0, 20)
    oled.text(ext_ip, 0, 30)
    oled.show()
    
def get_extip():
    global ext_ip
    r = urequests.get('http://mydomain.net/myip.php')
    #print(int(r.status_code)) #should be 200
    if(int(r.status_code) == 200):
        ext_ip = r.text
    r.close()
 
# Initialize Blynk
blynk = BlynkLib.Blynk(blynk_token)

p0 = Pin(0, Pin.OUT)    # create output pin on GPIO0
p2 = Pin(2, Pin.OUT)
p2.value(0)

# Register Virtual Pins
@blynk.VIRTUAL_WRITE(1)
def my_write_handler(value):
    if(value[0] == '1'):
        get_extip()
        display_txt()
        
@blynk.VIRTUAL_WRITE(3)
def my_write_handler(value): #turn on led
    if(value[0] == '1'):
        p0.on()              # set pin to "on" (high) level
    else:
        p0.off()

@blynk.VIRTUAL_READ(2)
def my_read_handler():
    # this widget will show some time in seconds..
    blynk.virtual_write(2, ext_ip)
    

# Add Timers
#timer.set_timeout(2, hello_world)
#timer.set_interval(3, print_me)
    
try:
    #print(my_ip)
    while True:
        blynk.run()
        timer.run()
        machine.idle()
except socker.error as e:
    if e.errno != error.EPIPE :
       raise
    blynk.connect()

results:

MPY: soft reboot
___ __ __
/ _ )/ /_ _____ / /__
/ _ / / // / _ / '/
/
//_, /////_
/
__/ for Python v0.2.0 (esp32)

1 Like