Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:laboratoare:2025:lab3 [2025/10/10 23:47]
dan.tudose
iothings:laboratoare:2025:lab3 [2025/10/11 00:29] (current)
dan.tudose [Lab 3. The MQTT Protocol]
Line 3: Line 3:
 MQTT (Message Queuing Telemetry Transport) is a lightweight,​ publish-subscribe network protocol designed for efficient communication in constrained environments. Originally developed by IBM in the late 1990s, MQTT has become a standard for IoT (Internet of Things) systems due to its low bandwidth requirements and minimal overhead. It is mostly used in Home Automation systems, Industrial IoT applications and Mobile Messaging and Telemetry. MQTT (Message Queuing Telemetry Transport) is a lightweight,​ publish-subscribe network protocol designed for efficient communication in constrained environments. Originally developed by IBM in the late 1990s, MQTT has become a standard for IoT (Internet of Things) systems due to its low bandwidth requirements and minimal overhead. It is mostly used in Home Automation systems, Industrial IoT applications and Mobile Messaging and Telemetry.
  
 +{{ :​iothings:​laboratoare:​2025:​mqtt-pubsub-model.jpg?​600 |}}
 ==== Key Concepts ==== ==== Key Concepts ====
  
Line 28: Line 29:
  
 In this lab, you'll interact with an MQTT broker, publish sensor data from your Sparrow sensor node, and visualize real-time telemetry. Familiarity with topics and QoS settings will be essential to design robust IoT communication systems. In this lab, you'll interact with an MQTT broker, publish sensor data from your Sparrow sensor node, and visualize real-time telemetry. Familiarity with topics and QoS settings will be essential to design robust IoT communication systems.
 +
 +
 +==== Platformio.ini ====
 +You will need to add this to yout Platformio project:
 +<code bash platformio.ini>​
 +; PlatformIO Project Configuration File
 +;
 +;   Build options: build flags, source filter
 +;   ​Upload options: custom upload port, speed and extra flags
 +;   ​Library options: dependencies,​ extra library storages
 +;   ​Advanced options: extra scripting
 +;
 +; Please visit documentation for the other options and examples
 +; https://​docs.platformio.org/​page/​projectconf.html
 + 
 +[env:​esp32-c6-sparrow]
 +platform = https://​github.com/​pioarduino/​platform-espressif32/​releases/​download/​54.03.20/​platform-espressif32.zip
 +board = esp32-c6-devkitm-1
 +framework = arduino
 + 
 +build_flags =
 +  -D ARDUINO_USB_MODE=1
 +  -D ARDUINO_USB_CDC_ON_BOOT=1
 +  -D ESP32_C6_env
 + 
 +monitor_speed = 115200
 + 
 +lib_deps =
 +  adafruit/​Adafruit NeoPixel@^1.11.0
 +  adafruit/​Adafruit BME680 Library
 +  bblanchon/​ArduinoJson @ ^7
 +  256dpi/MQTT @ ^2.5.2 ​      
 +</​code>​
  
 ===== MQTT “Hello World” (publish a heartbeat) ===== ===== MQTT “Hello World” (publish a heartbeat) =====
  
-Goal: connect to Wi-Fi, connect to MQTT, then publish a heartbeat every 5s to iot/<​yourname>/​heartbeat.+<note tip>Goal: connect to Wi-Fi, connect to MQTT, then publish a heartbeat every 5s to iot/<​yourname>/​heartbeat.</​note>​ 
 + 
 +This example connects an ESP32 to Wi-Fi and establishes an MQTT connection to a public broker (test.mosquitto.org). It sets up a unique client ID based on the ESP32’s MAC address, registers a “Last Will” message so that if the device disconnects unexpectedly,​ the broker automatically marks it as offline, and then publishes an “online” status when connected. It also subscribes to all topics under a user-defined base topic (like iot/​studentname/#​),​ so it can receive messages addressed to that namespace, and logs any received messages to the serial monitor. 
 + 
 +Once connected, the ESP32 enters a loop where it continuously maintains the MQTT session, reconnects if needed, and publishes a heartbeat message every five seconds containing its uptime in milliseconds. This heartbeat acts as a regular signal that the device is alive. The code’s use of non-blocking MQTT functions keeps the system responsive, while the combination of retained status messages and the Last Will feature ensures other clients always know the ESP32’s current state — whether it’s online, offline, or actively sending updates.
  
 <code C main.cpp>​ <code C main.cpp>​
-// src/​main.cpp 
 #include <​Arduino.h>​ #include <​Arduino.h>​
 #include <​WiFi.h>​ #include <​WiFi.h>​
-#include <PubSubClient.h>+#include <MQTT.h> ​  // 256dpi MQTT library
  
 ////////////////​ EDIT THESE ////////////////​ ////////////////​ EDIT THESE ////////////////​
-const char* WIFI_SSID ​    = "TP-Link_2A64"; +const char* WIFI_SSID ​    = "YOUR_SSID"; 
-const char* WIFI_PASSWORD = "99481100";+const char* WIFI_PASSWORD = "YOUR_PASSWORD";
 const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker
 const uint16_t MQTT_PORT ​ = 1883; const uint16_t MQTT_PORT ​ = 1883;
-const char* BASE_TOPIC ​   = "iot/dantudose"; ​        ​// change per student+const char* BASE_TOPIC ​   = "iot/studentname"; ​       // change per student
 ////////////////////////////////////////////​ ////////////////////////////////////////////​
  
-WiFiClient ​espClient+WiFiClient ​net
-PubSubClient ​mqtt(espClient);+MQTTClient ​mqtt(1024);  // 1KB message buffer
  
-void ensureWiFi() {+unsigned long lastPub = 0; 
 + 
 +void connectWiFi() {
   if (WiFi.status() == WL_CONNECTED) return;   if (WiFi.status() == WL_CONNECTED) return;
   WiFi.mode(WIFI_STA);​   WiFi.mode(WIFI_STA);​
Line 56: Line 95:
   Serial.print("​WiFi connecting"​);​   Serial.print("​WiFi connecting"​);​
   while (WiFi.status() != WL_CONNECTED) {   while (WiFi.status() != WL_CONNECTED) {
-    delay(500); Serial.print("​."​);​+    delay(500); 
 +    ​Serial.print("​."​);​
   }   }
   Serial.printf("​\nWiFi OK, IP: %s\n", WiFi.localIP().toString().c_str());​   Serial.printf("​\nWiFi OK, IP: %s\n", WiFi.localIP().toString().c_str());​
 } }
  
-void ensureMQTT() { +void messageReceived(String &topic, String &​payload) { 
-  ​if (mqtt.connected()) return; +  ​Serial.printf("Message on %s: %s\n", topic.c_str(), payload.c_str()); 
-  String clientId = String("sparrow-c6-") + String((uint32_t)ESP.getEfuseMac(), HEX); +}
-  Serial.println("MQTT connecting..."​)+
-  Serial.println("​Client ID:");  +
-  ​Serial.print(clientId);​+
  
 +void connectMQTT() {
 +  // Build a real String, then pass c_str()
 +  String clientId = "​esp32-client-"​ + String((uint32_t)ESP.getEfuseMac(),​ HEX);
 +
 +  Serial.println("​MQTT connecting..."​);​
   while (!mqtt.connect(clientId.c_str())) {   while (!mqtt.connect(clientId.c_str())) {
     Serial.print("​."​);​     Serial.print("​."​);​
     delay(1000);​     delay(1000);​
   }   }
-  Serial.println("​\nMQTT connected"​);​+  Serial.println("​\nMQTT connected!"); 
 + 
 +  // Optional subscription 
 +  String subTopic = String(BASE_TOPIC) + "/#";​ 
 +  mqtt.subscribe(subTopic);​ 
 +  Serial.printf("​Subscribed to %s\n", subTopic.c_str());
 } }
- 
-unsigned long lastPub = 0; 
  
 void setup() { void setup() {
   Serial.begin(115200);​   Serial.begin(115200);​
-  delay(1000); +  delay(500); 
-  ​WiFi.useStaticBuffers(true); ​  ​// small memory win on C6 + 
-  mqtt.setServer(MQTT_HOSTMQTT_PORT);+  ​connectWiFi();​ 
 + 
 +  mqtt.begin(MQTT_HOST, MQTT_PORT, net); 
 +  mqtt.onMessage(messageReceived);​ 
 + 
 +  // Optional: last will so brokers/​clients know if we drop 
 +  String willTopic = String(BASE_TOPIC) + "/​status";​ 
 +  mqtt.setWill(willTopic.c_str(),​ "​offline", ​true, 1); 
 + 
 +  connectMQTT();​ 
 + 
 +  ​// Publish "​online"​ once connected 
 +  mqtt.publish(willTopic"​online",​ true, 1);
 } }
  
 void loop() { void loop() {
-  ​ensureWiFi(); +  ​connectWiFi();       // ensure WiFi 
-  ​ensureMQTT(); +  ​if (!mqtt.connected()) connectMQTT(); 
-  mqtt.loop();​+  mqtt.loop();         // non-blocking 
 +  delay(10);
  
 +  // Publish every 5 seconds
   if (millis() - lastPub > 5000) {   if (millis() - lastPub > 5000) {
     lastPub = millis();     lastPub = millis();
     String topic = String(BASE_TOPIC) + "/​heartbeat";​     String topic = String(BASE_TOPIC) + "/​heartbeat";​
     String payload = String("​{\"​uptime_ms\":"​) + millis() + "​}";​     String payload = String("​{\"​uptime_ms\":"​) + millis() + "​}";​
-    bool ok = mqtt.publish(topic.c_str(), payload.c_str()); +    bool ok = mqtt.publish(topic,​ payload); 
-    Serial.printf("​Publish %s => %s (%s)\n",​ topic.c_str(),​ payload.c_str(),​ ok ? "​OK"​ : "​FAIL"​);​+    Serial.printf("​Publish %s => %s (%s)\n",​ 
 +                  ​topic.c_str(),​ payload.c_str(),​ ok ? "​OK"​ : "​FAIL"​);​
   }   }
 } }
Line 104: Line 164:
 ===== Subscribe & control the on-board NeoPixel ===== ===== Subscribe & control the on-board NeoPixel =====
  
-Goal: subscribe to iot/<​yourname>/​led and set the Sparrow’s single WS2812 LED color from JSON payloads like {"​r":​255,"​g":​0,"​b":​64}.+<note tip>Goal: subscribe to iot/<​yourname>/​led and set the Sparrow’s single WS2812 LED color from JSON payloads like {"​r":​255,"​g":​0,"​b":​64}
 +</​note>​ 
 + 
 +This example, once connected, subscribes to a topic that controls an RGB LED connected to the board. Whenever a new MQTT message arrives on that topic, the ESP32 reads the JSON payload, extracts the red, green, blue, and brightness values, and updates the LED accordingly.  
 + 
 +After setting the LED color, the device publishes an acknowledgment message to a separate MQTT topic, confirming the values it received and applied. This acknowledgment lets any remote controller or dashboard know that the LED update was successful. The whole process uses the non-blocking,​ event-driven design of the 256dpi library, meaning it can handle MQTT communication efficiently without freezing the microcontroller’s main loop. In essence, this sketch turns the ESP32 into a small, networked RGB controller that listens for MQTT commands and reports its actions back to the broker.
  
 <code C main.cpp>​ <code C main.cpp>​
 #include <​Arduino.h>​ #include <​Arduino.h>​
 #include <​WiFi.h>​ #include <​WiFi.h>​
-#include <PubSubClient.h>+#include <MQTT.h> ​             // 256dpi MQTT library
 #include <​ArduinoJson.h>​ #include <​ArduinoJson.h>​
 #include <​Adafruit_NeoPixel.h>​ #include <​Adafruit_NeoPixel.h>​
  
 ////////////////​ EDIT THESE ////////////////​ ////////////////​ EDIT THESE ////////////////​
-const char* WIFI_SSID ​    = "TP-Link_2A64"; +const char* WIFI_SSID ​    = "YOUR_SSID"; 
-const char* WIFI_PASSWORD = "99481100";+const char* WIFI_PASSWORD = "YOUR_PASSWORD";
 const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker
 const uint16_t MQTT_PORT ​ = 1883; const uint16_t MQTT_PORT ​ = 1883;
-const char* BASE_TOPIC ​   = "iot/dantudose"; ​        ​// change per student+const char* BASE_TOPIC ​   = "iot/studentname"; ​       // change per student
 ////////////////////////////////////////////​ ////////////////////////////////////////////​
  
Line 124: Line 189:
 Adafruit_NeoPixel pixel(1, NEOPIXEL_PIN,​ NEO_GRB + NEO_KHZ800);​ Adafruit_NeoPixel pixel(1, NEOPIXEL_PIN,​ NEO_GRB + NEO_KHZ800);​
  
-WiFiClient ​espClient+WiFiClient ​net
-PubSubClient ​mqtt(espClient);+MQTTClient ​mqtt(1024);         // 1KB message buffer
  
 +// ---------- Wi-Fi ----------
 void ensureWiFi() { void ensureWiFi() {
   if (WiFi.status() == WL_CONNECTED) return;   if (WiFi.status() == WL_CONNECTED) return;
   WiFi.mode(WIFI_STA);​   WiFi.mode(WIFI_STA);​
   WiFi.begin(WIFI_SSID,​ WIFI_PASSWORD);​   WiFi.begin(WIFI_SSID,​ WIFI_PASSWORD);​
-  while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("​."​);​ }+  ​Serial.print("​WiFi connecting"​);​ 
 +  ​while (WiFi.status() != WL_CONNECTED) { 
 +    ​delay(400); 
 +    ​Serial.print("​."​);​ 
 +  ​}
   Serial.printf("​\nIP:​ %s\n", WiFi.localIP().toString().c_str());​   Serial.printf("​\nIP:​ %s\n", WiFi.localIP().toString().c_str());​
 } }
  
-void onMessage(char* topic, ​byte* payload, unsigned int len) { +// ---------- MQTT message handler (256dpi signature) ---------- 
-  Serial.printf("​MQTT msg on %s: %.*s\n", topic, len, (char*)payload);​ +void onMessage(String &topic, ​String &payload) { 
-  ​StaticJsonDocument<​128> ​doc; +  Serial.printf("​MQTT msg on %s: %s\n", topic.c_str()payload.c_str()); 
-  DeserializationError err = deserializeJson(doc,​ payload, len); + 
-  if (err) return;+  ​// Create a dynamic document on the stack with a defined capacity 
 +  JsonDocument ​doc;   
 +  DeserializationError err = deserializeJson(doc,​ payload); 
 +  if (err) 
 +    Serial.printf("​JSON parse error: %s\n", err.c_str());​ 
 +    ​return
 +  } 
 + 
 +  int r = doc["​r"​] | 0; 
 +  int g = doc["​g"​] | 0; 
 +  int b = doc["​b"​] | 0; 
 +  int brightness = doc["​brightness"​] | 50;
  
-  int r = doc["​r"​] | 0, g = doc["​g"​] | 0, b = doc["​b"​] | 0; 
   pixel.setPixelColor(0,​ pixel.Color(r,​ g, b));   pixel.setPixelColor(0,​ pixel.Color(r,​ g, b));
-  pixel.setBrightness(doc["brightness"] | 50);  // optional 0..255+  pixel.setBrightness(brightness);​
   pixel.show();​   pixel.show();​
  
   // Acknowledge   // Acknowledge
   String ackTopic = String(BASE_TOPIC) + "/​led/​ack";​   String ackTopic = String(BASE_TOPIC) + "/​led/​ack";​
-  ​StaticJsonDocument<​96> ​ack; +  ​JsonDocument ​ack;  // also replace StaticJsonDocument here 
-  ack["​ok"​] = true; ack["​r"​] = r; ack["​g"​] = g; ack["​b"​] = b; +  ack["​ok"​] = true; 
-  char buf[96]; size_t n = serializeJson(ack,​ buf); +  ​ack["​r"​] = r; 
-  mqtt.publish(ackTopic.c_str(), buf, n);+  ​ack["​g"​] = g; 
 +  ​ack["​b"​] = b; 
 +  ack["​brightness"​] = brightness;​ 
 + 
 +  char buf[96]; 
 +  ​size_t n = serializeJson(ack,​ buf, sizeof(buf)); 
 +  mqtt.publish(ackTopic, String(buf, n));
 } }
  
 +
 +// ---------- MQTT connect / subscribe ----------
 void ensureMQTT() { void ensureMQTT() {
   if (mqtt.connected()) return;   if (mqtt.connected()) return;
-  while (!mqtt.connected()) { + 
-    String ​cid String("​sparrow-c6-led-"​+ String((uint32_t)ESP.getEfuseMac(),​ HEX); +  String ​clientId ​= "​sparrow-c6-led-"​ + String((uint32_t)ESP.getEfuseMac(),​ HEX); 
-    ​if ​(mqtt.connect(cid.c_str())) ​break;+ 
 +  Serial.println("MQTT connecting..."​);​ 
 +  while (!mqtt.connect(clientId.c_str())) ​
 +    Serial.print("​."​);
     delay(1000);​     delay(1000);​
   }   }
 +  Serial.println("​\nMQTT connected"​);​
 +
   String sub = String(BASE_TOPIC) + "/​led";​   String sub = String(BASE_TOPIC) + "/​led";​
-  mqtt.subscribe(sub.c_str());+  mqtt.subscribe(sub);​
   Serial.printf("​Subscribed:​ %s\n", sub.c_str());​   Serial.printf("​Subscribed:​ %s\n", sub.c_str());​
 } }
Line 168: Line 261:
 void setup() { void setup() {
   Serial.begin(115200);​   Serial.begin(115200);​
 +  delay(200);
 +
   pixel.begin();​   pixel.begin();​
-  pixel.clear();​ pixel.show();​ +  pixel.clear();​ 
-  mqtt.setServer(MQTT_HOST, MQTT_PORT);​ +  ​pixel.show();​ 
-  mqtt.setCallback(onMessage);​+ 
 +  // Broker + transport setup and callback 
 +  mqtt.begin(MQTT_HOST, MQTT_PORT, net); 
 +  mqtt.onMessage(onMessage);​
 } }
  
Line 177: Line 275:
   ensureWiFi();​   ensureWiFi();​
   ensureMQTT();​   ensureMQTT();​
 +
 +  // Process incoming packets and keepalive
   mqtt.loop();​   mqtt.loop();​
 +  delay(10);
 } }
  
Line 184: Line 285:
  
 ===== Publish Sensor Readings From BME680 as JSON ===== ===== Publish Sensor Readings From BME680 as JSON =====
-Goal: read temperature,​ humidity, pressure (and gas resistance) from the BME688 over I²C and publish every 10s to iot/<​yourname>/​bme688.+<note tip>Goal: read temperature,​ humidity, pressure (and gas resistance) from the BME688 over I²C and publish every 10s to iot/<​yourname>/​bme688
 +</​note>​ 
 + 
 +Every ten seconds, the ESP32 reads environmental data from the on-board BME680 sensor—including temperature,​ humidity, pressure, and gas resistance—and packages those readings into a JSON message. It then publishes this JSON payload to an MQTT topic dedicated to that device’s sensor data. Any other MQTT clients subscribed to that topic can instantly receive and process the latest environmental information,​ such as for logging, visualization,​ or automation. In short, this code makes the ESP32 function as a small, networked environmental node that continuously streams live sensor data to the MQTT ecosystem while maintaining reliable connection status reporting.
  
 <code C main.cpp>​ <code C main.cpp>​
Line 190: Line 294:
 #include <​WiFi.h>​ #include <​WiFi.h>​
 #include <​Wire.h>​ #include <​Wire.h>​
-#include <PubSubClient.h>+#include <MQTT.h> ​             
 #include <​ArduinoJson.h>​ #include <​ArduinoJson.h>​
 #include <​Adafruit_BME680.h>​ #include <​Adafruit_BME680.h>​
  
 ////////////////​ EDIT THESE ////////////////​ ////////////////​ EDIT THESE ////////////////​
-const char* WIFI_SSID ​    = "TP-Link_2A64"; +const char* WIFI_SSID ​    = "YOUR_SSID"; 
-const char* WIFI_PASSWORD = "99481100";+const char* WIFI_PASSWORD = "YOUR_PASSWORD";
 const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker
 const uint16_t MQTT_PORT ​ = 1883; const uint16_t MQTT_PORT ​ = 1883;
-const char* BASE_TOPIC ​   = "iot/dantudose"; ​        ​// change per student+const char* BASE_TOPIC ​   = "iot/studentname"; ​       // change per student
 ////////////////////////////////////////////​ ////////////////////////////////////////////​
  
Line 207: Line 311:
 Adafruit_BME680 bme;  // I2C Adafruit_BME680 bme;  // I2C
  
-WiFiClient ​espClient+WiFiClient ​net
-PubSubClient ​mqtt(espClient);+MQTTClient ​mqtt(1024);   // 1KB message buffer
  
 void ensureWiFi() { void ensureWiFi() {
Line 214: Line 318:
   WiFi.mode(WIFI_STA);​   WiFi.mode(WIFI_STA);​
   WiFi.begin(WIFI_SSID,​ WIFI_PASSWORD);​   WiFi.begin(WIFI_SSID,​ WIFI_PASSWORD);​
-  while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("​."​);​ }+  ​Serial.print("​WiFi connecting"​);​ 
 +  ​while (WiFi.status() != WL_CONNECTED) { 
 +    ​delay(400); 
 +    ​Serial.print("​."​);​ 
 +  ​}
   Serial.printf("​\nIP:​ %s\n", WiFi.localIP().toString().c_str());​   Serial.printf("​\nIP:​ %s\n", WiFi.localIP().toString().c_str());​
 } }
Line 220: Line 328:
 void ensureMQTT() { void ensureMQTT() {
   if (mqtt.connected()) return;   if (mqtt.connected()) return;
-  while (!mqtt.connected()) { + 
-    String cid = String("​sparrow-c6-sense-"​) + String((uint32_t)ESP.getEfuseMac(),​ HEX); +  // Optional Last Will so dashboards see offline state 
-    ​if ​(mqtt.connect(cid.c_str())) ​break;+  String willTopic = String(BASE_TOPIC) + "/​bme688/​status";​ 
 +  ​mqtt.setWill(willTopic.c_str(), "​offline",​ true, 1); 
 + 
 +  ​String cid = String("​sparrow-c6-sense-"​) + String((uint32_t)ESP.getEfuseMac(),​ HEX); 
 +  ​Serial.println("MQTT connecting..."​);​ 
 +  while (!mqtt.connect(cid.c_str())) ​
 +    Serial.print("​."​);
     delay(1000);​     delay(1000);​
   }   }
 +  Serial.println("​\nMQTT connected"​);​
 +
 +  // Publish "​online"​ status retained
 +  mqtt.publish(willTopic,​ "​online",​ true, 1);
 } }
  
Line 231: Line 349:
 void setup() { void setup() {
   Serial.begin(115200);​   Serial.begin(115200);​
 +  delay(200);
 +
   Wire.begin(SDA_PIN,​ SCL_PIN);   Wire.begin(SDA_PIN,​ SCL_PIN);
-  ​mqtt.setServer(MQTT_HOST, MQTT_PORT);+ 
 +  // MQTT broker + transport 
 +  ​mqtt.begin(MQTT_HOST, MQTT_PORT, net);
  
   if (!bme.begin(0x76)) {           // Sparrow uses 0x76   if (!bme.begin(0x76)) {           // Sparrow uses 0x76
Line 249: Line 371:
   ensureWiFi();​   ensureWiFi();​
   ensureMQTT();​   ensureMQTT();​
-  ​mqtt.loop();​+ 
 +  ​mqtt.loop();     // process incoming/​keepalive 
 +  delay(10);
  
   if (millis() - lastPub > 10000) {   if (millis() - lastPub > 10000) {
Line 258: Line 382:
       return;       return;
     }     }
-    ​StaticJsonDocument<​192> ​doc; + 
-    doc["​ts"​] = (uint32_t)(millis()/​1000);​ +    // Build JSON (ArduinoJson v7 style, no deprecated ​StaticJsonDocument
-    doc["​temp_c"​] = bme.temperature;​ +    JsonDocument ​doc; 
-    doc["​hum_pct"​] = bme.humidity;​+    doc["​ts"​] ​       = (uint32_t)(millis() / 1000); 
 +    doc["​temp_c"​] ​   = bme.temperature;​ 
 +    doc["​hum_pct"​] ​  ​= bme.humidity;​
     doc["​press_hpa"​] = bme.pressure / 100.0;     doc["​press_hpa"​] = bme.pressure / 100.0;
-    doc["​gas_ohm"​] = bme.gas_resistance;​+    doc["​gas_ohm"​] ​  ​= bme.gas_resistance
 + 
 +    String payload; 
 +    serializeJson(doc,​ payload);
  
-    char payload[192];​ 
-    size_t n = serializeJson(doc,​ payload); 
     String topic = String(BASE_TOPIC) + "/​bme688";​     String topic = String(BASE_TOPIC) + "/​bme688";​
-    bool ok = mqtt.publish(topic.c_str(), payload, n); +    bool ok = mqtt.publish(topic,​ payload); ​ // QoS0, non-retained 
-    Serial.printf("​Pub %s => %s (%s)\n",​ topic.c_str(),​ payload, ok ? "​OK"​ : "​FAIL"​);​+    Serial.printf("​Pub %s => %s (%s)\n",​ 
 +                  ​topic.c_str(),​ payload.c_str(), ok ? "​OK"​ : "​FAIL"​);​
   }   }
 } }
Line 278: Line 406:
  
 ===== QoS, Retain & LWT ===== ===== QoS, Retain & LWT =====
-Goal here is to add production-style robustness: MQTT session properties (LWT, retain, QoS), back-off reconnects, and how to flip to TLS.+<note tip>Goaladd production-style robustness: MQTT session properties (LWT, retain, QoS), back-off reconnects, and how to flip to TLS
 +</​note>​ 
 + 
 +This example turns the ESP32 into a fully interactive MQTT client that both publishes and subscribes to topics on a broker using QoS and retain messages. When the device connects, it registers itself with a unique client ID and announces its presence by publishing an “online” status message, while also defining a “last will” message that the broker will automatically send as “offline” if the connection is lost unexpectedly. The ESP32 subscribes to a specific topic for LED control commands so that it can receive JSON payloads over MQTT, parse them, and then acknowledge each command by publishing a confirmation message back to a separate acknowledgment topic. This creates a two-way communication channel where the device can be controlled remotely and confirm successful execution of commands. 
 + 
 +At the same time, the ESP32 regularly publishes telemetry data through MQTT. It sends heartbeat messages with uptime, signal strength, and network information,​ and it transmits environmental sensor readings from the BME680 to a designated topic as JSON data. All MQTT communication uses Quality of Service level 1 to ensure that messages are delivered at least once, providing reliable data exchange between the device and the broker. The code also manages automatic reconnection with exponential backoff, meaning it gracefully retries connecting to the MQTT broker when disconnected without flooding the network. In essence, from the MQTT point of view, this device behaves as a resilient, bidirectional IoT client that reports data, accepts remote commands, and maintains a persistent, reliable session with the broker.
  
 <code C main.cpp>​ <code C main.cpp>​
Line 291: Line 424:
  
 ////////////////​ EDIT THESE ////////////////​ ////////////////​ EDIT THESE ////////////////​
-const char* WIFI_SSID ​    = "TP-Link_2A64"; +const char* WIFI_SSID ​    = "YOUR_SSID"; 
-const char* WIFI_PASSWORD = "99481100";+const char* WIFI_PASSWORD = "YOUR_PASSWORD";
 const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker const char* MQTT_HOST ​    = "​test.mosquitto.org"; ​  // or your lab broker
 const uint16_t MQTT_PORT ​ = 1883; const uint16_t MQTT_PORT ​ = 1883;
-const char* BASE_TOPIC ​   = "iot/dantudose"; ​        // change per student+const char* BASE_TOPIC ​   = "iot/studentname"; ​        // change per student
 ////////////////////////////////////////////​ ////////////////////////////////////////////​
  
iothings/laboratoare/2025/lab3.1760129243.txt.gz · Last modified: 2025/10/10 23:47 by dan.tudose
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0