This is an old revision of the document!


Lab 3. The MQTT Protocol

MQTT “Hello World” (publish a heartbeat)

Goal: connect to Wi-Fi, connect to MQTT, then publish a heartbeat every 5s to iot/<yourname>/heartbeat.

main.cpp
// src/main.cpp
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
 
//////////////// EDIT THESE ////////////////
const char* WIFI_SSID     = "TP-Link_2A64";
const char* WIFI_PASSWORD = "99481100";
const char* MQTT_HOST     = "test.mosquitto.org";   // or your lab broker
const uint16_t MQTT_PORT  = 1883;
const char* BASE_TOPIC    = "iot/dantudose";         // change per student
////////////////////////////////////////////
 
WiFiClient espClient;
PubSubClient mqtt(espClient);
 
void ensureWiFi() {
  if (WiFi.status() == WL_CONNECTED) return;
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("WiFi connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(".");
  }
  Serial.printf("\nWiFi OK, IP: %s\n", WiFi.localIP().toString().c_str());
}
 
void ensureMQTT() {
  if (mqtt.connected()) return;
  String clientId = String("sparrow-c6-") + String((uint32_t)ESP.getEfuseMac(), HEX);
  Serial.println("MQTT connecting...");
  Serial.println("Client ID:"); 
  Serial.print(clientId);
 
  while (!mqtt.connect(clientId.c_str())) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("\nMQTT connected");
}
 
unsigned long lastPub = 0;
 
void setup() {
  Serial.begin(115200);
  delay(1000);
  WiFi.useStaticBuffers(true);   // small memory win on C6
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
}
 
void loop() {
  ensureWiFi();
  ensureMQTT();
  mqtt.loop();
 
  if (millis() - lastPub > 5000) {
    lastPub = millis();
    String topic = String(BASE_TOPIC) + "/heartbeat";
    String payload = String("{\"uptime_ms\":") + millis() + "}";
    bool ok = mqtt.publish(topic.c_str(), payload.c_str());
    Serial.printf("Publish %s => %s (%s)\n", topic.c_str(), payload.c_str(), ok ? "OK" : "FAIL");
  }
}

Test it out using this link.

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}.

main.cpp
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Adafruit_NeoPixel.h>
 
//////////////// EDIT THESE ////////////////
const char* WIFI_SSID     = "TP-Link_2A64";
const char* WIFI_PASSWORD = "99481100";
const char* MQTT_HOST     = "test.mosquitto.org";   // or your lab broker
const uint16_t MQTT_PORT  = 1883;
const char* BASE_TOPIC    = "iot/dantudose";         // change per student
////////////////////////////////////////////
 
#define NEOPIXEL_PIN 3
Adafruit_NeoPixel pixel(1, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
 
WiFiClient espClient;
PubSubClient mqtt(espClient);
 
void ensureWiFi() {
  if (WiFi.status() == WL_CONNECTED) return;
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); }
  Serial.printf("\nIP: %s\n", WiFi.localIP().toString().c_str());
}
 
void onMessage(char* topic, byte* payload, unsigned int len) {
  Serial.printf("MQTT msg on %s: %.*s\n", topic, len, (char*)payload);
  StaticJsonDocument<128> doc;
  DeserializationError err = deserializeJson(doc, payload, len);
  if (err) return;
 
  int r = doc["r"] | 0, g = doc["g"] | 0, b = doc["b"] | 0;
  pixel.setPixelColor(0, pixel.Color(r, g, b));
  pixel.setBrightness(doc["brightness"] | 50);  // optional 0..255
  pixel.show();
 
  // Acknowledge
  String ackTopic = String(BASE_TOPIC) + "/led/ack";
  StaticJsonDocument<96> ack;
  ack["ok"] = true; ack["r"] = r; ack["g"] = g; ack["b"] = b;
  char buf[96]; size_t n = serializeJson(ack, buf);
  mqtt.publish(ackTopic.c_str(), buf, n);
}
 
void ensureMQTT() {
  if (mqtt.connected()) return;
  while (!mqtt.connected()) {
    String cid = String("sparrow-c6-led-") + String((uint32_t)ESP.getEfuseMac(), HEX);
    if (mqtt.connect(cid.c_str())) break;
    delay(1000);
  }
  String sub = String(BASE_TOPIC) + "/led";
  mqtt.subscribe(sub.c_str());
  Serial.printf("Subscribed: %s\n", sub.c_str());
}
 
void setup() {
  Serial.begin(115200);
  pixel.begin();
  pixel.clear(); pixel.show();
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setCallback(onMessage);
}
 
void loop() {
  ensureWiFi();
  ensureMQTT();
  mqtt.loop();
}

Test it out using this link.

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.

main.cpp
#include <Arduino.h>
#include <WiFi.h>
#include <Wire.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Adafruit_BME680.h>
 
//////////////// EDIT THESE ////////////////
const char* WIFI_SSID     = "TP-Link_2A64";
const char* WIFI_PASSWORD = "99481100";
const char* MQTT_HOST     = "test.mosquitto.org";   // or your lab broker
const uint16_t MQTT_PORT  = 1883;
const char* BASE_TOPIC    = "iot/dantudose";         // change per student
////////////////////////////////////////////
 
// Sparrow I2C: SDA=21, SCL=22
#define SDA_PIN 21
#define SCL_PIN 22
Adafruit_BME680 bme;  // I2C
 
WiFiClient espClient;
PubSubClient mqtt(espClient);
 
void ensureWiFi() {
  if (WiFi.status() == WL_CONNECTED) return;
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); }
  Serial.printf("\nIP: %s\n", WiFi.localIP().toString().c_str());
}
 
void ensureMQTT() {
  if (mqtt.connected()) return;
  while (!mqtt.connected()) {
    String cid = String("sparrow-c6-sense-") + String((uint32_t)ESP.getEfuseMac(), HEX);
    if (mqtt.connect(cid.c_str())) break;
    delay(1000);
  }
}
 
unsigned long lastPub = 0;
 
void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
 
  if (!bme.begin(0x76)) {           // Sparrow uses 0x76
    Serial.println("BME688 not found!");
    for(;;) { delay(1000); }
  }
  // Reasonable oversampling; heater off for simplicity
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(0, 0);  // off
}
 
void loop() {
  ensureWiFi();
  ensureMQTT();
  mqtt.loop();
 
  if (millis() - lastPub > 10000) {
    lastPub = millis();
 
    if (!bme.performReading()) {
      Serial.println("BME read failed");
      return;
    }
    StaticJsonDocument<192> doc;
    doc["ts"] = (uint32_t)(millis()/1000);
    doc["temp_c"] = bme.temperature;
    doc["hum_pct"] = bme.humidity;
    doc["press_hpa"] = bme.pressure / 100.0;
    doc["gas_ohm"] = bme.gas_resistance;
 
    char payload[192];
    size_t n = serializeJson(doc, payload);
    String topic = String(BASE_TOPIC) + "/bme688";
    bool ok = mqtt.publish(topic.c_str(), payload, n);
    Serial.printf("Pub %s => %s (%s)\n", topic.c_str(), payload, ok ? "OK" : "FAIL");
  }
}

Test it out using this link.

iothings/laboratoare/2025/lab3.1760124125.txt.gz · Last modified: 2025/10/10 22:22 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