From 35af48211ed40e7671f70f5eb449206713c30052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Wed, 10 Apr 2024 09:39:53 +0200 Subject: [PATCH] [UNTESTED] Dallas, data-cache, debugLog --- lib/patrix/Patrix.cpp | 4 +- lib/patrix/Patrix.h | 2 + lib/patrix/base.h | 6 +++ lib/patrix/console.cpp | 4 ++ lib/patrix/data.cpp | 44 +++++++++++++++ lib/patrix/data.h | 10 ++++ lib/patrix/log.cpp | 22 +++++++- lib/patrix/log.h | 6 +++ lib/patrix/mqtt.cpp | 50 +++++++++-------- lib/patrix/mqtt.h | 4 +- lib/patrix/sensors/Dallas.h | 90 +++++++++++++++++++++++++++++++ lib/patrix/sensors/DallasSensor.h | 90 +++++++++++++++++++++++++++++++ lib/patrix/wifi.h | 2 +- platformio.ini | 6 ++- src/Fermenter.cpp | 11 +++- 15 files changed, 320 insertions(+), 31 deletions(-) create mode 100644 lib/patrix/base.h create mode 100644 lib/patrix/data.cpp create mode 100644 lib/patrix/data.h create mode 100644 lib/patrix/sensors/Dallas.h create mode 100644 lib/patrix/sensors/DallasSensor.h diff --git a/lib/patrix/Patrix.cpp b/lib/patrix/Patrix.cpp index 6a8a15c..75f3da7 100644 --- a/lib/patrix/Patrix.cpp +++ b/lib/patrix/Patrix.cpp @@ -1,9 +1,10 @@ -#include +#include "base.h" #include #include #include #include "mqtt.h" #include "log.h" +#include "data.h" void setup() { delay(500); @@ -17,5 +18,6 @@ void setup() { void loop() { consoleLoop(); mqttLoop(); + dataLoop(); patrixLoop(); } \ No newline at end of file diff --git a/lib/patrix/Patrix.h b/lib/patrix/Patrix.h index 84e17db..a5a3931 100644 --- a/lib/patrix/Patrix.h +++ b/lib/patrix/Patrix.h @@ -1,6 +1,8 @@ #ifndef SENSOR3_PATRIX_H #define SENSOR3_PATRIX_H +#include "base.h" + void patrixSetup(); void patrixLoop(); diff --git a/lib/patrix/base.h b/lib/patrix/base.h new file mode 100644 index 0000000..0c4e227 --- /dev/null +++ b/lib/patrix/base.h @@ -0,0 +1,6 @@ +#ifndef SENSOR3_BASE_H +#define SENSOR3_BASE_H + +#include + +#endif diff --git a/lib/patrix/console.cpp b/lib/patrix/console.cpp index 02ce640..36f8bd2 100644 --- a/lib/patrix/console.cpp +++ b/lib/patrix/console.cpp @@ -50,6 +50,7 @@ void consoleHandle(const char *cmd) { info("CONSOLE", "reboot : reboot system"); info("CONSOLE", "wifi : reconnect wifi"); info("CONSOLE", "mqtt : reconnect mqtt"); + info("CONSOLE", "debug : toggle debug log"); } else if (strcmp(cmd, "net") == 0) { info("CONSOLE", "MAC: %17s", WiFi.macAddress().c_str()); info("CONSOLE", "IP: %17s", WiFi.localIP().toString().c_str()); @@ -68,6 +69,9 @@ void consoleHandle(const char *cmd) { } else if (strcmp(cmd, "mqtt") == 0) { info("CONSOLE", "Reconnecting MQTT..."); mqttDisconnect(); + } else if (strcmp(cmd, "debug") == 0) { + setDebugEnabled(!isDebugEnabled()); + info("CONSOLE", "DEBUG: %s", isDebugEnabled() ? "ON" : "OFF"); } else { info("CONSOLE", "Unknown command: %s", cmd); } diff --git a/lib/patrix/data.cpp b/lib/patrix/data.cpp new file mode 100644 index 0000000..89f02de --- /dev/null +++ b/lib/patrix/data.cpp @@ -0,0 +1,44 @@ +#include "data.h" +#include "ArduinoJson.h" +#include "mqtt.h" + +#define ENTRY_COUNT 1500 + +struct Entry { + const char *name = ""; + time_t timestamp = 0; + double value = NAN; +}; + +Entry data[ENTRY_COUNT]; + +Entry *dataRead = data; + +Entry *dataWrite = data; + +size_t dataCount = 0; + +bool dataAdd(const char *name, const time_t timestamp, const double value) { + if (dataCount >= ENTRY_COUNT) { + return false; + } + dataWrite->name = name; + dataWrite->timestamp = timestamp; + dataWrite->value = value; + dataWrite = (dataWrite - data + 1) % ENTRY_COUNT + data; + dataCount++; + return true; +} + +void dataLoop() { + if (dataCount == 0) { + return; + } + JsonDocument json; + json["timestamp"] = dataRead->timestamp; + json["value"] = dataRead->value; + if (mqttPublishData(dataRead->name, json)) { + dataRead = (dataRead - data + 1) % ENTRY_COUNT + data; + dataCount--; + } +} \ No newline at end of file diff --git a/lib/patrix/data.h b/lib/patrix/data.h new file mode 100644 index 0000000..bdd75a9 --- /dev/null +++ b/lib/patrix/data.h @@ -0,0 +1,10 @@ +#ifndef SENSOR3_DATA_H +#define SENSOR3_DATA_H + +#include "base.h" + +bool dataAdd(const char *name, const time_t timestamp, const double value); + +void dataLoop(); + +#endif diff --git a/lib/patrix/log.cpp b/lib/patrix/log.cpp index 72e3d17..e86138d 100644 --- a/lib/patrix/log.cpp +++ b/lib/patrix/log.cpp @@ -4,6 +4,8 @@ #define SEPARATOR " | " +bool debugEnabled = false; + void getDateTime(char *buffer, size_t size) { time_t now; time(&now); @@ -23,7 +25,17 @@ void log(const char *level, const char *module, const char *format, ...) { va_end(vl); const size_t len = Serial.print(datetime) + Serial.print(SEPARATOR) + Serial.print(module) + Serial.print(SEPARATOR) + Serial.print(level) + Serial.print(SEPARATOR) + Serial.print(message) + Serial.println(); - mqttLog(len, SEPARATOR, datetime, module, level, message); + mqttPublishLog(len, SEPARATOR, datetime, module, level, message); +} + +void debug(const char *module, const char *format, ...) { + if (!debugEnabled) { + return; + } + va_list vl; + va_start(vl, format); + log("DEBUG", module, format, vl); + va_end(vl); } void info(const char *module, const char *format, ...) { @@ -39,3 +51,11 @@ void error(const char *module, const char *format, ...) { log("ERROR", module, format, vl); va_end(vl); } + +void setDebugEnabled(const bool enabled) { + debugEnabled = enabled; +} + +bool isDebugEnabled() { + return debugEnabled; +} diff --git a/lib/patrix/log.h b/lib/patrix/log.h index 0866f69..2b00442 100644 --- a/lib/patrix/log.h +++ b/lib/patrix/log.h @@ -1,8 +1,14 @@ #ifndef SENSOR3_LOG_H #define SENSOR3_LOG_H +void debug(const char *module, const char *format, ...); + void info(const char *module, const char *format, ...); void error(const char *module, const char *format, ...); +void setDebugEnabled(bool enabled); + +bool isDebugEnabled(); + #endif diff --git a/lib/patrix/mqtt.cpp b/lib/patrix/mqtt.cpp index a870a67..078f679 100644 --- a/lib/patrix/mqtt.cpp +++ b/lib/patrix/mqtt.cpp @@ -8,32 +8,23 @@ #define CONNECT_TIMEOUT_MILLISECONDS 5000 +#define TOPIC_LOG_FORMAT "log/%s" +#define TOPIC_CMD_FORMAT "cmd/%s" +#define TOPIC_DATA_FORMAT "data/%s/%s" + unsigned long mqttLastConnectTry = 0; WiFiClient espClient; PubSubClient mqtt(espClient); -char logTopic[32] = "log/UNSET"; +char logTopic[64] = "log/UNSET"; char cmdTopic[64] = "cmd/UNSET"; void mqttSetup() { - snprintf(logTopic, sizeof logTopic, "%s/%s", "log", HOSTNAME); - snprintf(cmdTopic, sizeof cmdTopic, "%s/%s", "cmd", HOSTNAME); -} - -void mqttLog(const size_t len, const char *separator, const char *datetime, const char *module, const char *level, const char *message) { - if (mqtt.beginPublish(logTopic, len, false)) { - mqtt.print(datetime); - mqtt.print(separator); - mqtt.print(module); - mqtt.print(separator); - mqtt.print(level); - mqtt.print(separator); - mqtt.print(message); - mqtt.endPublish(); - } + snprintf(logTopic, sizeof logTopic, TOPIC_LOG_FORMAT, HOSTNAME); + snprintf(cmdTopic, sizeof cmdTopic, TOPIC_CMD_FORMAT, HOSTNAME); } void mqttDisconnect() { @@ -69,11 +60,26 @@ void mqttLoop() { mqtt.loop(); } -bool mqttPublish(const char *topic, const JsonDocument &doc) { - if (!mqtt.connected()) { - return false; +void mqttPublishLog(const size_t len, const char *separator, const char *datetime, const char *module, const char *level, const char *message) { + if (mqtt.beginPublish(logTopic, len, false)) { + mqtt.print(datetime); + mqtt.print(separator); + mqtt.print(module); + mqtt.print(separator); + mqtt.print(level); + mqtt.print(separator); + mqtt.print(message); + mqtt.endPublish(); } - char buffer[512]; - const size_t size = serializeJson(doc, buffer); - return mqtt.publish(topic, buffer, size); +} + +bool mqttPublishData(const char *name, const JsonDocument &doc) { + if (mqtt.connected() != 0) { + char topic[128]; + snprintf(topic, sizeof topic, TOPIC_DATA_FORMAT, HOSTNAME, name); + char payload[512]; + const size_t size = serializeJson(doc, payload); + return mqtt.publish(topic, payload, size); + } + return false; } diff --git a/lib/patrix/mqtt.h b/lib/patrix/mqtt.h index cc4445b..187d6b9 100644 --- a/lib/patrix/mqtt.h +++ b/lib/patrix/mqtt.h @@ -9,8 +9,8 @@ void mqttLoop(); void mqttDisconnect(); -void mqttLog(size_t len, const char *separator, const char *datetime, const char *module, const char *level, const char *message); +void mqttPublishLog(const size_t len, const char *separator, const char *datetime, const char *module, const char *level, const char *message); -bool mqttPublish(const char *topic, const JsonDocument &doc); +bool mqttPublishData(const char *name, const JsonDocument &doc); #endif diff --git a/lib/patrix/sensors/Dallas.h b/lib/patrix/sensors/Dallas.h new file mode 100644 index 0000000..0390d1a --- /dev/null +++ b/lib/patrix/sensors/Dallas.h @@ -0,0 +1,90 @@ +#ifndef SENSOR2_DALLAS_H +#define SENSOR2_DALLAS_H + +#include "wifi.h" +#include "log.h" + +#include "OneWire.h" + +#include "DallasTemperature.h" + +#define DALLAS_TIMEOUT_MILLISECONDS 3000 + +class Dallas { + + +private: + + OneWire oneWire; + + DallasTemperature sensors; + + time_t timestamp = 0; + + unsigned long lastMillis = 0; + + bool converting = false; + + bool converted = false; + + bool first = true; + +public: + + explicit Dallas(int pin) : oneWire(pin), sensors(&oneWire) { + sensors.begin(); + sensors.setWaitForConversion(false); + } + + void loop() { + if (converting) { + if (sensors.isConversionComplete()) { + if (first) { + first = false; + uint8_t count = sensors.getDeviceCount(); + if (count == 0) { + error("DALLAS", "No devices found!"); + } else { + debug("DALLAS", "Found %d devices:", count); + uint64_t address; + for (int index = 0; index < count; ++index) { + sensors.getAddress((uint8_t *) &address, index); + debug("DALLAS", " - 0x%016llX = %5.1f C", address, sensors.getTempC((uint8_t *) &address)); + } + } + } + converting = false; + converted = true; + } else if (millis() - lastMillis > DALLAS_TIMEOUT_MILLISECONDS) { + error("DALLAS", "Timeout!"); + converting = false; + converted = false; + } + } else { + sensors.requestTemperatures(); + timestamp = getTime(); + lastMillis = millis(); + converting = true; + converted = false; + } + } + + double read(uint64_t address) { + float value = sensors.getTempC((uint8_t *) &address); + if (value <= DEVICE_DISCONNECTED_C) { + return NAN; + } + return value; + } + + time_t getTimestamp() const { + return timestamp; + } + + bool isConverted() const { + return converted; + } + +}; + +#endif diff --git a/lib/patrix/sensors/DallasSensor.h b/lib/patrix/sensors/DallasSensor.h new file mode 100644 index 0000000..d28dc9e --- /dev/null +++ b/lib/patrix/sensors/DallasSensor.h @@ -0,0 +1,90 @@ +#ifndef SENSOR2_DALLAS_SENSOR_H +#define SENSOR2_DALLAS_SENSOR_H + +#include "base.h" +#include "Dallas.h" +#include "wifi.h" +#include "mqtt.h" +#include "data.h" + +class DallasSensor { + +private: + + Dallas &sensors; + + uint64_t address; + + const char *name; + + const double valueThreshold; + + const time_t timeoutSec; + + const time_t minIntervalSec; + + double lastValue = NAN; + + time_t lastTimestamp = 0; + + double lastValidValue = NAN; + + time_t lastValidTimestamp = 0; + +public: + + DallasSensor(Dallas &sensors, const uint64_t address, const char *name, const double valueThreshold, const time_t timeoutSec, const time_t minIntervalSec) : + sensors(sensors), + name(name), + address(address), + valueThreshold(valueThreshold), + timeoutSec(timeoutSec), + minIntervalSec(minIntervalSec) { + // - + } + + void loop() { + const time_t now = getTime(); + if (now - lastTimestamp > timeoutSec) { + lastTimestamp = 0; + lastValue = NAN; + } + if (sensors.isConverted()) { + const double value = sensors.read(address); + const time_t timestamp = sensors.getTimestamp(); + const bool doPublish = !isnan(value) && (abs(lastValue - value) >= valueThreshold || now - lastTimestamp >= minIntervalSec); + if (doPublish) { + dataAdd(name, timestamp, value); + } + lastValue = value; + lastTimestamp = timestamp; + if (!isnan(value)) { + lastValidValue = value; + lastValidTimestamp = timestamp; + } + } + } + + const char *getName() const { + return name; + } + + double getLastValue() const { + return lastValue; + } + + time_t getLastTimestamp() const { + return lastTimestamp; + } + + double getLastValidValue() const { + return lastValidValue; + } + + time_t getLastValidTimestamp() const { + return lastValidTimestamp; + } + +}; + +#endif diff --git a/lib/patrix/wifi.h b/lib/patrix/wifi.h index afce175..cbe533b 100644 --- a/lib/patrix/wifi.h +++ b/lib/patrix/wifi.h @@ -1,7 +1,7 @@ #ifndef GAERBOX_WIFI_H #define GAERBOX_WIFI_H -#include +#include "base.h" void wifiSetup(); diff --git a/platformio.ini b/platformio.ini index a9b0546..1b7af36 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,5 +11,7 @@ monitor_port = /dev/ttyUSB0 monitor_speed = 115200 monitor_filters = esp32_exception_decoder build_flags = -D HOSTNAME=\"Fermenter\" -D WIFI_SSID=\"HappyNet\" -D WIFI_PKEY=\"1Grausame!Sackratte7\" -D OTA_PASSWORD=\"OtaAuthPatrixFermenter\" -D BOOT_DELAY=true -lib_deps = knolleary/PubSubClient - bblanchon/ArduinoJson \ No newline at end of file +lib_deps = milesburton/DallasTemperature + knolleary/PubSubClient + bblanchon/ArduinoJson + paulstoffregen/OneWire \ No newline at end of file diff --git a/src/Fermenter.cpp b/src/Fermenter.cpp index 7508389..1358e26 100644 --- a/src/Fermenter.cpp +++ b/src/Fermenter.cpp @@ -1,9 +1,16 @@ #include +#include "sensors/Dallas.h" +#include "sensors/DallasSensor.h" + +Dallas dallas(2); + +DallasSensor temperatur(dallas, 0xAA0121125E4A7528, "temperatur", 0.5, 5, 60); // TODO wrong address void patrixSetup() { - + } void patrixLoop() { - + dallas.loop(); + temperatur.loop(); } \ No newline at end of file