From 20771b3244842caebd7d38c4e95ab203016f4b35 Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Thu, 20 Jan 2022 16:59:24 +0100 Subject: [PATCH] Added option to change hw params. --- platformio.ini | 2 +- src/calc.cpp | 4 +- src/calc.hpp | 5 +- src/config.cpp | 312 ++++++++++++++++++++++++++++++---------------- src/config.hpp | 90 ++++++------- src/gyro.cpp | 28 ++--- src/main.cpp | 1 + src/resources.cpp | 6 +- src/resources.hpp | 71 +++++++++++ src/webserver.cpp | 198 +++++++++++++++++++---------- src/webserver.hpp | 1 + src/wifi.cpp | 5 +- src/wifi.hpp | 4 + 13 files changed, 475 insertions(+), 252 deletions(-) create mode 100644 src/resources.hpp diff --git a/platformio.ini b/platformio.ini index 1c6e1da..378a7f5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -115,7 +115,7 @@ extra_scripts = build_unflags = ${common_env_data.build_unflags} build_flags = ${common_env_data.build_flags} - -D COLLECT_PERFDATA # This option will collect runtime data for a few defined methods to measure time, dumped to serial and/or influxdb + -D COLLECT_PERFDATA -D LOG_LEVEL=5 lib_deps = ${common_env_data.lib_deps} diff --git a/src/calc.cpp b/src/calc.cpp index 7f0fba0..7cec263 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -27,8 +27,6 @@ SOFTWARE. #include #include -#define FORMULA_MAX_DEVIATION 1.6 - // // Use values to derive a formula // @@ -94,7 +92,7 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer, double dev = (g - fd.g[i]) < 0 ? (fd.g[i] - g) : (g - fd.g[i]); // If the deviation is more than 2 degress we mark it as failed. - if (dev * 1000 > FORMULA_MAX_DEVIATION) { + if (dev * 1000 > myHardwareConfig.getMaxFormulaCreationDeviation()) { #if LOG_LEVEL == 6 && !defined(CALC_DISABLE_LOGGING) char s[20]; snprintf(&s[0], sizeof(s), "%.8f", dev); diff --git a/src/calc.hpp b/src/calc.hpp index ba795fc..fa19c3b 100644 --- a/src/calc.hpp +++ b/src/calc.hpp @@ -32,8 +32,9 @@ SOFTWARE. double calculateGravity(double angle, double tempC, const char *tempFormula = 0); -double gravityTemperatureCorrectionC(double gravity, double tempC, - double calTempC = 20); +double gravityTemperatureCorrectionC( + double gravity, double tempC, + double calTempC = myHardwareConfig.getDefaultCalibrationTemp()); int createFormula(RawFormulaData &fd, char *formulaBuffer, int formulaBufferSize, int order); diff --git a/src/config.cpp b/src/config.cpp index 531a85e..7c54c2d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -23,8 +23,10 @@ SOFTWARE. */ #include #include +#include Config myConfig; +HardwareConfig myHardwareConfig; // // Create the config class with default settings. @@ -37,7 +39,7 @@ Config::Config() { snprintf(&buf[0], sizeof(buf), "" WIFI_MDNS "%s", getID()); _mDNS = String(&buf[0]); -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) Log.verbose(F("CFG : Created config for %s (%s)." CR), _id.c_str(), _mDNS.c_str()); #endif @@ -59,32 +61,32 @@ Config::Config() { // web and saving to file) // void Config::createJson(DynamicJsonDocument& doc) { - doc[CFG_PARAM_MDNS] = getMDNS(); - doc[CFG_PARAM_ID] = getID(); - doc[CFG_PARAM_OTA] = getOtaURL(); - doc[CFG_PARAM_SSID] = getWifiSSID(); - doc[CFG_PARAM_PASS] = getWifiPass(); - doc[CFG_PARAM_TEMPFORMAT] = String(getTempFormat()); - doc[CFG_PARAM_PUSH_BREWFATHER] = getBrewfatherPushUrl(); - doc[CFG_PARAM_PUSH_HTTP] = getHttpPushUrl(); - doc[CFG_PARAM_PUSH_HTTP2] = getHttpPushUrl2(); - doc[CFG_PARAM_PUSH_INFLUXDB2] = getInfluxDb2PushUrl(); - doc[CFG_PARAM_PUSH_INFLUXDB2_ORG] = getInfluxDb2PushOrg(); - doc[CFG_PARAM_PUSH_INFLUXDB2_BUCKET] = getInfluxDb2PushBucket(); - doc[CFG_PARAM_PUSH_INFLUXDB2_AUTH] = getInfluxDb2PushToken(); - doc[CFG_PARAM_PUSH_MQTT] = getMqttUrl(); - doc[CFG_PARAM_PUSH_MQTT_TOPIC] = getMqttTopic(); - doc[CFG_PARAM_PUSH_MQTT_USER] = getMqttUser(); - doc[CFG_PARAM_PUSH_MQTT_PASS] = getMqttPass(); - doc[CFG_PARAM_SLEEP_INTERVAL] = getSleepInterval(); - doc[CFG_PARAM_VOLTAGEFACTOR] = getVoltageFactor(); - doc[CFG_PARAM_GRAVITY_FORMULA] = getGravityFormula(); - doc[CFG_PARAM_GRAVITY_FORMAT] = String(getGravityFormat()); - doc[CFG_PARAM_TEMP_ADJ] = getTempSensorAdjC(); - doc[CFG_PARAM_GRAVITY_TEMP_ADJ] = isGravityTempAdj(); - doc[CFG_PARAM_GYRO_TEMP] = isGyroTemp(); + doc[PARAM_MDNS] = getMDNS(); + doc[PARAM_ID] = getID(); + doc[PARAM_OTA] = getOtaURL(); + doc[PARAM_SSID] = getWifiSSID(); + doc[PARAM_PASS] = getWifiPass(); + doc[PARAM_TEMPFORMAT] = String(getTempFormat()); + doc[PARAM_PUSH_BREWFATHER] = getBrewfatherPushUrl(); + doc[PARAM_PUSH_HTTP] = getHttpPushUrl(); + doc[PARAM_PUSH_HTTP2] = getHttpPushUrl2(); + doc[PARAM_PUSH_INFLUXDB2] = getInfluxDb2PushUrl(); + doc[PARAM_PUSH_INFLUXDB2_ORG] = getInfluxDb2PushOrg(); + doc[PARAM_PUSH_INFLUXDB2_BUCKET] = getInfluxDb2PushBucket(); + doc[PARAM_PUSH_INFLUXDB2_AUTH] = getInfluxDb2PushToken(); + doc[PARAM_PUSH_MQTT] = getMqttUrl(); + doc[PARAM_PUSH_MQTT_TOPIC] = getMqttTopic(); + doc[PARAM_PUSH_MQTT_USER] = getMqttUser(); + doc[PARAM_PUSH_MQTT_PASS] = getMqttPass(); + doc[PARAM_SLEEP_INTERVAL] = getSleepInterval(); + doc[PARAM_VOLTAGEFACTOR] = getVoltageFactor(); + doc[PARAM_GRAVITY_FORMULA] = getGravityFormula(); + doc[PARAM_GRAVITY_FORMAT] = String(getGravityFormat()); + doc[PARAM_TEMP_ADJ] = getTempSensorAdjC(); + doc[PARAM_GRAVITY_TEMP_ADJ] = isGravityTempAdj(); + doc[PARAM_GYRO_TEMP] = isGyroTemp(); - JsonObject cal = doc.createNestedObject(CFG_PARAM_GYRO_CALIBRATION); + JsonObject cal = doc.createNestedObject(PARAM_GYRO_CALIBRATION); cal["ax"] = _gyroCalibration.ax; cal["ay"] = _gyroCalibration.ay; cal["az"] = _gyroCalibration.az; @@ -92,7 +94,7 @@ void Config::createJson(DynamicJsonDocument& doc) { cal["gy"] = _gyroCalibration.gy; cal["gz"] = _gyroCalibration.gz; - JsonObject cal2 = doc.createNestedObject(CFG_PARAM_FORMULA_DATA); + JsonObject cal2 = doc.createNestedObject(PARAM_FORMULA_DATA); cal2["a1"] = reduceFloatPrecision(_formulaData.a[0], 2); cal2["a2"] = reduceFloatPrecision(_formulaData.a[1], 2); cal2["a3"] = reduceFloatPrecision(_formulaData.a[2], 2); @@ -111,13 +113,13 @@ void Config::createJson(DynamicJsonDocument& doc) { // bool Config::saveFile() { if (!_saveNeeded) { -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) Log.verbose(F("CFG : Skipping save, not needed." CR)); #endif return true; } -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) Log.verbose(F("CFG : Saving configuration to file." CR)); #endif @@ -131,7 +133,7 @@ bool Config::saveFile() { DynamicJsonDocument doc(CFG_JSON_BUFSIZE); createJson(doc); -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) serializeJson(doc, Serial); Serial.print(CR); #endif @@ -150,7 +152,7 @@ bool Config::saveFile() { // Load config file from disk // bool Config::loadFile() { -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) Log.verbose(F("CFG : Loading configuration from file." CR)); #endif @@ -187,92 +189,90 @@ bool Config::loadFile() { #if LOG_LEVEL == 6 Log.verbose(F("CFG : Parsed configuration file." CR)); #endif - if (!doc[CFG_PARAM_OTA].isNull()) setOtaURL(doc[CFG_PARAM_OTA]); - if (!doc[CFG_PARAM_MDNS].isNull()) setMDNS(doc[CFG_PARAM_MDNS]); - if (!doc[CFG_PARAM_SSID].isNull()) setWifiSSID(doc[CFG_PARAM_SSID]); - if (!doc[CFG_PARAM_PASS].isNull()) setWifiPass(doc[CFG_PARAM_PASS]); + if (!doc[PARAM_OTA].isNull()) setOtaURL(doc[PARAM_OTA]); + if (!doc[PARAM_MDNS].isNull()) setMDNS(doc[PARAM_MDNS]); + if (!doc[PARAM_SSID].isNull()) setWifiSSID(doc[PARAM_SSID]); + if (!doc[PARAM_PASS].isNull()) setWifiPass(doc[PARAM_PASS]); - if (!doc[CFG_PARAM_TEMPFORMAT].isNull()) { - String s = doc[CFG_PARAM_TEMPFORMAT]; + if (!doc[PARAM_TEMPFORMAT].isNull()) { + String s = doc[PARAM_TEMPFORMAT]; setTempFormat(s.charAt(0)); } - if (!doc[CFG_PARAM_PUSH_BREWFATHER].isNull()) - setBrewfatherPushUrl(doc[CFG_PARAM_PUSH_BREWFATHER]); + if (!doc[PARAM_PUSH_BREWFATHER].isNull()) + setBrewfatherPushUrl(doc[PARAM_PUSH_BREWFATHER]); - if (!doc[CFG_PARAM_PUSH_HTTP].isNull()) - setHttpPushUrl(doc[CFG_PARAM_PUSH_HTTP]); - if (!doc[CFG_PARAM_PUSH_HTTP2].isNull()) - setHttpPushUrl2(doc[CFG_PARAM_PUSH_HTTP2]); + if (!doc[PARAM_PUSH_HTTP].isNull()) setHttpPushUrl(doc[PARAM_PUSH_HTTP]); + if (!doc[PARAM_PUSH_HTTP2].isNull()) setHttpPushUrl2(doc[PARAM_PUSH_HTTP2]); - if (!doc[CFG_PARAM_PUSH_INFLUXDB2].isNull()) - setInfluxDb2PushUrl(doc[CFG_PARAM_PUSH_INFLUXDB2]); - if (!doc[CFG_PARAM_PUSH_INFLUXDB2_ORG].isNull()) - setInfluxDb2PushOrg(doc[CFG_PARAM_PUSH_INFLUXDB2_ORG]); - if (!doc[CFG_PARAM_PUSH_INFLUXDB2_BUCKET].isNull()) - setInfluxDb2PushBucket(doc[CFG_PARAM_PUSH_INFLUXDB2_BUCKET]); - if (!doc[CFG_PARAM_PUSH_INFLUXDB2_AUTH].isNull()) - setInfluxDb2PushToken(doc[CFG_PARAM_PUSH_INFLUXDB2_AUTH]); + if (!doc[PARAM_PUSH_INFLUXDB2].isNull()) + setInfluxDb2PushUrl(doc[PARAM_PUSH_INFLUXDB2]); + if (!doc[PARAM_PUSH_INFLUXDB2_ORG].isNull()) + setInfluxDb2PushOrg(doc[PARAM_PUSH_INFLUXDB2_ORG]); + if (!doc[PARAM_PUSH_INFLUXDB2_BUCKET].isNull()) + setInfluxDb2PushBucket(doc[PARAM_PUSH_INFLUXDB2_BUCKET]); + if (!doc[PARAM_PUSH_INFLUXDB2_AUTH].isNull()) + setInfluxDb2PushToken(doc[PARAM_PUSH_INFLUXDB2_AUTH]); - if (!doc[CFG_PARAM_PUSH_MQTT].isNull()) setMqttUrl(doc[CFG_PARAM_PUSH_MQTT]); - if (!doc[CFG_PARAM_PUSH_MQTT_TOPIC].isNull()) - setMqttTopic(doc[CFG_PARAM_PUSH_MQTT_TOPIC]); - if (!doc[CFG_PARAM_PUSH_MQTT_USER].isNull()) - setMqttUser(doc[CFG_PARAM_PUSH_MQTT_USER]); - if (!doc[CFG_PARAM_PUSH_MQTT_PASS].isNull()) - setMqttPass(doc[CFG_PARAM_PUSH_MQTT_PASS]); + if (!doc[PARAM_PUSH_MQTT].isNull()) setMqttUrl(doc[PARAM_PUSH_MQTT]); + if (!doc[PARAM_PUSH_MQTT_TOPIC].isNull()) + setMqttTopic(doc[PARAM_PUSH_MQTT_TOPIC]); + if (!doc[PARAM_PUSH_MQTT_USER].isNull()) + setMqttUser(doc[PARAM_PUSH_MQTT_USER]); + if (!doc[PARAM_PUSH_MQTT_PASS].isNull()) + setMqttPass(doc[PARAM_PUSH_MQTT_PASS]); - if (!doc[CFG_PARAM_SLEEP_INTERVAL].isNull()) - setSleepInterval(doc[CFG_PARAM_SLEEP_INTERVAL].as()); - if (!doc[CFG_PARAM_VOLTAGEFACTOR].isNull()) - setVoltageFactor(doc[CFG_PARAM_VOLTAGEFACTOR].as()); - if (!doc[CFG_PARAM_GRAVITY_FORMULA].isNull()) - setGravityFormula(doc[CFG_PARAM_GRAVITY_FORMULA]); - if (!doc[CFG_PARAM_GRAVITY_TEMP_ADJ].isNull()) - setGravityTempAdj(doc[CFG_PARAM_GRAVITY_TEMP_ADJ].as()); - if (!doc[CFG_PARAM_GYRO_TEMP].isNull()) - setGyroTemp(doc[CFG_PARAM_GYRO_TEMP].as()); - if (!doc[CFG_PARAM_GRAVITY_FORMAT].isNull()) { - String s = doc[CFG_PARAM_GRAVITY_FORMAT]; + if (!doc[PARAM_SLEEP_INTERVAL].isNull()) + setSleepInterval(doc[PARAM_SLEEP_INTERVAL].as()); + if (!doc[PARAM_VOLTAGEFACTOR].isNull()) + setVoltageFactor(doc[PARAM_VOLTAGEFACTOR].as()); + if (!doc[PARAM_GRAVITY_FORMULA].isNull()) + setGravityFormula(doc[PARAM_GRAVITY_FORMULA]); + if (!doc[PARAM_GRAVITY_TEMP_ADJ].isNull()) + setGravityTempAdj(doc[PARAM_GRAVITY_TEMP_ADJ].as()); + if (!doc[PARAM_GYRO_TEMP].isNull()) + setGyroTemp(doc[PARAM_GYRO_TEMP].as()); + if (!doc[PARAM_GRAVITY_FORMAT].isNull()) { + String s = doc[PARAM_GRAVITY_FORMAT]; setGravityFormat(s.charAt(0)); } - if (!doc[CFG_PARAM_TEMP_ADJ].isNull()) - setTempSensorAdjC(doc[CFG_PARAM_TEMP_ADJ].as()); + if (!doc[PARAM_TEMP_ADJ].isNull()) + setTempSensorAdjC(doc[PARAM_TEMP_ADJ].as()); - if (!doc[CFG_PARAM_GYRO_CALIBRATION]["ax"].isNull()) - _gyroCalibration.ax = doc[CFG_PARAM_GYRO_CALIBRATION]["ax"]; - if (!doc[CFG_PARAM_GYRO_CALIBRATION]["ay"].isNull()) - _gyroCalibration.ay = doc[CFG_PARAM_GYRO_CALIBRATION]["ay"]; - if (!doc[CFG_PARAM_GYRO_CALIBRATION]["az"].isNull()) - _gyroCalibration.az = doc[CFG_PARAM_GYRO_CALIBRATION]["az"]; - if (!doc[CFG_PARAM_GYRO_CALIBRATION]["gx"].isNull()) - _gyroCalibration.gx = doc[CFG_PARAM_GYRO_CALIBRATION]["gx"]; - if (!doc[CFG_PARAM_GYRO_CALIBRATION]["gy"].isNull()) - _gyroCalibration.gy = doc[CFG_PARAM_GYRO_CALIBRATION]["gy"]; - if (!doc[CFG_PARAM_GYRO_CALIBRATION]["gz"].isNull()) - _gyroCalibration.gz = doc[CFG_PARAM_GYRO_CALIBRATION]["gz"]; + if (!doc[PARAM_GYRO_CALIBRATION]["ax"].isNull()) + _gyroCalibration.ax = doc[PARAM_GYRO_CALIBRATION]["ax"]; + if (!doc[PARAM_GYRO_CALIBRATION]["ay"].isNull()) + _gyroCalibration.ay = doc[PARAM_GYRO_CALIBRATION]["ay"]; + if (!doc[PARAM_GYRO_CALIBRATION]["az"].isNull()) + _gyroCalibration.az = doc[PARAM_GYRO_CALIBRATION]["az"]; + if (!doc[PARAM_GYRO_CALIBRATION]["gx"].isNull()) + _gyroCalibration.gx = doc[PARAM_GYRO_CALIBRATION]["gx"]; + if (!doc[PARAM_GYRO_CALIBRATION]["gy"].isNull()) + _gyroCalibration.gy = doc[PARAM_GYRO_CALIBRATION]["gy"]; + if (!doc[PARAM_GYRO_CALIBRATION]["gz"].isNull()) + _gyroCalibration.gz = doc[PARAM_GYRO_CALIBRATION]["gz"]; - if (!doc[CFG_PARAM_FORMULA_DATA]["a1"].isNull()) - _formulaData.a[0] = doc[CFG_PARAM_FORMULA_DATA]["a1"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["a2"].isNull()) - _formulaData.a[1] = doc[CFG_PARAM_FORMULA_DATA]["a2"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["a3"].isNull()) - _formulaData.a[2] = doc[CFG_PARAM_FORMULA_DATA]["a3"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["a4"].isNull()) - _formulaData.a[3] = doc[CFG_PARAM_FORMULA_DATA]["a4"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["a5"].isNull()) - _formulaData.a[4] = doc[CFG_PARAM_FORMULA_DATA]["a5"].as(); + if (!doc[PARAM_FORMULA_DATA]["a1"].isNull()) + _formulaData.a[0] = doc[PARAM_FORMULA_DATA]["a1"].as(); + if (!doc[PARAM_FORMULA_DATA]["a2"].isNull()) + _formulaData.a[1] = doc[PARAM_FORMULA_DATA]["a2"].as(); + if (!doc[PARAM_FORMULA_DATA]["a3"].isNull()) + _formulaData.a[2] = doc[PARAM_FORMULA_DATA]["a3"].as(); + if (!doc[PARAM_FORMULA_DATA]["a4"].isNull()) + _formulaData.a[3] = doc[PARAM_FORMULA_DATA]["a4"].as(); + if (!doc[PARAM_FORMULA_DATA]["a5"].isNull()) + _formulaData.a[4] = doc[PARAM_FORMULA_DATA]["a5"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["g1"].isNull()) - _formulaData.g[0] = doc[CFG_PARAM_FORMULA_DATA]["g1"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["g2"].isNull()) - _formulaData.g[1] = doc[CFG_PARAM_FORMULA_DATA]["g2"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["g3"].isNull()) - _formulaData.g[2] = doc[CFG_PARAM_FORMULA_DATA]["g3"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["g4"].isNull()) - _formulaData.g[3] = doc[CFG_PARAM_FORMULA_DATA]["g4"].as(); - if (!doc[CFG_PARAM_FORMULA_DATA]["g5"].isNull()) - _formulaData.g[4] = doc[CFG_PARAM_FORMULA_DATA]["g5"].as(); + if (!doc[PARAM_FORMULA_DATA]["g1"].isNull()) + _formulaData.g[0] = doc[PARAM_FORMULA_DATA]["g1"].as(); + if (!doc[PARAM_FORMULA_DATA]["g2"].isNull()) + _formulaData.g[1] = doc[PARAM_FORMULA_DATA]["g2"].as(); + if (!doc[PARAM_FORMULA_DATA]["g3"].isNull()) + _formulaData.g[2] = doc[PARAM_FORMULA_DATA]["g3"].as(); + if (!doc[PARAM_FORMULA_DATA]["g4"].isNull()) + _formulaData.g[3] = doc[PARAM_FORMULA_DATA]["g4"].as(); + if (!doc[PARAM_FORMULA_DATA]["g5"].isNull()) + _formulaData.g[4] = doc[PARAM_FORMULA_DATA]["g5"].as(); myConfig.debug(); _saveNeeded = false; // Reset save flag @@ -292,7 +292,7 @@ void Config::formatFileSystem() { // Check if file system can be mounted, if not we format it. // void Config::checkFileSystem() { -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) Log.verbose(F("CFG : Checking if filesystem is valid." CR)); #endif @@ -308,7 +308,7 @@ void Config::checkFileSystem() { // Dump the configuration to the serial port // void Config::debug() { -#if LOG_LEVEL == 6 && !defined(CFG_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) Log.verbose(F("CFG : Dumping configration " CFG_FILENAME "." CR)); Log.verbose(F("CFG : ID; '%s'." CR), getID()); Log.verbose(F("CFG : WIFI; '%s', '%s'." CR), getWifiSSID(), getWifiPass()); @@ -332,4 +332,104 @@ void Config::debug() { #endif } +// +// Save json document to file +// +bool HardwareConfig::saveFile() { +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) + Log.verbose(F("CFG : Saving hardware configuration to file." CR)); +#endif + + File configFile = LittleFS.open(CFG_HW_FILENAME, "w"); + + if (!configFile) { + Log.error(F("CFG : Failed to open file " CFG_HW_FILENAME " for save." CR)); + return false; + } + + DynamicJsonDocument doc(512); + + doc[PARAM_HW_GYRO_READ_COUNT] = this->getGyroReadCount(); + doc[PARAM_HW_GYRO_READ_DELAY] = this->getGyroReadDelay(); + doc[PARAM_HW_GYRO_MOVING_THREASHOLD] = this->getGyroSensorMovingThreashold(); + doc[PARAM_HW_FORMULA_DEVIATION] = this->getMaxFormulaCreationDeviation(); + doc[PARAM_HW_WIFI_PORTALTIMEOUT] = this->getWifiPortalTimeout(); + doc[PARAM_HW_FORMULA_CALIBRATION_TEMP] = this->getDefaultCalibrationTemp(); + +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) + serializeJson(doc, Serial); + Serial.print(CR); +#endif + + serializeJson(doc, configFile); + configFile.flush(); + configFile.close(); + + Log.notice(F("CFG : Configuration saved to " CFG_HW_FILENAME "." CR)); + return true; +} + +// +// Load config file from disk +// +bool HardwareConfig::loadFile() { +#if LOG_LEVEL == 6 && !defined(DISABLE_LOGGING) + Log.verbose(F("CFG : Loading hardware configuration from file." CR)); +#endif + + if (!LittleFS.exists(CFG_HW_FILENAME)) { + Log.warning( + F("CFG : Configuration file does not exist " CFG_HW_FILENAME "." CR)); + return false; + } + + File configFile = LittleFS.open(CFG_HW_FILENAME, "r"); + + if (!configFile) { + Log.error(F("CFG : Failed to open " CFG_HW_FILENAME "." CR)); + return false; + } + + Log.notice(F("CFG : Size of configuration file=%d bytes." CR), + configFile.size()); + + DynamicJsonDocument doc(512); + DeserializationError err = deserializeJson(doc, configFile); +#if LOG_LEVEL == 6 + serializeJson(doc, Serial); + Serial.print(CR); +#endif + configFile.close(); + + if (err) { + Log.error( + F("CFG : Failed to parse " CFG_HW_FILENAME " file, Err: %s, %d." CR), + err.c_str(), doc.capacity()); + return false; + } + +#if LOG_LEVEL == 6 + Log.verbose(F("CFG : Parsed hardware configuration file." CR)); +#endif + + if (!doc[PARAM_HW_GYRO_READ_COUNT].isNull()) + this->setGyroReadCount(doc[PARAM_HW_GYRO_READ_COUNT].as()); + if (!doc[PARAM_HW_GYRO_READ_DELAY].isNull()) + this->setGyroReadDelay(doc[PARAM_HW_GYRO_READ_DELAY].as()); + if (!doc[PARAM_HW_GYRO_MOVING_THREASHOLD].isNull()) + this->setGyroSensorMovingThreashold( + doc[PARAM_HW_GYRO_MOVING_THREASHOLD].as()); + if (!doc[PARAM_HW_FORMULA_DEVIATION].isNull()) + this->setMaxFormulaCreationDeviation( + doc[PARAM_HW_FORMULA_DEVIATION].as()); + if (!doc[PARAM_HW_FORMULA_CALIBRATION_TEMP].isNull()) + this->SetDefaultCalibrationTemp( + doc[PARAM_HW_FORMULA_CALIBRATION_TEMP].as()); + if (!doc[PARAM_HW_WIFI_PORTALTIMEOUT].isNull()) + this->setWifiPortalTimeout(doc[PARAM_HW_WIFI_PORTALTIMEOUT].as()); + + Log.notice(F("CFG : Configuration file " CFG_HW_FILENAME " loaded." CR)); + return true; +} + // EOF diff --git a/src/config.hpp b/src/config.hpp index 9763349..f143e3b 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -25,63 +25,13 @@ SOFTWARE. #define SRC_CONFIG_HPP_ #include +#include #define CFG_JSON_BUFSIZE 3192 -#define CFG_APPNAME "GravityMon " // Name of firmware -#define CFG_FILENAME "/gravitymon.json" // Name of config file - -#define WIFI_DEFAULT_SSID "GravityMon" // Name of created SSID -#define WIFI_DEFAULT_PWD "password" // Password for created SSID -#define WIFI_MDNS "gravitymon" // Prefix for MDNS name -#define WIFI_PORTAL_TIMEOUT \ - 120 // Number of seconds until the config portal is closed - -#define CFG_PARAM_ID "id" -#define CFG_PARAM_MDNS "mdns" // Device name -#define CFG_PARAM_OTA "ota-url" -#define CFG_PARAM_SSID "wifi-ssid" -#define CFG_PARAM_PASS "wifi-pass" - -#define CFG_PARAM_PUSH_BREWFATHER "brewfather-push" -#define CFG_PARAM_PUSH_HTTP "http-push" -#define CFG_PARAM_PUSH_HTTP2 "http-push2" -#define CFG_PARAM_PUSH_INFLUXDB2 "influxdb2-push" -#define CFG_PARAM_PUSH_INFLUXDB2_ORG "influxdb2-org" -#define CFG_PARAM_PUSH_INFLUXDB2_BUCKET "influxdb2-bucket" -#define CFG_PARAM_PUSH_INFLUXDB2_AUTH "influxdb2-auth" -#define CFG_PARAM_PUSH_MQTT "mqtt-push" -#define CFG_PARAM_PUSH_MQTT_USER "mqtt-user" -#define CFG_PARAM_PUSH_MQTT_PASS "mqtt-pass" -#define CFG_PARAM_PUSH_MQTT_TOPIC "mqtt-topic" -#define CFG_PARAM_SLEEP_INTERVAL "sleep-interval" // Sleep interval -#define CFG_PARAM_TEMPFORMAT "temp-format" // C or F -#define CFG_PARAM_VOLTAGEFACTOR \ - "voltage-factor" // Factor to calculate the battery voltage -#define CFG_PARAM_GRAVITY_FORMULA \ - "gravity-formula" // Formula for calculating gravity -#define CFG_PARAM_GRAVITY_FORMAT "gravity-format" // Gravity format G or P -#define CFG_PARAM_GRAVITY_TEMP_ADJ \ - "gravity-temp-adjustment" // True/False. Adjust gravity for temperature -#define CFG_PARAM_TEMP_ADJ \ - "temp-adjustment-value" // Correction value for temp sensor -#define CFG_PARAM_GYRO_CALIBRATION "gyro-calibration-data" // READ ONLY -#define CFG_PARAM_GYRO_TEMP \ - "gyro-temp" // True/False. Use temp sensor in gyro (only in gravity mode) - -#define CFG_PARAM_FORMULA_DATA \ - "formula-calculation-data" // Raw data for the formula calculation - -#define CFG_PARAM_APP_NAME "app-name" -#define CFG_PARAM_APP_VER "app-ver" -#define CFG_PARAM_ANGLE "angle" -#define CFG_PARAM_GRAVITY "gravity" -#define CFG_PARAM_TEMP_C "temp-c" -#define CFG_PARAM_TEMP_F "temp-f" -#define CFG_PARAM_BATTERY "battery" -#define CFG_PARAM_SLEEP_MODE "sleep-mode" -#define CFG_PARAM_RSSI "rssi" -#define CFG_PARAM_ERROR "error" +#define CFG_APPNAME "GravityMon " // Name of firmware +#define CFG_FILENAME "/gravitymon.json" // Name of config file +#define CFG_HW_FILENAME "/hardware.json" // Name of config file for hw // Used for holding sensordata or sensoroffsets struct RawGyroData { @@ -102,6 +52,37 @@ struct RawFormulaData { double g[5]; }; +class HardwareConfig { + private: + int _wifiPortalTimeout = 120; + float _maxFormulaCreationDeviation = 1.6; + float _defaultCalibrationTemp = 20.0; + int _gyroSensorMovingThreashold = 500; + int _gyroReadCount = 50; + int _gyroReadDelay = 3150; // us, empirical, to hold sampling to 200 Hz + + public: + int getWifiPortalTimeout() { return _wifiPortalTimeout; } + void setWifiPortalTimeout(int t) { _wifiPortalTimeout = t; } + float getMaxFormulaCreationDeviation() { + return _maxFormulaCreationDeviation; + } + void setMaxFormulaCreationDeviation(float f) { + _maxFormulaCreationDeviation = f; + } + float getDefaultCalibrationTemp() { return _defaultCalibrationTemp; } + void SetDefaultCalibrationTemp(float t) { _defaultCalibrationTemp = t; } + int getGyroSensorMovingThreashold() { return _gyroSensorMovingThreashold; } + void setGyroSensorMovingThreashold(int t) { _gyroSensorMovingThreashold = t; } + int getGyroReadCount() { return _gyroReadCount; } + void setGyroReadCount(int c) { _gyroReadCount = c; } + int getGyroReadDelay() { return _gyroReadDelay; } + void setGyroReadDelay(int d) { _gyroReadDelay = d; } + + bool saveFile(); + bool loadFile(); +}; + class Config { private: bool _saveNeeded; @@ -340,6 +321,7 @@ class Config { }; extern Config myConfig; +extern HardwareConfig myHardwareConfig; #endif // SRC_CONFIG_HPP_ diff --git a/src/gyro.cpp b/src/gyro.cpp index cf696b9..fbcf1c1 100644 --- a/src/gyro.cpp +++ b/src/gyro.cpp @@ -28,14 +28,13 @@ GyroSensor myGyro; MPU6050 accelgyro; #define GYRO_USE_INTERRUPT // Use interrupt to detect when new sample is ready -#define SENSOR_MOVING_THREASHOLD 500 -#define SENSOR_READ_COUNT 50 -#define SENSOR_READ_DELAY 3150 // us, empirical, to hold sampling to 200 Hz - -#define GYRO_SHOW_MINMAX // Will calculate the min/max values when doing - // calibration +#define GYRO_SHOW_MINMAX // Will calculate the min/max values when doing + // calibration // #define GYRO_CALIBRATE_STARTUP // Will calibrate sensor at startup +#define PIN_SDA D3 +#define PIN_SCL D4 + // // Initialize the sensor chip. // @@ -43,7 +42,7 @@ bool GyroSensor::setup() { #if LOG_LEVEL == 6 && !defined(GYRO_DISABLE_LOGGING) Log.verbose(F("GYRO: Setting up hardware." CR)); #endif - Wire.begin(D3, D4); + Wire.begin(PIN_SDA, PIN_SCL); Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having // compilation difficulties @@ -215,11 +214,11 @@ bool GyroSensor::isSensorMoving(RawGyroData &raw) { #endif int x = abs(raw.gx), y = abs(raw.gy), z = abs(raw.gz); + int threashold = myHardwareConfig.getGyroSensorMovingThreashold(); - if (x > SENSOR_MOVING_THREASHOLD || y > SENSOR_MOVING_THREASHOLD || - z > SENSOR_MOVING_THREASHOLD) { - Log.notice(F("GYRO: Movement detected (%d)\t%d\t%d\t%d." CR), - SENSOR_MOVING_THREASHOLD, x, y, z); + if (x > threashold || y > threashold || z > threashold) { + Log.notice(F("GYRO: Movement detected (%d)\t%d\t%d\t%d." CR), threashold, x, + y, z); return true; } @@ -236,9 +235,10 @@ bool GyroSensor::read() { if (!_sensorConnected) return false; - readSensor(_lastGyroData, SENSOR_READ_COUNT, - SENSOR_READ_DELAY); // Last param is unused if GYRO_USE_INTERRUPT - // is defined. + readSensor( + _lastGyroData, myHardwareConfig.getGyroReadCount(), + myHardwareConfig.getGyroReadDelay()); // Last param is unused if + // GYRO_USE_INTERRUPT is defined. // If the sensor is unstable we return false to signal we dont have valid // value diff --git a/src/main.cpp b/src/main.cpp index 3400d7b..3956a86 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -120,6 +120,7 @@ void setup() { LOG_PERF_START("main-config-load"); myConfig.checkFileSystem(); myConfig.loadFile(); + myHardwareConfig.loadFile(); LOG_PERF_STOP("main-config-load"); // Setup watchdog diff --git a/src/resources.cpp b/src/resources.cpp index f4b93e7..2083723 100644 --- a/src/resources.cpp +++ b/src/resources.cpp @@ -24,20 +24,18 @@ SOFTWARE. #define INCBIN_OUTPUT_SECTION ".irom.text" #include -#if defined(EMBED_HTML) +#include +#if defined(EMBED_HTML) // Using minify to reduce memory usage. Reducing RAM memory usage with about 7% INCBIN(IndexHtm, "data/index.min.htm"); INCBIN(DeviceHtm, "data/device.min.htm"); INCBIN(ConfigHtm, "data/config.min.htm"); INCBIN(CalibrationHtm, "data/calibration.min.htm"); INCBIN(AboutHtm, "data/about.min.htm"); - #else - // Minium web interface for uploading htm files INCBIN(UploadHtm, "data/upload.min.htm"); - #endif // EOF diff --git a/src/resources.hpp b/src/resources.hpp new file mode 100644 index 0000000..add3db0 --- /dev/null +++ b/src/resources.hpp @@ -0,0 +1,71 @@ +/* +MIT License + +Copyright (c) 2021-22 Magnus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ +#ifndef SRC_RESOURCES_HPP_ +#define SRC_RESOURCES_HPP_ + +// Common strings used in json formats. +#define PARAM_ID "id" +#define PARAM_MDNS "mdns" +#define PARAM_OTA "ota-url" +#define PARAM_SSID "wifi-ssid" +#define PARAM_PASS "wifi-pass" +#define PARAM_PUSH_BREWFATHER "brewfather-push" +#define PARAM_PUSH_HTTP "http-push" +#define PARAM_PUSH_HTTP2 "http-push2" +#define PARAM_PUSH_INFLUXDB2 "influxdb2-push" +#define PARAM_PUSH_INFLUXDB2_ORG "influxdb2-org" +#define PARAM_PUSH_INFLUXDB2_BUCKET "influxdb2-bucket" +#define PARAM_PUSH_INFLUXDB2_AUTH "influxdb2-auth" +#define PARAM_PUSH_MQTT "mqtt-push" +#define PARAM_PUSH_MQTT_USER "mqtt-user" +#define PARAM_PUSH_MQTT_PASS "mqtt-pass" +#define PARAM_PUSH_MQTT_TOPIC "mqtt-topic" +#define PARAM_SLEEP_INTERVAL "sleep-interval" +#define PARAM_TEMPFORMAT "temp-format" +#define PARAM_VOLTAGEFACTOR "voltage-factor" +#define PARAM_GRAVITY_FORMULA "gravity-formula" +#define PARAM_GRAVITY_FORMAT "gravity-format" +#define PARAM_GRAVITY_TEMP_ADJ "gravity-temp-adjustment" +#define PARAM_TEMP_ADJ "temp-adjustment-value" +#define PARAM_GYRO_CALIBRATION "gyro-calibration-data" +#define PARAM_GYRO_TEMP "gyro-temp" +#define PARAM_FORMULA_DATA "formula-calculation-data" +#define PARAM_APP_NAME "app-name" +#define PARAM_APP_VER "app-ver" +#define PARAM_ANGLE "angle" +#define PARAM_GRAVITY "gravity" +#define PARAM_TEMP_C "temp-c" +#define PARAM_TEMP_F "temp-f" +#define PARAM_BATTERY "battery" +#define PARAM_SLEEP_MODE "sleep-mode" +#define PARAM_RSSI "rssi" +#define PARAM_ERROR "error" +#define PARAM_HW_GYRO_READ_COUNT "gyro-read-count" +#define PARAM_HW_GYRO_READ_DELAY "gyro-read-delay" +#define PARAM_HW_GYRO_MOVING_THREASHOLD "gyro-moving-threashold" +#define PARAM_HW_FORMULA_DEVIATION "formula-max-deviation" +#define PARAM_HW_FORMULA_CALIBRATION_TEMP "formula-calibration-temp" +#define PARAM_HW_WIFI_PORTALTIMEOUT "wifi-portaltimeout" + +#endif // SRC_RESOURCES_HPP_ diff --git a/src/webserver.cpp b/src/webserver.cpp index 82bf561..b17d6bb 100644 --- a/src/webserver.cpp +++ b/src/webserver.cpp @@ -26,6 +26,7 @@ SOFTWARE. #include #include #include +#include #include #include #include @@ -44,10 +45,10 @@ void WebServer::webHandleDevice() { #endif DynamicJsonDocument doc(100); - doc[CFG_PARAM_ID] = myConfig.getID(); - doc[CFG_PARAM_APP_NAME] = CFG_APPNAME; - doc[CFG_PARAM_APP_VER] = CFG_APPVER; - doc[CFG_PARAM_MDNS] = myConfig.getMDNS(); + doc[PARAM_ID] = myConfig.getID(); + doc[PARAM_APP_NAME] = CFG_APPNAME; + doc[PARAM_APP_VER] = CFG_APPVER; + doc[PARAM_MDNS] = myConfig.getMDNS(); #if LOG_LEVEL == 6 serializeJson(doc, Serial); Serial.print(CR); @@ -68,14 +69,14 @@ void WebServer::webHandleConfig() { DynamicJsonDocument doc(CFG_JSON_BUFSIZE); myConfig.createJson(doc); - doc[CFG_PARAM_PASS] = ""; // dont show the wifi password + doc[PARAM_PASS] = ""; // dont show the wifi password double angle = myGyro.getAngle(); double tempC = myTempSensor.getTempC(myConfig.isGyroTemp()); double gravity = calculateGravity(angle, tempC); - doc[CFG_PARAM_ANGLE] = reduceFloatPrecision(angle); - doc[CFG_PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat()); + doc[PARAM_ANGLE] = reduceFloatPrecision(angle); + doc[PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat()); if (myConfig.isGravityTempAdj()) { gravity = @@ -83,12 +84,12 @@ void WebServer::webHandleConfig() { } if (myConfig.isGravityPlato()) { - doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1); + doc[PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1); } else { - doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(gravity, 4); + doc[PARAM_GRAVITY] = reduceFloatPrecision(gravity, 4); } - doc[CFG_PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage()); + doc[PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage()); #if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING) serializeJson(doc, Serial); @@ -178,7 +179,7 @@ void WebServer::webHandleUploadFile() { // void WebServer::webHandleCalibrate() { LOG_PERF_START("webserver-api-calibrate"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/calibrate." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -197,7 +198,7 @@ void WebServer::webHandleCalibrate() { // Callback from webServer when / has been accessed. // void WebServer::webHandleFactoryReset() { - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/factory." CR)); if (!id.compareTo(myConfig.getID())) { @@ -224,23 +225,23 @@ void WebServer::webHandleStatus() { double tempC = myTempSensor.getTempC(myConfig.isGyroTemp()); double gravity = calculateGravity(angle, tempC); - doc[CFG_PARAM_ID] = myConfig.getID(); - doc[CFG_PARAM_ANGLE] = reduceFloatPrecision(angle); + doc[PARAM_ID] = myConfig.getID(); + doc[PARAM_ANGLE] = reduceFloatPrecision(angle); if (myConfig.isGravityTempAdj()) { gravity = gravityTemperatureCorrectionC(gravity, tempC); // } if (myConfig.isGravityPlato()) { - doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1); + doc[PARAM_GRAVITY] = reduceFloatPrecision(convertToPlato(gravity), 1); } else { - doc[CFG_PARAM_GRAVITY] = reduceFloatPrecision(gravity, 4); + doc[PARAM_GRAVITY] = reduceFloatPrecision(gravity, 4); } - doc[CFG_PARAM_TEMP_C] = reduceFloatPrecision(tempC, 1); - doc[CFG_PARAM_TEMP_F] = reduceFloatPrecision(convertCtoF(tempC), 1); - doc[CFG_PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage()); - doc[CFG_PARAM_TEMPFORMAT] = String(myConfig.getTempFormat()); - doc[CFG_PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat()); - doc[CFG_PARAM_SLEEP_MODE] = sleepModeAlwaysSkip; - doc[CFG_PARAM_RSSI] = WiFi.RSSI(); + doc[PARAM_TEMP_C] = reduceFloatPrecision(tempC, 1); + doc[PARAM_TEMP_F] = reduceFloatPrecision(convertCtoF(tempC), 1); + doc[PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage()); + doc[PARAM_TEMPFORMAT] = String(myConfig.getTempFormat()); + doc[PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat()); + doc[PARAM_SLEEP_MODE] = sleepModeAlwaysSkip; + doc[PARAM_RSSI] = WiFi.RSSI(); #if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING) serializeJson(doc, Serial); @@ -257,7 +258,7 @@ void WebServer::webHandleStatus() { // Callback from webServer when / has been accessed. // void WebServer::webHandleClearWIFI() { - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/clearwifi." CR)); if (!id.compareTo(myConfig.getID())) { @@ -276,7 +277,7 @@ void WebServer::webHandleClearWIFI() { // void WebServer::webHandleStatusSleepmode() { LOG_PERF_START("webserver-api-sleepmode"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/status/sleepmode." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -291,7 +292,7 @@ void WebServer::webHandleStatusSleepmode() { Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); #endif - if (_server->arg(CFG_PARAM_SLEEP_MODE).equalsIgnoreCase("true")) + if (_server->arg(PARAM_SLEEP_MODE).equalsIgnoreCase("true")) sleepModeAlwaysSkip = true; else sleepModeAlwaysSkip = false; @@ -304,7 +305,7 @@ void WebServer::webHandleStatusSleepmode() { // void WebServer::webHandleConfigDevice() { LOG_PERF_START("webserver-api-config-device"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/config/device." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -319,9 +320,9 @@ void WebServer::webHandleConfigDevice() { Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); #endif - myConfig.setMDNS(_server->arg(CFG_PARAM_MDNS).c_str()); - myConfig.setTempFormat(_server->arg(CFG_PARAM_TEMPFORMAT).charAt(0)); - myConfig.setSleepInterval(_server->arg(CFG_PARAM_SLEEP_INTERVAL).c_str()); + myConfig.setMDNS(_server->arg(PARAM_MDNS).c_str()); + myConfig.setTempFormat(_server->arg(PARAM_TEMPFORMAT).charAt(0)); + myConfig.setSleepInterval(_server->arg(PARAM_SLEEP_INTERVAL).c_str()); myConfig.saveFile(); _server->sendHeader("Location", "/config.htm#collapseOne", true); _server->send(302, "text/plain", "Device config updated"); @@ -333,7 +334,7 @@ void WebServer::webHandleConfigDevice() { // void WebServer::webHandleConfigPush() { LOG_PERF_START("webserver-api-config-push"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/config/push." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -347,21 +348,19 @@ void WebServer::webHandleConfigPush() { Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); #endif - myConfig.setHttpPushUrl(_server->arg(CFG_PARAM_PUSH_HTTP).c_str()); - myConfig.setHttpPushUrl2(_server->arg(CFG_PARAM_PUSH_HTTP2).c_str()); - myConfig.setBrewfatherPushUrl( - _server->arg(CFG_PARAM_PUSH_BREWFATHER).c_str()); - myConfig.setInfluxDb2PushUrl(_server->arg(CFG_PARAM_PUSH_INFLUXDB2).c_str()); - myConfig.setInfluxDb2PushOrg( - _server->arg(CFG_PARAM_PUSH_INFLUXDB2_ORG).c_str()); + myConfig.setHttpPushUrl(_server->arg(PARAM_PUSH_HTTP).c_str()); + myConfig.setHttpPushUrl2(_server->arg(PARAM_PUSH_HTTP2).c_str()); + myConfig.setBrewfatherPushUrl(_server->arg(PARAM_PUSH_BREWFATHER).c_str()); + myConfig.setInfluxDb2PushUrl(_server->arg(PARAM_PUSH_INFLUXDB2).c_str()); + myConfig.setInfluxDb2PushOrg(_server->arg(PARAM_PUSH_INFLUXDB2_ORG).c_str()); myConfig.setInfluxDb2PushBucket( - _server->arg(CFG_PARAM_PUSH_INFLUXDB2_BUCKET).c_str()); + _server->arg(PARAM_PUSH_INFLUXDB2_BUCKET).c_str()); myConfig.setInfluxDb2PushToken( - _server->arg(CFG_PARAM_PUSH_INFLUXDB2_AUTH).c_str()); - myConfig.setMqttUrl(_server->arg(CFG_PARAM_PUSH_MQTT).c_str()); - myConfig.setMqttTopic(_server->arg(CFG_PARAM_PUSH_MQTT_TOPIC).c_str()); - myConfig.setMqttUser(_server->arg(CFG_PARAM_PUSH_MQTT_USER).c_str()); - myConfig.setMqttPass(_server->arg(CFG_PARAM_PUSH_MQTT_PASS).c_str()); + _server->arg(PARAM_PUSH_INFLUXDB2_AUTH).c_str()); + myConfig.setMqttUrl(_server->arg(PARAM_PUSH_MQTT).c_str()); + myConfig.setMqttTopic(_server->arg(PARAM_PUSH_MQTT_TOPIC).c_str()); + myConfig.setMqttUser(_server->arg(PARAM_PUSH_MQTT_USER).c_str()); + myConfig.setMqttPass(_server->arg(PARAM_PUSH_MQTT_PASS).c_str()); myConfig.saveFile(); _server->sendHeader("Location", "/config.htm#collapseTwo", true); _server->send(302, "text/plain", "Push config updated"); @@ -392,7 +391,7 @@ String WebServer::getRequestArguments() { // void WebServer::webHandleConfigGravity() { LOG_PERF_START("webserver-api-config-gravity"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/config/gravity." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -407,11 +406,11 @@ void WebServer::webHandleConfigGravity() { Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); #endif - myConfig.setGravityFormat(_server->arg(CFG_PARAM_GRAVITY_FORMAT).charAt(0)); - myConfig.setGravityFormula(_server->arg(CFG_PARAM_GRAVITY_FORMULA).c_str()); + myConfig.setGravityFormat(_server->arg(PARAM_GRAVITY_FORMAT).charAt(0)); + myConfig.setGravityFormula(_server->arg(PARAM_GRAVITY_FORMULA).c_str()); myConfig.setGravityTempAdj( - _server->arg(CFG_PARAM_GRAVITY_TEMP_ADJ).equalsIgnoreCase("on") ? true - : false); + _server->arg(PARAM_GRAVITY_TEMP_ADJ).equalsIgnoreCase("on") ? true + : false); myConfig.saveFile(); _server->sendHeader("Location", "/config.htm#collapseThree", true); _server->send(302, "text/plain", "Gravity config updated"); @@ -423,7 +422,7 @@ void WebServer::webHandleConfigGravity() { // void WebServer::webHandleConfigHardware() { LOG_PERF_START("webserver-api-config-hardware"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/config/hardware." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -438,21 +437,86 @@ void WebServer::webHandleConfigHardware() { Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); #endif - myConfig.setVoltageFactor(_server->arg(CFG_PARAM_VOLTAGEFACTOR).toFloat()); + myConfig.setVoltageFactor(_server->arg(PARAM_VOLTAGEFACTOR).toFloat()); if (myConfig.isTempC()) { - myConfig.setTempSensorAdjC(_server->arg(CFG_PARAM_TEMP_ADJ)); + myConfig.setTempSensorAdjC(_server->arg(PARAM_TEMP_ADJ)); } else { - myConfig.setTempSensorAdjF(_server->arg(CFG_PARAM_TEMP_ADJ)); + myConfig.setTempSensorAdjF(_server->arg(PARAM_TEMP_ADJ)); } - myConfig.setOtaURL(_server->arg(CFG_PARAM_OTA).c_str()); + myConfig.setOtaURL(_server->arg(PARAM_OTA).c_str()); myConfig.setGyroTemp( - _server->arg(CFG_PARAM_GYRO_TEMP).equalsIgnoreCase("on") ? true : false); + _server->arg(PARAM_GYRO_TEMP).equalsIgnoreCase("on") ? true : false); myConfig.saveFile(); _server->sendHeader("Location", "/config.htm#collapseFour", true); _server->send(302, "text/plain", "Hardware config updated"); LOG_PERF_STOP("webserver-api-config-hardware"); } +// +// Update device parameters. +// +void WebServer::webHandleDeviceParam() { + LOG_PERF_START("webserver-api-device-param"); + String id = _server->arg(PARAM_ID); + Log.notice(F("WEB : webServer callback for /api/device/param." CR)); + + if (!id.equalsIgnoreCase(myConfig.getID())) { + Log.error(F("WEB : Wrong ID received %s, expected %s" CR), id.c_str(), + myConfig.getID()); + _server->send(400, "text/plain", "Invalid ID."); + LOG_PERF_STOP("webserver-api-device-param"); + return; + } + +#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING) + Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); +#endif + + for (int i = 0; i < _server->args(); i++) { + String s = _server->arg(i); + + if (_server->argName(i).equalsIgnoreCase(PARAM_HW_GYRO_READ_COUNT)) + myHardwareConfig.setGyroReadCount(s.toInt()); + else if (_server->argName(i).equalsIgnoreCase(PARAM_HW_GYRO_READ_DELAY)) + myHardwareConfig.setGyroReadDelay(s.toInt()); + else if (_server->argName(i).equalsIgnoreCase( + PARAM_HW_GYRO_MOVING_THREASHOLD)) + myHardwareConfig.setGyroSensorMovingThreashold(s.toInt()); + else if (_server->argName(i).equalsIgnoreCase(PARAM_HW_FORMULA_DEVIATION)) + myHardwareConfig.setMaxFormulaCreationDeviation(s.toFloat()); + else if (_server->argName(i).equalsIgnoreCase( + PARAM_HW_FORMULA_CALIBRATION_TEMP)) + myHardwareConfig.SetDefaultCalibrationTemp(s.toFloat()); + else if (_server->argName(i).equalsIgnoreCase(PARAM_HW_WIFI_PORTALTIMEOUT)) + myHardwareConfig.setWifiPortalTimeout(s.toInt()); + } + + myHardwareConfig.saveFile(); + + // Return the current configuration. + DynamicJsonDocument doc(512); + + doc[PARAM_HW_GYRO_READ_COUNT] = myHardwareConfig.getGyroReadCount(); + doc[PARAM_HW_GYRO_READ_DELAY] = myHardwareConfig.getGyroReadDelay(); + doc[PARAM_HW_GYRO_MOVING_THREASHOLD] = + myHardwareConfig.getGyroSensorMovingThreashold(); + doc[PARAM_HW_FORMULA_DEVIATION] = + myHardwareConfig.getMaxFormulaCreationDeviation(); + doc[PARAM_HW_WIFI_PORTALTIMEOUT] = myHardwareConfig.getWifiPortalTimeout(); + doc[PARAM_HW_FORMULA_CALIBRATION_TEMP] = + myHardwareConfig.getDefaultCalibrationTemp(); + +#if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING) + serializeJson(doc, Serial); + Serial.print(CR); +#endif + + String out; + serializeJson(doc, out); + _server->send(200, "application/json", out.c_str()); + LOG_PERF_STOP("webserver-api-device-param"); +} + // // Callback from webServer when / has been accessed. // @@ -467,25 +531,24 @@ void WebServer::webHandleFormulaRead() { Log.verbose(F("WEB : %s." CR), getRequestArguments().c_str()); #endif - doc[CFG_PARAM_ID] = myConfig.getID(); - doc[CFG_PARAM_ANGLE] = reduceFloatPrecision(myGyro.getAngle()); - doc[CFG_PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat()); - doc[CFG_PARAM_GRAVITY_FORMULA] = ""; - doc[CFG_PARAM_ERROR] = ""; + doc[PARAM_ID] = myConfig.getID(); + doc[PARAM_ANGLE] = reduceFloatPrecision(myGyro.getAngle()); + doc[PARAM_GRAVITY_FORMAT] = String(myConfig.getGravityFormat()); + doc[PARAM_GRAVITY_FORMULA] = ""; + doc[PARAM_ERROR] = ""; switch (_lastFormulaCreateError) { case ERR_FORMULA_INTERNAL: - doc[CFG_PARAM_ERROR] = "Internal error creating formula."; + doc[PARAM_ERROR] = "Internal error creating formula."; break; case ERR_FORMULA_NOTENOUGHVALUES: - doc[CFG_PARAM_ERROR] = "Not enough values to create formula."; + doc[PARAM_ERROR] = "Not enough values to create formula."; break; case ERR_FORMULA_UNABLETOFFIND: - doc[CFG_PARAM_ERROR] = - "Unable to find an accurate formula based on input."; + doc[PARAM_ERROR] = "Unable to find an accurate formula based on input."; break; default: - doc[CFG_PARAM_GRAVITY_FORMULA] = myConfig.getGravityFormula(); + doc[PARAM_GRAVITY_FORMULA] = myConfig.getGravityFormula(); break; } @@ -525,7 +588,7 @@ void WebServer::webHandleFormulaRead() { // void WebServer::webHandleFormulaWrite() { LOG_PERF_START("webserver-api-formula-write"); - String id = _server->arg(CFG_PARAM_ID); + String id = _server->arg(PARAM_ID); Log.notice(F("WEB : webServer callback for /api/formula/post." CR)); if (!id.equalsIgnoreCase(myConfig.getID())) { @@ -745,6 +808,9 @@ bool WebServer::setupWebServer() { _server->on("/api/config/hardware", HTTP_POST, std::bind(&WebServer::webHandleConfigHardware, this)); // Change hardware settings + _server->on("/api/device/param", HTTP_GET, + std::bind(&WebServer::webHandleDeviceParam, + this)); // Change device params _server->onNotFound(std::bind(&WebServer::webHandlePageNotFound, this)); _server->begin(); diff --git a/src/webserver.hpp b/src/webserver.hpp index 3c31d8f..e2a892c 100644 --- a/src/webserver.hpp +++ b/src/webserver.hpp @@ -60,6 +60,7 @@ class WebServer { void webHandleUploadFile(); void webHandleUpload(); void webHandleDevice(); + void webHandleDeviceParam(); void webHandlePageNotFound(); String getRequestArguments(); diff --git a/src/wifi.cpp b/src/wifi.cpp index b24f156..975f1b7 100644 --- a/src/wifi.cpp +++ b/src/wifi.cpp @@ -61,9 +61,9 @@ ESP_WiFiManager *myWifiManager; DoubleResetDetector *myDRD; WifiConnection myWifi; + const char *userSSID = USER_SSID; const char *userPWD = USER_SSID_PWD; - const int PIN_LED = 2; // @@ -128,7 +128,8 @@ void WifiConnection::startPortal() { myWifiManager = new ESP_WiFiManager(WIFI_MDNS); myWifiManager->setMinimumSignalQuality(-1); myWifiManager->setConfigPortalChannel(0); - myWifiManager->setConfigPortalTimeout(120); + myWifiManager->setConfigPortalTimeout( + myHardwareConfig.getWifiPortalTimeout()); if (myWifiManager->startConfigPortal(WIFI_DEFAULT_SSID, WIFI_DEFAULT_PWD)) { Log.notice(F("WIFI: Exited portal, connected to wifi. Rebooting..." CR)); diff --git a/src/wifi.hpp b/src/wifi.hpp index 67ba59a..049f7e3 100644 --- a/src/wifi.hpp +++ b/src/wifi.hpp @@ -26,6 +26,10 @@ SOFTWARE. #include +#define WIFI_DEFAULT_SSID "GravityMon" // Name of created SSID +#define WIFI_DEFAULT_PWD "password" // Password for created SSID +#define WIFI_MDNS "gravitymon" // Prefix for MDNS name + // tcp cleanup, to avoid memory crash. struct tcp_pcb; extern struct tcp_pcb* tcp_tw_pcbs;