This shows you the differences between two versions of the page.
|
iothings:laboratoare:2025_code:lab3_1 [2025/10/11 12:48] dan.tudose created |
iothings:laboratoare:2025_code:lab3_1 [2025/10/13 17:19] (current) dan.tudose |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| <code C main.cpp> | <code C main.cpp> | ||
| + | |||
| #include <Arduino.h> | #include <Arduino.h> | ||
| #include <WiFi.h> | #include <WiFi.h> | ||
| - | #include <MQTT.h> // 256dpi MQTT library | + | #include <PubSubClient.h> |
| - | + | ||
| - | //////////////// EDIT THESE //////////////// | + | #ifndef WIFI_SSID |
| - | const char* WIFI_SSID = "YOUR_SSID"; | + | #define WIFI_SSID "UPB-Guest" |
| - | const char* WIFI_PASSWORD = "YOUR_PASSWORD"; | + | #endif |
| - | const char* MQTT_HOST = "test.mosquitto.org"; // or your lab broker | + | #ifndef WIFI_PASSWORD |
| - | const uint16_t MQTT_PORT = 1883; | + | #define WIFI_PASSWORD "" |
| - | const char* BASE_TOPIC = "iot/studentname"; // change per student | + | #endif |
| - | //////////////////////////////////////////// | + | #ifndef MQTT_HOST |
| - | + | #define MQTT_HOST "test.mosquitto.org" | |
| - | WiFiClient net; | + | #endif |
| - | MQTTClient mqtt(1024); // 1KB message buffer | + | #ifndef MQTT_PORT |
| - | + | #define MQTT_PORT 1883 | |
| - | unsigned long lastPub = 0; | + | #endif |
| - | + | #ifndef BASE_TOPIC | |
| + | #define BASE_TOPIC "devices/esp32" | ||
| + | #endif | ||
| + | |||
| + | WiFiClient net; | ||
| + | PubSubClient mqtt(net); // PubSubClient uses a separate setServer(...) | ||
| + | unsigned long lastPub = 0; | ||
| + | |||
| + | // ---------- Wi-Fi ---------- | ||
| void connectWiFi() { | void connectWiFi() { | ||
| if (WiFi.status() == WL_CONNECTED) return; | if (WiFi.status() == WL_CONNECTED) return; | ||
| Line 28: | Line 37: | ||
| 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 messageReceived(String &topic, String &payload) { | + | // ---------- MQTT callback (PubSubClient signature) ---------- |
| - | Serial.printf("Message on %s: %s\n", topic.c_str(), payload.c_str()); | + | void mqttCallback(char* topic, byte* payload, unsigned int length) { |
| + | // payload is NOT null-terminated; build a String safely | ||
| + | String msg; | ||
| + | msg.reserve(length); | ||
| + | for (unsigned int i = 0; i < length; i++) msg += (char)payload[i]; | ||
| + | |||
| + | Serial.printf("Message on %s: %s\n", topic, msg.c_str()); | ||
| } | } | ||
| - | + | ||
| + | // ---------- MQTT connect & subscribe ---------- | ||
| void connectMQTT() { | void connectMQTT() { | ||
| - | // Build a real String, then pass c_str() | + | // Build clientId like before |
| String clientId = "esp32-client-" + String((uint32_t)ESP.getEfuseMac(), HEX); | String clientId = "esp32-client-" + String((uint32_t)ESP.getEfuseMac(), HEX); | ||
| - | + | ||
| + | // Last Will | ||
| + | String willTopic = String(BASE_TOPIC) + "/status"; | ||
| + | const char* willMsg = "offline"; | ||
| + | const bool willRetain = true; | ||
| + | const uint8_t willQos = 0; // PubSubClient is QoS 0 only | ||
| Serial.println("MQTT connecting..."); | Serial.println("MQTT connecting..."); | ||
| - | while (!mqtt.connect(clientId.c_str())) { | + | while (!mqtt.connect(clientId.c_str(), |
| + | willTopic.c_str(), willQos, willRetain, willMsg)) { | ||
| Serial.print("."); | Serial.print("."); | ||
| delay(1000); | delay(1000); | ||
| } | } | ||
| Serial.println("\nMQTT connected!"); | Serial.println("\nMQTT connected!"); | ||
| - | + | ||
| // Optional subscription | // Optional subscription | ||
| String subTopic = String(BASE_TOPIC) + "/#"; | String subTopic = String(BASE_TOPIC) + "/#"; | ||
| - | mqtt.subscribe(subTopic); | + | mqtt.subscribe(subTopic.c_str()); // QoS 0 |
| Serial.printf("Subscribed to %s\n", subTopic.c_str()); | Serial.printf("Subscribed to %s\n", subTopic.c_str()); | ||
| + | |||
| + | // Publish "online" once connected (retain) | ||
| + | mqtt.publish(willTopic.c_str(), "online", true); | ||
| } | } | ||
| - | + | ||
| void setup() { | void setup() { | ||
| Serial.begin(115200); | Serial.begin(115200); | ||
| delay(500); | delay(500); | ||
| - | + | ||
| connectWiFi(); | connectWiFi(); | ||
| - | + | ||
| - | mqtt.begin(MQTT_HOST, MQTT_PORT, net); | + | mqtt.setServer(MQTT_HOST, MQTT_PORT); |
| - | mqtt.onMessage(messageReceived); | + | mqtt.setCallback(mqttCallback); |
| - | + | ||
| - | // Optional: last will so brokers/clients know if we drop | + | // Match your 1KB buffer from 256dpi/client |
| - | String willTopic = String(BASE_TOPIC) + "/status"; | + | mqtt.setBufferSize(1024); |
| - | mqtt.setWill(willTopic.c_str(), "offline", true, 1); | + | |
| - | + | ||
| connectMQTT(); | connectMQTT(); | ||
| - | |||
| - | // Publish "online" once connected | ||
| - | mqtt.publish(willTopic, "online", true, 1); | ||
| } | } | ||
| - | + | ||
| void loop() { | void loop() { | ||
| - | connectWiFi(); // ensure WiFi | + | connectWiFi(); // ensure WiFi |
| - | if (!mqtt.connected()) connectMQTT(); | + | |
| - | mqtt.loop(); // non-blocking | + | if (!mqtt.connected()) { |
| + | connectMQTT(); | ||
| + | } | ||
| + | mqtt.loop(); // must be called often; non-blocking | ||
| delay(10); | delay(10); | ||
| - | + | ||
| // Publish every 5 seconds | // Publish every 5 seconds | ||
| if (millis() - lastPub > 5000) { | if (millis() - lastPub > 5000) { | ||
| Line 80: | Line 105: | ||
| 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, payload); | + | bool ok = mqtt.publish(topic.c_str(), payload.c_str()); // QoS 0 |
| Serial.printf("Publish %s => %s (%s)\n", | Serial.printf("Publish %s => %s (%s)\n", | ||
| topic.c_str(), payload.c_str(), ok ? "OK" : "FAIL"); | topic.c_str(), payload.c_str(), ok ? "OK" : "FAIL"); | ||