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;