diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/README.md b/README.md index 247ed11..011ddd5 100644 --- a/README.md +++ b/README.md @@ -5,22 +5,22 @@ Tested : 1.8 and 1.9.2 (updated) Description : WiFi manager for ESP8266 - ESP12 for micropython -Main Features:   +Main Features: - Web based connection manager - Save wifi password in passwd.dat (csv format) - Easy to apply -Usage : +Usage: -Upload main.py and networkconfig.py on esp -Write your code on main.py or import from main.py +Upload main.py and networkconfig.py to ESP. +Write your code into main.py or import it from main.py. -Logic: -1. step : Check passwd.dat file and try saved passwords -2. step : To publish web page to config new wifi -3. step : Saving password on passwd.dat file. -4. step : Run user code +Logic: +1. step: Check passwd.dat file and try saved networks/passwords. +2. step: Publish web page to configure new wifi. +3. step: Save network/password to passwd.dat file. +4. step: Run user code. ![alt text](https://github.com/tayfunulu/WiFiManager/blob/master/WiFi_Manager.png) diff --git a/main.py b/main.py index ff0711f..819aa15 100644 --- a/main.py +++ b/main.py @@ -1,77 +1,12 @@ -import network import networkconfig -import time -wlan_sta = network.WLAN(network.STA_IF) - -def do_connect(ntwrk_ssid, netwrk_pass): - sta_if = network.WLAN(network.STA_IF) - sta_if.active(True) - if not sta_if.isconnected(): - print('try to connect : '+ntwrk_ssid+' network...') - sta_if.connect(ntwrk_ssid, netwrk_pass) - a=0 - while not sta_if.isconnected() | (a > 99) : - time.sleep(0.1) - a+=1 - print('.', end='') - if sta_if.isconnected(): - print('\nConnected. Network config:', sta_if.ifconfig()) - return (True) - else : - print('\nProblem. Not Connected to :'+ntwrk_ssid) - return (False) - -def check_connection (): - global wlan_sta - # Firstly check is there any connection - if wlan_sta.isconnected(): - return (True) - try: - # connection of ESP to WiFi takes time - # wait 3 sec. and try again. - time.sleep(3) - if not wlan_sta.isconnected(): - # inside passwd file. there are list of WiFi network CSV file - f = open("passwd.dat") - data = f.readlines() - f.close() - # Search WiFi's in range - ssids_found = wlan_sta.scan() - - # matching... - for ipass in data: - ssid_list= ipass.strip("\n").split(";") - - for i in ssids_found: - if ssid_list[0] in i[0]: - print ("OK. WiFi is Founded") - if do_connect(ssid_list[0],ssid_list[1]): - return (True) - - if not wlan_sta.isconnected(): - if networkconfig.start(): - return (True) - else: - return (True) - - except OSError: - # Web server for connection manager - if networkconfig.start(): - return (True) - - return (False) - -if check_connection (): - - # Main Code is here - print ("ESP OK") - # to import your code; - # import sample_mqtt.py - -else: - print ("There is something wrong") +wlan = networkconfig.get_connection() +if wlan is None: + print("Could not initialize the network connection.") + while True: + pass # you shall not pass :D - +# Main Code goes here, wlan is a working network.WLAN(STA_IF) instance. +print("ESP OK") diff --git a/networkconfig.py b/networkconfig.py index 411d577..93740c7 100644 --- a/networkconfig.py +++ b/networkconfig.py @@ -3,201 +3,304 @@ import socket import ure import time +ap_ssid = "WifiManager" +ap_password = "tayfunulu" +ap_authmode = 3 # WPA2 + +NETWORK_PROFILES = 'wifi.dat' + wlan_ap = network.WLAN(network.AP_IF) wlan_sta = network.WLAN(network.STA_IF) -# setup for ssid -ssid_name= "WifiManager" -ssid_password = "tayfunulu" - server_socket = None -def do_connect(ntwrk_ssid, netwrk_pass): - sta_if = network.WLAN(network.STA_IF) - sta_if.active(True) - if not sta_if.isconnected(): - print('try to connect : '+ntwrk_ssid+' network...') - sta_if.active(True) - sta_if.connect(ntwrk_ssid, netwrk_pass) - a=0 - while not sta_if.isconnected() | (a > 99) : - time.sleep(0.1) - a+=1 - print('.', end='') - if sta_if.isconnected(): - print('\nConnected. Network config:', sta_if.ifconfig()) - return (True) - else : - print('\nProblem. Not Connected to :'+ntwrk_ssid) - return (False) + +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(): + with open(NETWORK_PROFILES) as f: + lines = f.readlines() + profiles = {} + for line in lines: + ssid, password = line.strip("\n").split(";") + profiles[ssid] = password + return profiles + + +def write_profiles(profiles): + lines = [] + for ssid, password in profiles.items(): + lines.append("%s;%s\n" % (ssid, password)) + with open(NETWORK_PROFILES, "w") as f: + f.write(''.join(lines)) + + +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_response(client, payload, status_code=200): - client.sendall("HTTP/1.0 {} OK\r\n".format(status_code)) - client.sendall("Content-Type: text/html\r\n") - client.sendall("Content-Length: {}\r\n".format(len(payload))) - client.sendall("\r\n") - - if len(payload) > 0: - client.sendall(payload) + client.sendall("HTTP/1.0 {} OK\r\n".format(status_code)) + client.sendall("Content-Type: text/html\r\n") + client.sendall("Content-Length: {}\r\n".format(len(payload))) + client.sendall("\r\n") + + if len(payload) > 0: + client.sendall(payload) + def handle_root(client): - global wlan_sta - response_header = """ -

Wi-Fi Client Setup

-
- - - - - - -
Wifi Name + + """) + + for ssid in ssids: + response.append("""\ + + + + """.format(ssid)) + + response.append("""\ + + + + + +
+ {0} +
Password:
+

+ +

+ +

 

+
+
+ + Your ssid and password information will be saved into the + "%(filename)s" file in your ESP module for future usage. + Be careful about security! + +
+
+

+ Some useful infos: +

+ + + """ % dict(filename=NETWORK_PROFILES)) + send_response(client, "\n".join(response)) - response_variable = "" - for ssid, *_ in wlan_sta.scan(): - response_variable += ''.format(ssid.decode("utf-8")) - - response_footer = """ -
Password
-

- -

 

-
-
!!! your ssid and password information will save "passwd.dat" file inside of your esp module to use next time... be careful for security !!!
-
-

Some useful infos:

- - - """ - send_response(client, response_header + response_variable + response_footer) def handle_configure(client, request): - match = ure.search("ssid=([^&]*)&password=(.*)", request) + match = ure.search("ssid=([^&]*)&password=(.*)", request) - if match is None: - send_response(client, "Parameters not found", status_code=400) - return (False) - # version 1.9 compatibility - try: - ssid = match.group(1).decode("utf-8").replace("%3F","?").replace("%21","!") - password = match.group(2).decode("utf-8").replace("%3F","?").replace("%21","!") - except: - ssid = match.group(1).replace("%3F","?").replace("%21","!") - password = match.group(2).replace("%3F","?").replace("%21","!") - - - if len(ssid) == 0: - send_response(client, "SSID must be provided", status_code=400) - return (False) + if match is None: + send_response(client, "Parameters not found", status_code=400) + return False + # version 1.9 compatibility + try: + ssid = match.group(1).decode("utf-8").replace("%3F", "?").replace("%21", "!") + password = match.group(2).decode("utf-8").replace("%3F", "?").replace("%21", "!") + except: + ssid = match.group(1).replace("%3F", "?").replace("%21", "!") + password = match.group(2).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 = """\ + +
+

+

+ + ESP successfully connected to WiFi network %(ssid)s. + +

+

+
+ + """ % dict(ssid=ssid) + send_response(client, response) + try: + profiles = read_profiles() + except OSError: + profiles = {} + profiles[ssid] = password + write_profiles(profiles) + return True + else: + response = """\ + +
+

+ + ESP could not connect to WiFi network %(ssid)s. + +

+

+
+ +
+
+ + """ % dict(ssid=ssid) + send_response(client, response) + return False - if do_connect(ssid, password): - response_footer = """ - -


-

:) YES, Wi-Fi Configured to """+ssid+"""

-

""" - send_response(client, response_footer) - try: - fo = open("passwd.dat","r") - ex_data = fo.read() - fo.close() - fo = open("passwd.dat","w") - ex_data = ssid+";"+password+"\n"+ex_data - fo.write(ex_data) - fo.close() - except: - fo = open("passwd.dat","w") - fo.write(ssid+";"+password+"\n") - fo.close() - - return (True) - else: - response_footer = """ - -
-

Wi-Fi Not Configured to """+ssid+"""

-

-
- -
- """ - send_response(client, response_footer ) - return (False) def handle_not_found(client, url): - send_response(client, "Path not found: {}".format(url), status_code=404) + send_response(client, "Path not found: {}".format(url), status_code=404) + def stop(): - global server_socket + global server_socket + + if server_socket: + server_socket.close() + server_socket = None - if server_socket: - server_socket.close() def start(port=80): - addr = socket.getaddrinfo('0.0.0.0', port)[0][-1] + global server_socket - global server_socket - global wlan_sta - global wlan_ap - global ssid_name - global ssid_password - stop() - - wlan_sta.active(True) - wlan_ap.active(True) - - wlan_ap.config(essid=ssid_name,password=ssid_password) - - - server_socket = socket.socket() - server_socket.bind(addr) - server_socket.listen(1) - - print('Connect to Wifi ssid :'+ssid_name+' , Default pass: '+ssid_password) - print('And connect to esp via your favorite web browser (like 192.168.4.1)') - print('listening on', addr) - - while True: - - if wlan_sta.isconnected(): - client.close - return (True) - - client, addr = server_socket.accept() - client.settimeout(5.0) - - print('client connected from', addr) + addr = socket.getaddrinfo('0.0.0.0', port)[0][-1] - request = b"" - try: - while not "\r\n\r\n" in request: - request += client.recv(512) - except OSError: - pass - - print("Request is: {}".format(request)) - if "HTTP" not in request: - # skip invalid requests - client.close() - continue - - # version 1.9 compatibility - try: - url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).decode("utf-8").rstrip("/") - except: - url = ure.search("(?:GET|POST) /(.*?)(?:\\?.*?)? HTTP", request).group(1).rstrip("/") - print("URL is {}".format(url)) + stop() - if url == "": - handle_root(client) - elif url == "configure": - handle_configure(client, request) - else: - handle_not_found(client, url) - - client.close() + 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) + 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: + 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()