|
|
@ -14,6 +14,7 @@ |
|
|
|
#include <GxEPD2_BW.h> |
|
|
|
#include <Fonts/FreeMonoBold9pt7b.h> |
|
|
|
#include <Fonts/FreeSans9pt7b.h> |
|
|
|
#include <Fonts/FreeSansBold9pt7b.h> |
|
|
|
#include <Fonts/Org_01.h> |
|
|
|
#include "bitmaps/Bitmaps128x250.h" |
|
|
|
#include <Adafruit_GFX.h> |
|
|
@ -49,7 +50,7 @@ Adafruit_VEML6075 uv = Adafruit_VEML6075(); |
|
|
|
XD0OTA ota("esp32-weatherstation"); |
|
|
|
XD0MQTT mqtt; |
|
|
|
|
|
|
|
struct __attribute__((packed)) { |
|
|
|
struct __attribute__((packed)) sensor_readings_t { |
|
|
|
float temperature = 0.0; // °C
|
|
|
|
float humidity = 0.0; // %H
|
|
|
|
float pressure = 0.0; // Pa
|
|
|
@ -59,8 +60,12 @@ struct __attribute__((packed)) { |
|
|
|
float uvi = 0.0; |
|
|
|
float uva = 0.0; |
|
|
|
float uvb = 0.0; |
|
|
|
float temperature_max = NAN; // °C
|
|
|
|
float temperature_min = NAN; // °C
|
|
|
|
} sensor_readings; |
|
|
|
|
|
|
|
sensor_readings_t sensors_a4cf1211c3e4, sensors_246f28d1fa5c, sensors_246f28d1a080, sensors_30aea47b0568; |
|
|
|
|
|
|
|
uint32_t lastDisplayUpdate = 0; |
|
|
|
bool bme280_active = false; |
|
|
|
bool bme680_active = false; |
|
|
@ -134,6 +139,15 @@ void getSensorMeasurements() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (sensor_readings.temperature > sensor_readings.temperature_max |
|
|
|
|| isnan(sensor_readings.temperature_max)) { |
|
|
|
sensor_readings.temperature_max = sensor_readings.temperature; |
|
|
|
} |
|
|
|
if (sensor_readings.temperature < sensor_readings.temperature_min |
|
|
|
|| isnan(sensor_readings.temperature_min)) { |
|
|
|
sensor_readings.temperature_min = sensor_readings.temperature; |
|
|
|
} |
|
|
|
|
|
|
|
if (uv_active) { |
|
|
|
sensor_readings.uvi = uv.readUVI(); |
|
|
|
sensor_readings.uva = uv.readUVA(); |
|
|
@ -150,6 +164,125 @@ void getSensorMeasurements() { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void receiveMqtt(const char* topic, const char* data) { |
|
|
|
sensor_readings_t* sensor = NULL; |
|
|
|
|
|
|
|
if (strstr(topic, "thomas/sensor/a4cf1211c3e4") == topic) { |
|
|
|
sensor = &sensors_a4cf1211c3e4; |
|
|
|
} else if (strstr(topic, "thomas/sensor/246f28d1fa5c") == topic) { |
|
|
|
sensor = &sensors_246f28d1fa5c; |
|
|
|
} else if (strstr(topic, "thomas/sensor/246f28d1a080") == topic) { |
|
|
|
sensor = &sensors_246f28d1a080; |
|
|
|
} else if (strstr(topic, "thomas/sensor/30aea47b0568") == topic) { |
|
|
|
sensor = &sensors_30aea47b0568; |
|
|
|
} |
|
|
|
|
|
|
|
char* topic_last = strrchr(topic, '/'); |
|
|
|
|
|
|
|
if (topic_last && sensor) { |
|
|
|
if (strcmp("/temperature", topic_last) == 0) { |
|
|
|
sensor->temperature = atof(data); |
|
|
|
} else if (strcmp("/humidity", topic_last) == 0) { |
|
|
|
sensor->humidity = atof(data); |
|
|
|
} else if (strcmp("/pressure", topic_last) == 0) { |
|
|
|
sensor->pressure = atof(data); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void displayValues() { |
|
|
|
static constexpr uint8_t y_offset = 8; |
|
|
|
display.setRotation(1); |
|
|
|
display.setFont(NULL); |
|
|
|
display.setTextColor(GxEPD_BLACK); |
|
|
|
display.setTextSize(1); |
|
|
|
display.setTextWrap(false); |
|
|
|
|
|
|
|
char timeStr[40]; |
|
|
|
getTime(timeStr, sizeof(timeStr), "%d. %b %Y %H:%M:%S"); |
|
|
|
|
|
|
|
display.setFullWindow(); |
|
|
|
display.firstPage(); |
|
|
|
do |
|
|
|
{ |
|
|
|
display.fillScreen(GxEPD_WHITE); |
|
|
|
|
|
|
|
// Title
|
|
|
|
display.setCursor(30,y_offset+0); |
|
|
|
display.println(timeStr); |
|
|
|
display.drawLine(0,y_offset+10,display.width(), y_offset+10, GxEPD_BLACK); |
|
|
|
|
|
|
|
// Temp
|
|
|
|
display.drawRect(0,y_offset+10,66,50,GxEPD_BLACK); |
|
|
|
display.setFont(NULL); |
|
|
|
display.setCursor(5,y_offset+15); |
|
|
|
display.printf("max: %.1f", sensor_readings.temperature_max); |
|
|
|
display.setFont(&FreeSansBold9pt7b); |
|
|
|
display.setCursor(5,y_offset+40); |
|
|
|
display.printf("%.1f*C", sensor_readings.temperature); |
|
|
|
display.setFont(NULL); |
|
|
|
display.setCursor(5,y_offset+45); |
|
|
|
display.printf("min: %.1f", sensor_readings.temperature_min); |
|
|
|
|
|
|
|
// Humidity
|
|
|
|
display.drawRect(65,y_offset+10,66,50,GxEPD_BLACK); |
|
|
|
display.setFont(NULL); |
|
|
|
display.setCursor(70,y_offset+15); |
|
|
|
display.print("Humidity"); |
|
|
|
display.setFont(&FreeSansBold9pt7b); |
|
|
|
display.setCursor(70,y_offset+40); |
|
|
|
display.printf("%.1f %", sensor_readings.humidity); |
|
|
|
|
|
|
|
// Pressure
|
|
|
|
display.drawRect(130,y_offset+10,66,50,GxEPD_BLACK); |
|
|
|
display.setFont(NULL); |
|
|
|
display.setCursor(135,y_offset+15); |
|
|
|
display.print("Pressure"); |
|
|
|
display.setFont(&FreeSansBold9pt7b); |
|
|
|
display.setCursor(135,y_offset+40); |
|
|
|
display.printf("%.1f\%", sensor_readings.pressure / 100.0F); |
|
|
|
|
|
|
|
// Other
|
|
|
|
display.drawRect(195,y_offset+10,56,122-10,GxEPD_BLACK); |
|
|
|
display.setFont(NULL); |
|
|
|
// VOC
|
|
|
|
display.setCursor(200,y_offset+15); |
|
|
|
display.println("VOC:"); |
|
|
|
display.setCursor(200,y_offset+25); |
|
|
|
display.printf("%.1f %", sensor_readings.voc); |
|
|
|
// PM
|
|
|
|
display.setCursor(200,y_offset+45); |
|
|
|
display.println("PM10 / 2.5:"); |
|
|
|
display.setCursor(200,y_offset+55); |
|
|
|
display.printf("%.1f %", sensor_readings.pm10); |
|
|
|
display.setCursor(200,y_offset+65); |
|
|
|
display.printf("%.1f %", sensor_readings.pm25); |
|
|
|
// UV
|
|
|
|
display.setCursor(200,y_offset+85); |
|
|
|
display.println("UV Index/A/B:"); |
|
|
|
display.setCursor(200,y_offset+95); |
|
|
|
display.printf("%.1f %", sensor_readings.uvi); |
|
|
|
display.setCursor(200,y_offset+105); |
|
|
|
display.printf("%.1f %", sensor_readings.uva); |
|
|
|
display.setCursor(200,y_offset+115); |
|
|
|
display.printf("%.1f %", sensor_readings.uvb); |
|
|
|
|
|
|
|
// other nodes
|
|
|
|
display.setFont(NULL); |
|
|
|
display.setCursor(0, y_offset+70); |
|
|
|
display.printf("246f28d1fa5c: %4.1f %4.1f %6.1f\n", sensors_246f28d1fa5c.temperature, sensors_246f28d1fa5c.humidity, sensors_246f28d1fa5c.pressure); |
|
|
|
display.printf("a4cf1211c3e4: %4.1f %4.1f %6.1f\n", sensors_a4cf1211c3e4.temperature, sensors_a4cf1211c3e4.humidity, sensors_a4cf1211c3e4.pressure); |
|
|
|
display.printf("246f28d1a080: %4.1f %4.1f %6.1f\n", sensors_246f28d1a080.temperature, sensors_246f28d1a080.humidity, sensors_246f28d1a080.pressure); |
|
|
|
display.printf("30aea47b0568: %4.1f %4.1f %6.1f\n", sensors_30aea47b0568.temperature, sensors_30aea47b0568.humidity, sensors_30aea47b0568.pressure); |
|
|
|
|
|
|
|
} |
|
|
|
while (display.nextPage()); |
|
|
|
|
|
|
|
display.powerOff(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void printValues() { |
|
|
|
if (bme280_active || bme680_active) { |
|
|
|
#define SEALEVELPRESSURE_HPA (1013.25) |
|
|
@ -332,6 +465,11 @@ void setup() |
|
|
|
ESP_LOGD(TAG, "connecting to MQTT"); |
|
|
|
mqtt.begin(); |
|
|
|
|
|
|
|
mqtt.subscribe("thomas/sensor/a4cf1211c3e4/#", receiveMqtt); |
|
|
|
mqtt.subscribe("thomas/sensor/246f28d1fa5c/#", receiveMqtt); |
|
|
|
mqtt.subscribe("thomas/sensor/246f28d1a080/#", receiveMqtt); |
|
|
|
mqtt.subscribe("thomas/sensor/30aea47b0568/#", receiveMqtt); |
|
|
|
|
|
|
|
ESP_LOGD(TAG, "setup done"); |
|
|
|
} |
|
|
|
|
|
|
@ -340,60 +478,13 @@ void setup() |
|
|
|
*/ |
|
|
|
void loop() |
|
|
|
{ |
|
|
|
ESP_LOGD(TAG, "loop()"); |
|
|
|
|
|
|
|
/* Do an e-paper display refresh every 2 minutes */ |
|
|
|
if (millis() - lastDisplayUpdate >= 1*60*1000) { |
|
|
|
lastDisplayUpdate = millis(); |
|
|
|
|
|
|
|
getSensorMeasurements(); |
|
|
|
|
|
|
|
display.setFullWindow(); |
|
|
|
display.setRotation(1); |
|
|
|
display.firstPage(); |
|
|
|
do |
|
|
|
{ |
|
|
|
display.fillScreen(GxEPD_WHITE); |
|
|
|
display.setTextColor(GxEPD_BLACK); |
|
|
|
display.setTextWrap(false); |
|
|
|
display.setCursor(0, 11); |
|
|
|
display.setFont(&FreeSans9pt7b); |
|
|
|
display.println("ESP32-Wetterstation"); |
|
|
|
display.drawFastHLine(0, 14, display.width(), GxEPD_BLACK); |
|
|
|
//display.setFont(NULL);
|
|
|
|
display.setCursor(0, 32); |
|
|
|
if (bme280_active || bme680_active) { |
|
|
|
display.print("Temperatur: "); |
|
|
|
display.print(sensor_readings.temperature); |
|
|
|
display.println(" *C"); |
|
|
|
display.print("Luftfeuchte: "); |
|
|
|
display.print(sensor_readings.humidity); |
|
|
|
display.println(" %"); |
|
|
|
display.print("Luftdruck:"); |
|
|
|
display.print(sensor_readings.pressure / 100.0F); |
|
|
|
display.println(" hPa"); |
|
|
|
} |
|
|
|
if (bme680_active) { |
|
|
|
display.print("Gas: "); |
|
|
|
display.print(sensor_readings.voc / 1000.0); |
|
|
|
display.println(" KOhms"); |
|
|
|
} |
|
|
|
if (!bme280_active && !bme680_active) { |
|
|
|
display.print("Temperatur: "); |
|
|
|
float esp32_temperature = (temprature_sens_read() - 32) / 1.8; |
|
|
|
display.println(esp32_temperature-29.40); |
|
|
|
display.println("kein BME Sensor"); |
|
|
|
} |
|
|
|
|
|
|
|
char timeStr[9]; |
|
|
|
getTime(timeStr, sizeof(timeStr), "%H:%M:%S"); |
|
|
|
display.setCursor(5, display.height()-5); |
|
|
|
display.setFont(&Org_01); |
|
|
|
display.print("Zeit: "); |
|
|
|
display.println(timeStr); |
|
|
|
} |
|
|
|
while (display.nextPage()); |
|
|
|
display.powerOff(); |
|
|
|
displayValues(); |
|
|
|
|
|
|
|
printValues(); |
|
|
|
sendValues(); |
|
|
|