mqtt topics as String + TSL2561 class
This commit is contained in:
parent
d03369e7ef
commit
70761270e2
27
src/bme680.h
27
src/bme680.h
@ -8,21 +8,23 @@ class BME680 {
|
|||||||
|
|
||||||
Adafruit_BME680 bme; // NOLINT(*-interfaces-global-init)
|
Adafruit_BME680 bme; // NOLINT(*-interfaces-global-init)
|
||||||
|
|
||||||
|
unsigned long last = 0UL;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
const char *name;
|
const String name;
|
||||||
|
|
||||||
unsigned long intervalMs;
|
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() {
|
void setup() {
|
||||||
if (bme.begin()) {
|
if (bme.begin()) {
|
||||||
Log.printf("BME680: Initialized.\n");
|
Log.printf("BME680 \"%s\": Initialized.\n", name.c_str());
|
||||||
} else {
|
} 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.setTemperatureOversampling(BME680_OS_8X);
|
||||||
bme.setHumidityOversampling(BME680_OS_2X);
|
bme.setHumidityOversampling(BME680_OS_2X);
|
||||||
@ -33,10 +35,9 @@ public:
|
|||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
const auto now = max(1UL, millis());
|
const auto now = max(1UL, millis());
|
||||||
static auto last = 0UL;
|
|
||||||
if (last == 0 || now - last >= intervalMs) {
|
if (last == 0 || now - last >= intervalMs) {
|
||||||
if (bme.beginReading() == 0) {
|
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();
|
setup();
|
||||||
}
|
}
|
||||||
last = now;
|
last = now;
|
||||||
@ -44,14 +45,14 @@ public:
|
|||||||
if (bme.remainingReadingMillis() == 0) {
|
if (bme.remainingReadingMillis() == 0) {
|
||||||
if (bme.endReading()) {
|
if (bme.endReading()) {
|
||||||
const auto humidityAbsolute = calculateHumidityAbsolute(bme.temperature, bme.humidity);
|
const auto humidityAbsolute = calculateHumidityAbsolute(bme.temperature, bme.humidity);
|
||||||
mqttPublish("garden/temperature", bme.temperature, "\xB0""C");
|
mqttPublish(name + "/temperature", bme.temperature, "\xB0""C");
|
||||||
mqttPublish("garden/pressure", bme.pressure / 100.0, "hPa");
|
mqttPublish(name + "/pressure", bme.pressure / 100.0, "hPa");
|
||||||
mqttPublish("garden/humidity/relative", bme.humidity, "%");
|
mqttPublish(name + "/humidity/relative", bme.humidity, "%");
|
||||||
mqttPublish("garden/humidity/absolute", humidityAbsolute, "mg/L");
|
mqttPublish(name + "/humidity/absolute", humidityAbsolute, "mg/L");
|
||||||
mqttPublish("garden/gas", bme.gas_resistance / 1000.0, "KOhms");
|
mqttPublish(name + "/gas", bme.gas_resistance / 1000.0, "KOhms");
|
||||||
mqttPublish("garden/altitude", bme.readAltitude(1013.25), "m");
|
mqttPublish(name + "/altitude", bme.readAltitude(1013.25), "m");
|
||||||
} else {
|
} else {
|
||||||
Log.printf("Failed to complete reading\n");
|
Log.printf("BME680 \"%s\": Failed to complete reading\n", name.c_str());
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/main.cpp
22
src/main.cpp
@ -3,23 +3,29 @@
|
|||||||
#include "tsl2561.h"
|
#include "tsl2561.h"
|
||||||
#include "wifi.h"
|
#include "wifi.h"
|
||||||
|
|
||||||
BME680 garden("garden");
|
TSL2561 gardenTSL("garden");
|
||||||
|
|
||||||
BME680 greenhouse("greenhouse");
|
BME680 gardenBME("garden");
|
||||||
|
|
||||||
|
BME680 greenhouseBME("greenhouse");
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
delay(500);
|
delay(500);
|
||||||
Log.printf("\n\n\nStartup\n");
|
Log.printf("\n\n\nStartup\n");
|
||||||
wifiConnect();
|
wifiConnect();
|
||||||
tsl2561Setup();
|
|
||||||
garden.setup();
|
|
||||||
greenhouse.setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
wifiLoop();
|
wifiLoop();
|
||||||
mqttLoop();
|
mqttLoop();
|
||||||
tsl2561Loop();
|
if (isSetupTimeAfterBootDelay()) {
|
||||||
garden.loop();
|
gardenTSL.setup();
|
||||||
greenhouse.loop();
|
gardenBME.setup();
|
||||||
|
greenhouseBME.setup();
|
||||||
|
}
|
||||||
|
if (isAfterBootDelay()) {
|
||||||
|
gardenTSL.loop();
|
||||||
|
gardenBME.loop();
|
||||||
|
greenhouseBME.loop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/mqtt.cpp
26
src/mqtt.cpp
@ -1,9 +1,7 @@
|
|||||||
#include "mqtt.h"
|
#include "mqtt.h"
|
||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
|
||||||
|
|
||||||
#include "wifi.h"
|
#include "wifi.h"
|
||||||
|
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <WiFiClient.h>
|
#include <WiFiClient.h>
|
||||||
|
|
||||||
@ -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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
mqttPublish(topic, String(value), unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mqttPublish(const char *topic, const String& value, const char *unit) {
|
void mqttPublish(const String& topic, const String& value, const char *unit) {
|
||||||
if (!isTimeSet()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
char buffer[200];
|
char buffer[200];
|
||||||
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), value.c_str(), unit);
|
snprintf(buffer, sizeof buffer, R"({"timestamp": %lld, "value": %s, "unit": "%s"})", time(nullptr), value.c_str(), unit);
|
||||||
mqttPublish(topic, buffer);
|
mqttPublish(topic, buffer);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mqttPublish(const char *topic, const char *payload) {
|
void mqttPublish(const String& topic, const String& payload) {
|
||||||
mqtt.publish(topic, payload);
|
mqtt.publish(topic.c_str(), payload.c_str());
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/mqtt.h
20
src/mqtt.h
@ -11,21 +11,21 @@ extern const String cmdTopic;
|
|||||||
|
|
||||||
void mqttLoop();
|
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 {
|
class LogClass final : public Stream {
|
||||||
|
|
||||||
@ -59,10 +59,10 @@ public:
|
|||||||
due = true;
|
due = true;
|
||||||
if (mqtt.connected()) {
|
if (mqtt.connected()) {
|
||||||
if (overflow > 0) {
|
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;
|
overflow = 0;
|
||||||
}
|
}
|
||||||
mqtt.publish(logTopic.c_str(), reinterpret_cast<const char *>(buffer));
|
mqttPublish(logTopic, reinterpret_cast<const char *>(buffer));
|
||||||
bufferWrite = buffer;
|
bufferWrite = buffer;
|
||||||
*bufferWrite = 0;
|
*bufferWrite = 0;
|
||||||
due = false;
|
due = false;
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
#include "tsl2561.h"
|
|
||||||
#include "mqtt.h"
|
|
||||||
|
|
||||||
#include <Adafruit_Sensor.h>
|
|
||||||
#include <Adafruit_TSL2561_U.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
#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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +1,57 @@
|
|||||||
#ifndef TSL2561_H
|
#ifndef TSL2561_H
|
||||||
#define TSL2561_H
|
#define TSL2561_H
|
||||||
|
|
||||||
void tsl2561Setup();
|
#include <Adafruit_TSL2561_U.h>
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
|||||||
29
src/wifi.cpp
29
src/wifi.cpp
@ -7,13 +7,16 @@
|
|||||||
#define WIFI_SSID "HappyNet"
|
#define WIFI_SSID "HappyNet"
|
||||||
#define WIFI_PASSWORD "1Grausame!Sackratte7"
|
#define WIFI_PASSWORD "1Grausame!Sackratte7"
|
||||||
#define NTP_SERVER "107.189.12.98" /* pool.ntp.org */
|
#define NTP_SERVER "107.189.12.98" /* pool.ntp.org */
|
||||||
|
#define BOOT_DELAY_SEC 5
|
||||||
|
|
||||||
auto wifiConnected = false;
|
auto wifiConnected = false;
|
||||||
|
|
||||||
auto timeSet = false;
|
auto timeSetSince = 0UL;
|
||||||
|
|
||||||
unsigned long wifiConnectBeginMillis = 0;
|
unsigned long wifiConnectBeginMillis = 0;
|
||||||
|
|
||||||
|
auto bootDelayOver = false;
|
||||||
|
|
||||||
void wifiConnect() {
|
void wifiConnect() {
|
||||||
wifiConnectBeginMillis = max(1UL, millis());
|
wifiConnectBeginMillis = max(1UL, millis());
|
||||||
WiFi.setHostname(HOSTNAME);
|
WiFi.setHostname(HOSTNAME);
|
||||||
@ -86,17 +89,24 @@ void timeLoop() {
|
|||||||
const auto now = time(nullptr);
|
const auto now = time(nullptr);
|
||||||
const auto nowHour = now / 3600;
|
const auto nowHour = now / 3600;
|
||||||
static unsigned long lastHour = 0;
|
static unsigned long lastHour = 0;
|
||||||
if (!timeSet) {
|
if (timeSetSince == 0) {
|
||||||
if (now > 1700000000) {
|
if (now > 1700000000) {
|
||||||
timeSet = true;
|
timeSetSince = now;
|
||||||
lastHour = nowHour;
|
lastHour = nowHour;
|
||||||
Log.printf("Got time: %s\n", getTimeString().c_str());
|
Log.printf("Got time: %s\n", getTimeString().c_str());
|
||||||
|
Log.printf("Delaying boot for %d seconds.\n", BOOT_DELAY_SEC);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (lastHour != nowHour) {
|
if (lastHour != nowHour) {
|
||||||
lastHour = nowHour;
|
lastHour = nowHour;
|
||||||
Log.printf("%s\n", getTimeString().c_str());
|
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;
|
return wifiConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTimeSet() {
|
bool isSetupTimeAfterBootDelay() {
|
||||||
return timeSet;
|
static auto needed = true;
|
||||||
|
if (needed && bootDelayOver) {
|
||||||
|
needed = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAfterBootDelay() {
|
||||||
|
return bootDelayOver;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,9 @@ String getTimeString();
|
|||||||
|
|
||||||
bool isWifiConnected();
|
bool isWifiConnected();
|
||||||
|
|
||||||
bool isTimeSet();
|
bool isSetupTimeAfterBootDelay();
|
||||||
|
|
||||||
|
bool isAfterBootDelay();
|
||||||
|
|
||||||
uint64_t uptimeMillis();
|
uint64_t uptimeMillis();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user