From 35f5dd24c67161d2d0ee1aeb8df78ae60eb16ae9 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 16:18:00 +0200 Subject: [PATCH 01/13] deep_sleep test --- src/main.cpp | 330 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 229 insertions(+), 101 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2b2c113..e1d3c7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,6 +42,10 @@ uint8_t temprature_sens_read(); static const char* TAG = "MAIN"; + +#define TIME_TO_SLEEP 60 // seconds +constexpr unsigned int dhcp_interval = 60*60; + WiFiMulti wifiMulti; GxEPD2_BW display(GxEPD2_213_B72(/*CS=SS*/ TFT_CS, /*DC=*/ TFT_DC, /*RST=*/ TFT_RST, /*BUSY=*/ -1)); // GDEH0213B72 static constexpr uint8_t y_offset = 6; @@ -56,6 +60,18 @@ BH1750 lightMeter; XD0OTA ota("esp32-weatherstation"); XD0MQTT mqtt; +struct __attribute__((packed)) network_t { + uint32_t ip; + uint32_t dns; + uint32_t gateway; + uint32_t subnet; + char ssid[64]; + char password[64]; + int32_t channel; + time_t last_dhcp; +}; +RTC_DATA_ATTR network_t network; + struct __attribute__((packed)) sensor_readings_t { float temperature = NAN; // °C float humidity = NAN; // %H @@ -79,15 +95,111 @@ sensor_readings_t sensors_a4cf1211c3e4, sensors_246f28d1fa5c, sensors_246f28d1a0 SensorHistory history_pressure(30); -uint32_t lastDisplayUpdate = 0; -uint32_t lastDisplayRefresh = 0; -bool bme280_active = false; -bool bme680_active = false; -bool uv_active = false; -bool light_active = false; -bool sds_active = false; +RTC_DATA_ATTR time_t lastDisplayRefresh = 0; +struct __attribute__((packed)) sensors_active_t { + bool bme280 = false; + bool bme680 = false; + bool uv = false; + bool light = false; + bool sds = false; +}; +RTC_DATA_ATTR sensors_active_t sensors_active; float station_height = 0; +RTC_DATA_ATTR int bootCount = 0; + + +time_t getTimestamp() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +} + + +void poweroffDevices() { + display.powerOff(); + + // ToDo: Sensors +} + + +void gotoSleep(unsigned int sleep_time = TIME_TO_SLEEP) { + mqtt.end(); + WiFi.disconnect(); + WiFi.mode(WIFI_OFF); + + poweroffDevices(); + + //rtc_gpio_isolate(GPIO_NUM_12); + + esp_sleep_enable_timer_wakeup(sleep_time * 1000000LL); + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); + Serial.println("going to to sleep for " + String(sleep_time) + + " Seconds"); + Serial.flush(); + esp_deep_sleep_start(); + delay(1); +} + +void wifiConnect() { + WiFi.persistent(false); + WiFi.setHostname("esp32-weatherstation"); + + wifiMulti.addAP(WIFI_SSID, WIFI_PASSWD); + wifiMulti.addAP(WIFI_SSID2, WIFI_PASSWD2); + wifiMulti.addAP(WIFI_SSID3, WIFI_PASSWD3); + + IPAddress ip = IPAddress(network.ip); + IPAddress dns = IPAddress(network.dns); + IPAddress subnet = IPAddress(network.subnet); + IPAddress gateway = IPAddress(network.gateway); + + Serial.println("millis(): " + String(millis())); + + Serial.println("previous dhcp: " + String(getTimestamp() - network.last_dhcp) + "s ago"); + + if ( ip != INADDR_NONE && dns != INADDR_NONE && gateway != INADDR_NONE && subnet != INADDR_NONE + && ((ip[0] == 192 && ip[1] == 168) || (ip[0] == 172 && ip[1] == 16)) + && strlen(network.ssid) > 0 && strlen(network.password) > 0 + && (getTimestamp() - network.last_dhcp < dhcp_interval) + ) { + + ESP_LOGD("WiFi", "STATIC IP"); + WiFi.config(ip, gateway, subnet, dns); + WiFi.begin(network.ssid, network.password, network.channel); + for (int tries=0; WiFi.status() != WL_CONNECTED && tries < 10; tries++) { + ESP_LOGD("WiFi", "."); + delay(500); + } + } else { + ESP_LOGD("WiFi", "DHCP"); + for (int tries=0; wifiMulti.run() != WL_CONNECTED && tries < 20; tries++) { + Serial.print("."); + delay(500); + } + + network.ip = (uint32_t)WiFi.localIP(); + network.dns = (uint32_t)WiFi.dnsIP(); + network.gateway = (uint32_t)WiFi.gatewayIP(); + network.subnet = (uint32_t)WiFi.subnetMask(); + strncpy(network.ssid, WiFi.SSID().c_str(), 64); + strncpy(network.password, WiFi.psk().c_str(), 64); + network.channel = WiFi.channel(); + network.last_dhcp = getTimestamp(); + } + + Serial.println("millis(): " + String(millis())); + + if(WiFi.status() == WL_CONNECTED) { + ESP_LOGD("WiFi", "connected"); + //ESP_LOGD("WiFi", (WiFi.localIP().toString().c_str())); + + } else { + ESP_LOGE("WiFi", "could not connect to WiFi"); + ESP_LOGE(TAG, "restarting"); + ESP.restart(); + } +} void helloWorld() { @@ -101,7 +213,11 @@ void helloWorld() // center bounding box by transposition of origin: uint16_t x = ((display.width() - tbw) / 2) - tbx; uint16_t y = ((display.height() - tbh) / 2) - tby; - display.setFullWindow(); + if (display.epd2.hasFastPartialUpdate) { + display.setPartialWindow(0, 0, display.width(), display.height()); + } else { + display.setFullWindow(); + } display.firstPage(); do { @@ -139,13 +255,14 @@ void getTime(char* ptr, size_t maxsize, const char* format) { void getSensorMeasurements() { - if (bme280_active) { + if (sensors_active.bme280) { bme280.takeForcedMeasurement(); sensor_readings.temperature = bme280.readTemperature(); sensor_readings.humidity = bme280.readHumidity(); sensor_readings.pressure_raw = bme280.readPressure(); } - if (bme680_active) { + if (sensors_active.bme680) { + bme680.endReading(); // ToDo if (bme680.performReading()) { sensor_readings.temperature = bme680.temperature; sensor_readings.humidity = bme680.humidity; @@ -174,13 +291,13 @@ void getSensorMeasurements() { history_pressure.addValue(sensor_readings.pressure); - if (uv_active) { + if (sensors_active.uv) { sensor_readings.uvi = uv.readUVI(); sensor_readings.uva = uv.readUVA(); sensor_readings.uvb = uv.readUVB(); } - if (light_active) { + if (sensors_active.light) { sensor_readings.lux = lightMeter.readLightLevel(); // auto-adjust sensitivity if (sensor_readings.lux < 0) { @@ -200,7 +317,7 @@ void getSensorMeasurements() { } } - if (sds_active) { + if (sensors_active.sds) { PmResult pm = sds.readPm(); if (pm.isOk()) { sensor_readings.pm10 = pm.pm10; @@ -354,7 +471,7 @@ void displayValues() { display.printf("%.1f k\xe9", sensor_readings.voc / 1000.0F); // PM float pm10, pm25; - if (sds_active) { + if (sensors_active.sds) { pm10 = sensor_readings.pm10; pm25 = sensor_readings.pm25; } else if (!isnan(sensors_a4cf1211c3e4.pm10) || !isnan(sensors_a4cf1211c3e4.pm25)) { @@ -378,7 +495,7 @@ void displayValues() { display.printf("%.1f", pm25); // Lux float lux; - if (light_active) { + if (sensors_active.light) { lux = sensor_readings.lux; } else if (!isnan(sensors_a4cf1211c3e4.lux)) { lux = sensors_a4cf1211c3e4.lux; @@ -395,7 +512,7 @@ void displayValues() { display.printf("%.1f lx", lux); // UV float uvi, uva, uvb; - if (uv_active) { + if (sensors_active.uv) { uvi = sensor_readings.uvi; uva = sensor_readings.uva; uvb = sensor_readings.uvb; @@ -449,7 +566,7 @@ void displayValues() { void printValues() { - if (bme280_active || bme680_active) { + if (sensors_active.bme280 || sensors_active.bme680) { #define SEALEVELPRESSURE_HPA (1013.25) Serial.print("Temperature = "); Serial.print(sensor_readings.temperature); @@ -468,7 +585,7 @@ void printValues() { Serial.println(" %"); } - if (bme680_active) { + if (sensors_active.bme680) { Serial.print("VOC = "); Serial.print(sensor_readings.voc / 1000.0F); Serial.println(" kOhm"); @@ -476,14 +593,14 @@ void printValues() { Serial.println(); - if (uv_active) { + if (sensors_active.uv) { Serial.print("UV Index reading: "); Serial.println(sensor_readings.uvi); Serial.print("Raw UVA reading: "); Serial.println(sensor_readings.uva); Serial.print("Raw UVB reading: "); Serial.println(sensor_readings.uvb); Serial.println(); } - if (sds_active) { + if (sensors_active.sds) { Serial.print("PM2.5 = "); Serial.print(sensor_readings.pm25); Serial.print(", PM10 = "); @@ -499,63 +616,56 @@ void printValues() { void sendValues() { /* send values MQTT */ - if (bme280_active || bme680_active) { + if (sensors_active.bme280 || sensors_active.bme680) { String topic_temperature = String("thomas/sensor/") + ota.getMAC() + String("/temperature"); String topic_humidity = String("thomas/sensor/") + ota.getMAC() + String("/humidity"); String topic_pressure = String("thomas/sensor/") + ota.getMAC() + String("/pressure"); - mqtt.publishf(topic_temperature.c_str(), "%.2f", sensor_readings.temperature); + mqtt.publishf2(topic_temperature.c_str(), 1, 1, "%.2f", sensor_readings.temperature); delay(10); - mqtt.publishf(topic_humidity.c_str(), "%.2f", sensor_readings.humidity); + mqtt.publishf2(topic_humidity.c_str(), 1, 1, "%.2f", sensor_readings.humidity); delay(10); - mqtt.publishf(topic_pressure.c_str(), "%.2f", sensor_readings.pressure); + mqtt.publishf2(topic_pressure.c_str(), 1, 1, "%.2f", sensor_readings.pressure); delay(10); } - if (bme680_active) { + if (sensors_active.bme680) { String topic_voc = String("thomas/sensor/") + ota.getMAC() + String("/voc"); - mqtt.publishf(topic_voc.c_str(), "%.2f", sensor_readings.voc / 1000.0F); - delay(10); - } - if (!bme280_active && !bme680_active) { - String topic_temperature = String("thomas/sensor/") + ota.getMAC() + String("/temperature"); - float esp32_temperature = (temprature_sens_read() - 32) / 1.8; - char temperature[8]; sprintf(temperature, "%.2f", esp32_temperature-29.40); - mqtt.publish(topic_temperature.c_str(), temperature, strlen(temperature)); + mqtt.publishf2(topic_voc.c_str(), 1, 1, "%.2f", sensor_readings.voc / 1000.0F); delay(10); } - if (uv_active) { + if (sensors_active.uv) { String topic_uvi = String("thomas/sensor/") + ota.getMAC() + String("/uvi"); String topic_uva = String("thomas/sensor/") + ota.getMAC() + String("/uva"); String topic_uvb = String("thomas/sensor/") + ota.getMAC() + String("/uvb"); - mqtt.publishf(topic_uvi.c_str(), "%.2f", sensor_readings.uvi); - mqtt.publishf(topic_uva.c_str(), "%.2f", sensor_readings.uva); - mqtt.publishf(topic_uvb.c_str(), "%.2f", sensor_readings.uvb); + mqtt.publishf2(topic_uvi.c_str(), 1, 1, "%.2f", sensor_readings.uvi); + mqtt.publishf2(topic_uva.c_str(), 1, 1, "%.2f", sensor_readings.uva); + mqtt.publishf2(topic_uvb.c_str(), 1, 1, "%.2f", sensor_readings.uvb); delay(10); } - if (light_active) { + if (sensors_active.light) { String topic_lux = String("thomas/sensor/") + ota.getMAC() + String("/lux"); - mqtt.publishf(topic_lux.c_str(), "%.2f", sensor_readings.lux); + mqtt.publishf2(topic_lux.c_str(), 1, 1, "%.2f", sensor_readings.lux); delay(10); } - if (sds_active) { + if (sensors_active.sds) { String topic_pm10 = String("thomas/sensor/") + ota.getMAC() + String("/pm10"); String topic_pm25 = String("thomas/sensor/") + ota.getMAC() + String("/pm25"); - mqtt.publishf(topic_pm10.c_str(), "%.2f", sensor_readings.pm10); - mqtt.publishf(topic_pm25.c_str(), "%.2f", sensor_readings.pm25); + mqtt.publishf2(topic_pm10.c_str(), 1, 1, "%.2f", sensor_readings.pm10); + mqtt.publishf2(topic_pm25.c_str(), 1, 1, "%.2f", sensor_readings.pm25); delay(10); } { String topic_battery = String("thomas/sensor/") + ota.getMAC() + String("/battery"); - mqtt.publishf(topic_battery.c_str(), "%.2f", (sensor_readings.battery/4096.0)*2*3.42); + mqtt.publishf2(topic_battery.c_str(), 1, 1, "%.2f", (sensor_readings.battery/4096.0)*2*3.42); delay(10); } { String topic_rssi = String("thomas/sensor/") + ota.getMAC() + String("/rssi"); - mqtt.publishf(topic_rssi.c_str(), "%d", sensor_readings.rssi); + mqtt.publishf2(topic_rssi.c_str(), 1, 1, "%d", sensor_readings.rssi); delay(10); } @@ -569,7 +679,11 @@ void sendValues() { void setup() { Serial.begin(115200); - delay(10); + + esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); + ++bootCount; + Serial.println("Boot number: " + String(bootCount)); + Serial.println("millis(): " + String(millis())); ESP_LOGD(TAG, "setup hardware and sensors"); @@ -583,20 +697,21 @@ void setup() adcAttachPin(_VBAT); adcStart(_VBAT); - // initialize e-paper display - SPI.begin(18, 19, 23, TFT_CS); // MISO is not connected to TFT_MISO! - display.init(); + Serial.println("millis(): " + String(millis())); #define BME_SDA 21 #define BME_SCL 22 Wire.begin(BME_SDA, BME_SCL); if (bme280.begin()) { - bme280_active = true; + sensors_active.bme280 = true; } else { ESP_LOGE(TAG, "Could not find a valid BME280 sensor, check wiring!"); } + + Serial.println("millis(): " + String(millis())); + if (bme680.begin()) { - bme680_active = true; + sensors_active.bme680 = true; // Set up oversampling and filter initialization bme680.setTemperatureOversampling(BME680_OS_8X); @@ -604,12 +719,15 @@ void setup() bme680.setPressureOversampling(BME680_OS_4X); bme680.setIIRFilterSize(BME680_FILTER_SIZE_3); bme680.setGasHeater(320, 150); // 320*C for 150 ms + bme680.beginReading(); } else { ESP_LOGE(TAG, "Could not find a valid BME680 sensor, check wiring!"); } + Serial.println("millis(): " + String(millis())); + if (uv.begin()) { - uv_active = true; + sensors_active.uv = true; uv.setIntegrationTime(VEML6075_100MS); // Set the integration constant uv.setHighDynamic(true); // Set the high dynamic mode @@ -622,55 +740,66 @@ void setup() Serial.println("Failed to communicate with VEML6075 sensor, check wiring?"); } + Serial.println("millis(): " + String(millis())); + if (lightMeter.begin()) { - light_active = true; + sensors_active.light = true; } else { Serial.println("Failed to communicate with BH1750 sensor, check wiring?"); } + Serial.println("millis(): " + String(millis())); + sds.begin(); - FirmwareVersionResult sds_fw = sds.queryFirmwareVersion(); - if (sds_fw.isOk()) { - sds_active = true; + Serial.println("millis(): " + String(millis())); - sds.setActiveReportingMode(); // ensures sensor is in 'active' reporting mode - sds.setCustomWorkingPeriod(5); // sensor sends data every 3 minutes - } else { - Serial.println("Failed to communicate with SDS011 sensor, check wiring?"); + if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { + FirmwareVersionResult sds_fw = sds.queryFirmwareVersion(); + if (sds_fw.isOk()) { + sensors_active.sds = true; + + sds.setActiveReportingMode(); // ensures sensor is in 'active' reporting mode + sds.setCustomWorkingPeriod(5); // sensor sends data every 3 minutes + } else { + Serial.println("Failed to communicate with SDS011 sensor, check wiring?"); + } } - //display.clearScreen(); - //display.refresh(); + Serial.println("millis(): " + String(millis())); - ESP_LOGD(TAG, "displaying welcome screen"); - helloWorld(); - display.powerOff(); + // initialize e-paper display + SPI.begin(18, 19, 23, TFT_CS); // MISO is not connected to TFT_MISO! + display.init(0, false, false); + display.setRotation(1); - ESP_LOGD(TAG, "connecting to WiFi"); + Serial.println("millis(): " + String(millis())); - WiFi.setHostname("esp32-weatherstation"); + if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { + // wakeup not caused by deep sleep + display.clearScreen(); + display.refresh(); + helloWorld(); + display.powerOff(); + } else { + // wakeup by deep sleep +// displayValues(); + } - wifiMulti.addAP(WIFI_SSID, WIFI_PASSWD); - wifiMulti.addAP(WIFI_SSID2, WIFI_PASSWD2); - wifiMulti.addAP(WIFI_SSID3, WIFI_PASSWD3); + ESP_LOGD(TAG, "connecting to WiFi"); + Serial.println("millis(): " + String(millis())); - for (int tries=0; wifiMulti.run() != WL_CONNECTED && tries < 10; tries++) { - Serial.print("."); - delay(500); - } + wifiConnect(); - if(wifiMulti.run() == WL_CONNECTED) { - Serial.println(""); - Serial.println("WiFi connected"); - Serial.println("IP address: "); - Serial.println(WiFi.localIP()); - displayIcoPartial(ico_wifi16, display.width()-20, y_offset+0, ico_wifi16_width, ico_wifi16_height); - } + WiFi.waitForConnectResult(); + //displayIcoPartial(ico_wifi16, display.width()-20, y_offset+0, ico_wifi16_width, ico_wifi16_height); - ESP_LOGD(TAG, "trying to fetch over-the-air update"); - if (WiFi.status() == WL_CONNECTED) { - ota.update(); + if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { + // wakeup not caused by deep sleep + ESP_LOGD(TAG, "trying to fetch over-the-air update"); + if (WiFi.status() == WL_CONNECTED) { + ota.update(); + } } WiFi.setSleep(true); @@ -684,7 +813,6 @@ void setup() if (!ota.getMAC().equals("246f28d1eff4")) mqtt.subscribe("thomas/sensor/246f28d1eff4/#", receiveMqtt); /* temp: publish version */ - delay(5000); String topic_version = String("thomas/sensor/") + ota.getMAC() + String("/version"); const char* fw_version_str = String(FW_VERSION).c_str(); mqtt.publish(topic_version.c_str(), fw_version_str, strlen(fw_version_str)); @@ -705,27 +833,27 @@ void setup() */ void loop() { - /* Do an e-paper display refresh every 1 minutes */ - if (millis() - lastDisplayUpdate >= 1*60*1000) { - lastDisplayUpdate = millis(); +/* if(wifiMulti.run() != WL_CONNECTED) { + Serial.println("WiFi not connected!"); + delay(1000); + }*/ /* Do a full refresh every hour */ - if (millis() - lastDisplayRefresh >= 60*60*1000) { - lastDisplayRefresh = millis(); - display.clearScreen(); - display.refresh(); - } - - getSensorMeasurements(); - displayValues(); - printValues(); - sendValues(); + if (getTimestamp() - lastDisplayRefresh >= 60*60) { + Serial.printf("last display refresh :%ds ago", getTimestamp() - lastDisplayRefresh); + lastDisplayRefresh = getTimestamp(); + display.clearScreen(); + display.refresh(); } - if(wifiMulti.run() != WL_CONNECTED) { - Serial.println("WiFi not connected!"); - delay(1000); - } + getSensorMeasurements(); + displayValues(); + printValues(); + sendValues(); + + int runtime = millis()/1000; + if (runtime < 0 || runtime >= TIME_TO_SLEEP) runtime = 0; + gotoSleep(TIME_TO_SLEEP - runtime); delay(2000); } From 638f8af729f5d30fe285a386ab2d1be9c7353c1f Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 17:30:00 +0200 Subject: [PATCH 02/13] remove printValues() --- src/main.cpp | 67 +++++++++++++--------------------------------------- 1 file changed, 17 insertions(+), 50 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e1d3c7a..bd29c1d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -260,6 +260,9 @@ void getSensorMeasurements() { sensor_readings.temperature = bme280.readTemperature(); sensor_readings.humidity = bme280.readHumidity(); sensor_readings.pressure_raw = bme280.readPressure(); + ESP_LOGI(TAG, "Temperature : %8.2f °C", sensor_readings.temperature); + ESP_LOGI(TAG, "Pressure (Raw): %8.2f Pa", sensor_readings.pressure_raw); + ESP_LOGI(TAG, "Humidity : %8.2f %", sensor_readings.humidity); } if (sensors_active.bme680) { bme680.endReading(); // ToDo @@ -268,6 +271,10 @@ void getSensorMeasurements() { sensor_readings.humidity = bme680.humidity; sensor_readings.pressure_raw = bme680.pressure; sensor_readings.voc = bme680.gas_resistance; + ESP_LOGI(TAG, "Temperature : %8.2f °C", sensor_readings.temperature); + ESP_LOGI(TAG, "Pressure (Raw): %8.2f Pa", sensor_readings.pressure_raw); + ESP_LOGI(TAG, "Humidity : %8.2f %", sensor_readings.humidity); + ESP_LOGI(TAG, "VOC : %5lu kOhm", sensor_readings.voc); } else { Serial.println("Failed to perform reading :("); } @@ -295,6 +302,9 @@ void getSensorMeasurements() { sensor_readings.uvi = uv.readUVI(); sensor_readings.uva = uv.readUVA(); sensor_readings.uvb = uv.readUVB(); + ESP_LOGI(TAG, "UVI : %8.2f", sensor_readings.uvi); + ESP_LOGI(TAG, "UVA : %8.2f", sensor_readings.uva); + ESP_LOGI(TAG, "UVB : %8.2f", sensor_readings.uvb); } if (sensors_active.light) { @@ -315,6 +325,7 @@ void getSensorMeasurements() { Serial.println(F("Setting MTReg to default value for normal light environment")); } } + ESP_LOGI(TAG, "Lux : %8.2f lx", sensor_readings.lux); } if (sensors_active.sds) { @@ -322,12 +333,18 @@ void getSensorMeasurements() { if (pm.isOk()) { sensor_readings.pm10 = pm.pm10; sensor_readings.pm25 = pm.pm25; + ESP_LOGI(TAG, "PM10 : %8.2f µg/m³", sensor_readings.pm10); + ESP_LOGI(TAG, "PM2.5 : %8.2f µg/m³", sensor_readings.pm25); } } sensor_readings.battery = analogRead(_VBAT); sensor_readings.rssi = WiFi.RSSI(); + ESP_LOGI(TAG, "RSSI : %5d dBm", sensor_readings.rssi); + ESP_LOGI(TAG, "Battery : %5d ", sensor_readings.battery); + ESP_LOGI(TAG, "Heap : %5lu", ESP.getFreeHeap()); + sensor_readings.lastUpdate = millis(); } @@ -565,55 +582,6 @@ void displayValues() { } -void printValues() { - if (sensors_active.bme280 || sensors_active.bme680) { - #define SEALEVELPRESSURE_HPA (1013.25) - Serial.print("Temperature = "); - Serial.print(sensor_readings.temperature); - Serial.println(" *C"); - - Serial.print("Pressure = "); - Serial.print(sensor_readings.pressure); - Serial.println(" hPa"); - - Serial.print("Pressure [RAW] = "); - Serial.print(sensor_readings.pressure_raw / 100.0F); - Serial.println(" hPa"); - - Serial.print("Humidity = "); - Serial.print(sensor_readings.humidity); - Serial.println(" %"); - } - - if (sensors_active.bme680) { - Serial.print("VOC = "); - Serial.print(sensor_readings.voc / 1000.0F); - Serial.println(" kOhm"); - } - - Serial.println(); - - if (sensors_active.uv) { - Serial.print("UV Index reading: "); Serial.println(sensor_readings.uvi); - Serial.print("Raw UVA reading: "); Serial.println(sensor_readings.uva); - Serial.print("Raw UVB reading: "); Serial.println(sensor_readings.uvb); - Serial.println(); - } - - if (sensors_active.sds) { - Serial.print("PM2.5 = "); - Serial.print(sensor_readings.pm25); - Serial.print(", PM10 = "); - Serial.println(sensor_readings.pm10); - } - - Serial.print("RSSI: "); Serial.println(sensor_readings.rssi); - Serial.print("Battery: "); Serial.println(sensor_readings.battery); - - Serial.print("Free HEAP: "); Serial.println(ESP.getFreeHeap()); - -} - void sendValues() { /* send values MQTT */ if (sensors_active.bme280 || sensors_active.bme680) { @@ -848,7 +816,6 @@ void loop() getSensorMeasurements(); displayValues(); - printValues(); sendValues(); int runtime = millis()/1000; From 8ad2f66131da6dd57d510561f214e15703dce01a Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 17:42:39 +0200 Subject: [PATCH 03/13] make lastUpdate absolute --- src/main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bd29c1d..c97cab7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -88,7 +88,7 @@ struct __attribute__((packed)) sensor_readings_t { float temperature_min = NAN; // °C int battery = 0; int8_t rssi = 0; - uint32_t lastUpdate = 0; + time_t lastUpdate = 0; } sensor_readings; sensor_readings_t sensors_a4cf1211c3e4, sensors_246f28d1fa5c, sensors_246f28d1a080, sensors_246f28d1eff4; @@ -345,7 +345,7 @@ void getSensorMeasurements() { ESP_LOGI(TAG, "Battery : %5d ", sensor_readings.battery); ESP_LOGI(TAG, "Heap : %5lu", ESP.getFreeHeap()); - sensor_readings.lastUpdate = millis(); + sensor_readings.lastUpdate = getTimestamp(); } @@ -386,7 +386,7 @@ void receiveMqtt(const char* topic, const char* data) { } else if (strcmp("/voc", topic_last) == 0) { sensor->voc = atof(data); } - sensor->lastUpdate = millis(); + sensor->lastUpdate = getTimestamp(); // ToDo } } @@ -562,16 +562,16 @@ void displayValues() { // other nodes display.setFont(NULL); display.setCursor(0, y_offset+70); - if (!ota.getMAC().equals("246f28d1fa5c") && millis() - sensors_246f28d1fa5c.lastUpdate < 15*60*1000) { + if (!ota.getMAC().equals("246f28d1fa5c") && getTimestamp() - sensors_246f28d1fa5c.lastUpdate < 15*60) { display.printf("246f28d1fa5c: %4.1f %4.1f %6.1f\n", sensors_246f28d1fa5c.temperature, sensors_246f28d1fa5c.humidity, sensors_246f28d1fa5c.pressure); } - if (!ota.getMAC().equals("a4cf1211c3e4") && millis() - sensors_a4cf1211c3e4.lastUpdate < 15*60*1000) { + if (!ota.getMAC().equals("a4cf1211c3e4") && getTimestamp() - sensors_a4cf1211c3e4.lastUpdate < 15*60) { display.printf("a4cf1211c3e4: %4.1f %4.1f %6.1f\n", sensors_a4cf1211c3e4.temperature, sensors_a4cf1211c3e4.humidity, sensors_a4cf1211c3e4.pressure); } - if (!ota.getMAC().equals("246f28d1a080") && millis() - sensors_246f28d1a080.lastUpdate < 15*60*1000) { + if (!ota.getMAC().equals("246f28d1a080") && getTimestamp() - sensors_246f28d1a080.lastUpdate < 15*60) { display.printf("246f28d1a080: %4.1f %4.1f %6.1f\n", sensors_246f28d1a080.temperature, sensors_246f28d1a080.humidity, sensors_246f28d1a080.pressure); } - if (!ota.getMAC().equals("246f28d1eff4") && millis() - sensors_246f28d1eff4.lastUpdate < 15*60*1000) { + if (!ota.getMAC().equals("246f28d1eff4") && getTimestamp() - sensors_246f28d1eff4.lastUpdate < 15*60) { display.printf("246f28d1eff4: %4.1f %4.1f %6.1f\n", sensors_246f28d1eff4.temperature, sensors_246f28d1eff4.humidity, sensors_246f28d1eff4.pressure); } From b04d242f209d5f1ac477b7946c8ceb05ad6aaa8c Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 18:13:18 +0200 Subject: [PATCH 04/13] ntp time --- src/main.cpp | 11 ++++++++++- src/network/XD0OTA.cpp | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index c97cab7..179b777 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -201,6 +201,13 @@ void wifiConnect() { } } +bool obtain_time() { + ESP_LOGI(TAG, "syncing time"); + configTzTime("CET-1CEST,M3.5.0/2,M10.5.0/3", "de.pool.ntp.org"); + struct tm timeinfo; + return getLocalTime(&timeinfo, 5000); +} + void helloWorld() { const char HelloWorld[] = "IchbinsBens!"; @@ -747,6 +754,7 @@ void setup() // wakeup not caused by deep sleep display.clearScreen(); display.refresh(); + lastDisplayRefresh = getTimestamp(); helloWorld(); display.powerOff(); } else { @@ -760,10 +768,11 @@ void setup() wifiConnect(); WiFi.waitForConnectResult(); - //displayIcoPartial(ico_wifi16, display.width()-20, y_offset+0, ico_wifi16_width, ico_wifi16_height); + displayIcoPartial(ico_wifi16, display.width()-20, y_offset+0, ico_wifi16_width, ico_wifi16_height); if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { // wakeup not caused by deep sleep + obtain_time(); ESP_LOGD(TAG, "trying to fetch over-the-air update"); if (WiFi.status() == WL_CONNECTED) { ota.update(); diff --git a/src/network/XD0OTA.cpp b/src/network/XD0OTA.cpp index 5793034..ef5ca85 100644 --- a/src/network/XD0OTA.cpp +++ b/src/network/XD0OTA.cpp @@ -57,7 +57,7 @@ String XD0OTA::getUpdateURL(String file, String extension) { } void XD0OTA::update(void) { - setClock(); + //setClock(); // try device specific image first String fwURL = getUpdateURL(getMAC(), ".bin"); From efde2d3ef96ee317d8c9c20dc65daeeafdb725c3 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 18:24:28 +0200 Subject: [PATCH 05/13] replace Serial.print --- src/main.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 179b777..5e0abdc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -134,8 +134,7 @@ void gotoSleep(unsigned int sleep_time = TIME_TO_SLEEP) { esp_sleep_enable_timer_wakeup(sleep_time * 1000000LL); esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); - Serial.println("going to to sleep for " + String(sleep_time) + - " Seconds"); + ESP_LOGI(TAG, "going to to sleep for %d seconds", sleep_time); Serial.flush(); esp_deep_sleep_start(); delay(1); @@ -156,7 +155,7 @@ void wifiConnect() { Serial.println("millis(): " + String(millis())); - Serial.println("previous dhcp: " + String(getTimestamp() - network.last_dhcp) + "s ago"); + ESP_LOGD(TAG, "previous dhcp: %lu s ago", getTimestamp() - network.last_dhcp); if ( ip != INADDR_NONE && dns != INADDR_NONE && gateway != INADDR_NONE && subnet != INADDR_NONE && ((ip[0] == 192 && ip[1] == 168) || (ip[0] == 172 && ip[1] == 16)) @@ -174,7 +173,7 @@ void wifiConnect() { } else { ESP_LOGD("WiFi", "DHCP"); for (int tries=0; wifiMulti.run() != WL_CONNECTED && tries < 20; tries++) { - Serial.print("."); + ESP_LOGD("WiFi", "."); delay(500); } @@ -283,7 +282,7 @@ void getSensorMeasurements() { ESP_LOGI(TAG, "Humidity : %8.2f %", sensor_readings.humidity); ESP_LOGI(TAG, "VOC : %5lu kOhm", sensor_readings.voc); } else { - Serial.println("Failed to perform reading :("); + ESP_LOGE(TAG, "Failed to perform BME680 reading :("); } } @@ -318,18 +317,18 @@ void getSensorMeasurements() { sensor_readings.lux = lightMeter.readLightLevel(); // auto-adjust sensitivity if (sensor_readings.lux < 0) { - Serial.println("Error reading light level"); + ESP_LOGE(TAG, "Error reading light level"); } else if (sensor_readings.lux > 40000.0) { if (lightMeter.setMTreg(32)) { - Serial.println(F("Setting MTReg to low value for high light environment")); + ESP_LOGD(TAG, "Setting MTReg to low value for high light environment"); } } else if (sensor_readings.lux <= 10.0) { if (lightMeter.setMTreg(138)) { - Serial.println(F("Setting MTReg to high value for low light environment")); + ESP_LOGD(TAG, "Setting MTReg to high value for low light environment"); } } else { // if (sensor_readings.lux > 10.0) if (lightMeter.setMTreg(69)) { - Serial.println(F("Setting MTReg to default value for normal light environment")); + ESP_LOGD(TAG, "Setting MTReg to default value for normal light environment"); } } ESP_LOGI(TAG, "Lux : %8.2f lx", sensor_readings.lux); @@ -657,7 +656,7 @@ void setup() esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); ++bootCount; - Serial.println("Boot number: " + String(bootCount)); + ESP_LOGI(TAG, "Boot number: %d", bootCount); Serial.println("millis(): " + String(millis())); ESP_LOGD(TAG, "setup hardware and sensors"); @@ -712,7 +711,7 @@ void setup() 2.95, 1.74, // UVB_C and UVB_D coefficients 0.001461, 0.002591); // UVA and UVB responses } else { - Serial.println("Failed to communicate with VEML6075 sensor, check wiring?"); + ESP_LOGW(TAG, "Failed to communicate with VEML6075 sensor, check wiring?"); } Serial.println("millis(): " + String(millis())); @@ -720,7 +719,7 @@ void setup() if (lightMeter.begin()) { sensors_active.light = true; } else { - Serial.println("Failed to communicate with BH1750 sensor, check wiring?"); + ESP_LOGW(TAG, "Failed to communicate with BH1750 sensor, check wiring?"); } Serial.println("millis(): " + String(millis())); @@ -737,7 +736,7 @@ void setup() sds.setActiveReportingMode(); // ensures sensor is in 'active' reporting mode sds.setCustomWorkingPeriod(5); // sensor sends data every 3 minutes } else { - Serial.println("Failed to communicate with SDS011 sensor, check wiring?"); + ESP_LOGW(TAG, "Failed to communicate with SDS011 sensor, check wiring?"); } } @@ -817,7 +816,6 @@ void loop() /* Do a full refresh every hour */ if (getTimestamp() - lastDisplayRefresh >= 60*60) { - Serial.printf("last display refresh :%ds ago", getTimestamp() - lastDisplayRefresh); lastDisplayRefresh = getTimestamp(); display.clearScreen(); display.refresh(); From 42fcf062b7608f6ab5719427292246d92ee90421 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 18:29:30 +0200 Subject: [PATCH 06/13] power down sensors --- src/main.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 5e0abdc..42234cc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -119,7 +119,26 @@ time_t getTimestamp() { void poweroffDevices() { display.powerOff(); - // ToDo: Sensors + if (sensors_active.bme680) { + bme680.setGasHeater(0, 0); + } + if (sensors_active.bme280) { + bme280.setSampling(Adafruit_BME280::MODE_SLEEP, + Adafruit_BME280::SAMPLING_X1, // temperature + Adafruit_BME280::SAMPLING_X1, // pressure + Adafruit_BME280::SAMPLING_X1, // humidity + Adafruit_BME280::FILTER_OFF ); + } + if (sensors_active.light) { + static constexpr byte BH1750_I2CADDR = 0x23; + Wire.beginTransmission(BH1750_I2CADDR); + Wire.write(BH1750_POWER_DOWN); + byte ack = Wire.endTransmission(); + } + if (sensors_active.uv) { + uv.shutdown(true); + + } } @@ -718,6 +737,7 @@ void setup() if (lightMeter.begin()) { sensors_active.light = true; + lightMeter.setMTreg((byte) BH1750_DEFAULT_MTREG); } else { ESP_LOGW(TAG, "Failed to communicate with BH1750 sensor, check wiring?"); } From c257fd696ce343b1f9da8e7c86d68c48ced0af88 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 18:44:54 +0200 Subject: [PATCH 07/13] disable debugging --- platformio.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 2a40a72..1af159f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,9 +18,9 @@ board = lolin_d32_pro board_build.f_cpu = 160000000L build_flags = - -DLOG_DEFAULT_LEVEL=ESP_LOG_VERBOSE - -DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE - -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE +; -DLOG_DEFAULT_LEVEL=ESP_LOG_VERBOSE +; -DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE +; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE ; -DBOARD_HAS_PSRAM ; -mfix-esp32-psram-cache-issue -DWIFI_SSID="\"${sysenv.WIFI_SSID}\"" From 7d7df040366af56b32f828c210e1432813872f4a Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 18:45:13 +0200 Subject: [PATCH 08/13] remove Serial.print --- src/network/XD0MQTT.cpp | 8 ++++---- src/network/XD0OTA.cpp | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/network/XD0MQTT.cpp b/src/network/XD0MQTT.cpp index 8b1e7e1..a323d77 100644 --- a/src/network/XD0MQTT.cpp +++ b/src/network/XD0MQTT.cpp @@ -106,10 +106,10 @@ bool XD0MQTT::begin(void) { mqtt_cfg.password = MQTT_PASSWORD; mqtt_cfg.user_context = (void*)this; - ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); - Serial.printf("BROKER URI: %s\n", MQTT_BROKER_URI); - Serial.printf("MQTT USERNAME: %s\n", MQTT_USERNAME); - Serial.printf("MQTT PASSWORD: %s\n", MQTT_PASSWORD); + ESP_LOGD(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "BROKER URI: %s\n", MQTT_BROKER_URI); + ESP_LOGI(TAG, "MQTT USERNAME: %s\n", MQTT_USERNAME); + ESP_LOGI(TAG, "MQTT PASSWORD: %s\n", MQTT_PASSWORD); client = esp_mqtt_client_init(&mqtt_cfg); //esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); esp_mqtt_client_start(client); diff --git a/src/network/XD0OTA.cpp b/src/network/XD0OTA.cpp index ef5ca85..32ab5f6 100644 --- a/src/network/XD0OTA.cpp +++ b/src/network/XD0OTA.cpp @@ -16,23 +16,21 @@ XD0OTA::XD0OTA(String deviceName) : deviceName{deviceName} {} void XD0OTA::setClock() { configTime(0, 0, "de.pool.ntp.org", "time.nist.gov"); // UTC - Serial.print(F("Waiting for NTP time sync: ")); + ESP_LOGI(TAG, "Waiting for NTP time sync: "); time_t now = time(nullptr); int tries = 0; while (now < 8 * 3600 * 2) { yield(); delay(500); - Serial.print(F(".")); + ESP_LOGI(TAG, "."); now = time(nullptr); tries++; if (tries>15) return; } - Serial.println(F("")); struct tm timeinfo; gmtime_r(&now, &timeinfo); - Serial.print(F("Current time: ")); - Serial.print(asctime(&timeinfo)); + ESP_LOGI(TAG, "Current time: %s", asctime(&timeinfo)); // setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1); // tzset(); From 7a13877184e7fcb53acf85e871ebedaf06bde443 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 20:55:24 +0200 Subject: [PATCH 09/13] fix mqtt non-terminated strings --- src/network/XD0MQTT.cpp | 14 ++++++++++---- src/network/XD0MQTT.h | 5 +++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/network/XD0MQTT.cpp b/src/network/XD0MQTT.cpp index a323d77..7ba6a03 100644 --- a/src/network/XD0MQTT.cpp +++ b/src/network/XD0MQTT.cpp @@ -60,13 +60,15 @@ esp_err_t XD0MQTT::mqtt_event_handler_cb(esp_mqtt_event_handle_t event) ESP_LOGI(TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic); ESP_LOGI(TAG, "DATA=%.*s\r\n", event->data_len, event->data); for (const auto &subscription : subscriptions_) { + char topic[128]; + strncpy(topic, event->topic, event->topic_len); topic[event->topic_len] = '\0'; // literal match - if (strcmp(event->topic, subscription.topic) == 0) { - subscription.cb(event->topic, event->data); + if (event->topic_len == strlen(subscription.topic) && strncmp(event->topic, subscription.topic, event->topic_len) == 0) { + subscription.cb(topic, event->data, event->data_len); // '#' wildcard } else if (subscription.topic[strlen(subscription.topic)-1] == '#'){ - if (strncmp(event->topic, subscription.topic, strlen(subscription.topic)-1) == 0) { - subscription.cb(event->topic, event->data); + if (event->topic_len >= strlen(subscription.topic) && strncmp(event->topic, subscription.topic, strlen(subscription.topic)-1) == 0) { + subscription.cb(topic, event->data, event->data_len); } } // ToDo: '+' wildcard @@ -128,6 +130,10 @@ void XD0MQTT::end(void) { esp_mqtt_client_destroy(client); } +bool XD0MQTT::isConnected(void) { + return connected; +} + bool XD0MQTT::publish(const char* topic, const char* data, int len, int qos, int retain) { int msg_id = esp_mqtt_client_publish(client, topic, data, len, qos, retain); ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); diff --git a/src/network/XD0MQTT.h b/src/network/XD0MQTT.h index a4699fd..43837da 100644 --- a/src/network/XD0MQTT.h +++ b/src/network/XD0MQTT.h @@ -17,7 +17,7 @@ #include "mqtt_client.h" -typedef std::function cb_t; +typedef std::function cb_t; struct subscription_t { const char* topic; @@ -37,9 +37,10 @@ class XD0MQTT { bool subscribe(const char* topic, const cb_t &cb, int qos=1); bool unsubscribe(const char* topic); esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event); - bool connected = false; + bool isConnected(void); std::vector subscriptions_; private: + bool connected = false; // openssl s_client -showcerts -connect home.xd0.de:8883 /dev/null|openssl x509 -outform PEM >mqtt_xd0.de.pem const char* rootCACertificate = \ "-----BEGIN CERTIFICATE-----\n" \ From b48fc67eb68e17f71a0ea365546e7a5d0a341bec Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 20:55:58 +0200 Subject: [PATCH 10/13] send JSON --- platformio.ini | 2 +- src/main.cpp | 109 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 89 insertions(+), 22 deletions(-) diff --git a/platformio.ini b/platformio.ini index 1af159f..d503fed 100644 --- a/platformio.ini +++ b/platformio.ini @@ -47,7 +47,7 @@ lib_deps = ; SDS011 sensor Library ; Nova Fitness Sds dust sensors library https://github.com/lewapek/sds-dust-sensors-arduino-library.git -; ArduinoJSON + ArduinoJSON monitor_speed = 115200 upload_speed = 115200 diff --git a/src/main.cpp b/src/main.cpp index 42234cc..42a9cdc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,8 @@ #include "network/XD0OTA.h" #include "network/XD0MQTT.h" +#include + #include "SensorHistory.h" #include "icons.h" @@ -57,8 +59,10 @@ SdsDustSensor sds(Serial2); Adafruit_VEML6075 uv = Adafruit_VEML6075(); BH1750 lightMeter; -XD0OTA ota("esp32-weatherstation"); +constexpr unsigned int JSON_BUF_LEN = 512; +constexpr unsigned int JSON_CAPACITY = JSON_OBJECT_SIZE(16) + 0*JSON_ARRAY_SIZE(2) + 120; XD0MQTT mqtt; +XD0OTA ota("esp32-weatherstation"); struct __attribute__((packed)) network_t { uint32_t ip; @@ -374,9 +378,11 @@ void getSensorMeasurements() { } -void receiveMqtt(const char* topic, const char* data) { +void receiveMqtt(const char* topic, const char* data, int data_len) { sensor_readings_t* sensor = NULL; + ESP_LOGI(TAG, "received MQTT message on subscribed topic %s", topic); + if (strstr(topic, "thomas/sensor/a4cf1211c3e4") == topic) { sensor = &sensors_a4cf1211c3e4; } else if (strstr(topic, "thomas/sensor/246f28d1fa5c") == topic) { @@ -390,8 +396,32 @@ void receiveMqtt(const char* topic, const char* data) { char* topic_last = strrchr(topic, '/'); if (topic_last && sensor) { - if (strcmp("/temperature", topic_last) == 0) { + if (strcmp("/json", topic_last) == 0) { + StaticJsonDocument jsonDoc; + DeserializationError err = deserializeJson(jsonDoc, data, data_len); + if (err) { + ESP_LOGW(TAG, "Error parsing JSON, code: %s", err.c_str()); + } else { + // got json + sensor->temperature = jsonDoc["temperature"].as(); + sensor->humidity = jsonDoc["humidity"].as(); + sensor->pressure = jsonDoc["pressure"].as(); + sensor->voc = jsonDoc["voc"].as(); + sensor->lux = jsonDoc["lux"].as(); + sensor->uvi = jsonDoc["uvi"].as(); + sensor->uva = jsonDoc["uva"].as(); + sensor->uvb = jsonDoc["uvb"].as(); + sensor->pm10 = jsonDoc["pm10"].as(); + sensor->pm25 = jsonDoc["pm2.5"].as(); + sensor->battery = jsonDoc["voltage"].as(); + sensor->rssi = jsonDoc["rssi"].as(); + sensor->lastUpdate = jsonDoc["timestamp"].as(); + ESP_LOGI(TAG, "got new values from %s, timestamp: %lu", topic, sensor->lastUpdate); + ESP_LOGI(TAG, "%lu seconds ago", topic, getTimestamp() - sensor->lastUpdate); + } + } else if (strcmp("/temperature", topic_last) == 0) { sensor->temperature = atof(data); + sensor->lastUpdate = getTimestamp(); } else if (strcmp("/humidity", topic_last) == 0) { sensor->humidity = atof(data); } else if (strcmp("/pressure", topic_last) == 0) { @@ -411,7 +441,6 @@ void receiveMqtt(const char* topic, const char* data) { } else if (strcmp("/voc", topic_last) == 0) { sensor->voc = atof(data); } - sensor->lastUpdate = getTimestamp(); // ToDo } } @@ -426,6 +455,7 @@ void displayValues() { char timeStr[40]; getTime(timeStr, sizeof(timeStr), "%d. %b %Y %H:%M:%S"); + ESP_LOGD(TAG, "displayValues()"); if (display.epd2.hasFastPartialUpdate) { display.setPartialWindow(0, 0, display.width(), display.height()); @@ -608,21 +638,57 @@ void displayValues() { void sendValues() { + for (int tries=0; mqtt.isConnected() == false && tries < 10; tries++) { + ESP_LOGD(TAG, "waiting for mqtt connection"); + delay(300); + } + + /* send values MQTT JSON */ + char buf[JSON_BUF_LEN]; + StaticJsonDocument jsonDoc; + if (sensors_active.bme280 || sensors_active.bme680) { + jsonDoc["temperature"] = sensor_readings.temperature; + jsonDoc["humidity"] = sensor_readings.humidity; + jsonDoc["pressure"] = sensor_readings.pressure; + } + if (sensors_active.bme680) { + jsonDoc["voc"] = sensor_readings.voc; + } + if (sensors_active.light) { + jsonDoc["lux"] = sensor_readings.lux; + } + if (sensors_active.uv) { + jsonDoc["uvi"] = sensor_readings.uvi; + jsonDoc["uva"] = sensor_readings.uva; + jsonDoc["uvb"] = sensor_readings.uvb; + } + if (sensors_active.sds) { + jsonDoc["pm10"] = sensor_readings.pm10; + jsonDoc["pm2.5"] = sensor_readings.pm25; + } + jsonDoc["voltage"] = sensor_readings.battery; + jsonDoc["rssi"] = sensor_readings.rssi; + jsonDoc["timestamp"] = sensor_readings.lastUpdate; + serializeJson(jsonDoc, buf, JSON_BUF_LEN); + String topic_json = String("thomas/sensor/") + ota.getMAC() + String("/json"); + mqtt.publish(topic_json.c_str(), buf, strlen(buf), 1, 1); + delay(10); + /* send values MQTT */ if (sensors_active.bme280 || sensors_active.bme680) { String topic_temperature = String("thomas/sensor/") + ota.getMAC() + String("/temperature"); String topic_humidity = String("thomas/sensor/") + ota.getMAC() + String("/humidity"); String topic_pressure = String("thomas/sensor/") + ota.getMAC() + String("/pressure"); - mqtt.publishf2(topic_temperature.c_str(), 1, 1, "%.2f", sensor_readings.temperature); + mqtt.publishf(topic_temperature.c_str(), "%.2f", sensor_readings.temperature); delay(10); - mqtt.publishf2(topic_humidity.c_str(), 1, 1, "%.2f", sensor_readings.humidity); + mqtt.publishf(topic_humidity.c_str(), "%.2f", sensor_readings.humidity); delay(10); - mqtt.publishf2(topic_pressure.c_str(), 1, 1, "%.2f", sensor_readings.pressure); + mqtt.publishf(topic_pressure.c_str(), "%.2f", sensor_readings.pressure); delay(10); } if (sensors_active.bme680) { String topic_voc = String("thomas/sensor/") + ota.getMAC() + String("/voc"); - mqtt.publishf2(topic_voc.c_str(), 1, 1, "%.2f", sensor_readings.voc / 1000.0F); + mqtt.publishf(topic_voc.c_str(), "%.2f", sensor_readings.voc / 1000.0F); delay(10); } @@ -630,35 +696,35 @@ void sendValues() { String topic_uvi = String("thomas/sensor/") + ota.getMAC() + String("/uvi"); String topic_uva = String("thomas/sensor/") + ota.getMAC() + String("/uva"); String topic_uvb = String("thomas/sensor/") + ota.getMAC() + String("/uvb"); - mqtt.publishf2(topic_uvi.c_str(), 1, 1, "%.2f", sensor_readings.uvi); - mqtt.publishf2(topic_uva.c_str(), 1, 1, "%.2f", sensor_readings.uva); - mqtt.publishf2(topic_uvb.c_str(), 1, 1, "%.2f", sensor_readings.uvb); + mqtt.publishf(topic_uvi.c_str(), "%.2f", sensor_readings.uvi); + mqtt.publishf(topic_uva.c_str(), "%.2f", sensor_readings.uva); + mqtt.publishf(topic_uvb.c_str(), "%.2f", sensor_readings.uvb); delay(10); } if (sensors_active.light) { String topic_lux = String("thomas/sensor/") + ota.getMAC() + String("/lux"); - mqtt.publishf2(topic_lux.c_str(), 1, 1, "%.2f", sensor_readings.lux); + mqtt.publishf(topic_lux.c_str(), "%.2f", sensor_readings.lux); delay(10); } if (sensors_active.sds) { String topic_pm10 = String("thomas/sensor/") + ota.getMAC() + String("/pm10"); String topic_pm25 = String("thomas/sensor/") + ota.getMAC() + String("/pm25"); - mqtt.publishf2(topic_pm10.c_str(), 1, 1, "%.2f", sensor_readings.pm10); - mqtt.publishf2(topic_pm25.c_str(), 1, 1, "%.2f", sensor_readings.pm25); + mqtt.publishf(topic_pm10.c_str(), "%.2f", sensor_readings.pm10); + mqtt.publishf(topic_pm25.c_str(), "%.2f", sensor_readings.pm25); delay(10); } { String topic_battery = String("thomas/sensor/") + ota.getMAC() + String("/battery"); - mqtt.publishf2(topic_battery.c_str(), 1, 1, "%.2f", (sensor_readings.battery/4096.0)*2*3.42); + mqtt.publishf(topic_battery.c_str(), "%.2f", (sensor_readings.battery/4096.0)*2*3.42); delay(10); } { String topic_rssi = String("thomas/sensor/") + ota.getMAC() + String("/rssi"); - mqtt.publishf2(topic_rssi.c_str(), 1, 1, "%d", sensor_readings.rssi); + mqtt.publishf(topic_rssi.c_str(), "%d", sensor_readings.rssi); delay(10); } @@ -803,10 +869,10 @@ void setup() ESP_LOGD(TAG, "connecting to MQTT"); mqtt.begin(); - if (!ota.getMAC().equals("a4cf1211c3e4")) mqtt.subscribe("thomas/sensor/a4cf1211c3e4/#", receiveMqtt); - if (!ota.getMAC().equals("246f28d1fa5c")) mqtt.subscribe("thomas/sensor/246f28d1fa5c/#", receiveMqtt); - if (!ota.getMAC().equals("246f28d1a080")) mqtt.subscribe("thomas/sensor/246f28d1a080/#", receiveMqtt); - if (!ota.getMAC().equals("246f28d1eff4")) mqtt.subscribe("thomas/sensor/246f28d1eff4/#", receiveMqtt); + if (!ota.getMAC().equals("a4cf1211c3e4")) mqtt.subscribe("thomas/sensor/a4cf1211c3e4/json", receiveMqtt); + if (!ota.getMAC().equals("246f28d1fa5c")) mqtt.subscribe("thomas/sensor/246f28d1fa5c/json", receiveMqtt); + if (!ota.getMAC().equals("246f28d1a080")) mqtt.subscribe("thomas/sensor/246f28d1a080/json", receiveMqtt); + if (!ota.getMAC().equals("246f28d1eff4")) mqtt.subscribe("thomas/sensor/246f28d1eff4/json", receiveMqtt); /* temp: publish version */ String topic_version = String("thomas/sensor/") + ota.getMAC() + String("/version"); @@ -842,8 +908,9 @@ void loop() } getSensorMeasurements(); - displayValues(); sendValues(); + delay(1); + displayValues(); int runtime = millis()/1000; if (runtime < 0 || runtime >= TIME_TO_SLEEP) runtime = 0; From d645d4b44fb2a595248dc0de18b1886b281687e0 Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 21:08:16 +0200 Subject: [PATCH 11/13] change Serial2 (SDS011) connection, enable PSRAM --- README.md | 4 ++-- platformio.ini | 4 ++-- src/main.cpp | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ff916ca..184cf30 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,8 @@ Serial (HardwareSerial2) SDS011 pin | ESP32 pin | Notes -----------|-----------|---------- -TXD | IO16 | -RXD | IO17 | +TXD | IO15 | (don't use IO16 together with PSRAM) +RXD | IO2 | (don't use IO17 together with PSRAM) GND | GND | 25µm | nc | 5V | VUSB | 5V diff --git a/platformio.ini b/platformio.ini index d503fed..59f4401 100644 --- a/platformio.ini +++ b/platformio.ini @@ -21,8 +21,8 @@ build_flags = ; -DLOG_DEFAULT_LEVEL=ESP_LOG_VERBOSE ; -DLOG_LOCAL_LEVEL=ESP_LOG_VERBOSE ; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE -; -DBOARD_HAS_PSRAM -; -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM + -mfix-esp32-psram-cache-issue -DWIFI_SSID="\"${sysenv.WIFI_SSID}\"" -DWIFI_PASSWD="\"${sysenv.WIFI_PASSWD}\"" -DWIFI_SSID2="\"${sysenv.WIFI_SSID2}\"" diff --git a/src/main.cpp b/src/main.cpp index 42a9cdc..558e28d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -738,6 +738,7 @@ void sendValues() { void setup() { Serial.begin(115200); + Serial2.begin(9600, SERIAL_8N1, /*rx*/15, /*tx*/2); // IMPORTANT: don't run with default pins 16, 17 as they are connected to PSRAM on boards that ship with it esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); ++bootCount; From e9ac5ec240f4e51bb5de96c6cb32438737cb33cb Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 21:17:42 +0200 Subject: [PATCH 12/13] fix psram --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 558e28d..b139123 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -811,7 +811,7 @@ void setup() Serial.println("millis(): " + String(millis())); - sds.begin(); + //sds.begin(); // don't call begin, only messes with Serial Serial.println("millis(): " + String(millis())); From 364c5dd69955f280a7c4b63f5f64b2f85833d39f Mon Sep 17 00:00:00 2001 From: Hendrik Langer Date: Fri, 9 Aug 2019 21:34:52 +0200 Subject: [PATCH 13/13] mqtt default values --- src/main.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b139123..d401d6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -403,19 +403,19 @@ void receiveMqtt(const char* topic, const char* data, int data_len) { ESP_LOGW(TAG, "Error parsing JSON, code: %s", err.c_str()); } else { // got json - sensor->temperature = jsonDoc["temperature"].as(); - sensor->humidity = jsonDoc["humidity"].as(); - sensor->pressure = jsonDoc["pressure"].as(); - sensor->voc = jsonDoc["voc"].as(); - sensor->lux = jsonDoc["lux"].as(); - sensor->uvi = jsonDoc["uvi"].as(); - sensor->uva = jsonDoc["uva"].as(); - sensor->uvb = jsonDoc["uvb"].as(); - sensor->pm10 = jsonDoc["pm10"].as(); - sensor->pm25 = jsonDoc["pm2.5"].as(); - sensor->battery = jsonDoc["voltage"].as(); - sensor->rssi = jsonDoc["rssi"].as(); - sensor->lastUpdate = jsonDoc["timestamp"].as(); + if (jsonDoc.containsKey("temperature")) sensor->temperature = jsonDoc["temperature"].as(); + if (jsonDoc.containsKey("humidity")) sensor->humidity = jsonDoc["humidity"].as(); + if (jsonDoc.containsKey("pressure")) sensor->pressure = jsonDoc["pressure"].as(); + if (jsonDoc.containsKey("voc")) sensor->voc = jsonDoc["voc"].as(); + if (jsonDoc.containsKey("lux")) sensor->lux = jsonDoc["lux"].as(); + if (jsonDoc.containsKey("uvi")) sensor->uvi = jsonDoc["uvi"].as(); + if (jsonDoc.containsKey("uva")) sensor->uva = jsonDoc["uva"].as(); + if (jsonDoc.containsKey("uvb")) sensor->uvb = jsonDoc["uvb"].as(); + if (jsonDoc.containsKey("pm10")) sensor->pm10 = jsonDoc["pm10"].as(); + if (jsonDoc.containsKey("pm2.5")) sensor->pm25 = jsonDoc["pm2.5"].as(); + if (jsonDoc.containsKey("voltage")) sensor->battery = jsonDoc["voltage"].as(); + if (jsonDoc.containsKey("rssi")) sensor->rssi = jsonDoc["rssi"].as(); + if (jsonDoc.containsKey("timestamp")) sensor->lastUpdate = jsonDoc["timestamp"].as(); ESP_LOGI(TAG, "got new values from %s, timestamp: %lu", topic, sensor->lastUpdate); ESP_LOGI(TAG, "%lu seconds ago", topic, getTimestamp() - sensor->lastUpdate); }