This commit is contained in:
Patrick Haßel 2024-04-11 13:43:09 +02:00
parent 5373bbd4a5
commit d29cb632ec
10 changed files with 273 additions and 102 deletions

View File

@ -5,11 +5,13 @@
#include "mqtt.h" #include "mqtt.h"
#include "log.h" #include "log.h"
#include "data.h" #include "data.h"
#include "config.h"
void setup() { void setup() {
delay(500); delay(500);
Serial.begin(115200); Serial.begin(115200);
info("Startup..."); info("Startup...");
configSetup();
mqttSetup(); mqttSetup();
wifiSetup(); wifiSetup();
patrixSetup(); patrixSetup();

49
lib/patrix/config.cpp Normal file
View File

@ -0,0 +1,49 @@
#include "config.h"
#include "log.h"
#include <nvs_flash.h>
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;
}

20
lib/patrix/config.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef SENSOR3_CONFIG_H
#define SENSOR3_CONFIG_H
#include <Preferences.h>
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

View File

@ -5,11 +5,26 @@
#include <WiFi.h> #include <WiFi.h>
#include "mqtt.h" #include "mqtt.h"
#include "wifi.h" #include "wifi.h"
#include "config.h"
char consoleBuffer[64] = ""; char consoleBuffer[64] = "";
char *consoleBufferW = consoleBuffer; 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(); const char *getFlashChipMode();
void consoleLoop() { void consoleLoop() {
@ -45,15 +60,91 @@ void consoleLoop() {
} }
} }
void consoleHandle(const char *cmd) { void consoleHandle(char *cmd) {
if (strcmp(cmd, "help") == 0) { char *first = strtok(cmd, " ");
info("help : print this help"); if (strcmp(first, "help") == 0) {
info("info : print system info"); _usage();
info("reboot : reboot system"); } else if (strcmp(first, "wifi") == 0) {
info("wifi : reconnect wifi"); _wifi();
info("mqtt : reconnect mqtt"); } else if (strcmp(first, "mqtt") == 0) {
info("debug : toggle debug log"); _mqtt();
} else if (strcmp(cmd, "info") == 0) { } 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 <SSID>");
info("wifi pkey <PKEY>");
info("mqtt reconnect");
info("mqtt host <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 millis = getUptimeMillis();
uint64_t seconds = millis / 1000; uint64_t seconds = millis / 1000;
uint32_t minutes = seconds / 60; uint32_t minutes = seconds / 60;
@ -104,23 +195,6 @@ void consoleHandle(const char *cmd) {
info("SDK:"); info("SDK:");
info(" version: %s", ESP.getSdkVersion()); 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");
} else if (!patrix_command((char *) cmd)) {
info("Unknown command: %s", cmd);
}
} }
const char *getFlashChipMode() { const char *getFlashChipMode() {

View File

@ -3,7 +3,7 @@
void consoleLoop(); void consoleLoop();
void consoleHandle(const char *cmd); void consoleHandle(char *cmd);
bool patrix_command(char *cmd); bool patrix_command(char *cmd);

View File

@ -36,7 +36,7 @@ void dataLoop() {
} }
JsonDocument json; JsonDocument json;
json["timestamp"] = dataRead->timestamp; json["timestamp"] = dataRead->timestamp;
json["value"] = dataRead->value; json["putDouble"] = dataRead->value;
if (mqttPublishData(dataRead->name, json)) { if (mqttPublishData(dataRead->name, json)) {
dataRead = (dataRead - data + 1) % ENTRY_COUNT + data; dataRead = (dataRead - data + 1) % ENTRY_COUNT + data;
dataCount--; dataCount--;

View File

@ -5,6 +5,7 @@
#include "console.h" #include "console.h"
#include "wifi.h" #include "wifi.h"
#include "log.h" #include "log.h"
#include "config.h"
#define CONNECT_TIMEOUT_MILLISECONDS 5000 #define CONNECT_TIMEOUT_MILLISECONDS 5000
@ -48,9 +49,10 @@ void mqttLoop() {
} }
if (isWiFiConnected() && isTimeSet() && !connected && (mqttLastConnectTry == 0 || millis() - mqttLastConnectTry > CONNECT_TIMEOUT_MILLISECONDS)) { 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(); mqttLastConnectTry = millis();
mqtt.setServer(MQTT_HOST, 1883); mqtt.setServer(host.c_str(), 1883);
if (!mqtt.connect(HOSTNAME, logTopic, 0, false, "MQTT disconnected")) { if (!mqtt.connect(HOSTNAME, logTopic, 0, false, "MQTT disconnected")) {
error("MQTT FAILED TO CONNECT"); error("MQTT FAILED TO CONNECT");
return; return;

View File

@ -2,6 +2,7 @@
#include "log.h" #include "log.h"
#include "mqtt.h" #include "mqtt.h"
#include "console.h" #include "console.h"
#include "config.h"
#include <WiFi.h> #include <WiFi.h>
#include <ArduinoOTA.h> #include <ArduinoOTA.h>
@ -55,12 +56,15 @@ void wifiConnect() {
WiFi.setAutoReconnect(false); WiFi.setAutoReconnect(false);
yield(); 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); WiFiClass::hostname(HOSTNAME);
yield(); yield();
WiFi.begin(WIFI_SSID, WIFI_PKEY); WiFi.begin(ssid, pkey);
yield(); yield();
} }

View File

@ -29,7 +29,7 @@ monitor_port = ${COMMON.monitor_port}
monitor_speed = ${COMMON.monitor_speed} monitor_speed = ${COMMON.monitor_speed}
monitor_filters = ${COMMON.monitor_filters} monitor_filters = ${COMMON.monitor_filters}
lib_deps = ${COMMON.lib_deps} 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] [env:Fermenter]
upload_port = 10.0.0.138 upload_port = 10.0.0.138

View File

@ -2,6 +2,7 @@
#include "sensors/Dallas.h" #include "sensors/Dallas.h"
#include "sensors/DallasSensor.h" #include "sensors/DallasSensor.h"
#include "ArduPID.h" #include "ArduPID.h"
#include "config.h"
#include <Arduino.h> #include <Arduino.h>
#define CONTROL_GPIO 4 #define CONTROL_GPIO 4
@ -27,9 +28,9 @@ double integral = 0;
double derivative = 0; double derivative = 0;
bool setDouble(const char *name, double *destinationPtr, double min, double max);
void patrixSetup() { void patrixSetup() {
configLoad();
analogWriteResolution(CONTROL_PWM_BITS); analogWriteResolution(CONTROL_PWM_BITS);
pid.begin(&temperatureCurrent, &heaterPWM, &temperatureTarget, proportional, integral, derivative); pid.begin(&temperatureCurrent, &heaterPWM, &temperatureTarget, proportional, integral, derivative);
@ -37,10 +38,9 @@ void patrixSetup() {
pid.start(); pid.start();
} }
void patrixLoop() { void patrixLoop() {
dallas.loop(); // dallas.loop();
sensor.loop(); // sensor.loop();
temperatureCurrent = sensor.getLastValue(); temperatureCurrent = sensor.getLastValue();
if (!isnan(temperatureCurrent)) { 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) { 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) { if (valueStr == nullptr) {
error("Missing value for \"%s\"", name); error("Missing value for \"%s\"", name);
return false; 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); error("Value out of range for \"%s\" [%f..%f]: %f", name, min, max, value);
return false; return false;
} }
if (*destinationPtr != value) {
*destinationPtr = value; *destinationPtr = value;
info("Value for \"%s\" set to: %f", name, value); info("Value for \"%s\" set to: %f", name, value);
configPutDouble(name, value);
} else {
info("Value for \"%s\" unchanged: %f", name, value);
}
return true; 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);
}