W poprzednich odcinkach najpierw omawialiśmy różne moduły MicroPythona oraz klasy w nim udostępnione, a dopiero po wstępie teoretycznym pokazywaliśmy przykłady praktyczne. Moduły związane z Wi-Fi są tak rozbudowane, że na ich temat można by napisać książkę, a nie odcinek kursu do czasopisma. Dlatego tym razem przejdziemy od razu do praktycznych przykładów, które pokażą, jak można zrealizować pewne typowe czynności.
Wyszukiwanie sieci Wi-Fi
Weźmy pod lupę kod przedstawiony na listingu 1. Jego zadaniem jest wykrycie wszystkich sieci Wi-Fi dostępnych w pobliżu i wyświetlenie ich na konsoli w formie tabelki.
import network # 1
station = network.WLAN(network.STA_IF) # 2
station.active(True) # 3
nets = station.scan() # 4
counter = 0 # 5
authmodes = ["Open", "WEP", "WPA", "WPA2", # 6
"WPA/WPA2", "WPA2-Ent", "WPA3",
"WPA2/WPA3", "WAPI”, "OWE"]
print("Nr | Channel | RSSI | Security | Hidden | SSID") # 7
for net in nets: # 8
print(f"{counter:2d} | {net[2]:7d} | {net[3]:4d} | # 9
{authmodes[net[4]]:9s} | {net[5]:6d} | {net[0]:s}")
counter += 1
Listing 1. Kod pliku wifi_scan.py
Aby wykonywać jakiekolwiek operacje związane z Wi-Fi, najpierw musimy zaimportować moduł network (linia 1). Następnie trzeba utworzyć instancję klasy WLAN, co czynimy w linii 2. W zależności od zastosowanego argumentu konstruktora tej klasy, możliwe są dwa tryby pracy:
- network.STA_IF – ESP32 łączy się z istniejącym access pointem, który wskażemy w kolejnych liniach, podobnie jak łączą się z nim komputery, smartfony, itp. W taki sposób możemy uzyskać dostęp do Internetu.
- network.AP_IF – ESP32 tworzy swój własny access point, do którego mogą podłączyć się inne urządzenia. W tym trybie pracy możemy stworzyć własny serwer HTTP i DNS, aby generować strony WWW, które mogą być przeglądane na komputerze lub smartfonie. Omówimy ten temat w przyszłości.
Następnie w linii 3 musimy uaktywnić naszą klasę, po czym wywołujemy metodę scan (linia 4). Ta metoda zwraca listę krotek, po jednej na każdą znalezioną sieć. Każda krótka składa się z następujących danych:
- nazwy sieci (SSID),
- BSSID, czyli hardware’owej nazwy sieci,
- numeru kanału,
- RSSI, czyli wartości mocy sygnału,
- rodzaju zabezpieczeń,
- informacji o tym, czy sieć jest ukryta.
Tak otrzymaną listę zapisujemy do zmiennej nets. Jak zapewne się spodziewasz, reszta programu służy jedynie do zdekodowania i wyświetlenia otrzymanych informacji w formie zrozumiałej dla człowieka. Każdą sieć oraz odpowiadające jej informacje wyświetlimy w osobnych liniach.
W linii 5 tworzymy zmienną, która będzie przydatna do wyświetlania liczby porządkowej, a następnie budujemy listę authmodes, która ma służyć do przekształcenia numeru zabezpieczenia na zrozumiały komunikat. „Open” oznacza, że każdy może połączyć się z daną siecią bez podawania hasła.
W linii 7 wyświetlamy nagłówek tabeli, a następnie rozpoczynamy pętlę, która iteruje po wszystkich elementach listy nets. W każdym obiegu pętli wyświetlamy informacje z kolejnej krotki (linia 9), po czym inkrementujemy licznik counter.
Uruchamiamy kod klawiszem F5. Efekt skanowania sieci widzimy na rysunku 1.
Czas NTP
W tym przykładzie zobaczymy, jak można połączyć się z siecią Wi-Fi oraz jak pobrać aktualny czas z serwera NTP. Najpierw jednak poznamy prostą sztuczkę pozwalającą bezpiecznie przechowywać nazwę sieci SSID oraz hasło, aby przypadkiem nie opublikować jej na GitHubie czy w inny sposób. Zobacz kod pokazany na listingu 2. Jest to plik Wi-Fi_config.py, który składa się tylko z dwóch linijek. Musimy ten plik przegrać do pamięci ESP32, a następnie zapisać w nim nazwę sieci oraz hasło. W ten sposób wrażliwe dane przechowujesz tylko w pamięci wewnętrznej ESP32, a na dysku w komputerze pozostaje plik z pustymi zmiennymi, niczym szablon gotowy do wypełnienia.
ssid = ""
password = ""
Listing 2. Kod pliku config.py
Możemy teraz przejść do analizy pliku sync_ntp_time.py, którego kod znajduje się na listingu 3. Na początku, jak zawsze, importujemy potrzebne moduły, w tym również moduł Wi-Fi_config zawierający nazwę i hasło do sieci Wi-Fi (linia 1).
import network
import ntptime
import time
import wifi_config # 1
def wifi_connect(): # 2
station = network.WLAN(network.STA_IF)
station.active(True)
if not station.isconnected(): # 3
print("Łączenie z siecią", end="")
station.connect(wifi_config.ssid, wifi_config.password) # 4
while not station.isconnected(): # 5
print(".", end="")
time.sleep_ms(250)
print()
print(f"Adres IP: {station.ifconfig()[0]}") # 6
def print_system_time(): # 7
Y, M, D, h, m, s, w, _ = time.localtime()
days = ["Poniedziałek", "Wtorek", "Środa", "Czwartek",
"Piątek", "Sobota", "Niedziela"]
print(f"{Y}.{M:02}.{D:02} {h:02}:{m:02}:{s:02} {days[w]}")
print("Czas przed synchronizacją: ", end="") # 8
print_system_time()
wifi_connect() # 9
ntptime.settime() # 10
print("Czas po synchronizacji: ", end="")
print_system_time()
Listing 3. Kod pliku sync_ntp_time.py
W linii 2 definiujemy funkcję Wi-Fi_connect, której celem jest nawiązanie połączenia z siecią Wi-Fi. Pierwsze dwie linie są identyczne, jak w poprzednim przykładzie. W linii 3 sprawdzamy czy połączenie z siecią już zostało nawiązane, aby uniknąć próby powiązania z access pointem, do którego jesteśmy już podłączeni. W linii 4 wywołujemy metodę connect, do której przekazujemy nazwę i hasło sieci, odczytane z modułu Wi-Fi_config.
Łączenie z siecią trwa kilka sekund. Aby pokazać na konsoli proces łączenia, w linii 5 mamy pętlę while, która wykonuje się tak długo, aż metoda isconnected() zwróci True. Jeżeli zwróci False, wówczas na konsoli wyświetlamy kropkę i czekamy 250 ms przed kolejnym sprawdzeniem. Finalnie, kiedy jesteśmy już połączeni z siecią Wi-Fi, możemy wyświetlić adres IP, jaki został nam przydzielony.
W linii 7 mamy funkcję wyświetlającą aktualny czas systemowy. Była ona omówiona w 3 odcinku kursu, opublikowanym w EP 07/2025.
Przechodzimy wreszcie do właściwego programu. W linii 8 wyświetlamy czas, jaki aktualnie jest ustawiony w mikrokontrolerze. W tym momencie jeszcze nie mamy połączenia z siecią, a czas jaki nam się ukaże, pochodzi z programu Thonny. Jeżeli synchronizacja czasu z Thonny jest wyłączona w ustawieniach, zamiast właściwej godziny zobaczymy odczyt: 00:00 w dniu 1 stycznia 2000 r.
W linii 9 wywołujemy funkcje: Wi-Fi_connect, a następnie settime z modułu ntptime. Funkcja pobierze aktualny czas i zapisze w systemie, po czym ponownie wyświetlimy czas systemowy, aby zobaczyć, że nasz program pracuje prawidłowo. Efekt działania tego kodu pokazuje rysunek 2.
Zwróć uwagę na to, że pobrany z serwera czas nie uwzględnia naszej strefy czasowej ani czasu letniego/zimowego. Musimy o to zadbać sami.
Ściąganie plików
Kolejny praktyczny przykład to pobieranie plików z Internetu. Opisaną poniżej metodę można wykorzystać do pobierania nie tylko plików HTML, ale także dowolnych danych zupełnie innego typu. Nic nie stoi na przeszkodzie, by były to pliki Pythona pobrane z GitHuba. Czy widzisz już, jaką funkcjonalność możemy zrobić? Bardzo łatwo możemy zrealizować program, który sam siebie zaktualizuje, kiedy tylko zauważy, że na GitHubie pojawiły się nowe pliki.
Zobaczmy kod pliku download_file.py, widoczny na listingu 4. Na początku importujemy m.in. moduł requests (linia 1), który obsługuje zapytania HTTP. W tym kodzie wykorzystamy funkcję Wi-Fi_connect (linia 2), którą omawialiśmy w poprzednim przykładzie.
import network
import requests # 1
import time
import wifi_config
def wifi_connect(): # 2
station = network.WLAN(network.STA_IF)
station.active(True)
if not station.isconnected():
print("Łączenie z siecią", end="")
station.connect(wifi_config.ssid, wifi_config.password)
while not station.isconnected():
print(".", end="")
time.sleep_ms(250)
print()
print(f"Adres IP: {station.ifconfig()[0]}")
def download_file(url): # 3
result = requests.get(url) # 4
if result.status_code == 200: # 5
return result.text
else:
return f"Error {result.status_code}"
if __name__ == "__main__": # 6
wifi_connect()
data = download_file("https://raw.githubusercontent.com/
leonow32/micropython/refs/heads/main/
Kurs_Elektronika_Praktyczna/
05_Wyswietlacz_OLED/ssd1309.py")
print(data)
Listing 4. Kod pliku download_file.py
Przejdźmy do linii 3, gdzie tworzymy funkcję pobierającą z Internetu plik, którego adres podajemy poprzez argument url. Cała magia sprowadzona jest do wywołania funkcji get z modułu requests (linia 4). Funkcja ta zwraca krotkę, którą zapisujemy do zmiennej result. W tej krotce znajdziemy mnóstwo informacji, ale nas najbardziej interesują zmienne status_code oraz text.
Po ściągnięciu danych z Internetu musimy najpierw sprawdzić, czy w ogóle udało nam się pobrać żądany plik. W linii 5 sprawdzamy, czy serwer HTTP odpowiedział kodem 200, tzn. przesłał żądany plik. Jeżeli nie uda się pobrać pliku, najczęściej dostaniemy kod błędu 404. Funkcja download_file zwraca zawartość pobranego zbioru lub kod błędu, jeżeli nie udało się go pobrać.
Czas na zasadniczą część naszego programu, który zaczyna się w linii 6 i składa się zaledwie z trzech linijek. Łączymy się z Internetem przy pomocy funkcji Wi-Fi_connect. Następnie próbujemy pobrać plik i zapisać go do zmiennej data, po czym wyświetlamy rezultat funkcją print. To wszystko!
W naszym przykładzie pobieramy plik ssd1309.py (omawiany w 5 części kursu) z repozytorium kursu na GitHubie. W taki sposób możemy pobrać każdy plik i zapisać go w pamięci systemu plików MicroPythona. Nic nie stoi na przeszkodzie, by pobrać program napisany w Pythonie, a następnie go uruchomić.
Ping
Przypatrzmy się jeszcze adresowi IP, który jest wyświetlany w logach. Każde urządzenie, połączone z routerem Wi-Fi dostaje unikalny adres IP. Dzięki temu urządzenia znajdujące się w jednej sieci, tzn. podłączone do tego samego routera, mogą komunikować się między sobą.
Możemy przesłać testowy pakiet danych z komputera do ESP32, aby sprawdzić komunikację. W tym celu musimy uruchomić konsolę systemową, wchodząc (w przypadku systemu Windows) do menu Start i wpisując „cmd”. Następnie, kiedy otworzy się konsola, wpisujemy polecenie ping wraz z adresem IP, jaki zobaczyliśmy na konsoli MicroPythona. Komputer prześle cztery testowe pakiety do ESP32 i jeżeli nie będzie żadnych błędów, to powinniśmy zobaczyć efekt analogiczny do tego z rysunku 4. Adres IP w Twoim przypadku oczywiście może być inny.
Adresy wszystkich urządzeń znajdujących się w Twojej sieci Wi-Fi możesz uzyskać logując się do ustawień routera. Wskazówkę jak to zrobić, znajdziesz na naklejce z tyłu routera. Zwykle wystarczy otworzyć przeglądarkę internetową i w pasku adresu wpisać IP routera 192.168.0.1. W moim przypadku wygląda to tak, jak na rysunku 5. Widać tam adresy wszystkich urządzeń, w tym mikrokontrolera ESP32 pod nazwą mpy-esp32s3 i pod adresem IP 192.168.0.112.
To, co widać na rysunku 5, jest stroną HTML – ale pobraną nie z Internetu, lecz z routera. Cały kod HTML, pliki CSS, pliki graficzne, itp. generowane są przez oprogramowanie routera i przesyłane do urządzenia, które z nim się połączyło. W ten sposób urządzenie bez wyświetlacza i klawiatury zostało wyposażone w rozbudowany i łatwy w obsłudze interfejs użytkownika, wyświetlany na komputerze, smartfonie, tablecie czy dowolnym innym urządzeniu wyposażonym w Wi-Fi i przeglądarkę internetową.
A gdyby tak nasz ESP32 mógł też robić takie cuda… Może!
W następnym odcinku stworzymy własny serwer HTTP. Dzięki niemu będziemy mogli połączyć się ESP32 przy pomocy dowolnej przeglądarki internetowej na komputerze lub telefonie, aby poprzez Wi-Fi kontrolować kolor diody WS2812, a także odczytywać temperaturę.
• Repozytorium kursu na GitHubie https://github.com/leonow32/micropython
• Dokumentacja modułu network https://docs.micropython.org/en/latest/library/network.html
Dominik Bieczyński
leonow32@gmail.com