====== 7. Internet a MQTT ======
===== Cíle cvičení =====
* Připojení Raspberry Pi Pico k internetu
* Připojení k MQTT brokeru a přihlášení k odběru zpráv
===== Připojení k Internetu =====
Připojení k Internetu je v MicroPythonu realizováno třídou [[https://docs.micropython.org/en/latest/library/network.WLAN.html|WLAN]] z modulu [[https://docs.micropython.org/en/latest/library/network.html|network]].
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, pwd)
while wlan.isconnected() == False:
pass
print('is connected')
===== MQTT =====
Aby bylo možné komunikovat, je třeba mít přístup na MQTT server, tzv. broker. Je buď možné využít veřejně dostupný (např. [[https://www.hivemq.com/public-mqtt-broker/|HiveMQ]], vytvořit si vlastní instanci v cloudu (např. [[https://devcenter.heroku.com/articles/cloudmqtt|Heroku]], [[https://cloud.google.com/iot/docs/how-tos/mqtt-bridge|Google]]) nebo si vytvořit vlastní, klidně na svém počítači. Patrně nejznámějším volně dostupným MQTT brokerem je [[https://mosquitto.org/|Mosquitto]]. Pro naše účely využijeme volně přístupný broker na adrese [[https://mqtt.eclipseprojects.io/]].
==== MQTT protokol =====
Pro využití [[https://www.root.cz/clanky/protokol-mqtt-komunikacni-standard-pro-iot/|MQTT]] potřebujeme znát následující pravidla komunikace:
* MQTT funguje na principu návrhového vzoru [[https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern|publisher-subscriber]]
* subscriber se přihlašuje k odběru zpráv, které přicházejí v rámci tématu (topic)
* publisher posílá zprávy do tématu, zpráva se dostane ke všem subscriberům, kteří se přihlásili k odběru
==== Python ====
Pro vytvoření odběratele zpráv na PC (server) použijeme knihovnu [[https://pypi.org/project/paho-mqtt/|paho-mqtt]].
pip install paho-mqtt
=== MQTT subscriber ===
Následující kód přečte dvě zprávy ze všech zpráv (topic ''#'' reprezentuje všechny zprávy), které v okamžiku připojení brokerem procházejí.
import paho.mqtt.subscribe as subscribe
topics = ['#']
m = subscribe.simple(topics, hostname="mqtt.eclipseprojects.io", retained=False, msg_count=2)
for a in m:
print(a.topic)
print(a.payload)
Pochopitelně nepotřebujeme přijímat všechny zprávy, ale pouze zprávy, které přijímat chceme. Následující kód se přihlásí k odběru topicu ''nsi/test'' a může přijímat zprávy, které do něj někdo pošle. Použijeme také asychronní zpracování dat pomocí callback funkce ''print_msg()'', která se zavolá v okamžiku, kdy se v topicu objeví zpráva:
import paho.mqtt.subscribe as subscribe
def print_msg(client, userdata, message):
print("%s : %s" % (message.topic, message.payload))
subscribe.callback(print_msg, "nsi/test", hostname="mqtt.eclipseprojects.io")
=== MQTT publisher ===
Aby se v topicu objevila zpráva, je třeba ji tam publikovat.
import paho.mqtt.publish as publish
publish.single("nsi/test", "nazdar!", hostname="mqtt.eclipseprojects.io")
==== MicroPython ====
Knihoven s podporou MQTT protokolu existuje v MicroPythonu několik, zde použijeme [[https://pypi.org/project/micropython-umqtt.simple/|umqtt.simple]]. Bohužel tuto knihovnu nelze v současnosti instalovat přes standardní správu balíčků v prostředí Thonny (**Tools -> Manage packages**), ovšem pokud je RPi Pico připojeno k Internetu, lze nainstalovat balíček přímo z online repozitáře.
import mip
mip.install('umqtt.simple')
=== MQTT subscriber ===
Dokumentaci k modulu lze najít [[https://mpython.readthedocs.io/en/master/library/mPython/umqtt.simple.html|zde]]. Základní příklad, ve kterém se klient přihlásí k odběru ''nsi/test'', by mohl vypadat např. takto (samozřejmě za předpokladu, že je RPi připojeno k Internetu):
import time
import ubinascii
from umqtt.simple import MQTTClient
MQTT_BROKER = "mqtt.eclipseprojects.io"
CLIENT_ID = ubinascii.hexlify(machine.unique_id())
SUBSCRIBE_TOPIC = b"nsi/test"
def sub(topic, msg):
print('received message %s on topic %s' % (msg, topic))
client = MQTTClient(CLIENT_ID, MQTT_BROKER, keepalive=60)
client.set_callback(sub)
client.connect()
print('Connected to MQTT Broker "%s"' % (MQTT_BROKER))
client.subscribe(SUBSCRIBE_TOPIC)
while True:
if True:
client.wait_msg()
else:
client.check_msg()
time.sleep(1)
=== MQTT publisher ===
import time
import ubinascii
from umqtt.simple import MQTTClient
MQTT_BROKER = "mqtt.eclipseprojects.io"
CLIENT_ID = ubinascii.hexlify(machine.unique_id())
SUBSCRIBE_TOPIC = b"nsi/test"
PUBLISH_TOPIC = b"nsi/test"
def sub(topic, msg):
print('received message %s on topic %s' % (msg, topic))
client = MQTTClient(CLIENT_ID, MQTT_BROKER, keepalive=60)
client.set_callback(sub)
client.connect()
print('Connected to MQTT Broker "%s"' % (MQTT_BROKER))
client.publish(PUBLISH_TOPIC, "ahoj!", qos=0)
==== Zadání 4. miniprojektu ====
Rozšiřte stávající serverovou aplikaci o vládání dat do databáze přes MQTT rozhraní nebo z Raspberry Pi Pico prostřednictvím již vytvořeného REST API. Využijte k tomu MQTT rozšíření Flasku [[https://pypi.org/project/Flask-MQTT/|flask-mqtt]].