Pripojenie do internetu

o pripojení do internetu, synchronizácii času, stiahnutí a nainštalovaní rozširujúcich modulov pre MicroPython a pripojení k MQTT brokeru

Video pre cvičenie

Motivácia

Na minulom cvičení sme vytvorili základnú podobu stavového stroja nášho chytrého zariadenia. V rámci neho sme vytvorili niekoľko stavov a zabezpečili sme, že zariadenie po spustení vykoná samodiagnostiku, overí, či nemá obnoviť výrobné nastavenia, a nakoniec odmerá teplotu a vlhkosť a uloží ich do súboru. Posledný krok, ktorý nám chýba k zabezpečeniu základnej činnosti zariadenia, je tieto údaje poslať do “cloudu” pomocou protokolu MQTT. No a presne tomu sa budeme venovať na tomto cvičení.

Stavový stroj zariadenia

Ciele

  • naučiť sa pripojiť mikrokontrolér k WiFi v jazyku MicroPython

  • naučiť sa nainštalovať rozširujúce moduly na MicroPython zariadenie

  • naučiť sa synchronizovať čas pomocou prokolu NTP

  • naučiť sa základy práce s komunikačným protokolom MQTT

Postup

Pripojenie k WiFi

Dnešným cieľom je zabezpečiť komunikáciu pomocou protokolu MQTT. Tento protokol patrí medzi aplikačné protokoly ISO/OSI modelu. Takže ak ho chceme využiť na komunikáciu, musíme sa najprv pripojiť do siete pomocou WiFi modulu.

Task

Rozšírte podobu konfiguračného súboru o konfiguráciu WiFi pripojenia.

Na koreňovej úrovni slovníka pridajte kľúč wifi a do neho pridajte slovník s kľúčmi ssid a key. Výsledná konfigurácia teda bude vyzerať nasledovne:

{
  ...
  "wifi": {
    "ssid": "<ssid>",
    "key": "<key>"
  }
}

Task

Do stavového stroja pridajte kostru nového stavu s názvom ConnectToWiFi, do ktorého sa zariadenie dostane po ukončení stavu Measurement, a z ktorého zariadenie prejde do stavu Sleep.

Task

V novovytvorenom stave sa pripojte do WiFi siete pomocou hodnôt uložených v konfiguračnom súbore.

Na pripojenie do siete použijeme funkciu s názvom do_connect(), ktorá sa nachádza priamo v dokumentácii jazyka MicroPython. Funkciu akurát mierne upravíme, aby:

  • bola inštančnou metódou stavu
  • mala dva parametre pre názov siete a kľúč do siete

Výsledná metóda bude vyzerať takto:

def _do_connect(self, ssid, key):
    import network
    wlan = network.WLAN(network.STA_IF)
    if not wlan.isconnected():
        print(f'Connecting to network {ssid}...')
        wlan.active(True)
        wlan.connect(ssid, key)
        while not wlan.isconnected():
            pass
    print('network config:', wlan.ipconfig('addr4'))

Task

Aktualizujte stav Sleep tak, aby sa nakoniec zariadenie od siete WiFi odpojilo.

Odpojiť od WiFi je možné zavolaním metódy .disconnect() nad sieťovým rozhraním. Rovnako je však možné zavolať aj metódu .deinit(), ktorá modul vypne. Tým dôjde aj k zníženiu spotreby zariadenia.

Task

Overte svoju implementáciu.

Ak ste postupovali správne, po úspešnom pripojení sa vám vypíše IP adresa a maska sieťového rozhrania, a pri prechode stavom Sleep sa zariadenie od siete odpojí a vypne WiFi modul.

Správny čas

Pri odosielaní nameraných dát budeme do správy pridávať aj informáciu o čase, kedy k meraniu došlo. To, kedy boli údaje namerané, je dôležité vedieť najmä vtedy, keď budeme údaje merať, alebo ich pošleme neskôr ako súbor meraní.

Mikrokontrolér RP2040, ktorý je osadený na doske Raspberry Pi Pico WH je už vybavený modulom hodín reálneho času (RTC). V tomto kroku teda urobíme všetko preto, aby sme ho vedeli nastaviť a rovnako tak využívať pre naše merania.

Pre úplnosť je potrebné dodať, že čas pri odosielaní, prijímaní a ukladaní do databázy budeme reprezentovať v štandarde UTC.

Task

Rozšírte svoj konfiguračný súbor o nový kľúč ntpHost, ktorý bude obsahovať názov servera, voči ktorému bude mikrokontrolér synchronizovať svoj čas.

Predvolenú hodnotu nastavte na pool.ntp.org.

Task

V stave inicializujúcom zariadenie nastavte hodnotu premennej npttime.host podľa aktuálnej hodnoty v konfigurácii.

Task

Aktualizujte stav ConnectToWifi tak, aby sa po pripojení do internetu automaticky zosynchronizoval aj čas pomocou protokolu NTP.

Task

Aktualizujte proces meraní o pridanie časovej značky k jednotlivým meraniam.

Upravte svoju implementáciu vzhľadom na to, ako v akom formáte údaje lokálne ukladáte.

Inštalácia modulu pre prácu s protokolom MQTT

V aktuálnom firmvéri jazyka MicroPython pre mikrokontrolér RP2040 sa nenachádza modul pre prácu s protokolom MQTT. V tomto kroku ho nainštalujeme.

Na inštaláciu máme dve možnosti:

  1. Inštalácia priamo z prostredia editora Thonny

    1. prejdite do menu Tools > Package management...

    2. v dialógovom okne vyhľadajte modul umqtt.simple

    3. kliknite na tlačidlo Install, pomocou ktorého modul nainštalujete

    Výhodou tohto prístupu je, že na inštaláciu modulu nie je potrebné, aby bol mikrokontrolér pripojený do siete. Problém však je, že ak máte na vašom počítači nainštalovaný Python vo verzii 3.12 a vyššie, inštalácia skončí s chybou. Ak je to váš prípad, na inštaláciu modulu použite druhú možnosť.

  2. Inštalácia z rozhrania REPL mikrokontroléra

    1. pripojte sa s vašim mikrokontrolérom do siete WiFi

    2. v rozhraní REPL (terminál, príkazový riadok mikrokontroléra) importujte modul mip:

      >>> import mip
    3. nad modulom mip spustite inštaláciu modulu zavolaním funkcie .install() s názvom inštalovaného modulu:

      >>> mip.install('umqtt.simple')

Umiestnenie nainštalovaného modulu bude /lib/umqtt/simple.mpy.

Pripojenie k MQTT brokeru

V tomto kroku zabezpečíme všetko potrebné pre pripojenie k MQTT brokeru - od úpravy konfiguračného súboru, cez vytvorenie klienta až po pripojenie a odpojenie od MQTT broker-a.

Task

Rozšírte podobu konfiguračného súboru o konfiguráciu pre pripojenie k MQTT broker-u.

Na koreňovej úrovni slovníka pridajte kľúč mqtt a do neho pridajte slovník s kľúčmi clientId, server, port, user a password. Výsledná konfigurácia teda bude vyzerať nasledovne:

{
  ...
  "mqtt": {
    "client_id": "unique client id",
    "server": "mqtt broker ip address",
    "port": 1883,
    "user": "username",
    "password": "password for user",
  }
}

Význam jednotlivých položiek je nasledovný:

  • client_id - jedinečný identifikátor MQTT klienta (ak sa k brokeru pripojí viac klientov s rovnakým id, spôsobí to problémy pri doručovaní správ)
  • server - adresa MQTT brokera
  • port - port, na ktorom počúva MQTT broker, štandardne sa jedná o port 1883
  • user - meno používateľa
  • password - heslo používateľa

Pre experimentovanie môžete použiť nasledovnú konfiguráciu, pomocou ktorej sa pripojíte na hlavný MQTT broker v architekúre Smart Department:

{
  ...
  "mqtt": {
    "client_id": "unique-client-id",
    "server": "147.232.205.176",
    "port": 1883,
    "user": "maker",
    "password": "mother.mqtt.password",
  }
}

Task

Do stavového stroja pridajte kostru nového stavu s názvom PublishData, do ktorého sa zariadenie dostane po ukončení stavu ConnectToWifi, a z ktorého zariadenie prejde do stavu Sleep.

Task

Vytvorte inštanciu MQTT klienta z triedy MQTTClient

MQTT klienta vytvoríte týmto fragmentom kódu:

from umqtt.simple import MQTTClient

client = MQTTClient(client_id, server, port, user, password)

Význam jednotlivých parametrov zodpovedá významu konfiguračných parametrov.

Task

Pripojte sa vytvoreným klientom k MQTT brokeru a následne sa odpojte.

Pripojenie zabezpečíte metódou .connect() a odpojenie zabezpečíte metódou .disconnect(). Výsledný fragment kódu, pomocou ktorého vytvoríte MQTT klienta, pripojíte sa k brokeru a následne sa od neho odpojíte, bude vyzerať takto:

from umqtt.simple import MQTTClient

client = MQTTClient(client_id, server, port, user, password)
client.connect()
# tu príde vaša komunikácia s MQTT brokerom
client.disconnect()

Task

Overte svoju implementáciu.

Ak ste postupovali správne, vaše zariadenie prejde všetkými stavmi bez chyby. Otestujte aj prípadnú chybu napr. nesprávnymi prihlasovacími údajmi alebo nesprávnou identifikáciou MQTT brokera.

Pred odchodom z cvičenia…

Ďalšie úlohy

  1. Aktuálna implementácia funkcie na pripojenie do siete WiFi nie je dobrá, pretože pokiaľ sa funkcii nepodarí pripojiť do siete, funkcia uviazne v nekonečnej slučke. Upravte preto túto funkciu tak, aby sa o pripojenie pokúsila 3x v niekoľkosekundových intervaloch. Pokiaľ k pripojeniu do siete nedôjde, ukončite funkciu zariadenia prechodom do stavu Error.

  2. Aktualizujte implementáciu stavu FactoryReset tak, aby vygeneroval náhodnú hodnotu identifikátora klienta pre komunikáciu s MQTT protokolom.

  3. Zabezpečte, aby v prípade vzniku akejkoľvek chyby vaše zariadenie prešlo do stavu Error.

  4. V module helpers.py vytvorte funkciu to_iso8601(), ktorá prevedie n-ticu reprezentujúcu aktuálny dátum a čas alebo časovú značku na reťazec reprezentujúci dátum a čas vo formáte podľa štandardu ISO 8601.

Ďalšie zdroje

  • MicroPython: Network basics
  • MicroPython Lib: umqtt.simple - zdrojové kódy, ukážkové príklady a dokumentácia
  • ISO 8601 - medzinárodný štandard pre zápis dátumu a času