This shows you the differences between two versions of the page.
si:laboratoare:11 [2024/12/14 20:55] florin.stancu removed |
si:laboratoare:11 [2024/12/15 17:36] (current) andreea.miu [Exercitii] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Laboratorul 11. CoAP & MQTT ====== | + | ===== Laboratorul 11. NuttX - MQTT ===== |
- | Internet of Things (IoT) este definit ca o colecție de noduri (things) care pot aduna informații din mediul în care se află, pot trimite aceste informații către o locație remote/locală și pot face anumite acțiuni. | + | ==== Despre IoT ==== |
- | Nodurile acestea sunt de obicei alimentate de la baterie, cu putere de procesare, memorie și lățime de bandă reduse. Nodurile sunt în general dispozitive embedded, identificate în mod unic, și conectate la Internet. | + | **Internet of Things** (IoT, sau “Internetul Lucrurilor”) este domeniul ce studiaza dispozitivele integrate (echipate cu senzori, modul de retea, firmware si software corespunzator etc.) prin prisma conexiunilor dintre acestea si a retelelor pe care le formeaza. |
+ | Dispozitivele IoT au ca scopuri principale colectarea si transmiterea de date, dar si efectuarea unor comenzi simple pe baza informatiilor primite. In viata cotidiana, retelele IoT sunt intalnite intr-o multitudine de spatii (orice spatiu poate deveni un spatiu //“inteligent”//), cateva exemple fiind: | ||
+ | * //sistemele de semaforizare inteligenta//, in care semafoarele isi schimba culoarea in functie de numarul de masini / pietoni in asteptare; | ||
+ | * //casele si cladirile inteligente//, in care putem controla temperatura, umiditatea, lumina ambientala etc. prin aplicatii mobile, asistent vocal, etc. | ||
+ | * //sere inteligente//, ce colecteaza date despre aer si sol si ajusteaza temperatura si frecventa de irigare a plantelor | ||
- | În acest laborator, vom utiliza două protocoale de comunicație frecvent utilizate în IoT. | + | Fie ca vorbim de senzori sau controllere, dispozitivele ce formeaza o retea IoT au resurse hardware limitate. De aceea, este ideal ca modalitatea de comunicare dintre dispozitive sa tina cont de restrictiile de memorie si alimentare. O modalitate eficienta prin care putem optimiza consumul de resurse este delegarea partii de management a datelor trimise, respectiv primite, cu ajutorul unui broker, ce va gestiona datele. |
+ | Aceasta paradigma este cunoscuta sub numele de //producator / consumator// (sau //“publisher / subscriber”//), si este implementata de multiple protocoale de comunicatie. In acest laborator vom folosi protocolul MQTT pentru a facilita transmisia de date, fiind unul dintre cele mai utilizate protocoale de comunicatie in retelele IoT. | ||
- | ==== CoAP ==== | ||
- | CoAP (Constrained Application Protocol) este un protocol de comunicare conceput pentru utilizarea în medii cu resurse limitate, în special în contextul IoT. Este folosit pe dispozitive cu resurse reduse (energie, memorie, lățime de bandă), și în rețelele cu pierderi de pachete. | ||
- | |||
- | CoAP funcționează peste UDP/IP și oferă un model simplu de interacțiune bazat pe cerere/răspuns, similar cu HTTP, ceea ce îl face potrivit pentru dispozitivele cu resurse limitate. | ||
- | |||
- | CoAP suportă cele 4 metode standard din HTTP, mai exact GET, POST, PUT și DELETE, care au aceeași semnificație cu cele din HTTP. De obicei nodul senzorial joacă rolul de server CoAP. | ||
- | * GET pentru a obține date de pe server | ||
- | * POST pentru a scrie o resursă de pe server | ||
- | * PUT pentru a actualiza o resursă de pe server | ||
- | * DELETE pentru a șterge o resursă de pe server | ||
- | |||
- | Există o multitudine de implementări software ale protocolului CoAP ([[https://en.wikipedia.org/wiki/Constrained_Application_Protocol#Implementations|Implementări]]), dar în acest laborator vom utiliza biblioteca [[https://github.com/hirotakaster/CoAP-simple-library|CoAP-simple-library]] pentru Arduino IDE pentru a rula un server CoAP și implementarea Python [[https://github.com/Tanganelli/CoAPthon|CoAPthon]] pentru a rula un client CoAP. | ||
- | |||
- | O captură Wireshark arată cum rulează protocolul CoAP peste protocolul UDP: | ||
- | |||
- | {{:iothings:laboratoare:lab7-coap-capture.png?600|}} | ||
==== MQTT ==== | ==== MQTT ==== | ||
- | MQTT (Message Queuing Telemetry Transport) este un protocol de comunicare eficient din punct de vedere al consumului de energie și fiabil. A fost dezvoltat pentru a facilita schimbul de mesaje între dispozitive cu resurse limitate, conectate în rețele cu lățime de bandă redusă, fiind ideal pentru IoT. | + | {{ :si:laboratoare:lab11-mqtt-flow.png?600 |}} |
- | MQTT este un protocol pentru transportul mesajelor de la un producător (publisher) la un consumator (subscriber). Spre deosebire de CoAP, care are o arhitectură client-server, MQTT folosește un intermediar (broker) pentru a livra mesajele de la producător la consumator. | + | In figura de mai sus putem observa modul de functionare al protocolului MQTT, in cadrul caruia intalnim urmatoarele: |
+ | * **Broker** - este reprezentat de un server si este elementul central al retelei, ce se ocupa de gestionarea datelor din reteaua IoT; | ||
+ | * **Clienti** - care sunt de 2 tipuri: | ||
+ | * //Producatori// (sau //“publisheri”//) - sunt dispozitivele care publica / trimit date catre broker, precum senzori si butoane | ||
+ | * //Consumatori// (sau //“subscriberi”//) - sunt dispozitivele ce primesc date de la broker, precum afisaje electronice sau aplicatii mobile | ||
+ | Mesajele transmise prin acest protocol sunt organizate folosind “topic”-uri, care descriu tipul de date transmise prin retea (de exemplu “temperatura”, “umiditate” etc.). Astfel, un client de tip subscriber se poate abona doar la topic-urile de interes pentru acesta, iar un clienti de tip publisher poate publica date pe anumite topic-uri, in functie de datele pe care le poate colecta. | ||
- | MQTT funcționează pe baza conceptului de topic-uri. Un topic este un identificator unic care definește un subiect de interes (ex. temperatura). | + | In cadrul laboratorului, vom folosi broker-ul MQTT public de la adresa //broker.hivemq.com//. |
- | Un dispozitiv care dorește să publice un mesaj se conectează la un broker MQTT. Brokerul este un server care intermediază comunicarea dintre clienții care publică și clienții care se abonează la mesaje. | ||
- | Când un client publică un mesaj, acesta specifică topicul mesajului. Brokerul transmite apoi mesajul tuturor clienților abonați la acel topic. | + | === MQTT in NuttX === |
- | Un client care dorește să se aboneze la mesaje se conectează la broker și specifică topicurile la care dorește să se aboneze. Când brokerul primește un mesaj pentru un topic la care un client este abonat, acesta transmite mesajul clientului. | + | Din NuttX, putem publica mesaje prin MQTT folosind aplicatia ''mqttc_pub'', din suita de aplicatii prezente in //nuttx-apps//. Dupa cum sugereaza si numele, aplicatia este un MQTT publisher, si are mai multe optiuni legate de publicarea mesajelor, printre care urmatoarele: |
- | {{:iothings:laboratoare:lab7-mqtt-flow.png|}} | + | * //-t// - topic-ul pe care se vor publica date (exemplu: //“temperature”//) |
+ | * //-m// - mesajul ce va fi publicat (exemplu: //“28 °C”//) | ||
- | ==== CoAP vs. MQTT ==== | + | ==== Exercitii ==== |
- | În această figură avem o comparație vizuală între protocoalele CoAP și MQTT. La MQTT avem un singur broker și mai mulți clienți care pot fi publisheri și/sau subscriberi. La CoAP putem avea mai multe servere care generează date (de obicei nodurile senzoriale) și mai mulți clienți care obțin acele date. | + | **1.** Folosind sistemul de build al NuttX, vom compila aplicatia ''mqttc_pub''. Codul sursa a acesteia il puteti gasi in ''apps/examples/mqttc''. |
- | {{:si:laboratoare:mqtt_coap.png?800|}} | + | * Pentru a compila aplicatia, revizuiti [[si:laboratoare/01|Laboratorul 01]]. Va trebui sa descarcati toolchain-ul, repository-urile //nuttx// si //nuttx-apps//, tabela de partitii si bootloader-ul. |
- | + | ||
- | + | ||
- | ==== Exerciții ==== | + | |
- | + | ||
- | Instalați Arduino IDE și adăugați board-ul ESP32 conform acestui [[https://randomnerdtutorials.com/installing-the-esp32-board-in-arduino-ide-windows-instructions/|tutorial]], dar alegeți tipul board-ului ''esp32-wrover-kit (all)'' pentru Sparrow ESP32. | + | |
- | + | ||
- | === Ex. 1 CoAP === | + | |
- | + | ||
- | Dorim să folosim CoAP pentru a stinge și aprinde un LED pe placa ESP32. Pentru asta trebuie ca placa ESP32 să fie configurată ca server CoAP și să răspundă la cererile primite de la clienți CoAP (laptop/dispozitiv mobil). | + | |
- | + | ||
- | == Ex. 1.1. Serverul CoAP pe ESP32 == | + | |
- | + | ||
- | Descărcați biblioteca [[https://github.com/hirotakaster/CoAP-simple-library|CoAP-simple-library]], dezarhivați-o și copiați-o în directorul cu biblioteci din Arduino IDE (de obicei în ''Documents/Arduino/libraries''). Este necesară repornirea Arduino IDE după instalarea unei biblioteci direct în acel director, în loc să utilizați Library Manager. | + | |
- | + | ||
- | {{:iothings:laboratoare:lab7-coap-server-png.png|}} | + | |
- | + | ||
- | Deschideți exemplul numit ''esp32'' din biblioteca ''CoAP_simple_library'' și ajustați codul astfel încât LED-ul să fie aprins prin CoAP. | + | |
- | + | ||
- | <note> | + | |
- | Pe placile Sparrow v1 (cele verzi), LED-ul este conectat la urmatoarele GPIO-uri: | + | |
- | * GPIO 25 - rosu | + | |
- | * GPIO 26 - verde | + | |
- | * GPIO 27 - albastru | + | |
- | Pe Sparrow v2 (placile albastre), folositi urmatoarele GPIO-uri: | + | |
- | * GPIO 13 - verde | + | |
- | * GPIO 14 - rosu | + | |
- | * GPIO 15 - albastru | + | |
- | </note> | + | |
<note important> | <note important> | ||
- | GPIO-urile la care este conectat LED-ul functioneaza in logica negativa. | + | Vom folosi o versiune diferita a toolchain-ului. Adaptati comenzile din primul laborator pentru numele acestui toolchain. |
- | </note> | + | |
- | + | ||
- | Conectați placa ESP32 la rețeaua WiFi (recomandăm să faceți un hotspot pe dispozitivul mobil, deoarece nu va merge cu rețeaua facultății). Completați în cod SSID-ul și parola rețelei. | + | |
- | + | ||
- | Rețineți adresa IP obținută de ESP32 pentru a fi utilizată în clientul CoAP. | + | |
- | + | ||
- | <note> | + | |
- | Portul implicit definit de CoAP este portul UDP 5683. În biblioteca ''CoAP_simple_library'' din Arduino IDE, portul este definit în fișierul ''libraries/CoAP_simple_library/coap-simple.h'' | + | |
<code> | <code> | ||
- | #define COAP_DEFAULT_PORT 5683 | + | wget https://github.com/espressif/crosstool-NG/releases/download/esp-14.2.0_20240906/xtensa-esp-elf-14.2.0_20240906-x86_64-linux-gnu.tar.xz |
</code> | </code> | ||
- | </note> | ||
- | |||
- | |||
- | == Ex. 1.2. Clientul CoAP == | ||
- | Instalați pe laptop biblioteca ''CoAPthon3'' din Python 3 folosind utilitarul ''pip'': | + | De asemenea, vom clona //nuttx// si //nuttx-apps// folosind urmatoarele comenzi: |
<code> | <code> | ||
- | python3 -mpip install CoAPthon3 | + | git clone --branch=si-lab-11 https://github.com/andreeaThePenguin/nuttx.git nuttx --depth 1 |
+ | git clone --branch=releases/12.7 https://github.com/andreeaThePenguin/nuttx-apps.git apps | ||
</code> | </code> | ||
- | <note important>Denumirea de ''CoAPthon'' este pentru Python 2 (nu se mai folosește).</note> | + | </note> |
- | Folosiți următoarea comandă pentru a aprinde și stinge LED-ul: | + | * Pentru a configura NuttX cu suport pentru aplicatia ''mqttc_pub'', vom folosi urmatoarea comanda: <code> |
- | + | ./tools/configure.sh esp32-sparrow-kit:mqttc | |
- | <code> | + | |
- | # pe sistemele *nix, pip a instalat coapclient.py în PATH | + | |
- | coapclient.py -o PUT -p "coap://192.168.1.151/light" -P "1" | + | |
</code> | </code> | ||
+ | * Compilati NuttX, folositi ''esptool'' pentru a sterge continutul memoriei flash a placii, si scrieti imaginea pe aceasta (vedeti [[si:laboratoare/01|Laboratorul 1]]). | ||
+ | * Conectati-va la seriala placii folosind utilitarul picocom: <code> | ||
+ | picocom /dev/ttyUSB0 -b 115200 </code> | ||
+ | * Verificati ca aplicatia e instalata, folosind comanda: ''?'', care va afiseaza toate aplicatiile disponibile pe versiunea de NuttX compilata si incarcata anterior. | ||
- | <note important>Folosiți adresa IP a plăcii ESP32. | + | **2.** Pentru a putea testa aplicatia, ne dorim sa cream un setup de tipul //Publisher-Subscriber//. Pentru aceasta, vom crea un MQTT subscriber care sa primeasca datele trimise de MQTT publisher (reprezentat de placa). |
- | Laptop-ul și placa ESP32 trebuie să fie conectate în aceeași rețea WiFi. | + | |
- | </note> | + | |
- | <hidden> | + | * Instalati libraria ''paho-mqtt'' pe masina virtuala: <code> |
- | == Ex. 1.3. Aplicația Android ''IoT CoAP'' == | + | pip3 install paho-mqtt |
+ | </code> | ||
+ | * Preluati scriptul Python 3 de mai jos, si plasati-l pe masina virtuala; acest script joaca rolul de MQTT subscriber din figura prezentata in laborator. Pregatiti un terminal separat (ideal: pe care sa il puteti vedea in paralel cu primul) din care veti rula la finalul exercitiului acest script. | ||
- | <note important> | + | <file python mqtt_subscriber.py> |
- | Atentie: Aplicația ''IoT CoAP'' nu mai funcționează pe noile versiuni de Android. | + | import paho.mqtt.client as mqtt |
- | </note> | + | import ssl |
- | Descărcați și instalați aplicația ''IoT CoAP'' din Google Play Store. Folosiți aplicația pentru a trimite mesaje către placa ESP32 pentru a aprinde și stinge LED-ul. | + | broker = "broker.hivemq.com" |
+ | port = 1883 | ||
+ | topic = "si-labs" | ||
- | {{:iothings:laboratoare:lab7-iot-coap-app.png|}} | + | # This is the Subscriber |
+ | def on_connect(client, userdata, flags, rc, properties): | ||
+ | print("Connected with result code: " + str(rc)) | ||
+ | print("Subscribing to topic: ", topic) | ||
+ | client.subscribe(topic) | ||
- | </hidden> | + | def on_message(client, userdata, msg): |
+ | print("Received message: ", str(msg.payload.decode("utf-8"))) | ||
- | === Ex. 2 MQTT === | + | client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) |
- | Dorim să controlăm LED-ul plăcii ESP32 prin protocolul MQTT. Placa ESP32 va avea rol de subscriber pe un anumit topic, iar laptopul va avea rol de publisher pe același topic. Astfel, prin mesajul MQTT trimis de la laptop vom aprinde și vom stinge LED-ul plăcii. | + | client.on_connect = on_connect |
+ | client.on_message = on_message | ||
- | Instalați biblioteca ''PubSubClient'' din Library Manager al Arduino IDE și deschideți exemplul ''mqtt_esp8266''. | + | if port == 8883: |
+ | client.tls_set(tls_version=ssl.PROTOCOL_TLSv1_2) | ||
+ | |||
+ | client.connect(broker, port, 60) | ||
- | {{:iothings:laboratoare:lab7-mqtt-esp8266.png|}} | + | client.loop_forever() |
+ | </file> | ||
- | Deși este scris pentru ESP8266, puteți rula programul pe ESP32 prin modificarea următoarei linii: | + | * Pentru a putea trimite mesaje folosind ESP32, vom conecta placa la WiFi. Puteti folosi orice retea WiFi disponibila (ideal: activati un hotspot cu ajutorul telefonului). Folositi urmatorii pasi pentru a conecta placa la reteaua WiFi: <code> |
+ | ifup wlan0 | ||
+ | wapi psk wlan0 <mypasswd> 3 | ||
+ | wapi essid wlan0 <myssid> 1 | ||
+ | renew wlan0 | ||
+ | </code> | ||
- | <code> | + | * In final, veti avea deschise 2 terminale: unul ce ruleaza scriptul Python (MQTT subscriber), si altul ce afiseaza seriala placii, pe care se afla MQTT publisher-ul. Pentru a publica date, folosim comanda: <code> |
- | - #include <ESP8266WiFi.h> | + | mqttc_pub -t si-labs -m <message> |
- | + #include <WiFi.h> | + | |
</code> | </code> | ||
+ | * Trimiteti mai multe date modificand topic-ul si valoarea. | ||
- | Placa ESP32 va folosi clientul MQTT pentru a se înregistra ca subscriber la topic-ul ''inTopic'' și pe laptop vom instala biblioteca ''paho-mqtt'' pentru a instanția un client MQTT în modul publisher. Pentru a instala ''paho-mqtt'', utilizați următoarea comandă: | + | <note important> |
+ | Schimbati numele topic-ului atat in scriptul Python, cat si in comanda de mai sus (altfel, veti primi si mesajele de la ceilalti colegi). | ||
+ | </note> | ||
- | <code> | + | **3.** Dorim sa trimitem date mai utile catre script-ul nostru de Python, pentru a simula un scenariu real de transmisie a datelor. Mai exact, vom prelua date de la senzorul LTR308, ce capteaza intensitatea luminoasa, apoi vom repeta setup-ul de la exercitiul 2. |
- | pip install paho-mqtt | + | |
+ | * Inspectati exemplul ''apps/examples/ltr308'' pentru a vedea cum se utilizeaza senzorul LTR308 (optional, puteti sa il si compilati si testati). Pornind de la acest exemplu, veti modifica aplicatia ''apps/examples/mqttc_pub''. | ||
+ | * Pentru a modifica aplicatia, vom folosi scheletul prezent pe branch-ul ''si-lab-11'' din ''nuttx-apps'' repo. Din directorul //apps//, schimbati branch-ul folosind: <code> | ||
+ | git checkout si-lab-11 | ||
</code> | </code> | ||
- | Folosiți {{:iothings:laboratoare:mypythonmqttclient.py.txt|acest}} program Python pentru a aprinde și stinge LED-ul pe placa ESP32. | + | <note tip> |
+ | Puteti verifica ca lucrati pe branch-ul corect folosind comanda ''git branch''. | ||
+ | </note> | ||
- | Veți utiliza broker-ul MQTT public de la adresa „test.mosquitto.org”, atât pentru clientul MQTT al ESP32, cât și pentru clientul Python. Din acest motiv, este important să schimbați numele topicului pentru a nu primi mesaje de la alte dispozitive din Internet care utilizează același server public. | + | * Urmati TODO-urile marcate cu **(3)** din ''apps/examples/mqttc_pub''. |
- | + | * Dupa completarea codului, revenim in directorul //nuttx//. Pentru a putea folosi senzorul LTR308, aplicam urmatoarele configuratii la rularea ''make menuconfig'', peste configuratia folosita initial, de ''mqttc'': | |
- | <note important> | + | * ''CONFIG_SENSORS=y'' |
- | Modificați topic-ul „inTopic” în „si-lab10-myLED-inTopic”. | + | * ''CONFIG_SENSORS_LTR308=y'' |
- | </note> | + | * Compilati NuttX si incarcati-l pe placa. Folosind setup-ul de la exercitiul 2, cu cele 2 terminale deschise in paralel, transmiteti date folosind aplicatia ''mqttc_pub'' si captati-le folosind scriptul Python. |
- | ===== Resources ===== | + | <note important> |
+ | Deoarece mesajul transmis este preluat de la senzor, rulam aplicatia folosim comanda: <code> | ||
+ | mqttc_pub -t si-labs</code> | ||
+ | </note> | ||
- | * https://github.com/Tanganelli/CoAPthon | + | ==== Resurse ==== |
- | * https://github.com/hirotakaster/CoAP-simple-library | + | * [[https://nuttx.apache.org/docs/latest/|Documentatia oficiala NuttX]] |
- | * https://en.wikipedia.org/wiki/Constrained_Application_Protocol | + | * [[https://robots.net/tech/what-is-mqtt-in-iot/| What is MQTT in IoT?]] |
- | * https://play.google.com/store/apps/details?id=ch.buedev.iot_coap&hl=en&gl=US | + | * [[https://nuttx.apache.org/docs/latest/platforms/xtensa/esp32/boards/esp32-devkitc/index.html#mqttc| ESP32 DevKitC - mqttc]] |
- | * https://www.digikey.de/en/maker/blogs/2019/how-to-use-mqtt-with-the-raspberry-pi | + |