This shows you the differences between two versions of the page.
— |
iothings:laboratoare:2025_code:lab3_4 [2025/10/11 13:20] (current) dan.tudose created |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | <code C main.cpp> | ||
+ | #include <Arduino.h> | ||
+ | #include <WiFi.h> | ||
+ | #include <WiFiClientSecure.h> | ||
+ | #include <MQTT.h> | ||
+ | #include <Wire.h> | ||
+ | #include <Adafruit_BME680.h> | ||
+ | #include <Adafruit_NeoPixel.h> | ||
+ | #include <ArduinoJson.h> | ||
+ | //////////////// EDIT THESE //////////////// | ||
+ | const char* WIFI_SSID = "YOUR_SSID"; | ||
+ | const char* WIFI_PASSWORD = "YOUR_PASSWORD"; | ||
+ | const char* MQTT_HOST = "test.mosquitto.org"; // or your lab broker | ||
+ | const uint16_t MQTT_PORT = 1883; | ||
+ | const char* BASE_TOPIC = "iot/studentname"; // change per student | ||
+ | //////////////////////////////////////////// | ||
+ | |||
+ | #define SDA_PIN 21 | ||
+ | #define SCL_PIN 22 | ||
+ | #define NEOPIXEL_PIN 3 | ||
+ | |||
+ | WiFiClient net; | ||
+ | MQTTClient mqtt(2048); | ||
+ | Adafruit_BME680 bme; | ||
+ | Adafruit_NeoPixel pixel(1, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); | ||
+ | |||
+ | unsigned long nextConnTry = 0; | ||
+ | uint32_t backoffMs = 1000; | ||
+ | unsigned long lastHeartbeat = 0; | ||
+ | unsigned long lastSensorPub = 0; | ||
+ | |||
+ | 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, RSSI: %d dBm\n", WiFi.localIP().toString().c_str(), WiFi.RSSI()); | ||
+ | } | ||
+ | |||
+ | void setLED(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) { | ||
+ | pixel.setBrightness(brightness); | ||
+ | pixel.setPixelColor(0, pixel.Color(r, g, b)); | ||
+ | pixel.show(); | ||
+ | } | ||
+ | |||
+ | void handleLEDJson(const String& payload) { | ||
+ | JsonDocument doc; | ||
+ | DeserializationError err = deserializeJson(doc, payload); | ||
+ | if (err) { Serial.printf("LED JSON parse error: %s\n", err.c_str()); return; } | ||
+ | uint8_t r = doc["r"].isNull() ? 0 : doc["r"].as<uint8_t>(); | ||
+ | uint8_t g = doc["g"].isNull() ? 0 : doc["g"].as<uint8_t>(); | ||
+ | uint8_t b = doc["b"].isNull() ? 0 : doc["b"].as<uint8_t>(); | ||
+ | uint8_t br = doc["brightness"].isNull() ? 100 : doc["brightness"].as<uint8_t>(); | ||
+ | setLED(r,g,b,br); | ||
+ | |||
+ | JsonDocument ack; | ||
+ | ack["ok"] = true; ack["r"] = r; ack["g"] = g; ack["b"] = b; ack["brightness"] = br; | ||
+ | String out; serializeJson(ack, out); | ||
+ | mqtt.publish((String(BASE_TOPIC)+"/led/ack").c_str(), out.c_str(), false, 1); | ||
+ | } | ||
+ | |||
+ | void messageReceived(String &topic, String &payload) { | ||
+ | Serial.printf("MSG [%s]: %s\n", topic.c_str(), payload.c_str()); | ||
+ | if (topic == String(BASE_TOPIC) + "/led") handleLEDJson(payload); | ||
+ | } | ||
+ | |||
+ | bool connectMQTT() { | ||
+ | String cid = String("sparrow-c6-qos1-") + String((uint32_t)ESP.getEfuseMac(), HEX); | ||
+ | mqtt.setCleanSession(true); | ||
+ | mqtt.setKeepAlive(30); | ||
+ | String willTopic = String(BASE_TOPIC) + "/status"; | ||
+ | mqtt.setWill(willTopic.c_str(), "{\"status\":\"offline\"}", true, 1); | ||
+ | |||
+ | Serial.printf("MQTT connecting to %s:%u as %s ...\n", MQTT_HOST, MQTT_PORT, cid.c_str()); | ||
+ | bool ok = mqtt.connect(cid.c_str(), nullptr, nullptr); | ||
+ | if (!ok) { Serial.printf("MQTT connect failed, error=%d\n", mqtt.lastError()); return false; } | ||
+ | |||
+ | mqtt.subscribe((String(BASE_TOPIC)+"/led").c_str(), 1); | ||
+ | mqtt.publish(willTopic.c_str(), "{\"status\":\"online\"}", true, 1); | ||
+ | Serial.println("MQTT connected"); | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | void ensureMQTT() { | ||
+ | if (mqtt.connected()) return; | ||
+ | if (millis() < nextConnTry) return; | ||
+ | if (!connectMQTT()) { | ||
+ | backoffMs = min<uint32_t>(backoffMs * 2, 30000); | ||
+ | nextConnTry = millis() + backoffMs; | ||
+ | Serial.printf("Retry in %lu ms\n", (unsigned long)backoffMs); | ||
+ | } else { | ||
+ | backoffMs = 1000; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | bool readBME(float& tC, float& hPct, float& pHpa, float& gas) { | ||
+ | if (!bme.performReading()) return false; | ||
+ | tC = bme.temperature; | ||
+ | hPct = bme.humidity; | ||
+ | pHpa = bme.pressure / 100.0; | ||
+ | gas = bme.gas_resistance; | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(115200); | ||
+ | pixel.begin(); | ||
+ | setLED(0,0,0,10); | ||
+ | |||
+ | Wire.begin(SDA_PIN, SCL_PIN); | ||
+ | if (!bme.begin(0x76)) { | ||
+ | Serial.println("BME688/BME680 not found at 0x76!"); | ||
+ | } else { | ||
+ | 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); | ||
+ | } | ||
+ | |||
+ | mqtt.begin(MQTT_HOST, MQTT_PORT, net); | ||
+ | mqtt.onMessage(messageReceived); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | ensureWiFi(); | ||
+ | ensureMQTT(); | ||
+ | mqtt.loop(); | ||
+ | |||
+ | if (mqtt.connected() && millis() - lastHeartbeat > 15000) { | ||
+ | lastHeartbeat = millis(); | ||
+ | JsonDocument hb; | ||
+ | hb["uptime_s"] = (uint32_t)(millis()/1000); | ||
+ | hb["ip"] = WiFi.localIP().toString(); | ||
+ | hb["rssi"] = WiFi.RSSI(); | ||
+ | String out; serializeJson(hb, out); | ||
+ | mqtt.publish((String(BASE_TOPIC)+"/heartbeat").c_str(), out.c_str(), true, 1); | ||
+ | Serial.printf("Heartbeat -> %s\n", out.c_str()); | ||
+ | } | ||
+ | |||
+ | if (mqtt.connected() && millis() - lastSensorPub > 10000) { | ||
+ | lastSensorPub = millis(); | ||
+ | float tC, hPct, pHpa, gas; | ||
+ | if (readBME(tC, hPct, pHpa, gas)) { | ||
+ | JsonDocument s; | ||
+ | s["ts"] = (uint32_t)(millis()/1000); | ||
+ | s["temp_c"] = tC; | ||
+ | s["hum_pct"] = hPct; | ||
+ | s["press_hpa"] = pHpa; | ||
+ | s["gas_ohm"] = gas; | ||
+ | String out; serializeJson(s, out); | ||
+ | mqtt.publish((String(BASE_TOPIC)+"/bme688").c_str(), out.c_str(), false, 1); | ||
+ | Serial.printf("Sensor -> %s\n", out.c_str()); | ||
+ | } else { | ||
+ | Serial.println("BME read failed"); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> |