From d29cb632ec05d967a659e5ffaa68256d960a0149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Thu, 11 Apr 2024 13:43:09 +0200 Subject: [PATCH] config --- lib/patrix/Patrix.cpp | 2 + lib/patrix/config.cpp | 49 +++++++++ lib/patrix/config.h | 20 ++++ lib/patrix/console.cpp | 220 +++++++++++++++++++++++++++-------------- lib/patrix/console.h | 2 +- lib/patrix/data.cpp | 2 +- lib/patrix/mqtt.cpp | 6 +- lib/patrix/wifi.cpp | 8 +- platformio.ini | 2 +- src/Fermenter.cpp | 64 +++++++----- 10 files changed, 273 insertions(+), 102 deletions(-) create mode 100644 lib/patrix/config.cpp create mode 100644 lib/patrix/config.h diff --git a/lib/patrix/Patrix.cpp b/lib/patrix/Patrix.cpp index 5fc1f8e..5ec47e7 100644 --- a/lib/patrix/Patrix.cpp +++ b/lib/patrix/Patrix.cpp @@ -5,11 +5,13 @@ #include "mqtt.h" #include "log.h" #include "data.h" +#include "config.h" void setup() { delay(500); Serial.begin(115200); info("Startup..."); + configSetup(); mqttSetup(); wifiSetup(); patrixSetup(); diff --git a/lib/patrix/config.cpp b/lib/patrix/config.cpp new file mode 100644 index 0000000..b7847af --- /dev/null +++ b/lib/patrix/config.cpp @@ -0,0 +1,49 @@ +#include "config.h" +#include "log.h" +#include + +Preferences config; + +void configSetup() { + config.begin("config", false); + const String &stored = config.getString("HOSTNAME", ""); + if (!stored.equals(HOSTNAME)) { + error(R"([WARNING] Stored config hostname mismatch: "%s" != "%s" [WARNING])", stored.c_str(), HOSTNAME); + } +} + +void configReset() { + info("[CONFIG RESET]"); + config.end(); + nvs_flash_erase(); + nvs_flash_init(); + config.begin("config", false); + config.putString("HOSTNAME", HOSTNAME); + configLoad(); +} + +String configGetString(const char *name, const char *fallback, bool allowEmpty) { + if (!config.isKey(name)) { + return fallback; + } + String value = config.getString(name); + if (!allowEmpty && value.isEmpty()) { + return fallback; + } + return value; +} + +bool configPutString(const char *name, const char *value) { + return config.putString(name, value) == strlen(value); +} + +double configGetDouble(const char *name, double fallback) { + if (!config.isKey(name)) { + return fallback; + } + return config.getDouble(name); +} + +bool configPutDouble(const char *name, double fallback) { + return config.value(name, fallback) == 0; +} diff --git a/lib/patrix/config.h b/lib/patrix/config.h new file mode 100644 index 0000000..a379a89 --- /dev/null +++ b/lib/patrix/config.h @@ -0,0 +1,20 @@ +#ifndef SENSOR3_CONFIG_H +#define SENSOR3_CONFIG_H + +#include + +void configSetup(); + +void configReset(); + +void configLoad(); + +String configGetString(const char *name, const char *fallback, bool allowEmpty); + +bool configPutString(const char *name, const char *value); + +double configGetDouble(const char *name, double fallback); + +bool configPutDouble(const char *name, double value); + +#endif diff --git a/lib/patrix/console.cpp b/lib/patrix/console.cpp index aee0382..79e3494 100644 --- a/lib/patrix/console.cpp +++ b/lib/patrix/console.cpp @@ -5,11 +5,26 @@ #include #include "mqtt.h" #include "wifi.h" +#include "config.h" char consoleBuffer[64] = ""; char *consoleBufferW = consoleBuffer; +void _debug(); + +void _reboot(); + +void _usage(); + +void _info(); + +void _wifi(); + +void _mqtt(); + +void _setConfigString(const char *name, bool allowEmpty); + const char *getFlashChipMode(); void consoleLoop() { @@ -45,84 +60,143 @@ void consoleLoop() { } } -void consoleHandle(const char *cmd) { - if (strcmp(cmd, "help") == 0) { - info("help : print this help"); - info("info : print system info"); - info("reboot : reboot system"); - info("wifi : reconnect wifi"); - info("mqtt : reconnect mqtt"); - info("debug : toggle debug log"); - } else if (strcmp(cmd, "info") == 0) { - uint64_t millis = getUptimeMillis(); - uint64_t seconds = millis / 1000; - uint32_t minutes = seconds / 60; - uint32_t hours = minutes / 60; - uint16_t days = hours / 24; - char datetime[26]; - getDateTime(datetime, sizeof datetime); - - info("WiFi:"); - info(" hostname: %s", HOSTNAME); - info(" mac: %s", WiFi.macAddress().c_str()); - info(" ip: %s", WiFi.localIP().toString().c_str()); - info(" gateway: %s", WiFi.gatewayIP().toString().c_str()); - info(" ssid: %s", WiFi.SSID().c_str()); - info(" bssid: %s", WiFi.BSSIDstr().c_str()); - info(" rssi: %d", WiFi.RSSI()); - - info("Time:"); - info(" uptime: %dd %2dh %2dm %2ds", days, hours % 24, minutes % 60, seconds % 60); - info(" sys: %s", datetime); - - info("Chip:"); - info(" model: %s", ESP.getChipModel()); - info(" cores: %d", ESP.getChipCores()); - info(" freq: %d", ESP.getCpuFreqMHz()); - - info("Flash:"); - info(" mode: %s", getFlashChipMode()); - info(" size: %d", ESP.getFlashChipSize()); - info(" speed: %d", ESP.getFlashChipSpeed()); - - info("Heap:"); - info(" size: %d", ESP.getHeapSize()); - info(" free: %d", ESP.getFreeHeap()); - info(" minFree: %d", ESP.getMinFreeHeap()); - info(" maxAlloc: %d", ESP.getMaxAllocHeap()); - - info("PS RAM:"); - info(" size: %d", ESP.getPsramSize()); - info(" free: %d", ESP.getFreePsram()); - info(" minFree: %d", ESP.getMinFreePsram()); - info(" maxAlloc: %d", ESP.getMaxAllocPsram()); - - info("SDK:"); - info(" size: %d", ESP.getSketchSize()); - info(" free: %d", ESP.getFreeSketchSpace()); - info(" MD5: %s", ESP.getSketchMD5().c_str()); - - info("SDK:"); - info(" version: %s", ESP.getSdkVersion()); - } else if (strcmp(cmd, "reboot") == 0) { - info("Rebooting..."); - delay(500); - yield(); - ESP.restart(); - } else if (strcmp(cmd, "wifi") == 0) { - info("Reconnecting WiFi..."); - wifiConnect(); - } else if (strcmp(cmd, "mqtt") == 0) { - info("Reconnecting MQTT..."); - mqttDisconnect(); - } else if (strcmp(cmd, "debug") == 0) { - setDebugEnabled(!isDebugEnabled()); - info("DEBUG: %s", isDebugEnabled() ? "ON" : "OFF"); +void consoleHandle(char *cmd) { + char *first = strtok(cmd, " "); + if (strcmp(first, "help") == 0) { + _usage(); + } else if (strcmp(first, "wifi") == 0) { + _wifi(); + } else if (strcmp(first, "mqtt") == 0) { + _mqtt(); + } else if (strcmp(first, "info") == 0) { + _info(); + } else if (strcmp(first, "reboot") == 0) { + _reboot(); + } else if (strcmp(first, "debug") == 0) { + _debug(); + } else if (strcmp(first, "config reset") == 0) { + configReset(); } else if (!patrix_command((char *) cmd)) { info("Unknown command: %s", cmd); } } +void _usage() { + info("help"); + info("info"); + info("debug"); + + info("reboot"); + info("config reset"); + + info("wifi reconnect"); + info("wifi ssid "); + info("wifi pkey "); + + info("mqtt reconnect"); + info("mqtt host "); +} + +void _debug() { + setDebugEnabled(!isDebugEnabled()); + info("DEBUG: %s", isDebugEnabled() ? "ON" : "OFF"); +} + +void _reboot() { + info("Rebooting..."); + delay(500); + yield(); + ESP.restart(); +} + +void _mqtt() { + char *sub = strtok(nullptr, " "); + if (strcmp(sub, "reconnect") == 0) { + info("Reconnecting MQTT..."); + mqttDisconnect(); + } else if (strcmp(sub, "host") == 0) { + _setConfigString("MQTT_HOST", false); + } +} + +void _wifi() { + char *sub = strtok(nullptr, " "); + if (strcmp(sub, "reconnect") == 0) { + info("Reconnecting WiFi..."); + wifiConnect(); + } else if (strcmp(sub, "ssid") == 0) { + _setConfigString("WIFI_SSID", false); + } else if (strcmp(sub, "pkey") == 0) { + _setConfigString("WIFI_PKEY", false); + } +} + +void _setConfigString(const char *name, bool allowEmpty) { + char *value = strtok(nullptr, ""); + if (!allowEmpty && strcmp(value, "") == 0) { + error(R"(Value for "%s" cannot be empty!")", name); + return; + } + if (!configPutString(name, value)) { + error(R"(Failed to persist "%s" = "%s")", name, value); + return; + } + info(R"(Set "%s" to "%s")", name, value); +} + +void _info() { + uint64_t millis = getUptimeMillis(); + uint64_t seconds = millis / 1000; + uint32_t minutes = seconds / 60; + uint32_t hours = minutes / 60; + uint16_t days = hours / 24; + char datetime[26]; + getDateTime(datetime, sizeof datetime); + + info("WiFi:"); + info(" hostname: %s", HOSTNAME); + info(" mac: %s", WiFi.macAddress().c_str()); + info(" ip: %s", WiFi.localIP().toString().c_str()); + info(" gateway: %s", WiFi.gatewayIP().toString().c_str()); + info(" ssid: %s", WiFi.SSID().c_str()); + info(" bssid: %s", WiFi.BSSIDstr().c_str()); + info(" rssi: %d", WiFi.RSSI()); + + info("Time:"); + info(" uptime: %dd %2dh %2dm %2ds", days, hours % 24, minutes % 60, seconds % 60); + info(" sys: %s", datetime); + + info("Chip:"); + info(" model: %s", ESP.getChipModel()); + info(" cores: %d", ESP.getChipCores()); + info(" freq: %d", ESP.getCpuFreqMHz()); + + info("Flash:"); + info(" mode: %s", getFlashChipMode()); + info(" size: %d", ESP.getFlashChipSize()); + info(" speed: %d", ESP.getFlashChipSpeed()); + + info("Heap:"); + info(" size: %d", ESP.getHeapSize()); + info(" free: %d", ESP.getFreeHeap()); + info(" minFree: %d", ESP.getMinFreeHeap()); + info(" maxAlloc: %d", ESP.getMaxAllocHeap()); + + info("PS RAM:"); + info(" size: %d", ESP.getPsramSize()); + info(" free: %d", ESP.getFreePsram()); + info(" minFree: %d", ESP.getMinFreePsram()); + info(" maxAlloc: %d", ESP.getMaxAllocPsram()); + + info("SDK:"); + info(" size: %d", ESP.getSketchSize()); + info(" free: %d", ESP.getFreeSketchSpace()); + info(" MD5: %s", ESP.getSketchMD5().c_str()); + + info("SDK:"); + info(" version: %s", ESP.getSdkVersion()); +} + const char *getFlashChipMode() { switch (ESP.getFlashChipMode()) { case FM_QIO: diff --git a/lib/patrix/console.h b/lib/patrix/console.h index a7bc96b..d5b4b12 100644 --- a/lib/patrix/console.h +++ b/lib/patrix/console.h @@ -3,7 +3,7 @@ void consoleLoop(); -void consoleHandle(const char *cmd); +void consoleHandle(char *cmd); bool patrix_command(char *cmd); diff --git a/lib/patrix/data.cpp b/lib/patrix/data.cpp index 89f02de..79c4540 100644 --- a/lib/patrix/data.cpp +++ b/lib/patrix/data.cpp @@ -36,7 +36,7 @@ void dataLoop() { } JsonDocument json; json["timestamp"] = dataRead->timestamp; - json["value"] = dataRead->value; + json["putDouble"] = dataRead->value; if (mqttPublishData(dataRead->name, json)) { dataRead = (dataRead - data + 1) % ENTRY_COUNT + data; dataCount--; diff --git a/lib/patrix/mqtt.cpp b/lib/patrix/mqtt.cpp index 775a440..9eb41f7 100644 --- a/lib/patrix/mqtt.cpp +++ b/lib/patrix/mqtt.cpp @@ -5,6 +5,7 @@ #include "console.h" #include "wifi.h" #include "log.h" +#include "config.h" #define CONNECT_TIMEOUT_MILLISECONDS 5000 @@ -48,9 +49,10 @@ void mqttLoop() { } if (isWiFiConnected() && isTimeSet() && !connected && (mqttLastConnectTry == 0 || millis() - mqttLastConnectTry > CONNECT_TIMEOUT_MILLISECONDS)) { - error("MQTT connecting MQTT host: %s", MQTT_HOST); + String host = configGetString("MQTT_HOST", MQTT_HOST, false); + error("MQTT connecting MQTT host: %s", host.c_str()); mqttLastConnectTry = millis(); - mqtt.setServer(MQTT_HOST, 1883); + mqtt.setServer(host.c_str(), 1883); if (!mqtt.connect(HOSTNAME, logTopic, 0, false, "MQTT disconnected")) { error("MQTT FAILED TO CONNECT"); return; diff --git a/lib/patrix/wifi.cpp b/lib/patrix/wifi.cpp index 3f99ad6..493d224 100644 --- a/lib/patrix/wifi.cpp +++ b/lib/patrix/wifi.cpp @@ -2,6 +2,7 @@ #include "log.h" #include "mqtt.h" #include "console.h" +#include "config.h" #include #include @@ -55,12 +56,15 @@ void wifiConnect() { WiFi.setAutoReconnect(false); yield(); - info("WIFI connecting: %s", WIFI_SSID); + String ssid = configGetString("WIFI_SSID", WIFI_SSID, false); + String pkey = configGetString("WIFI_PKEY", WIFI_PKEY, false); + + info("WIFI connecting: %s", ssid.c_str()); WiFiClass::hostname(HOSTNAME); yield(); - WiFi.begin(WIFI_SSID, WIFI_PKEY); + WiFi.begin(ssid, pkey); yield(); } diff --git a/platformio.ini b/platformio.ini index 490fe28..31515a7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ monitor_port = ${COMMON.monitor_port} monitor_speed = ${COMMON.monitor_speed} monitor_filters = ${COMMON.monitor_filters} lib_deps = ${COMMON.lib_deps} -build_flags = -D HOSTNAME=\"DEV\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixDEV\" -D BOOT_DELAY=true -D DEBUG_LOG=true +build_flags = -D HOSTNAME=\"DEV\" -D WIFI_SSID=\"${COMMON.WIFI_SSID}\" -D WIFI_PKEY=\"${COMMON.WIFI_PKEY}\" -D OTA_PASSWORD=\"OtaAuthPatrixDEV\" -D BOOT_DELAY=false -D DEBUG_LOG=false [env:Fermenter] upload_port = 10.0.0.138 diff --git a/src/Fermenter.cpp b/src/Fermenter.cpp index 3c4506c..1b6f2fb 100644 --- a/src/Fermenter.cpp +++ b/src/Fermenter.cpp @@ -2,6 +2,7 @@ #include "sensors/Dallas.h" #include "sensors/DallasSensor.h" #include "ArduPID.h" +#include "config.h" #include #define CONTROL_GPIO 4 @@ -27,9 +28,9 @@ double integral = 0; double derivative = 0; -bool setDouble(const char *name, double *destinationPtr, double min, double max); - void patrixSetup() { + configLoad(); + analogWriteResolution(CONTROL_PWM_BITS); pid.begin(&temperatureCurrent, &heaterPWM, &temperatureTarget, proportional, integral, derivative); @@ -37,10 +38,9 @@ void patrixSetup() { pid.start(); } - void patrixLoop() { - dallas.loop(); - sensor.loop(); +// dallas.loop(); +// sensor.loop(); temperatureCurrent = sensor.getLastValue(); if (!isnan(temperatureCurrent)) { @@ -66,22 +66,8 @@ void patrixLoop() { } } -bool patrix_command(char *cmd) { - const char *first = strtok(cmd, " "); - if (strcmp(first, "target") == 0) { - return setDouble("target", &temperatureTarget, -10, 80); - } else if (strcmp(first, "p") == 0) { - return setDouble("proportional", &proportional, NAN, NAN); - } else if (strcmp(first, "i") == 0) { - return setDouble("integral", &integral, NAN, NAN); - } else if (strcmp(first, "p") == 0) { - return setDouble("derivative", &derivative, NAN, NAN); - } - return false; -} - bool setDouble(const char *name, double *destinationPtr, double min, double max) { - const char *valueStr = strtok(nullptr, nullptr); + const char *valueStr = strtok(nullptr, ""); if (valueStr == nullptr) { error("Missing value for \"%s\"", name); return false; @@ -95,7 +81,41 @@ bool setDouble(const char *name, double *destinationPtr, double min, double max) error("Value out of range for \"%s\" [%f..%f]: %f", name, min, max, value); return false; } - *destinationPtr = value; - info("Value for \"%s\" set to: %f", name, value); + if (*destinationPtr != value) { + *destinationPtr = value; + info("Value for \"%s\" set to: %f", name, value); + configPutDouble(name, value); + } else { + info("Value for \"%s\" unchanged: %f", name, value); + } return true; } + +bool patrix_command(char *cmd) { + const char *first = strtok(cmd, " "); + bool result = false; + if (strcmp(first, "over") == 0) { + result = setDouble("over", &temperatureMaxOvershoot, 0, 20); + } else if (strcmp(first, "target") == 0) { + result = setDouble("target", &temperatureTarget, -10, 60); + } else if (strcmp(first, "p") == 0) { + result = setDouble("p", &proportional, NAN, NAN); + } else if (strcmp(first, "i") == 0) { + result = setDouble("i", &integral, NAN, NAN); + } else if (strcmp(first, "d") == 0) { + result = setDouble("d", &derivative, NAN, NAN); + } + if (result) { + pid.setCoefficients(proportional, integral, derivative); + } + return result; +} + +void configLoad() { + proportional = configGetDouble("p", 1); + integral = configGetDouble("i", 0); + derivative = configGetDouble("d", 0); + temperatureTarget = configGetDouble("target", 31); + temperatureMaxOvershoot = configGetDouble("over", 5); + pid.setCoefficients(proportional, integral, derivative); +} \ No newline at end of file