برد Esp32 میکروپایتون Micropython

راه‌اندازی قابلیت WiFi Manager در برد ESP32 با میکروپایتون micropython

setup-wifi-manager-in-esp32-with-micropython-and-upycraft-digispark
نوشته شده توسط CiferTech

در پروژه اینترنت اشیا که نیاز به اتصال و شبکه وای‌فای دارند و همچنین در مواردی ممکن است با تغییر مکان دستگاه نیاز به پروگرام کردن مجدد کد داریم تا مقادیر اطلاعات شبکه قبل را به اطلاعات جدید تغییر دهیم، 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 نمایش داده خواهد شد.

پروژه WiFi Manager با میکروپایتون - دیجی اسپارک

 

  • این آدرس ip را در مرورگر سرچ کنید دقت کنید که به اکسس پوینت ایجاد شده متصل باشید.

اتصال به WiFi Manager در تنظیمات مودم با میکروپایتون - دیجی اسپارک

  • در این صفحه وب شبکه وای فای مورد نظر را انتخاب و پسوورد شبکه را در محل مشخص شده وارد کنید و روی submit کلیک کنید.

  • اگر تمام موارد به درستی انجام شده باشد با این پیام در صفحه وب روبرو خواهید شد.

برنامه نویسی میکروپایتون در راه اندازی WiFi Manager - دیجی اسپارک

 

  • در نهایت در ترمینال upycraft یک آدرس ip جدید برای شما نمایش داده خواهد شده که با اتصال به شبکه وای‌فای اصلی به شما امکان اتصال به وب سرور کدنویسی شده را خواهد داد.

 


شرح پروژه WiFi Manager


با اضافه شدن کتابخانه Wi-Fi Manager در میکروپایتون MicroPython، دیگر لازم نیست SSID و رمز عبور شبکه محلی را جداگانه ارائه کنیم. هیچ کدنویسی مورد نیاز نخواهد بود. ما قادر خواهیم بود از طریق شبکه های دیگر یعنی Access Points به برد ESP32 خود متصل شویم. در این پروژه قصد داریم قابلیت WiFi Manager را به پروژه های خود اضافه کنیم، البته پروژ هایی که در آن ها قابلیت اتصالات وای‌فای وجود دارد و نیاز به تغییر اطلاعات شبکه در هر لحظه وجود دارد، به شدت نیازمند چنین قابلیتی هستند.

 

 


کتابخانه Wi-Fi Manager


میکروپایتون MicroPython حاوی کتابخانه مدیریت وای فای نیست، بنابراین باید خود این کتابخانه را آپلود کنیم. ابتدا فایلی در برنامه upycarft با نام wifimgr.py ایجاد می‌کنیم که حاوی کد های زیر است. چنانچه با برنامه Upycraft آشنایی ندارید. به آموزش بخش دوم آموزش میکروپایتون با ESP32 مراجعه کنید. در ادامه کد ها داخل برد ESP32 ما آپلود خواهند شد، که این مورد در کد اصلی به ما این امکان را می دهد تا از این کتابخانه و قابلیت های آن استفاده کنیم.
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>&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=(.*)", 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')

 


وسایل مورد نیاز


برد ESP32

 


کلام آخر با سایفر


در این آموزش یاد گرفتیم تا از کتابخانه WiFi Manager استفاده کنیم، با استفاده از کتابخانه WiFi Manager، ما مجبور نیستیم اعتبار شبکه خود را در اسکریپت MicroPython خود از اول و در زمانی که نیاز به تغییر است کدنویسی کنیم. این کتابخانه ESP32 را در حالت نقطه دسترسی تنظیم می کند و اتصالات شبکه موجود را در یک صفحه وب نمایش می دهد. این به شما امکان می دهد شبکه خود را انتخاب کرده و با استفاده از نام و رمز عبور به آن متصل شوید. هنگامی که برد ESP شما به شبکه متصل شد، به طور خودکار در حالت Station کار می کند.

چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریع‌ترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند می‌توانید از همین طریق اطلاع رسانی کنید.

 

در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی , از وبسایت دیجی اسپارک حمایت کنید.

 

درباره نویسنده

CiferTech

فقط 10 نوع آدم در این دنیا وجود داره، اونی که باینری میفهمه و اونی که باینری نمیفهمه! ^-^

~ اینستاگرام: CiferTech

تبادل نظر و رفع عیب با ثبت دیدگاه

۲ دیدگاه

  • سلام برنامه این ارور رو میده
    os.listdir(‘.’)
    Traceback (most recent call last):
    File “”, line 1, in
    NameError: name ‘os’ isn’t defined

    • با سلام، زمانی که پروژه رو تست کردم این ارور رو دریافت نکردم، پس باید مشکلی در زمان پروگرام شدن بوجود آمده باشد و یا تغییری در کد داده باشید. دقت کنید که ابتدا فایل کتابخانه را در esp32 پروگرام کنید، سپس کد دوم.