Lab #4: Používateľské nastavenia a pripojenie do internetu
o pripojení do internetu, vytvorení vlastného hotspot-u, synchronizácii času, externom module reálneho času, a stiahnutí rozširujúcich modulov pre MicroPython, dataclasses
Motivácia
- o pouzivatelskych nastaveniach
- o wifi
- o instalacii rozsirujucich balikov
Ciele
naučiť sa pripojiť mikrokontrolér k WiFi v jazyku MicroPython
naučiť sa nainštalovať rozširujúce moduly na MicroPython zariadenie
Postup
Používateľské nastavenia
Používateľ musí mať možnosť zmeniť správanie chytrého zariadenia.
Môže ísť napríklad o nastavenie pripojenia k WiFi, jednotiek teploty
alebo intervalu merania. Na rozdiel od statickej konfigurácie v module
constants.py môže používateľské nastavenia meniť používateľ
za behu zariadenia.
Na reprezentáciu nastavení vytvoríme dátovú triedu s názvom
Settings (pozri Dátové triedy). Všetky dátové
triedy sa budú nachádzať v balíku models, kde je aj trieda
BaseModel – predok každej dátovej triedy. Nastavenia budú
uložené v súbore settings.json a pri každom zapnutí
zariadenia sa z neho načítajú.
Task
Vytvorte triedu Settings, ktorá bude reprezentovať model
pre prácu s používateľskými nastaveniami.
Triedu vytvorte v module settings.py balíka
models. Momentálne nás bude v nastaveniach zaujímať:
- nastavenie pripojenia k WiFi (názov siete, heslo a časový limit pripojenia v sekundách),
- jednotka merania teploty, a
- identifikátor zariadenia, ktorý ho odlíši od ostatných zariadení – využijeme ho neskôr pri komunikácii so svetom.
Trieda Settings bude zatiaľ vyzerať takto:
import binascii
import machine
from hw.mixins.sensors.temperature import TemperatureUnit
from models.base import BaseModel, Field
class WiFi(BaseModel):
ssid: str = Field(default=None, type=str, optional=True)
password: str = Field(default=None, type=str, optional=True)
timeout: int = 10
class Settings(BaseModel):
wifi: WiFi = Field(default_factory=WiFi, type=WiFi)
units: str = TemperatureUnit.METRIC
device_id: str = binascii.hexlify(machine.unique_id()).decode()Predvolenou hodnotou identifikátora zariadenia je sériové číslo čipu
mikrokontroléra, ktoré vráti funkcia machine.unique_id().
Každé zariadenie tak má jedinečný identifikátor aj vtedy, keď ho
používateľ nezmení. Vy si však doň neskôr nastavíte svoj univerzitný
študentský identifikátor (jedinečný login), aby bolo zrejmé, ktoré
zariadenie je vaše.
Význam parametrov funkcie Field() (napr. prečo premenná
wifi používa parameter default_factory)
nájdete v kapitole Dátové
triedy.
Poznámka
Trieda nastavení v tejto podobe nie je kompletná. Postupne ju budeme rozširovať a pridávať nové možnosti podľa potreby.
Task
Overte funkčnosť vytvorenej triedy Settings.
Triedu môžete vyskúšať v REPL jazyka MicroPython. Vytvorte predvolené
nastavenia, zmeňte jednotku teploty a vytvorte nastavenia aj zo
slovníka, ako keby boli načítané zo súboru
settings.json:
>>> from models.settings import Settings
>>> settings = Settings()
>>> settings
Settings(wifi=WiFi(ssid=None,password=None,timeout=10),units='metric',device_id='e6614c311b7e6a2b')
>>> settings.units = 'imperial'
>>> settings.units
'imperial'
>>> settings = Settings(**{'wifi': {'ssid': 'my-network', 'password': 'secret'}})
>>> settings.wifi.ssid
'my-network'Ak ste postupovali správne, predvolené nastavenia budú mať prázdne
nastavenie WiFi, jednotky "metric" a identifikátor
zariadenia zhodný so sériovým číslom čipu (na vašom zariadení bude iný
ako v ukážke) a slovník s nastavením WiFi sa prevedie na objekt triedy
WiFi.
Task
Vytvorte validátor s názvom check_units() pre členskú
premennú units, ktorý overí, či je zadávaná jednotka
teploty platná.
Validátor je metóda, ktorá sa spustí pri priraďovaní hodnoty do členskej premennej. Predtým, ako sa hodnota priradí, sa najprv overí. Ak nie je platná, validátor vyvolá výnimku. V opačnom prípade sa hodnota priradí.
Validátor nemusíte volať sami – trieda BaseModel ho
spustí automaticky pri každom priradení hodnoty do danej členskej
premennej, aj pri vytváraní objektu.
Validátor na overenie hodnoty členskej premennej units
môže vyzerať nasledovne:
from models.base import validator
# ...
class Settings(BaseModel):
# ...
@validator('units')
def check_units(self, value):
if value not in (
TemperatureUnit.METRIC,
TemperatureUnit.IMPERIAL,
TemperatureUnit.STANDARD
):
raise ValueError(f'Unknown temperature unit "{value}".')Task
Overte vytvorený validátor.
Validátor vyskúšajte v REPL jazyka MicroPython tak, že do premennej
units priradíte neplatnú jednotku teploty:
>>> from models.settings import Settings
>>> settings = Settings()
>>> settings.units = 'kelvin'
Traceback (most recent call last):
...
ValueError: Unknown temperature unit "kelvin".
>>> settings.units
'metric'Ak ste postupovali správne, validátor odmietne neplatnú jednotku
teploty a premenná units si ponechá pôvodnú hodnotu.
Task
Podobným spôsobom vytvorte validátor positive() pre
členskú premennú timeout triedy WiFi, ktorý
overí, či je jej hodnota kladná.
Ak hodnota nie je kladná, validátor vyvolá výnimku
ValueError so správou
"Timeout must be positive.".
Ak ste postupovali správne, validátor odmietne nulovú aj zápornú
hodnotu a premenná timeout si ponechá pôvodnú hodnotu:
>>> from models.settings import Settings
>>> settings = Settings()
>>> settings.wifi.timeout = 0
Traceback (most recent call last):
...
ValueError: Timeout must be positive.
>>> settings.wifi.timeout
10Task
Vytvorte validátor check_device_id() pre členskú
premennú device_id, ktorý overí, či je identifikátor
zariadenia platný.
Identifikátor zariadenia bude neskôr súčasťou adries, na ktoré bude
zariadenie posielať údaje. Preto nesmie byť prázdny a môže obsahovať len
písmená bez diakritiky, číslice a znaky - a _.
Ak hodnota tieto podmienky nespĺňa, validátor vyvolá výnimku
ValueError so správou
"Invalid device ID \"<hodnota>\".".
Ak ste postupovali správne, validátor odmietne neplatný identifikátor
a premenná device_id si ponechá pôvodnú hodnotu:
>>> from models.settings import Settings
>>> settings = Settings()
>>> settings.device_id = 'ab123cd'
>>> settings.device_id = 'ab 123/cd'
Traceback (most recent call last):
...
ValueError: Invalid device ID "ab 123/cd".
>>> settings.device_id
'ab123cd'Prvé spustenie a obnova výrobných nastavení
Používateľské nastavenia sú pre fungovanie zariadenia veľmi dôležité.
Nastavenia budú na zariadení uložené v súbore, čím sa zabezpečí ich
perzistencia. Cesta k súboru s používateľskými nastaveniami sa nachádza
v konštante SETTINGS_FILE.
Súbor s nastaveniami bude uložený v priečinku
DATA_FOLDER. Do neho bude chytré zariadenie ukladať všetky
údaje, ktoré vzniknú počas jeho práce, napr. používateľské nastavenia,
merania či záznamy (logy).
V tomto kroku vyriešime tieto dôležité situácie:
- prvé spustenie zariadenia, keď súbor s používateľskými nastaveniami ešte neexistuje,
- poškodený súbor s nastaveniami, ktorý nie je možné načítať, a
- ručné vyvolanie obnovy výrobných nastavení.
Task
Vytvorte nový stav s názvom FactoryReset, ktorý vytvorí
predvolené nastavenia.
Stav FactoryReset vytvorte v module
factory_reset.py balíka states.
V tomto stave vytvoríte predvolené nastavenia a uložíte ich do súboru
settings.json v priečinku DATA_FOLDER. Celá
cesta k tomuto súboru sa nachádza v konštante
SETTINGS_FILE.
Predvolené nastavenia vytvoríte serializáciou inštancie triedy
Settings. Ako na to, nájdete v kapitole Dátové
triedy.
V tomto stave teda zabezpečte nasledovné:
- Ak neexistuje priečinok
DATA_FOLDER, tak ho vytvorte. - V súbore s cestou
SETTINGS_FILEvytvorte predvolené nastavenia. - Natvrdo reštartujte zariadenie.
Reštart zabezpečí, že sa zariadenie spustí s novými nastaveniami a
prejde bežným štartom cez stav Init, ktorý nastavenia zo
súboru načíta.
Task
Overte správnosť implementácie stavu FactoryReset.
Stav ešte nie je prepojený so stavom Init, preto ho
spustite priamo z REPL jazyka MicroPython. Využijete pri tom to,
že kontext dostáva počiatočný stav ako parameter:
>>> from context import Context
>>> from main import register_devices
>>> from states.factory_reset import FactoryReset
>>> Context(register_devices(), FactoryReset).run()Zariadenie sa po vytvorení nastavení reštartuje, takže sa k nemu bude potrebné znova pripojiť. Potom overte, či súbor s nastaveniami vznikol a čo obsahuje:
>>> from constants import SETTINGS_FILE
>>> print(open(SETTINGS_FILE).read())
{"wifi": {"ssid": null, "password": null, "timeout": 10}, "units": "metric", "device_id": "e6614c311b7e6a2b"}Ak ste postupovali správne, v priečinku DATA_FOLDER
vznikne súbor s predvolenými nastaveniami vo formáte JSON.
Poradie kľúčov v súbore sa môže od ukážky líšiť a identifikátor
zariadenia bude zhodný so sériovým číslom čipu vášho zariadenia.
Task
Zabezpečte prechod zo stavu Init do stavu
FactoryReset na základe podmienok prechodu.
Zariadenie prejde do stavu FactoryReset, ak:
- neexistuje súbor s nastaveniami,
- sa súbor s nastaveniami nepodarí načítať z ľubovoľného dôvodu, alebo
- je pri štarte ovládacie tlačidlo stlačené aspoň tak dlho, ako určuje
konštanta
LONG_PRESS_DURATION(v milisekundách).
V opačnom prípade bude pokračovať stavom
Measurement.
Stavový diagram zariadenia s novým stavom sa nachádza na obrázku 1.
---
# spolocna konfiguracia stavovych diagramov THSensor; vklada sa ako prvy
# riadok bloku ```mermaid, za nim nasleduje "flowchart LR" a samotny diagram
config:
flowchart:
curve: basis
nodeSpacing: 40
rankSpacing: 60
themeVariables:
fontSize: 20px
themeCSS: ".edgeLabel, .edgeLabel p, .labelBkg { background-color: var(--bs-body-bg) !important; }"
---
flowchart LR
start@{ shape: f-circ } --> init(Init)
init --> measurement(Measurement)
init -- "<code>SVC_PIN</code><br>grounded" --> terminal("Service<br>Terminal")
init -- "no/faulty<br><code>settings.json</code> /<br>long button press" --> reset("Factory<br>Reset")
measurement --> sleep(Sleep)
sleep --> sleepEnd@{ shape: fr-circ }
terminal --> terminalEnd@{ shape: fr-circ }
reset --> resetEnd@{ shape: fr-circ }
%% spolocne styly stavovych diagramov THSensor (farby podla
%% images/thsensor-state.diagram.complete.png); vklada sa na koniec diagramu
%% a stavy sa k nim priradia cez "class <stavy> <styl>"
classDef state fill:#cfe2ff,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef service fill:#cbc3a3,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef reset fill:#ffd6f5,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef config fill:#fddba7,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef error fill:#ffd7d9,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef ota fill:#c3f5c8,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef initial fill:#000,stroke:#fff,stroke-width:2px
classDef final fill:#fff,stroke:#000,stroke-width:2px
class init,measurement,sleep state
class terminal service
class reset reset
class start initial
class sleepEnd,terminalEnd,resetEnd final
Obr. 1: Stavový diagram zariadenia so stavom
FactoryReset
Ovládacie tlačidlo je v správcovi zariadení dostupné pod aliasom
ALIAS_CONTROL_BTN. Ak sa toto tlačidlo vo vašom správcovi
zariadení nenachádza, zaregistrujte ho (je pripojené na pin
BTN_PIN).
Diagnostická LED dióda svieti pri zapnutí nazeleno. Ak bude
používateľ pri zapnutí držať ovládacie tlačidlo stlačené dlhšie, ako
určuje konštanta LONG_PRESS_DURATION, zmeňte jej farbu na
fialovú (konštanta Color.PURPLE). Vďaka tomu bude
používateľ vedieť, že keď tlačidlo uvoľní, naozaj sa spustí obnova
výrobných nastavení.
Nastavenia zo súboru deserializujte a výsledný objekt typu
Settings uložte do členskej premennej kontextu
settings. Vďaka tomu budú nastavenia dostupné v celom
zariadení prostredníctvom kontextu. Členskú premennú
settings vytvorte už v konštruktore kontextu s hodnotou
None, aby existovala aj pred načítaním nastavení.
Pri implementácii nezabudnite, že kontrola prechodu do stavu
FactoryReset sa musí vykonať až po kontrole servisného
tlačidla, aby sa do servisného terminálu dalo dostať aj bez platných
nastavení.
Task
Overte vytvorenú implementáciu.
Pri overovaní vyskúšajte všetky situácie, ku ktorým môže pri štarte zariadenia dôjsť:
- súbor s nastaveniami neexistuje (zmažte ho) – zariadenie prejde do
stavu
FactoryReset, vytvorí predvolené nastavenia a po reštarte pokračuje stavomMeasurement, - súbor s nastaveniami je poškodený (napr. doň zapíšte neplatný
JSON alebo neznámy kľúč) – zariadenie prejde do stavu
FactoryReset, - súbor s nastaveniami je platný – zariadenie pokračuje stavom
Measurement, - ovládacie tlačidlo je pri štarte stlačené dlhšie ako
LONG_PRESS_DURATION– diagnostická LED dióda sa rozsvieti nafialovo a po uvoľnení tlačidla zariadenie prejde do stavuFactoryReset, - servisný pin
SVC_PINje uzemnený a súbor s nastaveniami neexistuje – zariadenie prejde do servisného terminálu.
Príkaz settings
K používateľským nastaveniam bude potrebné pristupovať aj zo servisného terminálu. Technik musí mať možnosť hodnoty nastavení zobraziť a zmeniť, zmenené nastavenia uložiť do súboru a v prípade potreby ich zo súboru znova načítať.
V tomto kroku preto vytvoríme príkaz settings s
niekoľkými podpríkazmi. Zmeny vykonané v servisnom termináli sa prejavia
v nastaveniach zariadenia hneď, do súboru sa však uložia až podpríkazom
na uloženie. Technik tak môže zmeniť viacero hodnôt naraz, alebo
neuložené zmeny zahodiť opätovným načítaním nastavení zo súboru.
Task
V module commands/settings.py vytvorte triedu
Settings, ktorá bude reprezentovať príkaz
settings.
O tejto triede bude platiť:
- bude potomkom triedy
BaseCommand, - názov príkazu bude
"settings", - opis príkazu bude
"Manage user settings.", - prvým parametrom príkazu bude názov podpríkazu (
show,get,set,savealeboload) a ďalšie parametre dostane vybraný podpríkaz, - ak príkaz nedostane žiadny parameter alebo dostane neznámy
podpríkaz, vypíše správu
"Error: Wrong usage."
Príkaz zaregistrujte rovnako ako ostatné príkazy.
Task
Rozšírte príkaz settings o podpríkaz show,
ktorý zobrazí aktuálnu podobu používateľských nastavení.
Výstup príkazu môže vyzerať nasledovne:
> settings show
wifi:
ssid: "iot-lab"
password: "Secret.Password"
timeout: 10
units: "metric"
device_id: "ab123cd"
Task
Rozšírte príkaz settings o podpríkaz get,
ktorý vráti aktuálnu hodnotu nastavenia na základe jeho kľúča.
Kľúč bude reprezentovaný ako cesta k požadovanej hodnote v
JSON štruktúre nastavení, pričom jednotlivé úrovne sa oddeľujú
bodkou (napr. wifi.ssid). Ak daný kľúč neexistuje, príkaz
vypíše chybovú správu
"Error: Key \"<kľúč>\" not found.". Ak podpríkaz
nedostane práve jeden parameter, vypíše správu
"Error: Wrong usage.".
Príklad použitia príkazu môže vyzerať nasledovne:
> settings get units
metric
> settings get wifi.ssid
iot-lab
> settings get wifi
ssid: "iot-lab"
password: "Secret.Password"
timeout: 10
> settings get wifi.port
Error: Key "wifi.port" not found.
> settings get
Error: Wrong usage.
Task
Rozšírte príkaz settings o podpríkaz set,
pomocou ktorého bude možné nastaviť novú hodnotu pre zadaný kľúč.
Podpríkaz dostane dva parametre: kľúč v rovnakom tvare ako pri
podpríkaze get a novú hodnotu. Keďže hodnota zadaná v
termináli je vždy reťazec, pred priradením ju preveďte na typ aktuálnej
hodnoty nastavenia (napr. na int). Podpríkaz vypíše chybovú
správu:
"Error: Wrong usage.", ak nedostane práve dva parametre,"Error: Key \"<kľúč>\" not found.", ak daný kľúč neexistuje,"Error: \"<kľúč>\" is a section, not a value.", ak kľúč neukazuje na hodnotu, ale na celú sekciu nastavení,- text výnimky, ak nová hodnota nie je platná (napr. ju odmietne validátor).
Zmena sa prejaví len v nastaveniach v pamäti zariadenia. Do súboru sa
uloží až podpríkazom save.
Príklad jeho použitia môže vyzerať nasledovne:
> settings set wifi.ssid iot-lab
wifi.ssid = iot-lab
> settings set units imperial
units = imperial
> settings set device_id ab123cd
device_id = ab123cd
> settings set units kelvin
Error: Unknown temperature unit "kelvin".
> settings set wifi iot-lab
Error: "wifi" is a section, not a value.
> settings set wifi.port 80
Error: Key "wifi.port" not found.
Task
Rozšírte príkaz settings o podpríkaz load,
ktorý načíta používateľské nastavenia zo súboru vo formáte
JSON.
Podpríkaz načíta nastavenia zo súboru SETTINGS_FILE a
nahradí nimi aktuálne nastavenia v kontexte. Všetky zmeny, ktoré ešte
neboli uložené podpríkazom save, sa tým zahodia. Podpríkaz
vypíše:
"Settings loaded.", ak sa nastavenia podarilo načítať,"Error: Settings file not found.", ak súbor s nastaveniami neexistuje,- text výnimky, ak súbor s nastaveniami nie je možné načítať (napr. je poškodený); aktuálne nastavenia v kontexte sa v takom prípade nezmenia.
Príklad použitia podpríkazu môže vyzerať nasledovne:
> settings set units imperial
units = imperial
> settings load
Settings loaded.
> settings get units
metric
Task
Rozšírte príkaz settings o podpríkaz save,
ktorý aktuálnu verziu používateľských nastavení uloží do súboru vo
formáte JSON.
Podpríkaz serializuje aktuálne nastavenia z kontextu a uloží ich do
súboru SETTINGS_FILE, čím sa prepíše jeho pôvodný obsah. Po
úspešnom uložení vypíše správu "Settings saved.". Uložené
nastavenia sa použijú pri ďalšom zapnutí zariadenia, prípadne po
zavolaní podpríkazu load.
Príklad použitia podpríkazu môže vyzerať nasledovne:
> settings set wifi.ssid iot-lab
wifi.ssid = iot-lab
> settings save
Settings saved.
> settings load
Settings loaded.
> settings get wifi.ssid
iot-lab
Ak ste postupovali správne, zmena hodnoty zostane zachovaná aj po opätovnom načítaní nastavení zo súboru, prípadne po reštarte zariadenia.
Nakoniec si do identifikátora zariadenia nastavte svoje študentské prihlasovacie meno a nastavenia uložte. Vďaka tomu bude vaše zariadenie odlíšiteľné od zariadení ostatných študentov.
WiFi modul
Vývojová doska RPi Pico 2 WH obsahuje aj WiFi modul s čipom CYW43439. Práve pomocou neho budeme komunikovať so svetom a pripojíme chytré zariadenie do internetu.
V jazyku MicroPython sa s WiFi
modulom pracuje pomocou triedy network.WLAN.
V tomto kroku ju zabalíme do samostatnej triedy, aby sme z WiFi modulu
spravili perifériu nášho projektu. Jej schopnosti opisujú mixiny
NetworkMixin a WiFiMixin, ktoré sú súčasťou
kostry projektu.
Task
Vytvorte triedu CYW43439, ktorá zapúzdri prístup k
inštancii triedy network.WLAN
na prácu s WiFi modulom.
O tejto triede bude platiť nasledovné:
- jej implementácia sa bude nachádzať v module
cyw43439.py, - názov zariadenia bude
"CYW43439", - opis zariadenia bude
"Built-in WiFi module (Raspberry Pi Pico 2 W)", - bude implementovať mixiny
NetworkMixinaWiFiMixina bude potomkom triedyBaseDevice, - konštruktor bude mať len voliteľný parameter
alias– WiFi modul je na doske zapojený napevno, preto mu piny pri vytváraní neodovzdávame, - metódy implementovaných mixinov prenechajú volanie inštancii triedy
network.WLAN.
Metódy, ktoré treba implementovať, predpisujú mixiny
NetworkMixin a WiFiMixin. Väčšina z nich len
odovzdá volanie rovnomennej metóde inštancie triedy network.WLAN.
Task
Vytvorené zariadenie zaregistrujte v správcovi zariadení a otestujte ho.
Pri registrácii použite alias ALIAS_WIFI. Zariadenie
môžete otestovať priamo z prostredia REPL napr. takto:
>>> from constants import ALIAS_WIFI
>>> from main import register_devices
>>> wifi = register_devices().get(ALIAS_WIFI)
>>> wifi.capabilities()
['NetworkMixin', 'WiFiMixin']
>>> wifi.active(True)
>>> wifi.active()
True
>>> wifi.isconnected()
False
>>> for network in wifi.scan():
... print(network[0], network[3])
...
b'iot-lab' -52
b'eduroam' -67Ak ste postupovali správne, WiFi modul sa aktivuje a metóda
.scan() vráti zoznam WiFi sietí v okolí. Každá sieť je
n-tica, ktorej prvou položkou je názov siete (SSID) a štvrtou
sila signálu (RSSI) v dBm.
Príkaz net
Na prácu so sieťovým rozhraním vytvoríme v servisnom termináli
samostatný príkaz net. Technikovi umožní zistiť, či je
zariadenie pripojené do siete a s akou adresou, vyhľadať dostupné WiFi
siete alebo sa do niektorej z nich ručne pripojiť – napríklad aby
vyskúšal prihlasovacie údaje skôr, ako ich uloží do nastavení.
Príkaz bude mať niekoľko podpríkazov, pomocou ktorých bude možné sieťové rozhranie ovládať a zistiť jeho stav.
Task
V module commands/net.py vytvorte triedu
Net, ktorá bude reprezentovať príkaz net.
O tejto triede bude platiť:
- bude potomkom triedy
BaseCommand, - názov príkazu bude
"net", - opis príkazu bude
"Manage network interface.", - prvým parametrom príkazu bude názov podpríkazu (
scan,connect,disconnect,deactivatealebostat) a ďalšie parametre dostane vybraný podpríkaz, - ak príkaz nedostane žiadny parameter alebo dostane neznámy
podpríkaz, vypíše správu
"Error: Wrong usage.", - sieťové rozhranie si vyžiada od správcu zariadení pomocou aliasu
ALIAS_WIFI.
Príkaz zaregistrujte rovnako ako ostatné príkazy.
Task
Vytvorte podpríkaz scan, ktorý vyhľadá WiFi siete v
okolí.
Podpríkaz najprv aktivuje sieťové rozhranie (ak ešte nie je aktívne)
a potom pomocou metódy .scan() zistí dostupné siete. Pre
každú nájdenú sieť vypíše:
- jej názov (SSID); namiesto prázdneho názvu skrytej siete
vypíše
(hidden), - číslo kanála,
- silu signálu (RSSI) v dBm,
- spôsob zabezpečenia:
open,WEP,WPA,WPA2aleboWPA/WPA2.
Význam jednotlivých položiek, ktoré metóda .scan() pre
každú sieť vráti, nájdete v kapitole Práca s WiFi modulom.
Pozor – spôsob zabezpečenia nie je jednoduchý číselný kód, ale bitová
maska.
Príklad použitia podpríkazu môže vyzerať nasledovne:
> net scan
SSID CH RSSI SECURITY
-------------------------------- --- ----- ---------
iot-lab 6 -52 WPA2
eduroam 1 -67 WPA2
TUKE-guest 11 -74 open
(hidden) 11 -81 WPA/WPA2
Task
Vytvorte podpríkaz connect, pomocou ktorého sa
zariadenie pripojí k zadanej WiFi sieti.
Podpríkaz dostane dva parametre: názov siete (SSID) a heslo. Zadané údaje sa do nastavení neukladajú. Technik si tak môže overiť, či sú prihlasovacie údaje správne.
Metóda .connect() triedy network.WLAN
na pripojenie nečaká – len ho spustí a hneď sa vráti. Podpríkaz preto
musí počkať, kým sa zariadenie pripojí, alebo kým neuplynie časový limit
v sekundách, ktorý je uložený v nastaveniach
(wifi.timeout). Priebeh pripájania môžete sledovať metódou
.status(), ktorá vráti stav pripojenia (napr.
network.STAT_GOT_IP,
network.STAT_WRONG_PASSWORD alebo
network.STAT_NO_AP_FOUND).
Podpríkaz vypíše:
"Connecting to <ssid>..."na začiatku pripájania,- po úspešnom pripojení názov siete, IP adresu, masku siete, adresu brány a DNS servera,
"Error: Wrong password.", ak je heslo nesprávne,"Error: Network not found.", ak sieť so zadaným názvom nie je v dosahu,"Error: Connection timed out.", ak sa zariadenie nepripojí v časovom limite,"Error: Wrong usage.", ak podpríkaz nedostane práve dva parametre.
Príklad použitia podpríkazu môže vyzerať nasledovne:
> net connect iot-lab Secret.Password
Connecting to iot-lab...
SSID : iot-lab
IP : 192.168.1.42
Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
> net connect iot-lab wrong-password
Connecting to iot-lab...
Error: Wrong password.
> net connect no-such-network secret
Connecting to no-such-network...
Error: Network not found.
Task
Rozšírte príkaz net o podpríkazy disconnect
a deactivate.
O týchto podpríkazoch bude platiť:
disconnect– odpojí zariadenie od WiFi siete a vypíše správu"Disconnecting from network..."; ak zariadenie nie je pripojené, vypíše správu"Error: Not connected.",deactivate– vypne sieťové rozhranie a vypíše správu"Deactivating interface.".
Príklad použitia podpríkazov môže vyzerať nasledovne:
> net disconnect
Disconnecting from network...
> net disconnect
Error: Not connected.
> net deactivate
Deactivating interface.
Task
Vytvorte podpríkaz stat, ktorý zobrazí aktuálny stav
sieťového rozhrania.
Podpríkaz vypíše:
- či je sieťové rozhranie aktívne,
- stav pripojenia, napr.
idle,connecting,connected,wrong passwordalebono AP found(číselné hodnoty stavov zodpovedajú konštantámnetwork.STAT_*), - MAC adresu rozhrania.
Ak je zariadenie pripojené do siete, vypíše navyše:
- názov siete (SSID), číslo kanála a silu signálu (RSSI),
- IP adresu, masku siete, adresu brány a DNS servera.
Príklad použitia podpríkazu môže vyzerať nasledovne:
> net stat
Active : no
Status : idle
MAC : 28:cd:c1:0f:3a:52
> net connect iot-lab Secret.Password
...
> net stat
Active : yes
Status : connected
MAC : 28:cd:c1:0f:3a:52
SSID : iot-lab
Channel : 6
RSSI : -52 dBm
IP : 192.168.1.42
Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
> net disconnect
Disconnecting from network...
> net stat
Active : yes
Status : idle
MAC : 28:cd:c1:0f:3a:52
> net deactivate
Deactivating interface.
> net stat
Active : no
Status : idle
MAC : 28:cd:c1:0f:3a:52
Pripojenie do WiFi siete a odpojenie od nej
Stavový diagram zariadenia s novými stavmi
ConnectNetwork a DisconnectNetwork sa nachádza
na obrázku 2.
---
# spolocna konfiguracia stavovych diagramov THSensor; vklada sa ako prvy
# riadok bloku ```mermaid, za nim nasleduje "flowchart LR" a samotny diagram
config:
flowchart:
curve: basis
nodeSpacing: 40
rankSpacing: 60
themeVariables:
fontSize: 20px
themeCSS: ".edgeLabel, .edgeLabel p, .labelBkg { background-color: var(--bs-body-bg) !important; }"
---
flowchart LR
start@{ shape: f-circ } --> init(Init)
init --> measurement(Measurement)
init -- "<code>SVC_PIN</code><br>grounded" --> terminal("Service<br>Terminal")
init -- "no/faulty<br><code>settings.json</code> /<br>long button press" --> reset("Factory<br>Reset")
measurement --> connect("Connect<br>Network")
connect --> disconnect("Disconnect<br>Network")
disconnect --> sleep(Sleep)
sleep --> sleepEnd@{ shape: fr-circ }
terminal --> terminalEnd@{ shape: fr-circ }
reset --> resetEnd@{ shape: fr-circ }
%% spolocne styly stavovych diagramov THSensor (farby podla
%% images/thsensor-state.diagram.complete.png); vklada sa na koniec diagramu
%% a stavy sa k nim priradia cez "class <stavy> <styl>"
classDef state fill:#cfe2ff,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef service fill:#cbc3a3,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef reset fill:#ffd6f5,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef config fill:#fddba7,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef error fill:#ffd7d9,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef ota fill:#c3f5c8,stroke:#9aa3ad,stroke-width:3px,color:#343a40,font-weight:bold
classDef initial fill:#000,stroke:#fff,stroke-width:2px
classDef final fill:#fff,stroke:#000,stroke-width:2px
class init,measurement,connect,disconnect,sleep state
class terminal service
class reset reset
class start initial
class sleepEnd,terminalEnd,resetEnd final
Obr. 2: Stavový diagram zariadenia so stavmi
ConnectNetwork a
DisconnectNetwork
Vytvorenie príkazu
pip
Podobne ako jazyk Python je
možné aj jazyk MicroPython
rozširovať pomocou balíkov, ktoré je možné doinštalovať. V jazyku Python na to slúži nástroj
príkazového riadka pip. V prostredí jazyka MicroPython máme niekoľko spôsobov,
ako na mikrokontroléri inštalovať nové balíky. Nás v tomto kroku bude
zaujímať modul mip,
ktorý sa používa podobne ako nástroj pip. Keďže balíky
sťahuje z internetu, zariadenie musí byť pri inštalácii pripojené do
siete.
V tomto kroku vytvoríme v servisnom termináli samostatný príkaz
pip, pomocou ktorého bude možné rozšíriť aktuálne
schopnosti mikrokontroléra o nové balíky.
Viac informácií o inštalovaní nových balíkov v prostredí jazyka MicroPython sa dozviete v kapitole Inštalácia balíkov.
Task
V module pip.py vytvorte triedu Pip, ktorá
bude reprezentovať príkaz pip na inštaláciu nových
balíkov.
O tejto triede bude platiť:
- bude potomkom triedy
BaseCommand, - názov príkazu bude
"pip", - opis príkazu bude
"Install packages.", - podpríkaz
install <balík>nainštaluje zadaný balík pomocou funkciemip.install(), - pred inštaláciou overí, či je zariadenie pripojené do siete (WiFi
modul s aliasom
ALIAS_WIFI); ak nie je, vypíše správu"Error: Not connected."a inštaláciu nespustí, - ak príkaz nedostane podpríkaz
installs práve jedným názvom balíka, vypíše správu"Error: Wrong usage."
Príkaz zaregistrujte rovnako ako ostatné príkazy.
Poznámka
Funkcia mip.install() vypisuje priebeh inštalácie
funkciou print() na štandardný výstup, nie do výstupného
prúdu príkazu. Jej výpis preto uvidíte v konzole cez USB, nie v
klientovi sériovej linky. Príkaz pip by preto mal sám
vypísať, ktorý balík inštaluje a či inštalácia skončila.
Task
Overte funkčnosť príkazu pip.
Najprv vyskúšajte inštaláciu bez pripojenia do siete a potom sa
pripojte a nainštalujte balík pathlib zo štandardnej
knižnice jazyka MicroPython (micropython-lib):
> pip install pathlib
Error: Not connected.
> net connect iot-lab Secret.Password
Connecting to iot-lab...
SSID : iot-lab
IP : 192.168.1.42
Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
> pip install pathlib
Installing pathlib...
Done.
Nainštalované balíky sa uložia do priečinka /lib na
mikrokontroléri, odkiaľ ich je možné importovať rovnako ako vstavané
moduly. Či sa balík naozaj nainštaloval, môžete overiť priamo z
prehliadača súborov vášho IDE alebo z prostredia REPL jazyka MicroPython:
>>> import os
>>> os.listdir('/lib')
['pathlib.mpy']
>>> from pathlib import PathAk ste postupovali správne, priečinok /lib bude
obsahovať nainštalovaný balík a jeho import prebehne bez chyby.
Upozornenie
Ak máte v prostredí PyCharm zapnutú
synchronizáciu projektu (voľba Synchronize), dajte si
pozor. Synchronizácia zabezpečí, že na zariadení bude len to, čo je vo
vašom projekte. Priečinky /lib s nainštalovanými balíkmi a
/data s používateľskými nastaveniami však v projekte nie
sú, a preto by ich synchronizácia zo zariadenia vymazala. Import
nainštalovaných balíkov by potom zlyhal a zariadenie by pri štarte
prešlo do stavu FactoryReset.
Ďalšie úlohy
- Rozšírte príkaz
reseto podpríkazfactory, ktorý obnoví výrobné nastavenia zariadenia.
Ďalšie zdroje
Práca s WiFi modulom – scan WiFi sietí, pripojenie k WiFi, vytvorenie prístupového bodu
Inštalácia balíkov – inštalácia balíkov do mikrokontroléra v jazyku MicroPython
Dátové triedy – ako na dátové triedy pomocou triedy
BaseModel