در پروژه اینترنت اشیا که نیاز به اتصال و شبکه وایفای دارند و همچنین در مواردی ممکن است با تغییر مکان دستگاه نیاز به پروگرام کردن مجدد کد داریم تا مقادیر اطلاعات شبکه قبل را به اطلاعات جدید تغییر دهیم، wifi manager به ما این امکان را میدهد تا در هر زمان قابلیت تغییر این مقادری را بدون نیاز به آپلود مجدد کد داشته باشیم. در ادامه پروژه WiFi Manager با مرجع تخصصی میکروپایتون به زبان فارسی، دیجی اسپارک همراه باشید.
WiFi Manager
با اضافه شدن کتابخانه مدیریت Wi-Fi در MicroPython، دیگر لازم نیست SSID و رمز عبور شبکه محلی را جداگانه در برنامه اضافه کنیم. و هیچ کدنویسی مجددی مورد نیاز نخواهد بود. ما قادر خواهیم بود از طریق ساخت شبکه Access Points با بردهای ESP32 خود به طور خودکار و بدون هیچ مشکلی برای وارد کردن دستی اطلاعات شبکه در هر بار متصل شویم. اتصالات چندگانه SSID و همچنین متغیرهای سفارشی اضافی نیز می توانند از این طریق پیاده سازی شوند.
تراشه ESP32 وای فای بلوتوث
تراشه قدرتمند ESP32 می تواند به عنوان یک سیستم کامل مستقل یا به عنوان یک دستگاه MCU عمل کند و بار اضافی ارتباطات را در پردازنده اصلی برنامه کاهش دهد. ESP32 می تواند با سیستم های دیگر ارتباط برقرار کند تا از طریق SPI عملکرد Wi-Fi و بلوتوث را ارائه دهد. ESP32 با سوئیچ های آنتن داخلی، RF balun، تقویت کننده قدرت، تقویت کننده دریافت، فیلترها و ماژول های مدیریت توان یکپارچه شده است. ESP32 با حداقل الزامات برد مدار چاپی (PCB) ، عملکرد و تطبیق پذیری بی نظیری را به برنامه های شما اضافه می کند. برد ESP32 نسل پیشرفته ESP8266 است. یکی از تفاوتهای آن بلوتوث داخلیاش میباشد. همچنین دارای هسته وایفای ۲,۴ گیگا هرتزی و بلوتوث داخلی تولید شده با تکنولوژی ۴۰ نانومتری شرکت TSMC میباشد. این ماژول دارای بهترین پرفورمنس در مصرف انرژی میباشد یعنی با کمترین مصرف انرژی بهترین نتیجه را برای ما به همراه دارد. اگر بخواهیم دقیقتر به این برد نگاه کنیم باید بگوییم که این یک chip است که پلتفرم NodeMCU در اون پیاده سازی شده که به این نوع چیپ ها System on a chip microcontrollers هم گفته میشود.
شرح کار پروژه میکروپایتون
در اولین قدم پس از آپلود کدهای پروژه WiFi Manager در برد ESP32 با دنبال کردن دستور عمل پایین و کد های زیر به آن خواهید رسید، یک اکسس پوینت برای شما ایجاد خواهد شد با نامی که انتخاب کرده که بطور پیشفرض با نام wifi manager خواهد بود، کلیک کرده پسووردی که از قبل در کد مشخص کرده اید را وارد کنید، سپس پنجره پایین را مشاهده خواهید کرد، البته ip آدرس این صفحه وب در ترمینال upycraft نمایش داده خواهد شد.
- این آدرس ip را در مرورگر سرچ کنید دقت کنید که به اکسس پوینت ایجاد شده متصل باشید.
- در این صفحه وب شبکه وای فای مورد نظر را انتخاب و پسوورد شبکه را در محل مشخص شده وارد کنید و روی submit کلیک کنید.
- اگر تمام موارد به درستی انجام شده باشد با این پیام در صفحه وب روبرو خواهید شد.
- در نهایت در ترمینال upycraft یک آدرس ip جدید برای شما نمایش داده خواهد شده که با اتصال به شبکه وایفای اصلی به شما امکان اتصال به وب سرور کدنویسی شده را خواهد داد.
شرح پروژه WiFi Manager
با اضافه شدن کتابخانه Wi-Fi Manager در میکروپایتون MicroPython، دیگر لازم نیست SSID و رمز عبور شبکه محلی را جداگانه ارائه کنیم. هیچ کدنویسی مورد نیاز نخواهد بود. ما قادر خواهیم بود از طریق شبکه های دیگر یعنی Access Points به برد ESP32 خود متصل شویم. در این پروژه قصد داریم قابلیت WiFi Manager را به پروژه های خود اضافه کنیم، البته پروژ هایی که در آن ها قابلیت اتصالات وایفای وجود دارد و نیاز به تغییر اطلاعات شبکه در هر لحظه وجود دارد، به شدت نیازمند چنین قابلیتی هستند.
کتابخانه Wi-Fi Manager
import network import socket import ure import time ap_ssid = "cifer" ap_password = "123456789" ap_authmode = 3 # WPA2 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(): 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_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> </tbody> </table> <p style="text-align: center;"> <input type="submit" value="Submit" /> </p> </form> <p> </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=(.*)", 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 Exception: 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 = """\ <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 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) 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()
کد های پروژه WiFi Manager
در این مرحله نوبت به فایل اصلی پروژه WiFi Manager با میکروپایتون که قصد اجرای سناریو مدیریت شبکه های وایفای را داریم میرسد. دراین کد یک وب سرور ساده با قابلیت کنترل یک GPIO در برد ESP32 است، با اضافه کردن قابلیت WiFi Manager به این کد میتوانیم در هر لحظه شبکه وایفای متصل شده به این برد را تغییر دهیم. در مرحله اول در نرمافزار upycraft یک فایل جدید با نام Main.py بسازید، این فایل در کنار فایل کتابخانه اجرا خواهد شد.
import wifimgr from time import sleep import machine import gc try: import usocket as socket except: import socket led = machine.Pin(2, machine.Pin.OUT) wlan = wifimgr.get_connection() if wlan is None: print("Could not initialize the network connection.") while True: pass print("ESP OK") led_state = "OFF" def web_page(): html = """<html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"> <style> html { font-family: Arial; display: inline-block; margin: 0px auto; text-align: center; } .button { background-color: #ce1b0e; border: none; color: white; padding: 16px 40px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; } .button1 { background-color: #000000; } </style> </head> <body> <h2>ESP MicroPython Web Server</h2> <p>LED state: <strong>""" + led_state + """</strong></p> <p> <i class="fas fa-lightbulb fa-3x" style="color:#c81919;"></i> <a href=\"?led_2_on\"><button class="button">LED ON</button></a> </p> <p> <i class="far fa-lightbulb fa-3x" style="color:#000000;"></i> <a href=\"?led_2_off\"><button class="button button1">LED OFF</button></a> </p> </body> </html>""" return html s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', 80)) s.listen(5) while True: try: if gc.mem_free() < 102000: gc.collect() conn, addr = s.accept() conn.settimeout(3.0) print('Received HTTP GET connection request from %s' % str(addr)) request = conn.recv(1024) conn.settimeout(None) request = str(request) print('GET Rquest Content = %s' % request) led_on = request.find('/?led_2_on') led_off = request.find('/?led_2_off') if led_on == 6: print('LED ON -> GPIO2') led_state = "ON" led.on() if led_off == 6: print('LED OFF -> GPIO2') led_state = "OFF" led.off() response = web_page() conn.send('HTTP/1.1 200 OK\n') conn.send('Content-Type: text/html\n') conn.send('Connection: close\n\n') conn.sendall(response) conn.close() except OSError as e: conn.close() print('Connection closed')
وسایل مورد نیاز
کلام آخر با سایفر
چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریعترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند میتوانید از همین طریق اطلاع رسانی کنید.
در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی , از وبسایت دیجی اسپارک حمایت کنید.
سلام برنامه این ارور رو میده
os.listdir(‘.’)
Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘os’ isn’t defined
با سلام، زمانی که پروژه رو تست کردم این ارور رو دریافت نکردم، پس باید مشکلی در زمان پروگرام شدن بوجود آمده باشد و یا تغییری در کد داده باشید. دقت کنید که ابتدا فایل کتابخانه را در esp32 پروگرام کنید، سپس کد دوم.