diff --git a/bin/firmware.bin b/bin/firmware.bin index 3dc38567..b4465dfd 100644 Binary files a/bin/firmware.bin and b/bin/firmware.bin differ diff --git a/bin/firmware32.bin b/bin/firmware32.bin index 305d5077..59b0ddee 100644 Binary files a/bin/firmware32.bin and b/bin/firmware32.bin differ diff --git a/bin/firmware32c3.bin b/bin/firmware32c3.bin index 66ea9271..1a37b196 100644 Binary files a/bin/firmware32c3.bin and b/bin/firmware32c3.bin differ diff --git a/bin/firmware32lite.bin b/bin/firmware32lite.bin index 9a6cdb59..b9a8e7d1 100644 Binary files a/bin/firmware32lite.bin and b/bin/firmware32lite.bin differ diff --git a/bin/firmware32s2.bin b/bin/firmware32s2.bin index f463925d..55f70f26 100644 Binary files a/bin/firmware32s2.bin and b/bin/firmware32s2.bin differ diff --git a/bin/firmware32s3.bin b/bin/firmware32s3.bin index d782676a..c95263c4 100644 Binary files a/bin/firmware32s3.bin and b/bin/firmware32s3.bin differ diff --git a/bin/version.json b/bin/version.json index d6b01dc7..65b880bc 100644 --- a/bin/version.json +++ b/bin/version.json @@ -1 +1 @@ -{ "project":"gravmon", "version":"2.0.1", "html": [ ] } \ No newline at end of file +{ "project":"gravmon", "version":"2.1.0", "html": [ ] } \ No newline at end of file diff --git a/html/app.js.gz b/html/app.js.gz index b614bfaf..9011833a 100644 Binary files a/html/app.js.gz and b/html/app.js.gz differ diff --git a/patch/arduino/variants/lolin_s3_mini/pins_arduino.h b/patch/arduino/variants/lolin_s3_mini/pins_arduino.h deleted file mode 100644 index eb250db0..00000000 --- a/patch/arduino/variants/lolin_s3_mini/pins_arduino.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include - -#define USB_VID 0x303a -#define USB_PID 0x8167 - -#define EXTERNAL_NUM_INTERRUPTS 46 -#define NUM_DIGITAL_PINS 48 -#define NUM_ANALOG_INPUTS 18 - - -static const uint8_t LED_BUILTIN = 47; -#define BUILTIN_LED LED_BUILTIN // backward compatibility -#define LED_BUILTIN LED_BUILTIN -#define RGB_BUILTIN LED_BUILTIN+SOC_GPIO_PIN_COUNT -#define RGB_BRIGHTNESS 64 - -#define analogInputToDigitalPin(p) (((p)<20)?(analogChannelToDigitalPin(p)):-1) -#define digitalPinToInterrupt(p) (((p)<49)?(p):-1) -#define digitalPinHasPWM(p) (p < 46) - -static const uint8_t TX = 43; -static const uint8_t RX = 44; - -static const uint8_t SDA = 35; -static const uint8_t SCL = 36; - -static const uint8_t SS = 10; -static const uint8_t MOSI = 11; -static const uint8_t MISO = 13; -static const uint8_t SCK = 12; - -static const uint8_t A0 = 1; -static const uint8_t A1 = 2; -static const uint8_t A2 = 3; -static const uint8_t A3 = 4; -static const uint8_t A4 = 5; -static const uint8_t A5 = 6; -static const uint8_t A6 = 7; -static const uint8_t A7 = 8; -static const uint8_t A8 = 9; -static const uint8_t A9 = 10; -static const uint8_t A10 = 11; -static const uint8_t A11 = 12; -static const uint8_t A12 = 13; -static const uint8_t A13 = 14; -static const uint8_t A14 = 15; -static const uint8_t A15 = 16; -static const uint8_t A16 = 17; -static const uint8_t A17 = 18; - -static const uint8_t T1 = 1; -static const uint8_t T2 = 2; -static const uint8_t T3 = 3; -static const uint8_t T4 = 4; -static const uint8_t T5 = 5; -static const uint8_t T6 = 6; -static const uint8_t T7 = 7; -static const uint8_t T8 = 8; -static const uint8_t T9 = 9; -static const uint8_t T10 = 10; -static const uint8_t T11 = 11; -static const uint8_t T12 = 12; -static const uint8_t T13 = 13; -static const uint8_t T14 = 14; - -#endif /* Pins_Arduino_h */ diff --git a/platformio.ini b/platformio.ini index 364beb86..95ecb5e8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,10 +13,11 @@ lib_dir = lib include_dir = lib [common_env_data] -upload_speed = 921600 +; upload_speed = 921600 +upload_speed = 460800 monitor_speed = 115200 platform = espressif8266@4.2.1 -platform32 = espressif32@6.6.0 +platform32 = espressif32@6.9.0 build_unflags = build_flags = -Wl,-Map,output.map @@ -25,26 +26,27 @@ build_flags = #-D FORCE_GRAVITY_MODE #-D COLLECT_PERFDATA -D USE_LITTLEFS=true - -D CFG_APPVER="\"2.0.1\"" - #-D CFG_GITREV=\""beta-3\"" + -D CFG_APPVER="\"2.1.0\"" + ; -D CFG_GITREV=\""beta-3\"" #-D ENABLE_REMOTE_UI_DEVELOPMENT !python script/git_rev.py + -D MAX_SKETCH_SPACE=0x1c0000 lib_deps = # Using local copy of these libraries # https://github.com/mp-se/i2cdevlib.git# - # https://github.com/mp-se/OneWire # https://github.com/mp-se/Arduino-Temperature-Control-Library https://github.com/mp-se/tinyexpr#v1.0.0 - https://github.com/mp-se/Arduino-Log#1.1.2 - https://github.com/mp-se/ArduinoJson#v6.21.5 - https://github.com/mp-se/arduinoCurveFitting#v1.0.6 - https://github.com/mp-se/arduino-mqtt#v2.5.2 - https://github.com/mp-se/ESPAsyncWebServer#0.1.1 - https://github.com/mp-se/ESPAsyncTCP#0.1.0 - https://github.com/mp-se/espframework#1.0.7 - https://github.com/mp-se/OneWireNg#0.13.3 + https://github.com/bblanchon/ArduinoJson#v7.2.1 + https://github.com/256dpi/arduino-mqtt#v2.5.2 + https://github.com/mp-se/espframework#1.1.2 + https://github.com/pstolarz/OneWireNg#0.13.3 + https://github.com/mathieucarbou/ESPAsyncWebServer#v3.4.5 +lib_deps8266 = + https://github.com/esphome/ESPAsyncTCP#v2.0.0 lib_deps32 = - https://github.com/mp-se/NimBLE-Arduino#1.4.1 + https://github.com/mathieucarbou/AsyncTCP#v3.3.1 +lib_ble32 = + https://github.com/h2zero/NimBLE-Arduino#2.1.1 extra_scripts = script/copy_firmware.py script/create_versionjson.py @@ -64,12 +66,12 @@ build_unflags = ${common_env_data.build_unflags} build_flags = ${common_env_data.build_flags} -D LOG_LEVEL=5 - -D DISABLE_LED + -D ESPFWK_DISABLE_LED #-D USE_SERIAL_PINS # Use the TX/RX pins for the serial port #-D RUN_HARDWARE_TEST # Will run diagnositc setup to validate the GPIO configurations lib_deps = - https://github.com/mp-se/incbin#v1.0.0 ${common_env_data.lib_deps} + ${common_env_data.lib_deps8266} board = d1_mini build_type = release board_build.filesystem = littlefs @@ -87,9 +89,9 @@ build_flags = ${common_env_data.build_flags} -D LOG_LEVEL=5 lib_deps = - https://github.com/mp-se/incbin#v1.0.0 https://github.com/bxparks/AUnit#v1.7.1 ${common_env_data.lib_deps} + ${common_env_data.lib_deps8266} ESP8266httpUpdate DNSServer board = d1_mini @@ -116,6 +118,7 @@ build_flags = lib_deps = ${common_env_data.lib_deps} ${common_env_data.lib_deps32} + ${common_env_data.lib_ble32} lib_ignore = board = wemos_d1_mini32 build_type = release @@ -138,12 +141,13 @@ build_flags = #-D CORE_DEBUG_LEVEL=6 -D ESP32C3 -D ARDUINO_ESP32C3_DEV - -D DISABLE_LED + -D ESPFWK_DISABLE_LED #-D ARDUINO_USB_CDC_ON_BOOT=1 #-DUSE_SERIAL_PINS # Use the TX/RX pins for the serial port lib_deps = ${common_env_data.lib_deps} - ${common_env_data.lib_deps32} + ${common_env_data.lib_deps32} + ${common_env_data.lib_ble32} lib_ignore = board = lolin_c3_mini build_type = release @@ -171,6 +175,7 @@ build_flags = #-D RUN_HARDWARE_TEST # Will run diagnositc setup to validate the GPIO configurations lib_deps = ${common_env_data.lib_deps} + ${common_env_data.lib_deps32} lib_ignore = board = lolin_s2_mini build_type = release @@ -184,7 +189,7 @@ platform = ${common_env_data.platform32} upload_speed = ${common_env_data.upload_speed} monitor_speed = ${common_env_data.monitor_speed} extra_scripts = - pre:script/patch_arduino.py + ; pre:script/patch_arduino.py ${common_env_data.extra_scripts} build_unflags = ${common_env_data.build_unflags} @@ -195,12 +200,13 @@ build_flags = -D CORE_DEBUG_LEVEL=2 -D ESP32S3 -D ARDUINO_ESP32S3_DEV - #-D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 #-D USE_SERIAL_PINS # Use the TX/RX pins for the serial port #-D RUN_HARDWARE_TEST # Will run diagnositc setup to validate the GPIO configurations lib_deps = ${common_env_data.lib_deps} - ${common_env_data.lib_deps32} + ${common_env_data.lib_deps32} + ${common_env_data.lib_ble32} lib_ignore = board = lolin_s3_mini build_type = release @@ -228,6 +234,7 @@ build_flags = lib_deps = ${common_env_data.lib_deps} ${common_env_data.lib_deps32} + ${common_env_data.lib_ble32} lib_ignore = board = lolin32_lite build_type = release diff --git a/script/patch_arduino.py b/script/patch_arduino.py index b97538d1..4fec619d 100644 --- a/script/patch_arduino.py +++ b/script/patch_arduino.py @@ -1,12 +1,12 @@ -Import("env") -import shutil +# Import("env") +# import shutil -framework_dir = env.PioPlatform().get_package_dir("framework-arduinoespressif32") -name = env.get( "PIOENV" )#print(FRAMEWORK_DIR) -dir = env.GetLaunchDir() +# framework_dir = env.PioPlatform().get_package_dir("framework-arduinoespressif32") +# name = env.get( "PIOENV" )#print(FRAMEWORK_DIR) +# dir = env.GetLaunchDir() -if name == "gravity32s3-release" : - source = dir + "/patch/arduino/variants/lolin_s3_mini/pins_arduino.h" - target = framework_dir + "/variants/lolin_s3_mini/pins_arduino.h" - print( "Copy file : " + source + " -> " + target ) - shutil.copyfile( source, target ) +# if name == "gravity32s3-release" : +# source = dir + "/patch/arduino/variants/lolin_s3_mini/pins_arduino.h" +# target = framework_dir + "/variants/lolin_s3_mini/pins_arduino.h" +# print( "Copy file : " + source + " -> " + target ) +# shutil.copyfile( source, target ) diff --git a/src/ble.cpp b/src/ble.cpp index 2d721be1..9923f3da 100644 --- a/src/ble.cpp +++ b/src/ble.cpp @@ -138,10 +138,14 @@ void BleSender::sendTiltData(String& color, float tempF, float gravSG, BLEAdvertisementData advData = BLEAdvertisementData(); advData.setFlags(0x04); - advData.setManufacturerData(beacon.getData()); + const NimBLEBeacon::BeaconData& beaconData = beacon.getData(); + // advData.setManufacturerData(beacon.getData()); + advData.setManufacturerData( + std::string(reinterpret_cast(&beaconData), sizeof(beaconData))); _advertising->setAdvertisementData(advData); - _advertising->setAdvertisementType(BLE_GAP_CONN_MODE_NON); + // _advertising->setAdvertisementType(BLE_GAP_CONN_MODE_NON); + _advertising->setConnectableMode(BLE_GAP_CONN_MODE_NON); _advertising->start(); delay(_beaconTime); @@ -194,7 +198,8 @@ void BleSender::sendCustomBeaconData(float battery, float tempC, float gravity, advData.setManufacturerData(mf); _advertising->setAdvertisementData(advData); - _advertising->setAdvertisementType(BLE_GAP_CONN_MODE_NON); + // _advertising->setAdvertisementType(BLE_GAP_CONN_MODE_NON); + _advertising->setConnectableMode(BLE_GAP_CONN_MODE_NON); _advertising->start(); delay(_beaconTime); _advertising->stop(); diff --git a/src/calc.cpp b/src/calc.cpp index 375b4466..beed0c60 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -21,101 +21,13 @@ 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. */ -#include #include #include +#include #include #include -int createFormula(RawFormulaData &fd, char *formulaBuffer, - int formulaBufferSize, int order) { - int noAngles = 0; - RawFormulaData fd2; - - // Check how many valid values we have got and make sure we have a full - // series. - for (int i = 0; i < FORMULA_DATA_SIZE; i++) { - if (fd.a[i]) { - fd2.a[noAngles] = fd.a[i]; - fd2.g[noAngles] = fd.g[i]; - noAngles++; - } - } - -#if LOG_LEVEL == 6 - Log.verbose( - F("CALC: Trying to create formula using order = %d, found %d angles" CR), - order, noAngles); -#endif - - if (noAngles < 3) { - writeErrorLog("CALC: Not enough values for deriving formula"); - return ERR_FORMULA_NOTENOUGHVALUES; - } else { - double coeffs[order + 1]; - int ret = fitCurve(order, noAngles, fd2.a, fd2.g, - sizeof(coeffs) / sizeof(double), coeffs); - - // Returned value is 0 if no error - if (ret == 0) { -#if LOG_LEVEL == 6 - Log.verbose(F("CALC: Finshied processing data points, order = %d." CR), - order); -#endif - - // Print the formula based on 'order' - if (order == 4) { - snprintf(formulaBuffer, formulaBufferSize, - "%.8f*tilt^4+%.8f*tilt^3+%.8f*tilt^2+%.8f*tilt+%.8f", - coeffs[0], coeffs[1], coeffs[2], coeffs[3], coeffs[4]); - } else if (order == 3) { - snprintf(formulaBuffer, formulaBufferSize, - "%.8f*tilt^3+%.8f*tilt^2+%.8f*tilt+%.8f", coeffs[0], coeffs[1], - coeffs[2], coeffs[3]); - } else if (order == 2) { - snprintf(formulaBuffer, formulaBufferSize, "%.8f*tilt^2+%.8f*tilt+%.8f", - coeffs[0], coeffs[1], coeffs[2]); - } else { // order == 1 - snprintf(formulaBuffer, formulaBufferSize, "%.8f*tilt+%.8f", coeffs[0], - coeffs[1]); - } - -#if LOG_LEVEL == 6 - Log.verbose(F("CALC: Formula: %s" CR), formulaBuffer); -#endif - - bool valid = true; - - for (int i = 0; i < 5; i++) { - if (fd.a[i] == 0 && valid) break; - - double g = calculateGravity(fd.a[i], 0, 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 > myConfig.getMaxFormulaCreationDeviation()) { - writeErrorLog( - "CALC: Validation failed on angle %.2f, deviation too large %.4f " - "SG, formula order %d", - fd.a[i], dev * 1000, order); - valid = false; - } - } - - if (!valid) { - return ERR_FORMULA_UNABLETOFFIND; - } - - Log.info(F("CALC: Found formula '%s'." CR), formulaBuffer); - return 0; - } - } - - writeErrorLog("CALC: Internal error finding formula."); - return ERR_FORMULA_INTERNAL; -} - double calculateGravity(double angle, double temp, const char *tempFormula) { const char *formula = myConfig.getGravityFormula(); diff --git a/src/calc.hpp b/src/calc.hpp index fc2e14e2..3acd8c50 100644 --- a/src/calc.hpp +++ b/src/calc.hpp @@ -26,16 +26,10 @@ SOFTWARE. #include -constexpr auto ERR_FORMULA_NOTENOUGHVALUES = -1; -constexpr auto ERR_FORMULA_INTERNAL = -2; -constexpr auto ERR_FORMULA_UNABLETOFFIND = -3; - double calculateGravity(double angle, double tempC, const char *tempFormula = 0); double gravityTemperatureCorrectionC(double gravity, double tempC, double calTempC); -int createFormula(RawFormulaData &fd, char *formulaBuffer, - int formulaBufferSize, int order); #endif // SRC_CALC_HPP_ diff --git a/src/config.cpp b/src/config.cpp index e69bc2ae..8c70020d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -28,7 +28,7 @@ SOFTWARE. #include GravmonConfig::GravmonConfig(String baseMDNS, String fileName) - : BaseConfig(baseMDNS, fileName, JSON_BUFFER_SIZE_XL) {} + : BaseConfig(baseMDNS, fileName) {} void GravmonConfig::createJson(JsonObject& doc) { // Call base class functions @@ -57,7 +57,7 @@ void GravmonConfig::createJson(JsonObject& doc) { doc[PARAM_SKIP_SSL_ON_TEST] = isSkipSslOnTest(); doc[PARAM_VOLTAGE_PIN] = getVoltagePin(); - JsonObject cal = doc.createNestedObject(PARAM_GYRO_CALIBRATION); + JsonObject cal = doc[PARAM_GYRO_CALIBRATION].to(); cal["ax"] = _gyroCalibration.ax; cal["ay"] = _gyroCalibration.ay; cal["az"] = _gyroCalibration.az; @@ -65,17 +65,17 @@ void GravmonConfig::createJson(JsonObject& doc) { cal["gy"] = _gyroCalibration.gy; cal["gz"] = _gyroCalibration.gz; - JsonArray fdArray = doc.createNestedArray(PARAM_FORMULA_DATA); + JsonArray fdArray = doc[PARAM_FORMULA_DATA].to(); for (int i = 0; i < FORMULA_DATA_SIZE; i++) { - JsonObject fd = fdArray.createNestedObject(); - fd["a"] = serialized(String(_formulaData.a[i], DECIMALS_TILT)); - fd["g"] = serialized(String(_formulaData.g[i], DECIMALS_SG)); + fdArray[i]["a"] = serialized(String(_formulaData.a[i], DECIMALS_TILT)); + fdArray[i]["g"] = serialized(String(_formulaData.g[i], DECIMALS_SG)); } doc[PARAM_GYRO_READ_COUNT] = this->getGyroReadCount(); // doc[PARAM_GYRO_READ_DELAY] = this->getGyroReadDelay(); doc[PARAM_GYRO_MOVING_THREASHOLD] = this->getGyroSensorMovingThreashold(); - doc[PARAM_FORMULA_DEVIATION] = this->getMaxFormulaCreationDeviation(); + doc[PARAM_FORMULA_DEVIATION] = + serialized(String(this->getMaxFormulaCreationDeviation(), DECIMALS_TILT)); doc[PARAM_FORMULA_CALIBRATION_TEMP] = this->getDefaultCalibrationTemp(); doc[PARAM_PUSH_INTERVAL_POST] = this->getPushIntervalPost(); doc[PARAM_PUSH_INTERVAL_POST2] = this->getPushIntervalPost2(); @@ -205,8 +205,8 @@ void GravmonConfig::migrateSettings() { return; } - DynamicJsonDocument doc(JSON_BUFFER_SIZE_L); - DynamicJsonDocument doc2(JSON_BUFFER_SIZE_L); + JsonDocument doc; + JsonDocument doc2; DeserializationError err = deserializeJson(doc, configFile); configFile.close(); @@ -217,7 +217,7 @@ void GravmonConfig::migrateSettings() { } JsonObject obj = doc.as(); - JsonObject obj2 = doc2.createNestedObject(); + JsonObject obj2 = doc2.as(); serializeJson(obj, EspSerial); EspSerial.print(CR); @@ -230,12 +230,11 @@ void GravmonConfig::migrateSettings() { obj2[PARAM_BLE_TILT_COLOR] = obj["ble"]; - JsonArray fdArray = obj2.createNestedArray(PARAM_FORMULA_DATA); + JsonArray fdArray = obj2[PARAM_FORMULA_DATA].to(); for (int i = 0; i < FORMULA_DATA_SIZE; i++) { - JsonObject fd = fdArray.createNestedObject(); String num(i + 1); - fd["a"] = obj["formula-calculation-data"]["a" + num]; - fd["g"] = obj["formula-calculation-data"]["g" + num]; + fdArray[i]["a"] = obj["formula-calculation-data"]["a" + num]; + fdArray[i]["g"] = obj["formula-calculation-data"]["g" + num]; } obj2[PARAM_HTTP_POST_TARGET] = obj["http-push"]; @@ -284,8 +283,8 @@ void GravmonConfig::migrateHwSettings() { return; } - DynamicJsonDocument doc(JSON_BUFFER_SIZE_L); - DynamicJsonDocument doc2(JSON_BUFFER_SIZE_L); + JsonDocument doc; + JsonDocument doc2; DeserializationError err = deserializeJson(doc, configFile); configFile.close(); @@ -296,7 +295,7 @@ void GravmonConfig::migrateHwSettings() { } JsonObject obj = doc.as(); - JsonObject obj2 = doc2.createNestedObject(); + JsonObject obj2 = doc2.as(); serializeJson(obj, EspSerial); EspSerial.print(CR); diff --git a/src/config.hpp b/src/config.hpp index d2252ae7..2d2cf943 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -50,7 +50,7 @@ struct RawGyroData { }; // Used for holding formulaData (used for calculating formula on device) -#define FORMULA_DATA_SIZE 10 +#define FORMULA_DATA_SIZE 20 struct RawFormulaData { double a[FORMULA_DATA_SIZE]; @@ -109,10 +109,11 @@ class GravmonConfig : public BaseConfig { // Gyro calibration and formula calculation data RawGyroData _gyroCalibration = {0, 0, 0, 0, 0, 0}; - RawFormulaData _formulaData = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; + RawFormulaData _formulaData = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}; - float _maxFormulaCreationDeviation = 3; // SG + float _maxFormulaCreationDeviation = 0.01; // SG float _defaultCalibrationTemp = 20.0; // C int _gyroSensorMovingThreashold = 500; int _tempSensorResolution = 9; // bits diff --git a/src/gyro.cpp b/src/gyro.cpp index bb12b6fc..24229995 100644 --- a/src/gyro.cpp +++ b/src/gyro.cpp @@ -231,14 +231,15 @@ bool GyroSensor::isSensorMoving(RawGyroData &raw) { int x = abs(raw.gx), y = abs(raw.gy), z = abs(raw.gz); int threashold = myConfig.getGyroSensorMovingThreashold(); + _sensorMoving = false; 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; + _sensorMoving = true; } - return false; + return _sensorMoving; } bool GyroSensor::read() { diff --git a/src/gyro.hpp b/src/gyro.hpp index c3eb8730..117aa57c 100644 --- a/src/gyro.hpp +++ b/src/gyro.hpp @@ -52,6 +52,7 @@ class GyroSensor { float _initialSensorTemp = INVALID_TEMPERATURE; RawGyroData _calibrationOffset; RawGyroData _lastGyroData; + bool _sensorMoving = false; void debug(); void applyCalibration(); @@ -66,6 +67,7 @@ class GyroSensor { bool read(); void calibrateSensor(); uint8_t getGyroID(); + bool isSensorMoving() { return _sensorMoving; } const RawGyroData &getLastGyroData() { return _lastGyroData; } float getAngle() { return _angle; } diff --git a/src/history.cpp b/src/history.cpp index 2712dc19..da8f3fd3 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -23,38 +23,54 @@ SOFTWARE. */ #include +#include #include +#include -FloatHistoryLog::FloatHistoryLog(String fName) { +HistoryLog::HistoryLog(String fName) { _fName = fName; File runFile = LittleFS.open(_fName, "r"); if (runFile) { for (int i = 0; i < 10; i++) { - _runTime[i] = runFile.readStringUntil('\n').toFloat(); - if (_runTime[i]) { - _average += _runTime[i]; + String s = runFile.readStringUntil('\n'); + + sscanf(s.c_str(), "%f;%f;%d", &_log[i]._runTime, &_log[i]._gravity, + &_log[i]._sleepTime); + + // Log.notice(F("HIST: Parsed %F, %F, %d (%s)." CR), _log[i]._runTime, + // _log[i]._gravity, _log[i]._sleepTime, s.c_str()); + + if (_log[i]._runTime) { + _average._runTime += _log[i]._runTime; + _average._gravity += _log[i]._gravity; + _average._sleepTime += _log[i]._sleepTime; _count++; } } runFile.close(); - _average = _average / _count; + _average._runTime = _average._runTime / _count; + _average._gravity = _average._gravity / _count; + _average._sleepTime = _average._sleepTime / _count; } } -void FloatHistoryLog::addEntry(float time) { +void HistoryLog::addLog(float runTime, float gravity, int sleepTime) { for (int i = (10 - 1); i > 0; i--) { - _runTime[i] = _runTime[i - 1]; + _log[i] = _log[i - 1]; } - _runTime[0] = time; + _log[0]._runTime = runTime; + _log[0]._gravity = gravity; + _log[0]._sleepTime = sleepTime; save(); } -void FloatHistoryLog::save() { +void HistoryLog::save() { File runFile = LittleFS.open(_fName, "w"); if (runFile) { for (int i = 0; i < 10; i++) { - runFile.println(_runTime[i], 2); + runFile.printf("%.4f;%.5f;%d\n", _log[i]._runTime, _log[i]._gravity, + _log[i]._sleepTime); } runFile.close(); } diff --git a/src/history.hpp b/src/history.hpp index 720523d8..7faf689d 100644 --- a/src/history.hpp +++ b/src/history.hpp @@ -28,18 +28,26 @@ SOFTWARE. constexpr auto RUNTIME_FILENAME = "/runtime.log"; -class FloatHistoryLog { +class HistoryLog { + public: + struct LogEntry { + float _runTime; + float _gravity; + int _sleepTime; + }; + private: String _fName; - float _average = 0; - float _runTime[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + LogEntry _average = {0, 0, 0}; + LogEntry _log[10] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, + {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; int _count = 0; void save(); public: - explicit FloatHistoryLog(String fName); - void addEntry(float time); - float getAverage() { return _average; } + explicit HistoryLog(String fName); + void addLog(float runTime, float gravity, int sleepTime); + const LogEntry& getAverage() { return _average; } }; #endif // SRC_HISTORY_HPP_ diff --git a/src/main.cpp b/src/main.cpp index b50c1c88..18595918 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -78,7 +78,7 @@ uint32_t pushMillis = 0; // Used to control how often we will send push data uint32_t runtimeMillis; // Used to calculate the total time since start/wakeup uint32_t stableGyroMillis; // Used to calculate the total time since last // stable gyro reading - +bool skipRunTimeLog = false; RunMode runMode = RunMode::gravityMode; void checkSleepMode(float angle, float volt); @@ -218,7 +218,7 @@ void setup() { } else { // We cant use LED on ESP32C3 since that pin is connected to GYRO ledOn(LedColor::RED); // Red or fast flashing to indicate connection - // error + // error } interval = 1000; // Change interval from 200ms to 1s @@ -273,7 +273,7 @@ bool loopReadGravity() { angle, tempC, gravitySG, corrGravitySG); #endif - bool pushExpired = (abs((int32_t)(millis() - pushMillis)) > + bool pushExpired = (abs(static_cast((millis() - pushMillis))) > (myConfig.getSleepInterval() * 1000)); if (myConfig.isIgnoreLowAnges() && @@ -342,6 +342,16 @@ bool loopReadGravity() { GravmonPush push(&myConfig); push.sendAll(angle, gravitySG, corrGravitySG, tempC, (millis() - runtimeMillis) / 1000); + + // Only log when in gravity mode + if (!skipRunTimeLog && runMode == RunMode::gravityMode) { + Log.notice( + F("Main: Updating history log with, runtime, gravity and " + "interval." CR)); + float runtime = (millis() - runtimeMillis); + HistoryLog runLog(RUNTIME_FILENAME); + runLog.addLog(runtime, gravitySG, myConfig.getSleepInterval()); + } } } PERF_END("loop-push"); @@ -362,7 +372,7 @@ bool loopReadGravity() { // Wrapper for loopGravity that only calls every 200ms so that we dont overload // this. void loopGravityOnInterval() { - if (abs((int32_t)(millis() - loopMillis)) > interval) { + if (abs(static_cast((millis() - loopMillis))) > interval) { loopReadGravity(); loopMillis = millis(); // printHeap("MAIN"); @@ -378,17 +388,10 @@ void loopGravityOnInterval() { } } -bool skipRunTimeLog = false; - void goToSleep(int sleepInterval) { float volt = myBatteryVoltage.getVoltage(); float runtime = (millis() - runtimeMillis); - if (!skipRunTimeLog) { - FloatHistoryLog runLog(RUNTIME_FILENAME); - runLog.addEntry(runtime); - } - Log.notice(F("MAIN: Entering deep sleep for %ds, run time %Fs, " "battery=%FV." CR), sleepInterval, diff --git a/src/pushtarget.cpp b/src/pushtarget.cpp index 84efb6d1..8da23189 100644 --- a/src/pushtarget.cpp +++ b/src/pushtarget.cpp @@ -29,12 +29,12 @@ SOFTWARE. #include #include +#include #include #include #include #include #include - constexpr auto PUSHINT_FILENAME = "/push.dat"; // Use iSpindle format for compatibility, HTTP POST @@ -171,8 +171,7 @@ GravmonPush::GravmonPush(GravmonConfig* gravmonConfig) void GravmonPush::sendAll(float angle, float gravitySG, float corrGravitySG, float tempC, float runTime) { printHeap("PUSH"); - _http.setReuse(true); - _httpSecure.setReuse(true); + _http->setReuse(true); TemplatingEngine engine; setupTemplateEngine(engine, angle, gravitySG, corrGravitySG, tempC, runTime, @@ -185,7 +184,12 @@ void GravmonPush::sendAll(float angle, float gravitySG, float corrGravitySG, PERF_BEGIN("push-http"); String tpl = getTemplate(GravmonPush::TEMPLATE_HTTP1); String doc = engine.create(tpl.c_str()); - sendHttpPost(doc); + + if (myConfig.isHttpPostSSL() && myConfig.isSkipSslOnTest() && + runMode != RunMode::gravityMode) + Log.notice(F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + sendHttpPost(doc); PERF_END("push-http"); } @@ -193,7 +197,12 @@ void GravmonPush::sendAll(float angle, float gravitySG, float corrGravitySG, PERF_BEGIN("push-http2"); String tpl = getTemplate(GravmonPush::TEMPLATE_HTTP2); String doc = engine.create(tpl.c_str()); - sendHttpPost2(doc); + + if (myConfig.isHttpPost2SSL() && myConfig.isSkipSslOnTest() && + runMode != RunMode::gravityMode) + Log.notice(F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + sendHttpPost2(doc); PERF_END("push-http2"); } @@ -201,7 +210,12 @@ void GravmonPush::sendAll(float angle, float gravitySG, float corrGravitySG, PERF_BEGIN("push-http3"); String tpl = getTemplate(GravmonPush::TEMPLATE_HTTP3); String doc = engine.create(tpl.c_str()); - sendHttpGet(doc); + + if (myConfig.isHttpGetSSL() && myConfig.isSkipSslOnTest() && + runMode != RunMode::gravityMode) + Log.notice(F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + sendHttpGet(doc); PERF_END("push-http3"); } @@ -209,7 +223,12 @@ void GravmonPush::sendAll(float angle, float gravitySG, float corrGravitySG, PERF_BEGIN("push-influxdb2"); String tpl = getTemplate(GravmonPush::TEMPLATE_INFLUX); String doc = engine.create(tpl.c_str()); - sendInfluxDb2(doc); + + if (myConfig.isHttpInfluxDb2SSL() && myConfig.isSkipSslOnTest() && + runMode != RunMode::gravityMode) + Log.notice(F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + sendInfluxDb2(doc); PERF_END("push-influxdb2"); } @@ -217,11 +236,15 @@ void GravmonPush::sendAll(float angle, float gravitySG, float corrGravitySG, PERF_BEGIN("push-mqtt"); String tpl = getTemplate(GravmonPush::TEMPLATE_MQTT); String doc = engine.create(tpl.c_str()); - sendMqtt(doc); + + if (myConfig.isMqttSSL() && myConfig.isSkipSslOnTest() && + runMode != RunMode::gravityMode) + Log.notice(F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + sendMqtt(doc); PERF_END("push-mqtt"); } - engine.freeMemory(); intDelay.save(); } diff --git a/src/resources.hpp b/src/resources.hpp index 212fb2e9..1fc971e4 100644 --- a/src/resources.hpp +++ b/src/resources.hpp @@ -77,6 +77,7 @@ constexpr auto PARAM_PUSH_RETURN_CODE = "push_return_code"; constexpr auto PARAM_PUSH_ENABLED = "push_enabled"; constexpr auto PARAM_SELF = "self_check"; constexpr auto PARAM_SELF_GYRO_CONNECTED = "gyro_connected"; +constexpr auto PARAM_SELF_GYRO_MOVING = "gyro_moving"; constexpr auto PARAM_SELF_GYRO_CALIBRATION = "gyro_calibration"; constexpr auto PARAM_SELF_TEMP_CONNECTED = "temp_connected"; constexpr auto PARAM_SELF_GRAVITY_FORMULA = "gravity_formula"; diff --git a/src/webserver.cpp b/src/webserver.cpp index 6de6683e..1c438748 100644 --- a/src/webserver.cpp +++ b/src/webserver.cpp @@ -54,8 +54,7 @@ void GravmonWebServer::webHandleConfigRead(AsyncWebServerRequest *request) { PERF_BEGIN("webserver-api-config-read"); Log.notice(F("WEB : webServer callback for /api/config(read)." CR)); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_L); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); myConfig.createJson(obj); response->setLength(); @@ -77,8 +76,7 @@ void GravmonWebServer::webHandleConfigWrite(AsyncWebServerRequest *request, myConfig.saveFile(); myBatteryVoltage.read(); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); obj = response->getRoot().as(); obj[PARAM_SUCCESS] = true; obj[PARAM_MESSAGE] = "Configuration updated"; @@ -95,8 +93,7 @@ void GravmonWebServer::webHandleCalibrate(AsyncWebServerRequest *request) { PERF_BEGIN("webserver-api-calibrate"); Log.notice(F("WEB : webServer callback for /api/calibrate." CR)); _sensorCalibrationTask = true; - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); obj[PARAM_SUCCESS] = true; obj[PARAM_MESSAGE] = "Scheduled device calibration"; @@ -113,8 +110,7 @@ void GravmonWebServer::webHandleCalibrateStatus( PERF_BEGIN("webserver-api-calibrate-status"); Log.notice(F("WEB : webServer callback for /api/calibrate/status." CR)); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); obj[PARAM_STATUS] = static_cast(_sensorCalibrationTask); obj[PARAM_SUCCESS] = false; @@ -152,8 +148,7 @@ void GravmonWebServer::webHandleFactoryDefaults( LittleFS.end(); Log.notice(F("WEB : Deleted files in filesystem, rebooting." CR)); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); obj[PARAM_SUCCESS] = true; obj[PARAM_MESSAGE] = "Factory reset completed, rebooting"; @@ -177,8 +172,7 @@ void GravmonWebServer::webHandleStatus(AsyncWebServerRequest *request) { ESP_RESET(); } - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_L); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); double angle = 0; // Indicate we have no valid gyro value @@ -214,11 +208,7 @@ void GravmonWebServer::webHandleStatus(AsyncWebServerRequest *request) { obj[PARAM_HARDWARE] = "ispindel"; #endif - if (myGyro.isConnected()) { - obj[PARAM_ANGLE] = serialized(String(angle, DECIMALS_TILT)); - } else { - obj[PARAM_ANGLE] = -1; // Indicate that there is no connection to gyro - } + obj[PARAM_ANGLE] = serialized(String(angle, DECIMALS_TILT)); if (myConfig.isGravityTempAdj()) { gravity = gravityTemperatureCorrectionC( @@ -257,25 +247,24 @@ void GravmonWebServer::webHandleStatus(AsyncWebServerRequest *request) { obj[PARAM_WIFI_SETUP] = (runMode == RunMode::wifiSetupMode) ? true : false; obj[PARAM_GRAVITYMON1_CONFIG] = LittleFS.exists("/gravitymon.json"); - FloatHistoryLog runLog(RUNTIME_FILENAME); - obj[PARAM_RUNTIME_AVERAGE] = serialized(String( - runLog.getAverage() ? runLog.getAverage() / 1000 : 0, DECIMALS_RUNTIME)); + obj[PARAM_RUNTIME_AVERAGE] = serialized( + String(_averageRunTime ? _averageRunTime / 1000 : 0, DECIMALS_RUNTIME)); - JsonObject self = obj.createNestedObject(PARAM_SELF); float v = myBatteryVoltage.getVoltage(); #if defined(ESP32LITE) - self[PARAM_SELF_BATTERY_LEVEL] = true; // No hardware support for these - self[PARAM_SELF_TEMP_CONNECTED] = true; + obj[PARAM_SELF][PARAM_SELF_BATTERY_LEVEL] = true; // No hardware support for these + obj[PARAM_SELF][PARAM_SELF_TEMP_CONNECTED] = true; #else - self[PARAM_SELF_BATTERY_LEVEL] = v < 3.2 || v > 5.1 ? false : true; - self[PARAM_SELF_TEMP_CONNECTED] = myTempSensor.isSensorAttached(); + obj[PARAM_SELF][PARAM_SELF_BATTERY_LEVEL] = v < 3.2 || v > 5.1 ? false : true; + obj[PARAM_SELF][PARAM_SELF_TEMP_CONNECTED] = myTempSensor.isSensorAttached(); #endif - self[PARAM_SELF_GRAVITY_FORMULA] = + obj[PARAM_SELF][PARAM_SELF_GRAVITY_FORMULA] = strlen(myConfig.getGravityFormula()) > 0 ? true : false; - self[PARAM_SELF_GYRO_CALIBRATION] = myConfig.hasGyroCalibration(); - self[PARAM_SELF_GYRO_CONNECTED] = myGyro.isConnected(); - self[PARAM_SELF_PUSH_TARGET] = + obj[PARAM_SELF][PARAM_SELF_GYRO_CALIBRATION] = myConfig.hasGyroCalibration(); + obj[PARAM_SELF][PARAM_SELF_GYRO_CONNECTED] = myGyro.isConnected(); + obj[PARAM_SELF][PARAM_SELF_GYRO_MOVING] = myGyro.isSensorMoving(); + obj[PARAM_SELF][PARAM_SELF_PUSH_TARGET] = myConfig.isBleActive() || myConfig.hasTargetHttpPost() || myConfig.hasTargetHttpPost() || myConfig.hasTargetHttpGet() || myConfig.hasTargetMqtt() || myConfig.hasTargetInfluxDb2() @@ -298,8 +287,7 @@ void GravmonWebServer::webHandleSleepmode(AsyncWebServerRequest *request, JsonObject obj = json.as(); sleepModeAlwaysSkip = obj[PARAM_SLEEP_MODE].as(); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); obj = response->getRoot().as(); obj[PARAM_SLEEP_MODE] = sleepModeAlwaysSkip; response->setLength(); @@ -307,78 +295,6 @@ void GravmonWebServer::webHandleSleepmode(AsyncWebServerRequest *request, PERF_END("webserver-api-sleepmode"); } -void GravmonWebServer::webHandleFormulaCreate(AsyncWebServerRequest *request) { - if (!isAuthenticated(request)) { - return; - } - - PERF_BEGIN("webserver-api-formula-create"); - Log.notice(F("WEB : webServer callback for /api/formula." CR)); - - int e, createErr; - char buf[100]; - RawFormulaData fd = myConfig.getFormulaData(); - - e = createFormula(fd, &buf[0], sizeof(buf), 2); - - if (e) { - // If we fail with order=2 try with 3 - Log.warning(F("WEB : Failed to find formula with order 3." CR), e); - e = createFormula(fd, &buf[0], sizeof(buf), 3); - } - - if (e) { - // If we fail with order=3 try with 4 - Log.warning(F("WEB : Failed to find formula with order 4." CR), e); - e = createFormula(fd, &buf[0], sizeof(buf), 4); - } - - if (e) { - // If we fail with order=4 then we mark it as failed - Log.error( - F("WEB : Unable to find formula based on provided values err=%d." CR), - e); - createErr = e; - } else { - // Save the formula as succesful - Log.info(F("WEB : Found valid formula: '%s'" CR), &buf[0]); - myConfig.setGravityFormula(buf); - myConfig.saveFile(); - createErr = 0; - } - - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); - JsonObject obj = response->getRoot().as(); - - obj[PARAM_SUCCESS] = createErr ? false : true; - obj[PARAM_GRAVITY_FORMULA] = ""; - obj[PARAM_MESSAGE] = ""; - - switch (createErr) { - case ERR_FORMULA_INTERNAL: - obj[PARAM_MESSAGE] = "Internal error creating formula."; - break; - case ERR_FORMULA_NOTENOUGHVALUES: - obj[PARAM_MESSAGE] = - "Not enough values to create formula, need at least 3 angles."; - break; - case ERR_FORMULA_UNABLETOFFIND: - obj[PARAM_MESSAGE] = - "Unable to find an accurate formula based on input, check error log " - "and graph below."; - break; - default: - obj[PARAM_GRAVITY_FORMULA] = myConfig.getGravityFormula(); - obj[PARAM_MESSAGE] = "New formula created based on the entered values."; - break; - } - - response->setLength(); - request->send(response); - PERF_END("webserver-api-formula-create"); -} - void GravmonWebServer::webHandleConfigFormatWrite( AsyncWebServerRequest *request, JsonVariant &json) { if (!isAuthenticated(request)) { @@ -408,8 +324,7 @@ void GravmonWebServer::webHandleConfigFormatWrite( success += writeFile(TPL_FNAME_MQTT, obj[PARAM_FORMAT_MQTT]) ? 1 : 0; } - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); obj = response->getRoot().as(); obj[PARAM_SUCCESS] = success > 0 ? true : false; obj[PARAM_MESSAGE] = success > 0 ? "Format template stored" @@ -433,8 +348,7 @@ void GravmonWebServer::webHandleTestPush(AsyncWebServerRequest *request, _pushTestEnabled = false; _pushTestLastSuccess = false; _pushTestLastCode = 0; - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); obj = response->getRoot().as(); obj[PARAM_SUCCESS] = true; obj[PARAM_MESSAGE] = "Scheduled test for " + _pushTestTarget; @@ -446,8 +360,7 @@ void GravmonWebServer::webHandleTestPush(AsyncWebServerRequest *request, void GravmonWebServer::webHandleTestPushStatus(AsyncWebServerRequest *request) { PERF_BEGIN("webserver-api-test-push-status"); Log.notice(F("WEB : webServer callback for /api/test/push/status." CR)); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); String s; @@ -501,8 +414,7 @@ void GravmonWebServer::webHandleHardwareScan(AsyncWebServerRequest *request) { Log.notice(F("WEB : webServer callback for /api/hardware." CR)); _hardwareScanTask = true; _hardwareScanData = ""; - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_S); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); obj[PARAM_SUCCESS] = true; obj[PARAM_MESSAGE] = "Scheduled hardware scanning"; @@ -519,8 +431,7 @@ void GravmonWebServer::webHandleHardwareScanStatus( Log.notice(F("WEB : webServer callback for /api/hardware/status." CR)); if (_hardwareScanTask || !_hardwareScanData.length()) { - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_L); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); obj[PARAM_STATUS] = static_cast(_hardwareScanTask); obj[PARAM_SUCCESS] = false; @@ -555,8 +466,7 @@ void GravmonWebServer::webHandleConfigFormatRead( PERF_BEGIN("webserver-api-config-format-read"); Log.notice(F("WEB : webServer callback for /api/config/format(read)." CR)); - AsyncJsonResponse *response = - new AsyncJsonResponse(false, JSON_BUFFER_SIZE_XL); + AsyncJsonResponse *response = new AsyncJsonResponse(false); JsonObject obj = response->getRoot().as(); String s; @@ -587,6 +497,9 @@ bool GravmonWebServer::setupWebServer() { BaseWebServer::setupWebServer(); MDNS.addService("gravitymon", "tcp", 80); + HistoryLog runLog(RUNTIME_FILENAME); + _averageRunTime = runLog.getAverage()._runTime; + // Static content Log.notice(F("WEB : Setting up handlers for gravmon web server." CR)); @@ -597,27 +510,20 @@ bool GravmonWebServer::setupWebServer() { handler = new AsyncCallbackJsonWebHandler( "/api/format", std::bind(&GravmonWebServer::webHandleConfigFormatWrite, this, - std::placeholders::_1, std::placeholders::_2), - JSON_BUFFER_SIZE_L); + std::placeholders::_1, std::placeholders::_2)); _server->addHandler(handler); handler = new AsyncCallbackJsonWebHandler( "/api/sleepmode", std::bind(&GravmonWebServer::webHandleSleepmode, this, - std::placeholders::_1, std::placeholders::_2), - JSON_BUFFER_SIZE_S); - _server->addHandler(handler); - handler = new AsyncCallbackJsonWebHandler( - "/api/config", - std::bind(&GravmonWebServer::webHandleConfigWrite, this, - std::placeholders::_1, std::placeholders::_2), - JSON_BUFFER_SIZE_L); + std::placeholders::_1, std::placeholders::_2)); _server->addHandler(handler); _server->on("/api/config", HTTP_GET, std::bind(&GravmonWebServer::webHandleConfigRead, this, std::placeholders::_1)); - _server->on("/api/formula", HTTP_GET, - std::bind(&GravmonWebServer::webHandleFormulaCreate, this, - std::placeholders::_1)); + handler = new AsyncCallbackJsonWebHandler( + "/api/config", std::bind(&GravmonWebServer::webHandleConfigWrite, this, + std::placeholders::_1, std::placeholders::_2)); + _server->addHandler(handler); _server->on("/api/calibrate/status", HTTP_GET, std::bind(&GravmonWebServer::webHandleCalibrateStatus, this, std::placeholders::_1)); @@ -640,10 +546,8 @@ bool GravmonWebServer::setupWebServer() { std::bind(&GravmonWebServer::webHandleTestPushStatus, this, std::placeholders::_1)); handler = new AsyncCallbackJsonWebHandler( - "/api/push", - std::bind(&GravmonWebServer::webHandleTestPush, this, - std::placeholders::_1, std::placeholders::_2), - JSON_BUFFER_SIZE_S); + "/api/push", std::bind(&GravmonWebServer::webHandleTestPush, this, + std::placeholders::_1, std::placeholders::_2)); _server->addHandler(handler); Log.notice(F("WEB : Web server started." CR)); @@ -676,6 +580,7 @@ void GravmonWebServer::loop() { Log.notice(F("WEB : Running scheduled push test for %s" CR), _pushTestTarget.c_str()); + printHeap("TEST"); TemplatingEngine engine; GravmonPush push(&myConfig); push.setupTemplateEngine(engine, angle, gravitySG, corrGravitySG, tempC, @@ -685,31 +590,52 @@ void GravmonWebServer::loop() { myConfig.hasTargetHttpPost()) { String tpl = push.getTemplate(GravmonPush::TEMPLATE_HTTP1); String doc = engine.create(tpl.c_str()); - push.sendHttpPost(doc); + + if (myConfig.isHttpPostSSL() && myConfig.isSkipSslOnTest()) + Log.notice( + F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + push.sendHttpPost(doc); _pushTestEnabled = true; } else if (!_pushTestTarget.compareTo(PARAM_FORMAT_POST2) && myConfig.hasTargetHttpPost2()) { String tpl = push.getTemplate(GravmonPush::TEMPLATE_HTTP2); String doc = engine.create(tpl.c_str()); - push.sendHttpPost2(doc); + if (myConfig.isHttpPost2SSL() && myConfig.isSkipSslOnTest()) + Log.notice( + F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + push.sendHttpPost2(doc); _pushTestEnabled = true; } else if (!_pushTestTarget.compareTo(PARAM_FORMAT_GET) && myConfig.hasTargetHttpGet()) { String tpl = push.getTemplate(GravmonPush::TEMPLATE_HTTP3); String doc = engine.create(tpl.c_str()); - push.sendHttpGet(doc); + if (myConfig.isHttpGetSSL() && myConfig.isSkipSslOnTest()) + Log.notice( + F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + push.sendHttpGet(doc); _pushTestEnabled = true; } else if (!_pushTestTarget.compareTo(PARAM_FORMAT_INFLUXDB) && myConfig.hasTargetInfluxDb2()) { String tpl = push.getTemplate(GravmonPush::TEMPLATE_INFLUX); String doc = engine.create(tpl.c_str()); - push.sendInfluxDb2(doc); + if (myConfig.isHttpInfluxDb2SSL() && myConfig.isSkipSslOnTest()) + Log.notice( + F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + push.sendInfluxDb2(doc); _pushTestEnabled = true; } else if (!_pushTestTarget.compareTo(PARAM_FORMAT_MQTT) && myConfig.hasTargetMqtt()) { String tpl = push.getTemplate(GravmonPush::TEMPLATE_MQTT); String doc = engine.create(tpl.c_str()); - push.sendMqtt(doc); + if (myConfig.isMqttSSL() && myConfig.isSkipSslOnTest()) + Log.notice( + F("PUSH: SSL enabled, skip run when not in gravity mode." CR)); + else + push.sendMqtt(doc); _pushTestEnabled = true; } @@ -728,19 +654,17 @@ void GravmonWebServer::loop() { } if (_hardwareScanTask) { - DynamicJsonDocument doc(JSON_BUFFER_SIZE_L); - JsonObject obj = doc.createNestedObject(); + JsonDocument doc; + JsonObject obj = doc.to(); obj[PARAM_STATUS] = false; obj[PARAM_SUCCESS] = true; obj[PARAM_MESSAGE] = ""; Log.notice(F("WEB : Scanning hardware." CR)); - // Scan the i2c bus for devices - // Wire.begin(PIN_SDA, PIN_SCL); // Should already have been done in - // gyro.cpp - JsonArray i2c = obj.createNestedArray(PARAM_I2C); + // Scan the i2c bus for devices, initialized in gyro.cpp + JsonArray i2c = obj[PARAM_I2C].to(); - for (int i = 1; i < 127; i++) { + for (int i = 1, j = 0; i < 127; i++) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. @@ -748,59 +672,58 @@ void GravmonWebServer::loop() { int err = Wire.endTransmission(); if (err == 0) { - JsonObject sensor = i2c.createNestedObject(); - sensor[PARAM_ADRESS] = "0x" + String(i, 16); + Log.notice(F("WEB : Found device at 0x%02X." CR), i); + i2c[j][PARAM_ADRESS] = "0x" + String(i, 16); + j++; } } // Scan onewire - JsonArray onew = obj.createNestedArray(PARAM_ONEWIRE); + JsonArray onew = obj[PARAM_ONEWIRE].to(); - for (int i = 0; i < mySensors.getDS18Count(); i++) { + for (int i = 0, j = 0; i < mySensors.getDS18Count(); i++) { DeviceAddress adr; - JsonObject sensor = onew.createNestedObject(); mySensors.getAddress(&adr[0], i); - sensor[PARAM_ADRESS] = String(adr[0], 16) + String(adr[1], 16) + + Log.notice(F("WEB : Found onewire device %d." CR), i); + onew[j][PARAM_ADRESS] = String(adr[0], 16) + String(adr[1], 16) + String(adr[2], 16) + String(adr[3], 16) + String(adr[4], 16) + String(adr[5], 16) + String(adr[6], 16) + String(adr[7], 16); switch (adr[0]) { case DS18S20MODEL: - sensor[PARAM_FAMILY] = "DS18S20"; + onew[j][PARAM_FAMILY] = "DS18S20"; break; case DS18B20MODEL: - sensor[PARAM_FAMILY] = "DS18B20"; + onew[j][PARAM_FAMILY] = "DS18B20"; break; case DS1822MODEL: - sensor[PARAM_FAMILY] = "DS1822"; + onew[j][PARAM_FAMILY] = "DS1822"; break; case DS1825MODEL: - sensor[PARAM_FAMILY] = "DS1825"; + onew[j][PARAM_FAMILY] = "DS1825"; break; case DS28EA00MODEL: - sensor[PARAM_FAMILY] = "DS28EA00"; + onew[j][PARAM_FAMILY] = "DS28EA00"; break; } - sensor[PARAM_RESOLUTION] = mySensors.getResolution(); + onew[j][PARAM_RESOLUTION] = mySensors.getResolution(); + j++; } - // TODO: Test the gyro - JsonObject gyro = obj.createNestedObject(PARAM_GYRO); + // Test the gyro switch (myGyro.getGyroID()) { case 0x34: - gyro[PARAM_FAMILY] = "MPU6050"; + obj[PARAM_GYRO][PARAM_FAMILY] = "MPU6050"; break; case 0x38: - gyro[PARAM_FAMILY] = "MPU6500"; + obj[PARAM_GYRO][PARAM_FAMILY] = "MPU6500"; break; default: - gyro[PARAM_FAMILY] = "0x" + String(myGyro.getGyroID(), 16); + obj[PARAM_GYRO][PARAM_FAMILY] = "0x" + String(myGyro.getGyroID(), 16); break; } - // TODO: Test GPIO - - JsonObject cpu = obj.createNestedObject(PARAM_CHIP); + JsonObject cpu = obj[PARAM_CHIP].to(); #if defined(ESP8266) cpu[PARAM_FAMILY] = "ESP8266"; @@ -811,7 +734,7 @@ void GravmonWebServer::loop() { cpu[PARAM_REVISION] = chip_info.revision; cpu[PARAM_CORES] = chip_info.cores; - JsonArray feature = cpu.createNestedArray(PARAM_FEATURES); + JsonArray feature = cpu[PARAM_FEATURES].to(); if (chip_info.features & CHIP_FEATURE_EMB_FLASH) feature.add("embedded flash"); diff --git a/src/webserver.hpp b/src/webserver.hpp index dc67595a..f18d2b3f 100644 --- a/src/webserver.hpp +++ b/src/webserver.hpp @@ -38,6 +38,8 @@ class GravmonWebServer : public BaseWebServer { int _pushTestLastCode; bool _pushTestLastSuccess, _pushTestEnabled; + float _averageRunTime = 0; + void webHandleStatus(AsyncWebServerRequest *request); void webHandleConfigRead(AsyncWebServerRequest *request); void webHandleConfigWrite(AsyncWebServerRequest *request, JsonVariant &json); @@ -45,7 +47,6 @@ class GravmonWebServer : public BaseWebServer { void webHandleConfigFormatWrite(AsyncWebServerRequest *request, JsonVariant &json); void webHandleSleepmode(AsyncWebServerRequest *request, JsonVariant &json); - void webHandleFormulaCreate(AsyncWebServerRequest *request); void webHandleTestPush(AsyncWebServerRequest *request, JsonVariant &json); void webHandleTestPushStatus(AsyncWebServerRequest *request); void webHandleCalibrate(AsyncWebServerRequest *request); diff --git a/src_docs/source/conf.py b/src_docs/source/conf.py index 3b987b9a..ea79fdeb 100644 --- a/src_docs/source/conf.py +++ b/src_docs/source/conf.py @@ -22,7 +22,7 @@ author = 'Magnus Persson' # The full version, including alpha/beta/rc tags -release = '2.0.0-beta2' +release = '2.1.0' # -- General configuration --------------------------------------------------- @@ -48,7 +48,7 @@ # html_theme = 'furo' html_logo = "images/gravitymon_logo.png" -html_title = "GravityMon v2.0.0" +html_title = "GravityMon v2.1.0" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/src_docs/source/configuration.rst b/src_docs/source/configuration.rst index 4b3de0ff..b6cd9385 100644 --- a/src_docs/source/configuration.rst +++ b/src_docs/source/configuration.rst @@ -246,48 +246,53 @@ Gravity - Formula * **Gravity formula:** - Gravity formula is compatible with standard iSpindle formulas so any existing calculation option can be used. You can also use - the feature to create the formula by supplying the raw data. + Gravity formula is syntax is the same as in the iSpindle, but the formula needs to be in SG since this is the internal format used. When choosing plato + the SG value will be converted and presented as Plato. On this page to create the formula by supplying the raw data. If you use the internal formula + creator then you can enter data in plato and conversion will be handled in the device, the output formula will always be in SG. The gravity formula accepts two parameters, **tilt** for the angle or **temp** for temperature (temperature inserted into the formula will be in celsius). I would recommend to use the formula calculation feature instead since this is much easier. * **Data for gravity calculation:** - Enter your gravity data SG + Angle. You can enter up to 10 datapoints. Order does not matter and values with zero as angle will be ignored. + Enter your gravity data SG + Angle. You can enter up to 20 datapoints. Order does not matter and values with zero as angle will be ignored. * **Max allowed deviation:** This is the maximum deviation on the formula allowed for it to be accepted. Once the formula has been derived it will be validated against the supplied - data and of the deviation on any point is bigger the formula will be rejected. + data and of the deviation on any point is bigger the formula will be rejected. Example for SG can be 0.02 points or 0.5 for Plato. Setting a higher values + will allow you to see more options. -* **Calculate new formula:** +* **Calculate formula:** - When you submit the values the device will try create a formula with increasing level of complexity. It will start - with a order 2 formula and then try 3 and 4. + When you submit the values the device will create formulas for order 1 to 4 and show those that are within the accepted deviation. You can also see + how the formula performs in relation to your datapoints and what the deviation is per angle. The more data points you have the better the graph. - Once the formula has been created it will validate the formula against the supplied angles/gravity and if there is a too - high difference, it will fail. You can adjust the max allowed deviation if you have issues. - Under the Support / Error Log you will also find hints to what problem the formula creator encountered. Here is an example: +.. image:: images/ui-gravity-formula-current.png + :width: 800 + :alt: Gravity Current - `CALC: Validation failed on angle 33.430000, deviation too large 5.86, formula order 4` +Here a graph is shown with your current formula compared with the entered data points. - `CALC: Validation failed on angle 33.430000, deviation too large 3.14, formula order 2` - This means that the angle 33.43 had a deviation of 5.8 SG and since the default threshold is 3, it will fail. You - can also see that it has failed on that point in both a order 2 and 4 formula. +.. image:: images/ui-gravity-formula-formula.png + :width: 800 + :alt: Gravity Formula +Here you can see the generated formulas. A drop down selector is available on the top to make it easy to select the formula you want. -Gravity - Analysis -++++++++++++++++++ +.. image:: images/ui-gravity-formula-table.png + :width: 800 + :alt: Gravity Table + +Table with calculated values per angle that has been used and the deviation from the entered data. -.. image:: images/ui-gravity-analysis.png +.. image:: images/ui-gravity-formula-graph.png :width: 800 - :alt: Gravity Analysis + :alt: Gravity Graph -Here you can see a graph over the entered values and also how that aligns with the current formula. This can allow you to spot any -values that might be invalid. +Here a graph is shown with the created formulas. You can deselect a formula by selecting the color in the legend. Push targets diff --git a/src_docs/source/functionality.rst b/src_docs/source/functionality.rst index 39abfa19..757a4d14 100644 --- a/src_docs/source/functionality.rst +++ b/src_docs/source/functionality.rst @@ -81,8 +81,9 @@ The main features Another big difference is that this software can create the gravity formula in the device, just enter the angle/gravity data that you have collected. You will also see a graph simulating how the formula would work. - Currently the device can handle 10 data points which should be enough to get a accurate formula. At least 3 data points - is needed to get an accurate formula. + Currently the device can handle 20 data points which should be enough to get a accurate formula. + + You can also analyse how the formula compares to your raw data and formulas of different complexities. * **Customize the data format being sent to push targets** diff --git a/src_docs/source/images/ui-gravity-analysis.png b/src_docs/source/images/ui-gravity-analysis.png deleted file mode 100644 index 2e8b733a..00000000 Binary files a/src_docs/source/images/ui-gravity-analysis.png and /dev/null differ diff --git a/src_docs/source/images/ui-gravity-formula-current.png b/src_docs/source/images/ui-gravity-formula-current.png new file mode 100644 index 00000000..8cb7cd22 Binary files /dev/null and b/src_docs/source/images/ui-gravity-formula-current.png differ diff --git a/src_docs/source/images/ui-gravity-formula-formula.png b/src_docs/source/images/ui-gravity-formula-formula.png new file mode 100644 index 00000000..f56a604f Binary files /dev/null and b/src_docs/source/images/ui-gravity-formula-formula.png differ diff --git a/src_docs/source/images/ui-gravity-formula-graph.png b/src_docs/source/images/ui-gravity-formula-graph.png new file mode 100644 index 00000000..197a4eac Binary files /dev/null and b/src_docs/source/images/ui-gravity-formula-graph.png differ diff --git a/src_docs/source/images/ui-gravity-formula-table.png b/src_docs/source/images/ui-gravity-formula-table.png new file mode 100644 index 00000000..8b2ec819 Binary files /dev/null and b/src_docs/source/images/ui-gravity-formula-table.png differ diff --git a/src_docs/source/images/ui-gravity-formula.png b/src_docs/source/images/ui-gravity-formula.png index 6ef71637..7f62fe1f 100644 Binary files a/src_docs/source/images/ui-gravity-formula.png and b/src_docs/source/images/ui-gravity-formula.png differ diff --git a/src_docs/source/index.rst b/src_docs/source/index.rst index f97c825a..d8a4421c 100644 --- a/src_docs/source/index.rst +++ b/src_docs/source/index.rst @@ -93,7 +93,7 @@ the following libraries and without these this would have been much more difficu Json parser/creator used in configuration files and API's -* https://github.com/PaulStoffregen/OneWire +* https://github.com/pstolarz/OneWireNg Communication library used for interacting with temperature sensor. @@ -101,10 +101,6 @@ the following libraries and without these this would have been much more difficu Interaction with the DS18B20 sensor -* https://github.com/Rotario/arduinoCurveFitting - - Create the gravity formula. - * https://github.com/256dpi/arduino-mqtt Library for sending data to mqtt based on lightweight mqtt implementation. diff --git a/src_docs/source/releases.rst b/src_docs/source/releases.rst index 9164611e..b851f08a 100644 --- a/src_docs/source/releases.rst +++ b/src_docs/source/releases.rst @@ -3,10 +3,40 @@ Releases ######## +v2.1.0 +====== + +New features +++++++++++++ +* Updated formula creator. + + * Allow user more choice when it comes to selecting the order and varifying result. + * Will now correctly handle Plato data as input + * Formula will still be created for SG since this is the internal format used by Gravitymon + * Moved formula creation from device code to UI code to allow for more flexible formula creation. + * Removed dependant library and API. + +* Extended formula points from 10 to 20 + +.. note:: + Update the formula deviation (default 3) to a value according to your selected gravity format eg. SG = 0.003 + +* Added warning when mqtt payload exceeds 700 bytes to avoid crashes +* Optimized code to reduce memory usage to allow for larger payloads when pushing data +* Update dependant libraries to latest version (Json 7, AsyncWebServer, EspFwk) + +Bugs fixed +++++++++++ +* UI no shows clearly when gyro is moving and average is not calculated +* Fixed broken link to removing old iSpindle configuration. +* Fixed limitation that lowest plato was 1 (now 0) +* Corrected docs on home assistant auto registration option. +* Skip SSL when in config mode flag now works correctly + v2.0.1 ====== -* Disable LED on esp8266 since it interfear with gyro communication. +* Disable LED on esp8266 since it might collide with gyro communication. v2.0.0 ====== diff --git a/src_docs/source/services.rst b/src_docs/source/services.rst index bd0bece5..f96f49d6 100644 --- a/src_docs/source/services.rst +++ b/src_docs/source/services.rst @@ -231,12 +231,12 @@ template will create two sensors and update the values for them. .. warning:: - The registration will occur when you save the format template. If Home Assistant - is restarted then the device will disappear. The first method is the most persistent one. + The registration will be sent on every push so the downside is that this will consume more time thus reducing battery life. .. warning:: - This will only work on 1.1+ since the the memory allocation on previous versions are not enough to handle this large payload. - Earlier version can handle 2 of the values. + + This method is not recommended for an ESP8266 since the low RAM memory will not be enough and there is a high probability that the device + will crash insted. Testing shows that more than 1000 characters of data will likley crash the device. :: diff --git a/test/tests.cpp b/test/tests.cpp index aedbefa4..0bad4387 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -30,68 +30,23 @@ using aunit::Printer; using aunit::TestRunner; using aunit::Verbosity; -/*extern "C" { - void write_bytes(int fd, char* buf, int n) { - Serial.print(*buf); - } -}*/ - -/* - // Boolean - assertEqual(a, b) - assertNotEqual(a, b) - assertLess(a, b) - assertMore(a, b) - assertLessOrEqual(a, b) - assertMoreOrEqual(a, b) - - // String - assertStringCaseEqual(a, b) - assertStringCaseNotEqual(a, b) - assertNear(a, b, error) - assertNotNear(a, b, error) - checkTestDone(name) - checkTestNotDone(name) - checkTestPass(name) - checkTestNotPass(name) - checkTestFail(name) - checkTestNotFail(name) - checkTestSkip(name) - checkTestNotSkip(name) - checkTestExpire(name) [*] - checkTestNotExpire(name) [*] - assertTestDone(name) - assertTestNotDone(name) - assertTestPass(name) - assertTestNotPass(name) - assertTestFail(name) - assertTestNotFail(name) - assertTestSkip(name) - assertTestNotSkip(name) - assertTestExpire(name) [*] - assertTestNotExpire(name) [*] -*/ - -//SerialDebug mySerial; - void setup() { Serial.begin(115200); Serial.println("Gravitymon - Unit Test Build"); delay(2000); Printer::setPrinter(&Serial); // TestRunner::setVerbosity(Verbosity::kAll); - /* - TestRunner::exclude("calc_*"); - TestRunner::exclude("ble_*"); - TestRunner::exclude("config_*"); - TestRunner::exclude("gyro_*"); - TestRunner::exclude("helper_*"); - TestRunner::exclude("json_*"); - TestRunner::exclude("templating_*"); - TestRunner::exclude("tempsensor_*"); - TestRunner::exclude("webserver_*"); - TestRunner::exclude("wifi_*"); - */ + + // TestRunner::exclude("calc_*"); + // TestRunner::exclude("ble_*"); + // TestRunner::exclude("config_*"); + // TestRunner::exclude("gyro_*"); + // TestRunner::exclude("helper_*"); + // TestRunner::exclude("json_*"); + // TestRunner::exclude("templating_*"); + // TestRunner::exclude("tempsensor_*"); + // TestRunner::exclude("webserver_*"); + // TestRunner::exclude("wifi_*"); } void loop() { diff --git a/test/tests_calc.cpp b/test/tests_calc.cpp index 1c9c2fe2..fcd9df8c 100644 --- a/test/tests_calc.cpp +++ b/test/tests_calc.cpp @@ -26,80 +26,6 @@ SOFTWARE. #include #include -// TODO: Add more test cases to explore formula creation error conditions when -// values are out of bounds -// TODO: Add more test cases to check order 3 + 4 formula creation as well. - -test(calc_createFormula1) { - char buffer[100]; - RawFormulaData fd = { - {0.0, 25.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {0.0, 1.0, 1.02, 1.033, 1.00011, 1.0, 1.0, 1.0, 1.0, 1.0}}; - int i = createFormula(fd, &buffer[0], sizeof(buffer), 2); - assertEqual(i, ERR_FORMULA_NOTENOUGHVALUES); -} - -test(calc_createFormula2) { - char buffer[100]; - RawFormulaData fd = { - {25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0}, - {1.0, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.1}}; - int i = createFormula(fd, &buffer[0], sizeof(buffer), 2); - assertEqual(i, 0); - assertEqual(&buffer[0], "0.00000909*tilt^2+0.00124545*tilt+0.96445455"); -} - -test(calc_createFormula3) { - char buffer[100]; - RawFormulaData fd = { - {25.0, 30.0, 35.0, 45.0, 55.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {1.0, 1.1, 1.2, 1.3, 1.4, 0.0, 0.0, 0.0, 0.0, 0.0}}; - float f = myConfig.getMaxFormulaCreationDeviation(); - myConfig.setMaxFormulaCreationDeviation(10); // Change threashold to pass - int i = createFormula(fd, &buffer[0], sizeof(buffer), 3); - myConfig.setMaxFormulaCreationDeviation(f); // Restore to default for next test - assertEqual(i, 0); - assertEqual(&buffer[0], "0.00001140*tilt^3+-0.00161278*tilt^2+0.08512845*tilt+-0.30122180"); -} - -test(calc_createFormula4) { - char buffer[100]; - RawFormulaData fd = { - {25.0, 30.0, 35.0, 45.0, 55.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {1.0, 1.1, 1.2, 1.3, 1.4, 1.0, 1.0, 1.0, 1.0, 1.0}}; - int i = createFormula(fd, &buffer[0], sizeof(buffer), 4); - assertEqual(i, 0); - assertEqual(&buffer[0], "0.00000200*tilt^4+-0.00030333*tilt^3+0.01645000*tilt^2+-0.36241667*tilt+3.73750001"); -} - -test(calc_createFormula5) { - char buffer[100]; - RawFormulaData fd = { - {25.0, 30.0, 35.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {1.0, 1.1, 1.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; - int i = createFormula(fd, &buffer[0], sizeof(buffer), 1); - assertEqual(i, 0); - assertEqual(&buffer[0], "0.02000000*tilt+0.50000000"); -} - -test(calc_createFormula6) { - char buffer[100]; - RawFormulaData fd = { - {25.0, 30.0, 35.0, 45.0, 55.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {1.0, 1.1, 1.2, 1.3, 1.4, 0.0, 0.0, 0.0, 0.0, 0.0}}; - int i = createFormula(fd, &buffer[0], sizeof(buffer), 3); - assertEqual(i, -3); -} - -/*test(calc_createFormula7) { // TODO: Find data that will cause INTERNAL_ERROR in the fitCurve library... - char buffer[100]; - RawFormulaData fd = { - {25.0, 30.0, 35.0, 45.0, 55.0, 0.0, 0.0, 0.0, 0.0, 0.0}, - {1.0, 1.1, 1.2, 1.3, 1.4, 0.0, 0.0, 0.0, 0.0, 0.0}}; - int i = createFormula(fd, &buffer[0], sizeof(buffer), 3); - assertEqual(i, -1); -}*/ - test(calc_calculateGravity1) { const char* formula = "0.00000909*tilt^2+0.00124545*tilt+0.96445455"; double g = calculateGravity(30, 20, formula); diff --git a/test/tests_helper.cpp b/test/tests_helper.cpp index 258b5c75..dad2970d 100644 --- a/test/tests_helper.cpp +++ b/test/tests_helper.cpp @@ -123,13 +123,13 @@ test(helper_writeErrorLog) { // Include for code coverage assertEqual(1,1); } -test(helper_floatHistory) { +test(helper_history) { LittleFS.begin(); - FloatHistoryLog hist("/history.log"); - hist.addEntry(1.0); - hist.addEntry(1.0); - float f = hist.getAverage(); + HistoryLog hist("/history.log"); + hist.addLog(1.0, 2.0, 300); + hist.addLog(1.0, 2.1, 600); + float f = hist.getAverage()._runTime; assertEqual(f, 1.0); } diff --git a/test/tests_json.cpp b/test/tests_json.cpp index c37d3558..2009f761 100644 --- a/test/tests_json.cpp +++ b/test/tests_json.cpp @@ -27,7 +27,7 @@ SOFTWARE. test(json_FormattingString) { String out; - DynamicJsonDocument doc(500); + JsonDocument doc; doc["key-string"] = "string-1"; serializeJson(doc, out); @@ -37,7 +37,7 @@ test(json_FormattingString) { test(json_FormattingString2) { String in = "{\"key-string\":\"string-1\"}"; - DynamicJsonDocument doc(500); + JsonDocument doc; deserializeJson(doc, in); String val = doc["key-string"]; @@ -46,7 +46,7 @@ test(json_FormattingString2) { test(json_FormattingFloat) { String out; - DynamicJsonDocument doc(500); + JsonDocument doc; doc["key-float"] = 1.1234; serializeJson(doc, out); @@ -56,7 +56,7 @@ test(json_FormattingFloat) { test(json_FormattingFloat2) { String in = "{\"key-float\":1.1234}"; - DynamicJsonDocument doc(500); + JsonDocument doc; deserializeJson(doc, in); float val = doc["key-float"]; diff --git a/test/tests_templating.cpp b/test/tests_templating.cpp index 4cb70a1a..5be785c7 100644 --- a/test/tests_templating.cpp +++ b/test/tests_templating.cpp @@ -45,8 +45,8 @@ test(template_applyTemplate1) { String s = e.create(t.c_str()); String id = myConfig.getID(); String rssi = String(WiFi.RSSI()); - String v = "{\"name\" : \"gravitymon\", \"ID\": \"" + id + - "\", \"token\" : \"\", \"interval\": 900, \"temperature\": 21.20, " + String v = "{\"name\": \"gravitymon\", \"ID\": \"" + id + + "\", \"token\": \"\", \"interval\": 900, \"temperature\": 21.20, " "\"temp_units\": \"C\", \"gravity\": 1.1230, \"angle\": 45.000, " "\"battery\": 3.88" ", \"RSSI\": " + rssi + ", \"corr-gravity\": 1.2230, \"gravity-unit\": " @@ -64,8 +64,8 @@ test(template_applyTemplate2) { String s = e.create(t.c_str()); String id = myConfig.getID(); String rssi = String(WiFi.RSSI()); - String v = "{\"name\" : \"gravitymon\", \"ID\": \"" + id + - "\", \"token\" : \"\", \"interval\": 900, \"temperature\": 21.20, " + String v = "{\"name\": \"gravitymon\", \"ID\": \"" + id + + "\", \"token\": \"\", \"interval\": 900, \"temperature\": 21.20, " "\"temp_units\": \"C\", \"gravity\": 1.1230, \"angle\": 45.000, " "\"battery\": 3.88" ", \"RSSI\": " + rssi + ", \"corr-gravity\": 1.2230, \"gravity-unit\": "