diff --git a/src/bme680.h b/src/bme680.h index bcaa897..d394d87 100644 --- a/src/bme680.h +++ b/src/bme680.h @@ -8,21 +8,23 @@ class BME680 { Adafruit_BME680 bme; // NOLINT(*-interfaces-global-init) + unsigned long last = 0UL; + public: - const char *name; + const String name; unsigned long intervalMs; - explicit BME680(const char *name, const unsigned long interval_ms = 5000) : name(name), intervalMs(interval_ms) { + explicit BME680(const String& name, const unsigned long interval_ms = 5000) : name(name), intervalMs(interval_ms) { // } void setup() { if (bme.begin()) { - Log.printf("BME680: Initialized.\n"); + Log.printf("BME680 \"%s\": Initialized.\n", name.c_str()); } else { - Log.printf("BME680: Failed to initialize.\n"); + Log.printf("BME680 \"%s\": Failed to initialize.\n", name.c_str()); } bme.setTemperatureOversampling(BME680_OS_8X); bme.setHumidityOversampling(BME680_OS_2X); @@ -33,10 +35,9 @@ public: void loop() { const auto now = max(1UL, millis()); - static auto last = 0UL; if (last == 0 || now - last >= intervalMs) { if (bme.beginReading() == 0) { - Log.print("BME680: Failed to request reading.\n"); + Log.printf("BME680 \"%s\": Failed to request reading.\n", name.c_str()); setup(); } last = now; @@ -44,14 +45,14 @@ public: if (bme.remainingReadingMillis() == 0) { if (bme.endReading()) { const auto humidityAbsolute = calculateHumidityAbsolute(bme.temperature, bme.humidity); - mqttPublish("garden/temperature", bme.temperature, "\xB0""C"); - mqttPublish("garden/pressure", bme.pressure / 100.0, "hPa"); - mqttPublish("garden/humidity/relative", bme.humidity, "%"); - mqttPublish("garden/humidity/absolute", humidityAbsolute, "mg/L"); - mqttPublish("garden/gas", bme.gas_resistance / 1000.0, "KOhms"); - mqttPublish("garden/altitude", bme.readAltitude(1013.25), "m"); + mqttPublish(name + "/temperature", bme.temperature, "\xB0""C"); + mqttPublish(name + "/pressure", bme.pressure / 100.0, "hPa"); + mqttPublish(name + "/humidity/relative", bme.humidity, "%"); + mqttPublish(name + "/humidity/absolute", humidityAbsolute, "mg/L"); + mqttPublish(name + "/gas", bme.gas_resistance / 1000.0, "KOhms"); + mqttPublish(name + "/altitude", bme.readAltitude(1013.25), "m"); } else { - Log.printf("Failed to complete reading\n"); + Log.printf("BME680 \"%s\": Failed to complete reading\n", name.c_str()); setup(); } } diff --git a/src/main.cpp b/src/main.cpp index 1c614cc..f13da4f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,23 +3,29 @@ #include "tsl2561.h" #include "wifi.h" -BME680 garden("garden"); +TSL2561 gardenTSL("garden"); -BME680 greenhouse("greenhouse"); +BME680 gardenBME("garden"); + +BME680 greenhouseBME("greenhouse"); void setup() { delay(500); Log.printf("\n\n\nStartup\n"); wifiConnect(); - tsl2561Setup(); - garden.setup(); - greenhouse.setup(); } void loop() { wifiLoop(); mqttLoop(); - tsl2561Loop(); - garden.loop(); - greenhouse.loop(); + if (isSetupTimeAfterBootDelay()) { + gardenTSL.setup(); + gardenBME.setup(); + greenhouseBME.setup(); + } + if (isAfterBootDelay()) { + gardenTSL.loop(); + gardenBME.loop(); + greenhouseBME.loop(); + } } diff --git a/src/mqtt.cpp b/src/mqtt.cpp index 4001e69..84f6c0f 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -1,9 +1,7 @@ #include "mqtt.h" - -#include - #include "wifi.h" +#include #include #include @@ -64,41 +62,37 @@ void mqttLoop() { } } -void mqttPublish(const char *topic, const int32_t value, const char *unit) { +void mqttPublish(const String& topic, const int32_t value, const char *unit) { mqttPublish(topic, String(value), unit); } -void mqttPublish(const char *topic, const int64_t value, const char *unit) { +void mqttPublish(const String& topic, const int64_t value, const char *unit) { mqttPublish(topic, String(value), unit); } -void mqttPublish(const char *topic, const uint32_t value, const char *unit) { +void mqttPublish(const String& topic, const uint32_t value, const char *unit) { mqttPublish(topic, String(value), unit); } -void mqttPublish(const char *topic, const uint64_t value, const char *unit) { +void mqttPublish(const String& topic, const uint64_t value, const char *unit) { mqttPublish(topic, String(value), unit); } -void mqttPublish(const char *topic, const float value, const char *unit) { +void mqttPublish(const String& topic, const float value, const char *unit) { mqttPublish(topic, String(value), unit); } -void mqttPublish(const char *topic, const double value, const char *unit) { +void mqttPublish(const String& topic, const double value, const char *unit) { mqttPublish(topic, String(value), unit); } -bool mqttPublish(const char *topic, const String& value, const char *unit) { - if (!isTimeSet()) { - return true; - } +void mqttPublish(const String& topic, const String& value, const char *unit) { char buffer[200]; snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), value.c_str(), unit); mqttPublish(topic, buffer); - return false; } -void mqttPublish(const char *topic, const char *payload) { - mqtt.publish(topic, payload); +void mqttPublish(const String& topic, const String& payload) { + mqtt.publish(topic.c_str(), payload.c_str()); yield(); } diff --git a/src/mqtt.h b/src/mqtt.h index 3c6e5f5..31e311a 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -11,21 +11,21 @@ extern const String cmdTopic; void mqttLoop(); -void mqttPublish(const char *topic, int32_t value, const char *unit); +void mqttPublish(const String& topic, int32_t value, const char *unit); -void mqttPublish(const char *topic, int64_t value, const char *unit); +void mqttPublish(const String& topic, int64_t value, const char *unit); -void mqttPublish(const char *topic, uint32_t value, const char *unit); +void mqttPublish(const String& topic, uint32_t value, const char *unit); -void mqttPublish(const char *topic, uint64_t value, const char *unit); +void mqttPublish(const String& topic, uint64_t value, const char *unit); -void mqttPublish(const char *topic, float value, const char *unit); +void mqttPublish(const String& topic, float value, const char *unit); -void mqttPublish(const char *topic, double value, const char *unit); +void mqttPublish(const String& topic, double value, const char *unit); -bool mqttPublish(const char *topic, const String& value, const char *unit); +void mqttPublish(const String& topic, const String& value, const char *unit); -void mqttPublish(const char *topic, const char *payload); +void mqttPublish(const String& topic, const String& payload); class LogClass final : public Stream { @@ -59,10 +59,10 @@ public: due = true; if (mqtt.connected()) { if (overflow > 0) { - mqtt.publish(logTopic.c_str(), "\n### LOG BUFFER OVERFLOW BY %d BYTES ###\n"); + mqttPublish(logTopic, "\n### LOG BUFFER OVERFLOW BY %d BYTES ###\n"); overflow = 0; } - mqtt.publish(logTopic.c_str(), reinterpret_cast(buffer)); + mqttPublish(logTopic, reinterpret_cast(buffer)); bufferWrite = buffer; *bufferWrite = 0; due = false; diff --git a/src/tsl2561.cpp b/src/tsl2561.cpp deleted file mode 100644 index 198a246..0000000 --- a/src/tsl2561.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "tsl2561.h" -#include "mqtt.h" - -#include -#include -#include - -#define TSL2561_INTERVAL_MS 5000 - -auto tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT); - -void tsl2561Setup() { - if (tsl.begin()) { - Log.printf("TSL2561: Initialized.\n"); - } else { - Log.printf("TSL2561: Failed to initialize.\n"); - } - tsl.enableAutoRange(true); - tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); -} - -void sensorRead() { - uint16_t broadband; - uint16_t ir; - tsl.getLuminosity(&broadband, &ir); - const auto illuminance = tsl.calculateLux(broadband, ir); - if (illuminance == 65536) { - Log.printf("TSL2561: Failed to read.\n"); - tsl2561Setup(); - } else { - mqttPublish("garden/illuminance", illuminance, "lux"); - } -} - -void tsl2561Loop() { - const auto now = millis(); - static unsigned long last = 0; - if (last == 0 || now - last >= TSL2561_INTERVAL_MS) { - last = max(1UL, now); - sensorRead(); - } -} diff --git a/src/tsl2561.h b/src/tsl2561.h index bdbf23f..837c306 100644 --- a/src/tsl2561.h +++ b/src/tsl2561.h @@ -1,8 +1,57 @@ #ifndef TSL2561_H #define TSL2561_H -void tsl2561Setup(); +#include -void tsl2561Loop(); +class TSL2561 { + + Adafruit_TSL2561_Unified tsl; + + unsigned long last = 0UL; + +public: + + const String name; + + unsigned long intervalMs; + + explicit TSL2561(const String& name, const uint8_t address = TSL2561_ADDR_FLOAT, const unsigned long interval_ms = 5000) : tsl(Adafruit_TSL2561_Unified(address)), name(name), intervalMs(interval_ms) { + // + } + + void setup() { + if (tsl.begin()) { + Log.printf("TSL2561 \"%s\": Initialized.\n", name.c_str()); + } else { + Log.printf("TSL2561 \"%s\": Failed to initialize.\n", name.c_str()); + } + tsl.enableAutoRange(true); + tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS); + } + + void loop() { + const auto now = millis(); + if (last == 0 || now - last >= intervalMs) { + last = max(1UL, now); + read(); + } + } + +private: + + void read() { + uint16_t broadband; + uint16_t ir; + tsl.getLuminosity(&broadband, &ir); + const auto illuminance = tsl.calculateLux(broadband, ir); + if (illuminance == 65536) { + Log.printf("TSL2561 \"%s\": Failed to read.\n", name.c_str()); + setup(); + } else { + mqttPublish(name + "/illuminance", illuminance, "lux"); + } + } + +}; #endif diff --git a/src/wifi.cpp b/src/wifi.cpp index bb71ecb..1c10bb8 100644 --- a/src/wifi.cpp +++ b/src/wifi.cpp @@ -7,13 +7,16 @@ #define WIFI_SSID "HappyNet" #define WIFI_PASSWORD "1Grausame!Sackratte7" #define NTP_SERVER "107.189.12.98" /* pool.ntp.org */ +#define BOOT_DELAY_SEC 5 auto wifiConnected = false; -auto timeSet = false; +auto timeSetSince = 0UL; unsigned long wifiConnectBeginMillis = 0; +auto bootDelayOver = false; + void wifiConnect() { wifiConnectBeginMillis = max(1UL, millis()); WiFi.setHostname(HOSTNAME); @@ -86,17 +89,24 @@ void timeLoop() { const auto now = time(nullptr); const auto nowHour = now / 3600; static unsigned long lastHour = 0; - if (!timeSet) { + if (timeSetSince == 0) { if (now > 1700000000) { - timeSet = true; + timeSetSince = now; lastHour = nowHour; Log.printf("Got time: %s\n", getTimeString().c_str()); + Log.printf("Delaying boot for %d seconds.\n", BOOT_DELAY_SEC); } } else { if (lastHour != nowHour) { lastHour = nowHour; Log.printf("%s\n", getTimeString().c_str()); } + if (!bootDelayOver) { + bootDelayOver = time(nullptr) - timeSetSince > BOOT_DELAY_SEC; + if (bootDelayOver) { + Log.printf("Boot delay complete.\n"); + } + } } } @@ -137,6 +147,15 @@ bool isWifiConnected() { return wifiConnected; } -bool isTimeSet() { - return timeSet; +bool isSetupTimeAfterBootDelay() { + static auto needed = true; + if (needed && bootDelayOver) { + needed = false; + return true; + } + return false; +} + +bool isAfterBootDelay() { + return bootDelayOver; } diff --git a/src/wifi.h b/src/wifi.h index 1937f62..8b968da 100644 --- a/src/wifi.h +++ b/src/wifi.h @@ -11,7 +11,9 @@ String getTimeString(); bool isWifiConnected(); -bool isTimeSet(); +bool isSetupTimeAfterBootDelay(); + +bool isAfterBootDelay(); uint64_t uptimeMillis();