#include "ESPAsyncWebServer.h" #include #include #include // Sensors #include "HDC1080Sensor.h" #include "CCS811Sensor.h" #include "MS5611Sensor.h" #include "BMP280Sensor.h" //#include "src/ESPinfluxdb.h" // https://github.com/hwwong/ESP_influxdb // 14.04.2019 #include "http_static.h" // HTTP pages and JSON request templates // ********************** Config ********************** // DeepSleep time send data every 60 seconds const int sleepTimeS = 60; // WiFi Config #define WiFi_SSID "Ischtar" #define WiFi_Password "highfive" // NTP conf const char* ntpServer = "pool.ntp.org"; const long gmtOffset_sec = 0; const int daylightOffset_sec = 3600; struct tm timeinfo; // Create AsyncWebServer object on port 80 AsyncWebServer server(80); // Globals for HDC1080 :: Temp/Humidity HDC1080Sensor HDC1080_sensors; double hdc1080_temp, hdc1080_humidity; bool hdc1080_err; // Globals for CCS811 :: eTVOC/eCO2 CCS811Sensor CCS811_sensors; uint16_t ccs811_eco2, ccs811_etvoc, ccs811_errstat, ccs811_raw; // Globals for MS5611 :: Pressure/Altitude MS5611Sensor MS5611_sensors; double ms5611_temp, ms5611_pressure, ms5611_altitude; // Globals for BMP280 :: Temp/Hum/Pressure BMP280Sensor BMP280_sensors; float bmp280_temp, bmp280_humidity, bmp280_pressure, bmp280_altitude; // loop cycle #define workCycle 60 //seconds // ******************** Config End ******************** void scanI2CDevices() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for (address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) { Serial.print("0"); } Serial.print(address, HEX); Serial.println(" !"); nDevices++; } else if (error == 4) { Serial.print("Unknown error at address 0x"); if (address < 16) { Serial.print("0"); } Serial.println(address, HEX); } } if (nDevices == 0) { Serial.println("No I2C devices found\n"); } else { Serial.println("done\n"); } } // ---------- HDC1080 ---------- String readHDC1080Temperature() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(hdc1080_temp)) { Serial.println("Failed to read from HDC1080 sensor!"); return "--"; } else { return String(hdc1080_temp); } } String readHDC1080Humidity() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(hdc1080_humidity)) { Serial.println("Failed to read from HDC1080 sensor!"); return "--"; } else { return String(hdc1080_humidity); } } // ---------- End HDC1080 ---------- // ---------- CCS11 ---------- String processCCS811Error(err_t errstat) { if ( errstat == CCS811_ERRSTAT_OK_NODATA ) { Serial.println("CCS811: waiting for (new) data"); return "loading"; } else if ( errstat & CCS811_ERRSTAT_I2CFAIL ) { Serial.println("CCS811: I2C error"); return "i2c error"; } else { // Serial.print("CCS811: errstat="); Serial.print(errstat, HEX); // Serial.print("="); Serial.println( ccs811.errstat_str(errstat) ); return "error"; } } String readCCS811TVOC() { if( ccs811_errstat==CCS811_ERRSTAT_OK ){ return String(ccs811_etvoc); } else { return processCCS811Error(ccs811_errstat); } } String readCCS811ECO2() { if( ccs811_errstat==CCS811_ERRSTAT_OK ){ return String(ccs811_eco2); } else { return processCCS811Error(ccs811_errstat); } } // ---------- End CCS11 ---------- // ---------- MS5611 ---------- String readMS5611Temperature() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(ms5611_temp)) { Serial.println("Failed to read from MS5611 sensor!"); return "--"; } else { return String(ms5611_temp); } } String readMS5611Pressure() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(ms5611_pressure)) { Serial.println("Failed to read from MS5611 sensor!"); return "--"; } else { return String(ms5611_temp); } } String readMS5611Altitude() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(ms5611_altitude)) { Serial.println("Failed to read from MS5611 sensor!"); return "--"; } else { return String(ms5611_altitude); } } // ---------- End MS5611 ---------- // ---------- BMP280 ---------- String readBMP280Temperature() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(bmp280_temp)) { Serial.println("Failed to read from BMP280 sensor!"); return "--"; } else { return String(bmp280_temp); } } String readBMP280Humidity() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(bmp280_humidity)) { Serial.println("Failed to read from BMP280 sensor!"); return "--"; } else { return String(bmp280_humidity); } } String readBMP280Pressure() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(bmp280_pressure)) { Serial.println("Failed to read from BMP280 sensor!"); return "--"; } else { return String(bmp280_pressure); } } String readBMP280Altitude() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) if (isnan(bmp280_altitude)) { Serial.println("Failed to read from BMP280 sensor!"); return "--"; } else { return String(bmp280_altitude); } } // ---------- End BMP280 ---------- String formatISO8601() { char timestamp[20]; // Buffer for timestamp // Format the time into ISO 8601 format strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%SZ", &timeinfo); // Convert the formatted timestamp to a String object return String(timestamp); } // Replaces placeholder in HTML template with real values // SSR if you will String processor(const String& var){ if(var == "TEMPERATURE"){ return readHDC1080Temperature(); } else if(var == "HUMIDITY"){ return readHDC1080Humidity(); } else if(var == "TVOC"){ return readCCS811TVOC(); } else if(var == "ECO2"){ return readCCS811ECO2(); } else if(var == "TIMESTAMP"){ return formatISO8601(); } return String(); } void connectToWiFi() { WiFi.mode(WIFI_STA); WiFi.begin(WiFi_SSID, WiFi_Password); Serial.println(); Serial.print("Connecting to WiFi: "); Serial.print(WiFi_SSID); int attempts = 0; while (WiFi.status() != WL_CONNECTED && attempts < 10) { delay(500); Serial.print("."); attempts++; } if (WiFi.status() == WL_CONNECTED) { Serial.println("\nWiFi connected"); Serial.print("IP address: http://"); Serial.println(WiFi.localIP()); } else { Serial.println("\nFailed to connect to WiFi"); // Handle connection failure, e.g., retry or reset the ESP32 } } void setup() { Serial.begin(115200); delay(10); Serial.println(""); connectToWiFi(); delay(10); Serial.println(""); // Config NTP configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); // i2c Wire.begin(); // humidity and temperature HDC1080_sensors.init(); // eCO2 and eTVOC, temp and humidity needed to adjust values CCS811_sensors.init(&hdc1080_temp, &hdc1080_humidity); // Todo add pointer to temp, we might allight Altimeter by another sens // MS5611_sensors.init(); // humidity, temperature, pressure and altitude BMP280_sensors.init(); // Pages and JSONs server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/html", http_static::index_html, processor); }); // Deprecated server.on("/api/sensors.json", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/html", http_static::sensor_things_resp, processor); }); // DEPRECATED lightweight named endpoints server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", readHDC1080Temperature().c_str()); }); server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", readHDC1080Humidity().c_str()); }); server.on("/tvoc", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", readCCS811TVOC().c_str()); }); server.on("/eco2", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", readCCS811ECO2().c_str()); }); // For prometheus scrapping. to be deprecated as well server.on("/metrics", HTTP_GET, [](AsyncWebServerRequest *request) { String response = "hdc1080_temperature " + String(readHDC1080Temperature()) + "\n"; response += "hdc1080_humidity " + String(readHDC1080Humidity()) + "\n"; response += "ccs811_tvoc " + String(readCCS811TVOC()) + "\n"; response += "ccs811_eco2 " + String(readCCS811ECO2()) + "\n"; response += "bmp280_temperature " + String(readBMP280Temperature()) + "\n"; response += "bmp280_humidity " + String(readBMP280Humidity()) + "\n"; response += "bmp280_pressure " + String(readBMP280Pressure()) + "\n"; response += "bmp280_altitude " + String(readBMP280Altitude()) + "\n"; request->send(200, "text/plain", response); }); // Start server server.begin(); } void loop() { if (WiFi.status() != WL_CONNECTED) { Serial.println("WiFi connection lost. Reconnecting..."); connectToWiFi(); } if(!getLocalTime(&timeinfo)){ Serial.println("Failed to obtain time"); return; } scanI2CDevices(); Serial.print(&timeinfo, "[%M-%d-%Y--%H:%M:%S]: "); HDC1080_sensors.read_values(&hdc1080_temp, &hdc1080_humidity, &hdc1080_err); CCS811_sensors.read_values(&ccs811_eco2, &ccs811_etvoc, &ccs811_errstat, &ccs811_raw); BMP280_sensors.read_values(&bmp280_temp, &bmp280_humidity, &bmp280_pressure, &bmp280_altitude); Serial.print("T="); Serial.print(readHDC1080Temperature()); Serial.print(" / "); Serial.print(readBMP280Temperature()); Serial.print(" °C "); Serial.print("H="); Serial.print(readHDC1080Humidity()); Serial.print(" / "); Serial.print(readBMP280Humidity()); Serial.print(" % "); Serial.print("eco2="); Serial.print(readCCS811ECO2()); Serial.print(" ppm "); Serial.print("etvoc="); Serial.print(readCCS811TVOC()); Serial.print(" ppb "); Serial.print("pressure="); Serial.print(readBMP280Pressure()); Serial.print(" Pa "); Serial.print("alt="); Serial.print(readBMP280Altitude()); Serial.print(" m "); Serial.println(""); // Wait delay(workCycle*1000); }