From 545f274a47e675f48b5360a36e87110bef6d9f18 Mon Sep 17 00:00:00 2001 From: Magnus Persson Date: Wed, 2 Feb 2022 13:23:16 +0100 Subject: [PATCH] Refactored to free up heap for SSL --- src/calc.cpp | 20 ++++-- src/config.cpp | 22 ++++--- src/config.hpp | 13 ++-- src/gyro.cpp | 13 ++-- src/helper.cpp | 49 ++++++++------ src/helper.hpp | 12 ++-- src/main.cpp | 26 +++++--- src/pushtarget.cpp | 158 ++++++++++++++++++++++----------------------- src/pushtarget.hpp | 17 +++-- src/webserver.cpp | 25 ++++--- src/wifi.cpp | 63 +++++++++++------- src/wifi.hpp | 24 ------- 12 files changed, 237 insertions(+), 205 deletions(-) diff --git a/src/calc.cpp b/src/calc.cpp index 6c965e2..4624cf8 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -49,7 +49,8 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer, #endif if (!noAngles) { - myLastErrors.addEntry(F("CALC: Not enough values for deriving formula")); + ErrorFileLog errLog; + errLog.addEntry(F("CALC: Not enough values for deriving formula")); return ERR_FORMULA_NOTENOUGHVALUES; } else { double coeffs[order + 1]; @@ -103,7 +104,10 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer, } if (!valid) { - myLastErrors.addEntry(F("CALC: Error validating created formula. Deviation to large, formula rejected.")); + ErrorFileLog errLog; + errLog.addEntry( + F("CALC: Error validating created formula. Deviation to large, " + "formula rejected.")); return ERR_FORMULA_UNABLETOFFIND; } @@ -112,7 +116,8 @@ int createFormula(RawFormulaData &fd, char *formulaBuffer, } } - myLastErrors.addEntry(F("CALC: Internal error finding formula.")); + ErrorFileLog errLog; + errLog.addEntry(F("CALC: Internal error finding formula.")); return ERR_FORMULA_INTERNAL; } @@ -157,7 +162,8 @@ double calculateGravity(double angle, double temp, const char *tempFormula) { return g; } - myLastErrors.addEntry("CALC: Failed to parse gravity expression " + String(err)); + ErrorFileLog errLog; + errLog.addEntry("CALC: Failed to parse gravity expression " + String(err)); return 0; } @@ -203,8 +209,10 @@ double gravityTemperatureCorrectionC(double gravity, double tempC, return g; } - myLastErrors.addEntry( - "CALC: Failed to parse expression for gravity temperature correction " + String(err)); + ErrorFileLog errLog; + errLog.addEntry( + "CALC: Failed to parse expression for gravity temperature correction " + + String(err)); return gravity; } diff --git a/src/config.cpp b/src/config.cpp index b192267..b9cda42 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -134,7 +134,8 @@ bool Config::saveFile() { File configFile = LittleFS.open(CFG_FILENAME, "w"); if (!configFile) { - myLastErrors.addEntry(F("CFG : Failed to save configuration.")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Failed to save configuration.")); return false; } @@ -164,14 +165,16 @@ bool Config::loadFile() { #endif if (!LittleFS.exists(CFG_FILENAME)) { - myLastErrors.addEntry(F("CFG : Configuration file does not exist.")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Configuration file does not exist.")); return false; } File configFile = LittleFS.open(CFG_FILENAME, "r"); if (!configFile) { - myLastErrors.addEntry(F("CFG : Failed to load configuration.")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Failed to load configuration.")); return false; } @@ -187,7 +190,8 @@ bool Config::loadFile() { configFile.close(); if (err) { - myLastErrors.addEntry(F("CFG : Failed to parse configuration (json)")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Failed to parse configuration (json)")); return false; } @@ -328,7 +332,8 @@ bool HardwareConfig::saveFile() { File configFile = LittleFS.open(CFG_HW_FILENAME, "w"); if (!configFile) { - myLastErrors.addEntry(F("CFG : Failed to write hardware configuration ")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Failed to write hardware configuration ")); return false; } @@ -371,7 +376,8 @@ bool HardwareConfig::loadFile() { File configFile = LittleFS.open(CFG_HW_FILENAME, "r"); if (!configFile) { - myLastErrors.addEntry(F("CFG : Failed to read hardware configuration ")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Failed to read hardware configuration ")); return false; } @@ -387,8 +393,8 @@ bool HardwareConfig::loadFile() { configFile.close(); if (err) { - myLastErrors.addEntry( - F("CFG : Failed to parse hardware configuration (json)")); + ErrorFileLog errLog; + errLog.addEntry(F("CFG : Failed to parse hardware configuration (json)")); return false; } diff --git a/src/config.hpp b/src/config.hpp index c7e29f7..4a1e789 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -107,9 +107,9 @@ class Config { String _token = ""; String _httpUrl = ""; - String _httpHeader[2] = { "Content-Type: application/json", "" }; + String _httpHeader[2] = {"Content-Type: application/json", ""}; String _http2Url = ""; - String _http2Header[2] = { "Content-Type: application/json", "" }; + String _http2Header[2] = {"Content-Type: application/json", ""}; String _influxDb2Url = ""; String _influxDb2Org = ""; @@ -154,6 +154,7 @@ class Config { _saveNeeded = true; } bool isOtaActive() { return _otaURL.length() ? true : false; } + bool isOtaSSL() { return _otaURL.startsWith("https://"); } const char* getWifiSSID() { return _wifiSSID.c_str(); } void setWifiSSID(String s) { @@ -195,6 +196,7 @@ class Config { _saveNeeded = true; } bool isHttpActive() { return _httpUrl.length() ? true : false; } + bool isHttpSSL() { return _httpUrl.startsWith("https://"); } const char* getHttp2Url() { return _http2Url.c_str(); } void setHttp2Url(String s) { @@ -206,7 +208,8 @@ class Config { _http2Header[idx] = s; _saveNeeded = true; } - bool isHttpActive2() { return _http2Url.length() ? true : false; } + bool isHttp2Active() { return _http2Url.length() ? true : false; } + bool isHttp2SSL() { return _http2Url.startsWith("https://"); } // InfluxDB2 const char* getInfluxDb2PushUrl() { return _influxDb2Url.c_str(); } @@ -232,12 +235,14 @@ class Config { } // MQTT - bool isMqttActive() { return _mqttUrl.length() ? true : false; } const char* getMqttUrl() { return _mqttUrl.c_str(); } void setMqttUrl(String s) { _mqttUrl = s; _saveNeeded = true; } + bool isMqttActive() { return _mqttUrl.length() ? true : false; } + bool isMqttSSL() { return _mqttPort > 8000 ? true : false; } + int getMqttPort() { return _mqttPort; } void setMqttPort(String s) { _mqttPort = s.toInt(); diff --git a/src/gyro.cpp b/src/gyro.cpp index d11f208..a7c238e 100644 --- a/src/gyro.cpp +++ b/src/gyro.cpp @@ -44,7 +44,8 @@ bool GyroSensor::setup() { // compilation difficulties if (!accelgyro.testConnection()) { - myLastErrors.addEntry(F("GYRO: Failed to connect to gyro, is it connected?")); + ErrorFileLog errLog; + errLog.addEntry(F("GYRO: Failed to connect to gyro, is it connected?")); _sensorConnected = false; } else { #if !defined(GYRO_DISABLE_LOGGING) @@ -240,16 +241,16 @@ bool GyroSensor::read() { // If the sensor is unstable we return false to signal we dont have valid // value if (isSensorMoving(_lastGyroData)) { -#if !defined(GYRO_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(GYRO_DISABLE_LOGGING) Log.notice(F("GYRO: Sensor is moving." CR)); #endif _validValue = false; } else { _validValue = true; _angle = calculateAngle(_lastGyroData); -#if !defined(GYRO_DISABLE_LOGGING) +#if LOG_LEVEL == 6 && !defined(GYRO_DISABLE_LOGGING) Log.verbose(F("GYRO: Sensor values %d,%d,%d\t%F" CR), _lastGyroData.ax, - _lastGyroData.ay, _lastGyroData.az, _angle); + _lastGyroData.ay, _lastGyroData.az, _angle); #endif } @@ -286,7 +287,9 @@ void GyroSensor::applyCalibration() { if ((_calibrationOffset.ax + _calibrationOffset.ay + _calibrationOffset.az + _calibrationOffset.gx + _calibrationOffset.gy + _calibrationOffset.gz) == 0) { - myLastErrors.addEntry(F("GYRO: No valid calibration values, please calibrate the device.")); + ErrorFileLog errLog; + errLog.addEntry( + F("GYRO: No valid calibration values, please calibrate the device.")); return; } diff --git a/src/helper.cpp b/src/helper.cpp index 13187fd..e1e0487 100644 --- a/src/helper.cpp +++ b/src/helper.cpp @@ -37,9 +37,16 @@ SOFTWARE. #include SerialDebug mySerial; -ErrorFileLog myLastErrors; BatteryVoltage myBatteryVoltage; +// tcp cleanup, to avoid memory crash. +struct tcp_pcb; +extern struct tcp_pcb* tcp_tw_pcbs; +extern "C" void tcp_abort(struct tcp_pcb* pcb); +void tcp_cleanup() { + while (tcp_tw_pcbs) tcp_abort(tcp_tw_pcbs); +} + // // Convert sg to plato // @@ -61,7 +68,7 @@ float convertCtoF(float c) { return (c * 1.8) + 32.0; } float convertFtoC(float f) { return (f - 32.0) / 1.8; } // -// +// Load error log from disk // ErrorFileLog::ErrorFileLog() { File errFile = LittleFS.open(ERR_FILENAME, "r"); @@ -76,7 +83,7 @@ ErrorFileLog::ErrorFileLog() { } // -// +// Add new entry to top of error log // void ErrorFileLog::addEntry(String err) { for (int i = (ERR_COUNT - 1); i > 0; i--) { @@ -88,7 +95,7 @@ void ErrorFileLog::addEntry(String err) { } // -// +// Save error log // void ErrorFileLog::save() { File errFile = LittleFS.open(ERR_FILENAME, "w"); @@ -101,18 +108,14 @@ void ErrorFileLog::save() { } // -// +// Load history log of floats // FloatHistoryLog::FloatHistoryLog(String fName) { - /*File debug = LittleFS.open(fName, "r"); - String s = debug.readString(); - Serial.println( s.c_str() ); - debug.close();*/ _fName = fName; File runFile = LittleFS.open(_fName, "r"); if (runFile) { - for(int i = 0; i<10; i++) { + for (int i = 0; i < 10; i++) { _runTime[i] = runFile.readStringUntil('\n').toFloat(); if (_runTime[i]) { _average += _runTime[i]; @@ -120,12 +123,12 @@ FloatHistoryLog::FloatHistoryLog(String fName) { } } runFile.close(); - _average = _average/_count; + _average = _average / _count; } } // -// +// Add entry to top of log // void FloatHistoryLog::addEntry(float time) { for (int i = (10 - 1); i > 0; i--) { @@ -136,7 +139,7 @@ void FloatHistoryLog::addEntry(float time) { } // -// +// Save log // void FloatHistoryLog::save() { File runFile = LittleFS.open(_fName, "w"); @@ -151,12 +154,16 @@ void FloatHistoryLog::save() { // // Print the heap information. // -void printHeap() { -#if LOG_LEVEL == 6 && !defined(HELPER_DISABLE_LOGGING) +void printHeap(String prefix) { +#if LOG_LEVEL == 6 || LOG_LEVEL == 5 #if defined(ESP8266) - Log.verbose(F("HELP: Heap %d kb, HeapFrag %d %%, FreeSketch %d kb." CR), - ESP.getFreeHeap() / 1024, ESP.getHeapFragmentation(), - ESP.getFreeSketchSpace() / 1024); + Log.notice( + F("%s: Free-heap %d kb, Heap-rag %d %%, Max-block %d kb Stack=%d b." CR), + prefix.c_str(), ESP.getFreeHeap() / 1024, ESP.getHeapFragmentation(), + ESP.getMaxFreeBlockSize() / 1024, ESP.getFreeContStack()); + // Log.notice(F("%s: Heap %d kb, HeapFrag %d %%, FreeSketch %d kb." CR), + // prefix.c_str(), ESP.getFreeHeap() / 1024, + // ESP.getHeapFragmentation(), ESP.getFreeSketchSpace() / 1024); #else // defined (ESP32) Log.verbose(F("HELP: Heap %d kb, FreeSketch %d kb." CR), ESP.getFreeHeap() / 1024, ESP.getFreeSketchSpace() / 1024); @@ -306,13 +313,14 @@ void PerfLogging::print() { void PerfLogging::pushInflux() { if (!myConfig.isInfluxDb2Active()) return; + WiFiClient wifi; HTTPClient http; String serverPath = String(myConfig.getInfluxDb2PushUrl()) + "/api/v2/write?org=" + String(myConfig.getInfluxDb2PushOrg()) + "&bucket=" + String(myConfig.getInfluxDb2PushBucket()); - http.begin(myWifi.getWifiClient(), serverPath); + http.begin(wifi, serverPath); // Create body for influxdb2, format used // key,host=mdns value=0.0 @@ -375,7 +383,8 @@ void PerfLogging::pushInflux() { } http.end(); - myWifi.closeWifiClient(); + wifi.stop(); + tcp_cleanup(); } #endif // COLLECT_PERFDATA diff --git a/src/helper.hpp b/src/helper.hpp index 6d69f89..d0d5769 100644 --- a/src/helper.hpp +++ b/src/helper.hpp @@ -32,6 +32,9 @@ SOFTWARE. #define RUNTIME_FILENAME "/runtime.log" +// tcp cleanup +void tcp_cleanup(); + // Sleep mode void deepSleep(int t); @@ -55,7 +58,7 @@ float reduceFloatPrecision(float f, int dec = 2); // Logging via serial void printTimestamp(Print* _logOutput, int _logLevel); void printNewline(Print* _logOutput); -void printHeap(); +void printHeap(String prefix = "HELP"); // Classes class SerialDebug { @@ -78,12 +81,12 @@ class FloatHistoryLog { private: String _fName; float _average = 0; - float _runTime[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + float _runTime[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; int _count = 0; void save(); public: - FloatHistoryLog(String fName); + explicit FloatHistoryLog(String fName); void addEntry(float time); float getAverage() { return _average; } }; @@ -167,7 +170,7 @@ extern PerfLogging myPerfLogging; // Use these to collect performance data from various parts of the code #define LOG_PERF_START(s) myPerfLogging.start(s) #define LOG_PERF_STOP(s) myPerfLogging.stop(s) -// #define LOG_PERF_PRINT() myPerfLogging.print() +// #define LOG_PERF_PRINT() myPerfLogging.print() #define LOG_PERF_PRINT() #define LOG_PERF_CLEAR() myPerfLogging.clear() #define LOG_PERF_PUSH() myPerfLogging.pushInflux() @@ -185,7 +188,6 @@ extern PerfLogging myPerfLogging; // Global instance created extern SerialDebug mySerial; -extern ErrorFileLog myLastErrors; extern BatteryVoltage myBatteryVoltage; #endif // SRC_HELPER_HPP_ diff --git a/src/main.cpp b/src/main.cpp index 90da60d..d9a75f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,6 +40,7 @@ int interval = 200; // ms, time to wait between changes to output bool sleepModeAlwaysSkip = false; // Flag set in web interface to override normal behaviour uint32_t loopMillis = 0; // Used for main loop to run the code every _interval_ +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 @@ -173,7 +174,9 @@ void setup() { LOG_PERF_STOP("main-temp-setup"); if (!myGyro.setup()) { - myLastErrors.addEntry(F("MAIN: Failed to initialize the gyro, is it connected?")); + ErrorFileLog errLog; + errLog.addEntry( + F("MAIN: Failed to initialize the gyro, is it connected?")); } else { LOG_PERF_START("main-gyro-read"); myGyro.read(); @@ -207,7 +210,8 @@ void setup() { LOG_PERF_STOP("main-setup"); Log.notice(F("Main: Setup completed." CR)); - stableGyroMillis = millis(); // Dont include time for wifi connection + pushMillis = stableGyroMillis = + millis(); // Dont include time for wifi connection } // @@ -245,10 +249,15 @@ bool loopReadGravity() { #endif LOG_PERF_START("loop-push"); - // Force the transmission if we are going to sleep - myPushTarget.send(angle, gravitySG, corrGravitySG, tempC, - (millis() - runtimeMillis) / 1000, - runMode == RunMode::gravityMode ? true : false); + bool pushExpired = (abs((int32_t)(millis() - pushMillis)) > + (myConfig.getSleepInterval() * 1000)); + + if (pushExpired || runMode == RunMode::gravityMode) { + pushMillis = millis(); + PushTarget push; + push.send(angle, gravitySG, corrGravitySG, tempC, + (millis() - runtimeMillis) / 1000); + } LOG_PERF_STOP("loop-push"); return true; } else { @@ -265,7 +274,7 @@ void loopGravityOnInterval() { if (abs((int32_t)(millis() - loopMillis)) > interval) { loopReadGravity(); loopMillis = millis(); - printHeap(); + // printHeap("MAIN"); LOG_PERF_START("loop-gyro-read"); myGyro.read(); LOG_PERF_STOP("loop-gyro-read"); @@ -310,8 +319,7 @@ void loop() { loopGravityOnInterval(); // If we switched mode, dont include this in the log. - if (runMode!=RunMode::configurationMode) - skipRunTimeLog = true; + if (runMode != RunMode::configurationMode) skipRunTimeLog = true; break; case RunMode::gravityMode: diff --git a/src/pushtarget.cpp b/src/pushtarget.cpp index 1b0c4aa..6370717 100644 --- a/src/pushtarget.cpp +++ b/src/pushtarget.cpp @@ -32,40 +32,14 @@ SOFTWARE. #include #include -PushTarget myPushTarget; - // // Send the data to targets // void PushTarget::send(float angle, float gravitySG, float corrGravitySG, - float tempC, float runTime, bool force) { - uint32_t timePassed = abs((int32_t)(millis() - _ms)); - uint32_t interval = myConfig.getSleepInterval() * 1000; - - if ((timePassed < interval) && !force) { -#if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING) - Log.verbose(F("PUSH: Timer has not expired %l vs %l." CR), timePassed, - interval); -#endif - return; - } - - _ms = millis(); - -#if defined(ESP8266) - if (ESP.getFreeContStack() < 1500) { - if (!_memErrorReported) { - myLastErrors.addEntry("PUSH: Low on memory, skipping push " + - String(ESP.getFreeContStack())); - } else { - Log.error(F("PUSH: Low on memory, skipping push %d" CR), - ESP.getFreeContStack()); - } - _memErrorReported = true; // Dont report this again unti restarted. - myWifi.closeWifiClient(); - return; - } -#endif + float tempC, float runTime) { + printHeap("StartPush"); + http.setReuse(false); + httpSecure.setReuse(false); TemplatingEngine engine; engine.initialize(angle, gravitySG, corrGravitySG, tempC, runTime); @@ -76,15 +50,17 @@ void PushTarget::send(float angle, float gravitySG, float corrGravitySG, LOG_PERF_STOP("push-brewfather"); } + printHeap("http1"); if (myConfig.isHttpActive()) { LOG_PERF_START("push-http"); - sendHttp(engine, 0); + sendHttp(engine, myConfig.isHttpSSL(), 0); LOG_PERF_STOP("push-http"); } - if (myConfig.isHttpActive2()) { + printHeap("http2"); + if (myConfig.isHttp2Active()) { LOG_PERF_START("push-http2"); - sendHttp(engine, 1); + sendHttp(engine, myConfig.isHttp2SSL(), 1); LOG_PERF_STOP("push-http2"); } @@ -96,7 +72,7 @@ void PushTarget::send(float angle, float gravitySG, float corrGravitySG, if (myConfig.isMqttActive()) { LOG_PERF_START("push-mqtt"); - sendMqtt(engine); + sendMqtt(engine, myConfig.isMqttSSL()); LOG_PERF_STOP("push-mqtt"); } @@ -117,15 +93,13 @@ void PushTarget::sendInfluxDb2(TemplatingEngine& engine) { "&bucket=" + String(myConfig.getInfluxDb2PushBucket()); String doc = engine.create(TemplatingEngine::TEMPLATE_INFLUX); - HTTPClient http; - http.begin(myWifi.getWifiClient(), serverPath); + http.begin(wifi, serverPath); #if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING) Log.verbose(F("PUSH: url %s." CR), serverPath.c_str()); Log.verbose(F("PUSH: data %s." CR), doc.c_str()); #endif - // Send HTTP POST request String auth = "Token " + String(myConfig.getInfluxDb2PushToken()); http.addHeader(F("Authorization"), auth.c_str()); int httpResponseCode = http.POST(doc); @@ -134,12 +108,14 @@ void PushTarget::sendInfluxDb2(TemplatingEngine& engine) { Log.notice(F("PUSH: InfluxDB2 push successful, response=%d" CR), httpResponseCode); } else { - myLastErrors.addEntry("PUSH: Influxdb push failed response=" + - String(httpResponseCode)); + ErrorFileLog errLog; + errLog.addEntry("PUSH: Influxdb push failed response=" + + String(httpResponseCode)); } http.end(); - myWifi.closeWifiClient(); + wifi.stop(); + tcp_cleanup(); } // @@ -153,16 +129,13 @@ void PushTarget::sendBrewfather(TemplatingEngine& engine) { String serverPath = myConfig.getBrewfatherPushUrl(); String doc = engine.create(TemplatingEngine::TEMPLATE_BREWFATHER); - // Your Domain name with URL path or IP address with path - HTTPClient http; - http.begin(myWifi.getWifiClient(), serverPath); + http.begin(wifi, serverPath); #if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING) Log.verbose(F("PUSH: url %s." CR), serverPath.c_str()); Log.verbose(F("PUSH: json %s." CR), doc.c_str()); #endif - // Send HTTP POST request http.addHeader(F("Content-Type"), F("application/json")); int httpResponseCode = http.POST(doc); @@ -170,12 +143,14 @@ void PushTarget::sendBrewfather(TemplatingEngine& engine) { Log.notice(F("PUSH: Brewfather push successful, response=%d" CR), httpResponseCode); } else { - myLastErrors.addEntry("PUSH: Brewfather push failed response=" + - String(httpResponseCode)); + ErrorFileLog errLog; + errLog.addEntry("PUSH: Brewfather push failed response=" + + String(httpResponseCode)); } http.end(); - myWifi.closeWifiClient(); + wifi.stop(); + tcp_cleanup(); } // @@ -193,21 +168,20 @@ void PushTarget::addHttpHeader(HTTPClient& http, String header) { value.c_str()); http.addHeader(name, value); } else { - myLastErrors.addEntry("PUSH: Unable to set header, invalid value " + header); + ErrorFileLog errLog; + errLog.addEntry("PUSH: Unable to set header, invalid value " + header); } } // // Send data to http target // -void PushTarget::sendHttp(TemplatingEngine& engine, int index) { +void PushTarget::sendHttp(TemplatingEngine& engine, bool isSecure, int index) { #if !defined(PUSH_DISABLE_LOGGING) Log.notice(F("PUSH: Sending values to http (%s)" CR), index ? "http2" : "http"); #endif - String serverPath, doc; - HTTPClient http; if (index == 0) { serverPath = myConfig.getHttpUrl(); @@ -217,48 +191,65 @@ void PushTarget::sendHttp(TemplatingEngine& engine, int index) { doc = engine.create(TemplatingEngine::TEMPLATE_HTTP2); } - if (serverPath.startsWith("https://")) { - myWifi.getWifiClientSecure().setInsecure(); - Log.notice(F("PUSH: HTTP, SSL enabled without validation." CR)); - http.begin(myWifi.getWifiClientSecure(), serverPath); - } else { - http.begin(myWifi.getWifiClient(), serverPath); - } - - if (index == 0) { - addHttpHeader(http, myConfig.getHttpHeader(0)); - addHttpHeader(http, myConfig.getHttpHeader(1)); - } else { - addHttpHeader(http, myConfig.getHttp2Header(0)); - addHttpHeader(http, myConfig.getHttp2Header(1)); - } + int httpResponseCode; #if LOG_LEVEL == 6 && !defined(PUSH_DISABLE_LOGGING) Log.verbose(F("PUSH: url %s." CR), serverPath.c_str()); Log.verbose(F("PUSH: json %s." CR), doc.c_str()); #endif - // Send HTTP POST request - // http.addHeader(F("Content-Type"), F("application/json")); - int httpResponseCode = http.POST(doc); + if (isSecure) { + Log.notice(F("PUSH: HTTP, SSL enabled without validation." CR)); + wifiSecure.setInsecure(); + httpSecure.begin(wifiSecure, serverPath); + + if (index == 0) { + addHttpHeader(httpSecure, myConfig.getHttpHeader(0)); + addHttpHeader(httpSecure, myConfig.getHttpHeader(1)); + } else { + addHttpHeader(httpSecure, myConfig.getHttp2Header(0)); + addHttpHeader(httpSecure, myConfig.getHttp2Header(1)); + } + + httpResponseCode = httpSecure.POST(doc); + } else { + http.begin(wifi, serverPath); + + if (index == 0) { + addHttpHeader(http, myConfig.getHttpHeader(0)); + addHttpHeader(http, myConfig.getHttpHeader(1)); + } else { + addHttpHeader(http, myConfig.getHttp2Header(0)); + addHttpHeader(http, myConfig.getHttp2Header(1)); + } + + httpResponseCode = http.POST(doc); + } if (httpResponseCode == 200) { Log.notice(F("PUSH: HTTP push successful, response=%d" CR), httpResponseCode); } else { - myLastErrors.addEntry( + ErrorFileLog errLog; + errLog.addEntry( "PUSH: HTTP push failed response=" + String(httpResponseCode) + String(index == 0 ? " (http)" : " (http2)")); } - http.end(); - myWifi.closeWifiClient(); + if (isSecure) { + httpSecure.end(); + wifiSecure.stop(); + } else { + http.end(); + wifi.stop(); + } + tcp_cleanup(); } // // Send data to http target // -void PushTarget::sendMqtt(TemplatingEngine& engine) { +void PushTarget::sendMqtt(TemplatingEngine& engine, bool isSecure) { #if !defined(PUSH_DISABLE_LOGGING) Log.notice(F("PUSH: Sending values to mqtt." CR)); #endif @@ -268,13 +259,12 @@ void PushTarget::sendMqtt(TemplatingEngine& engine) { String doc = engine.create(TemplatingEngine::TEMPLATE_MQTT); int port = myConfig.getMqttPort(); - if (port > 8000) { - // Allow secure channel, but without certificate validation - myWifi.getWifiClientSecure().setInsecure(); + if (myConfig.isMqttSSL()) { Log.notice(F("PUSH: MQTT, SSL enabled without validation." CR)); - mqtt.begin(url.c_str(), port, myWifi.getWifiClientSecure()); + wifiSecure.setInsecure(); + mqtt.begin(url.c_str(), port, wifiSecure); } else { - mqtt.begin(myConfig.getMqttUrl(), port, myWifi.getWifiClient()); + mqtt.begin(myConfig.getMqttUrl(), port, wifi); } mqtt.connect(myConfig.getMDNS(), myConfig.getMqttUser(), @@ -310,8 +300,9 @@ void PushTarget::sendMqtt(TemplatingEngine& engine) { if (mqtt.publish(topic, value)) { Log.notice(F("PUSH: MQTT publish successful on %s" CR), topic.c_str()); } else { - myLastErrors.addEntry("PUSH: MQTT push on " + topic + - " failed error=" + String(mqtt.lastError())); + ErrorFileLog errLog; + errLog.addEntry("PUSH: MQTT push on " + topic + + " failed error=" + String(mqtt.lastError())); } index = next + 1; @@ -319,7 +310,12 @@ void PushTarget::sendMqtt(TemplatingEngine& engine) { } mqtt.disconnect(); - myWifi.closeWifiClient(); + if (isSecure) { + wifiSecure.stop(); + } else { + wifi.stop(); + } + tcp_cleanup(); } // EOF diff --git a/src/pushtarget.hpp b/src/pushtarget.hpp index 5b5f7a9..7a2ef94 100644 --- a/src/pushtarget.hpp +++ b/src/pushtarget.hpp @@ -28,30 +28,29 @@ SOFTWARE. #if defined(ESP8266) #include +#include #else // defined (ESP32) #include #endif class PushTarget { private: - uint32_t _ms; // Used to check that we do not post to often - bool _memErrorReported = - false; // Avoid filling the error log with memory errors. + WiFiClient wifi; + WiFiClientSecure wifiSecure; + HTTPClient http; + HTTPClient httpSecure; void sendBrewfather(TemplatingEngine& engine); - void sendHttp(TemplatingEngine& engine, int index); + void sendHttp(TemplatingEngine& engine, bool isSecure, int index); void sendInfluxDb2(TemplatingEngine& engine); - void sendMqtt(TemplatingEngine& engine); + void sendMqtt(TemplatingEngine& engine, bool isSecure); void addHttpHeader(HTTPClient& http, String header); public: - PushTarget() { _ms = millis(); } void send(float angle, float gravitySG, float corrGravitySG, float tempC, - float runTime, bool force = false); + float runTime); }; -extern PushTarget myPushTarget; - #endif // SRC_PUSHTARGET_HPP_ // EOF diff --git a/src/webserver.cpp b/src/webserver.cpp index 9539244..d872d9e 100644 --- a/src/webserver.cpp +++ b/src/webserver.cpp @@ -52,7 +52,8 @@ void WebServerHandler::webHandleDevice() { doc[PARAM_MDNS] = myConfig.getMDNS(); FloatHistoryLog runLog(RUNTIME_FILENAME); - doc[PARAM_RUNTIME_AVERAGE] = reduceFloatPrecision(runLog.getAverage()?runLog.getAverage()/1000:0, 1); + doc[PARAM_RUNTIME_AVERAGE] = reduceFloatPrecision( + runLog.getAverage() ? runLog.getAverage() / 1000 : 0, 1); #if LOG_LEVEL == 6 serializeJson(doc, Serial); @@ -97,7 +98,8 @@ void WebServerHandler::webHandleConfig() { doc[PARAM_BATTERY] = reduceFloatPrecision(myBatteryVoltage.getVoltage()); FloatHistoryLog runLog(RUNTIME_FILENAME); - doc[PARAM_RUNTIME_AVERAGE] = reduceFloatPrecision(runLog.getAverage()?runLog.getAverage()/1000:0, 1); + doc[PARAM_RUNTIME_AVERAGE] = reduceFloatPrecision( + runLog.getAverage() ? runLog.getAverage() / 1000 : 0, 1); #if LOG_LEVEL == 6 && !defined(WEB_DISABLE_LOGGING) serializeJson(doc, Serial); @@ -211,7 +213,8 @@ void WebServerHandler::webHandleFactoryDefaults() { Log.notice(F("WEB : webServer callback for /api/factory." CR)); if (!id.compareTo(myConfig.getID())) { - _server->send(200, "text/plain", "Removing configuration and restarting..."); + _server->send(200, "text/plain", + "Removing configuration and restarting..."); LittleFS.remove(CFG_FILENAME); LittleFS.remove(CFG_HW_FILENAME); LittleFS.remove(ERR_FILENAME); @@ -386,13 +389,14 @@ void WebServerHandler::webHandleConfigPush() { if (_server->hasArg(PARAM_PUSH_INFLUXDB2)) myConfig.setInfluxDb2PushUrl(_server->arg(PARAM_PUSH_INFLUXDB2).c_str()); if (_server->hasArg(PARAM_PUSH_INFLUXDB2_ORG)) - myConfig.setInfluxDb2PushOrg(_server->arg(PARAM_PUSH_INFLUXDB2_ORG).c_str()); + myConfig.setInfluxDb2PushOrg( + _server->arg(PARAM_PUSH_INFLUXDB2_ORG).c_str()); if (_server->hasArg(PARAM_PUSH_INFLUXDB2_BUCKET)) myConfig.setInfluxDb2PushBucket( - _server->arg(PARAM_PUSH_INFLUXDB2_BUCKET).c_str()); + _server->arg(PARAM_PUSH_INFLUXDB2_BUCKET).c_str()); if (_server->hasArg(PARAM_PUSH_INFLUXDB2_AUTH)) myConfig.setInfluxDb2PushToken( - _server->arg(PARAM_PUSH_INFLUXDB2_AUTH).c_str()); + _server->arg(PARAM_PUSH_INFLUXDB2_AUTH).c_str()); if (_server->hasArg(PARAM_PUSH_MQTT)) myConfig.setMqttUrl(_server->arg(PARAM_PUSH_MQTT).c_str()); if (_server->hasArg(PARAM_PUSH_MQTT_PORT)) @@ -452,8 +456,8 @@ void WebServerHandler::webHandleConfigGravity() { myConfig.setGravityFormula(_server->arg(PARAM_GRAVITY_FORMULA).c_str()); if (_server->hasArg(PARAM_GRAVITY_TEMP_ADJ)) myConfig.setGravityTempAdj( - _server->arg(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"); @@ -493,7 +497,7 @@ void WebServerHandler::webHandleConfigHardware() { myConfig.setOtaURL(_server->arg(PARAM_OTA).c_str()); if (_server->hasArg(PARAM_GYRO_TEMP)) myConfig.setGyroTemp( - _server->arg(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"); @@ -672,7 +676,8 @@ void WebServerHandler::webHandleConfigFormatWrite() { _server->sendHeader("Location", "/format.htm", true); _server->send(302, "text/plain", "Format updated"); } else { - myLastErrors.addEntry(F("WEB : Unable to store format file")); + ErrorFileLog errLog; + errLog.addEntry(F("WEB : Unable to store format file")); _server->send(400, "text/plain", "Unable to store format in file."); } diff --git a/src/wifi.cpp b/src/wifi.cpp index 5805e51..23ddd42 100644 --- a/src/wifi.cpp +++ b/src/wifi.cpp @@ -23,11 +23,14 @@ SOFTWARE. */ #if defined(ESP8266) #include +#include #include #else // defined (ESP32) #include #include #include +#include +#include #endif #include @@ -192,8 +195,9 @@ bool WifiConnection::waitForConnection(int maxTime) { if (i++ > (maxTime * 10)) { // Try for maxTime seconds. Since delay is 100ms. - myLastErrors.addEntry("WIFI: Failed to connect to wifi " + - String(WiFi.status())); + ErrorFileLog errLog; + errLog.addEntry("WIFI: Failed to connect to wifi " + + String(WiFi.status())); WiFi.disconnect(); Serial.print(CR); return false; // Return to main that we have failed to connect. @@ -237,31 +241,36 @@ bool WifiConnection::updateFirmware() { Log.verbose(F("WIFI: Updating firmware." CR)); #endif + WiFiClient wifi; + WiFiClientSecure wifiSecure; + HTTPUpdateResult ret; String serverPath = myConfig.getOtaURL(); serverPath += "firmware.bin"; - HTTPUpdateResult ret; if (serverPath.startsWith("https://")) { - myWifi.getWifiClientSecure().setInsecure(); + wifiSecure.setInsecure(); Log.notice(F("WIFI: OTA, SSL enabled without validation." CR)); - ret = ESPhttpUpdate.update(myWifi.getWifiClientSecure(), serverPath); + ret = ESPhttpUpdate.update(wifiSecure, serverPath); } else { - ret = ESPhttpUpdate.update(myWifi.getWifiClient(), serverPath); + ret = ESPhttpUpdate.update(wifi, serverPath); } switch (ret) { - case HTTP_UPDATE_FAILED: - myLastErrors.addEntry("WIFI: OTA update failed " + - String(ESPhttpUpdate.getLastError())); - break; + case HTTP_UPDATE_FAILED: { + ErrorFileLog errLog; + errLog.addEntry("WIFI: OTA update failed " + + String(ESPhttpUpdate.getLastError())); + } break; case HTTP_UPDATE_NO_UPDATES: break; - case HTTP_UPDATE_OK: + case HTTP_UPDATE_OK: { Log.notice("WIFI: OTA Update sucesfull, rebooting."); delay(100); ESP_RESET(); break; + } } + return false; } @@ -272,16 +281,18 @@ void WifiConnection::downloadFile(const char *fname) { #if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING) Log.verbose(F("WIFI: Download file %s." CR), fname); #endif + WiFiClient wifi; + WiFiClientSecure wifiSecure; HTTPClient http; String serverPath = myConfig.getOtaURL(); serverPath += fname; - if (serverPath.startsWith("https://")) { - myWifi.getWifiClientSecure().setInsecure(); + if (myConfig.isOtaSSL()) { + wifiSecure.setInsecure(); Log.notice(F("WIFI: OTA, SSL enabled without validation." CR)); - http.begin(myWifi.getWifiClientSecure(), serverPath); + http.begin(wifiSecure, serverPath); } else { - http.begin(myWifi.getWifiClient(), serverPath); + http.begin(wifi, serverPath); } int httpResponseCode = http.GET(); @@ -292,11 +303,11 @@ void WifiConnection::downloadFile(const char *fname) { f.close(); Log.notice(F("WIFI: Downloaded file %s." CR), fname); } else { - myLastErrors.addEntry("WIFI: Failed to download html-file " + - String(httpResponseCode)); + ErrorFileLog errLog; + errLog.addEntry("WIFI: Failed to download html-file " + + String(httpResponseCode)); } http.end(); - myWifi.closeWifiClient(); } // @@ -306,17 +317,19 @@ bool WifiConnection::checkFirmwareVersion() { #if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING) Log.verbose(F("WIFI: Checking if new version exist." CR)); #endif + WiFiClient wifi; + WiFiClientSecure wifiSecure; HTTPClient http; String serverPath = myConfig.getOtaURL(); serverPath += "version.json"; // Your Domain name with URL path or IP address with path - if (serverPath.startsWith("https://")) { - myWifi.getWifiClientSecure().setInsecure(); + if (myConfig.isOtaSSL()) { + wifiSecure.setInsecure(); Log.notice(F("WIFI: OTA, SSL enabled without validation." CR)); - http.begin(myWifi.getWifiClientSecure(), serverPath); + http.begin(wifiSecure, serverPath); } else { - http.begin(myWifi.getWifiClient(), serverPath); + http.begin(wifi, serverPath); } // Send HTTP GET request @@ -332,7 +345,8 @@ bool WifiConnection::checkFirmwareVersion() { DynamicJsonDocument ver(300); DeserializationError err = deserializeJson(ver, payload); if (err) { - myLastErrors.addEntry(F("WIFI: Failed to parse version.json")); + ErrorFileLog errLog; + errLog.addEntry(F("WIFI: Failed to parse version.json")); } else { #if LOG_LEVEL == 6 && !defined(WIFI_DISABLE_LOGGING) Log.verbose(F("WIFI: Project %s version %s." CR), @@ -378,11 +392,12 @@ bool WifiConnection::checkFirmwareVersion() { httpResponseCode); } http.end(); - myWifi.closeWifiClient(); + #if LOG_LEVEL == 6 Log.verbose(F("WIFI: OTA found new version %s." CR), _newFirmware ? "true" : "false"); #endif + return _newFirmware; } diff --git a/src/wifi.hpp b/src/wifi.hpp index caaa9cc..f986d75 100644 --- a/src/wifi.hpp +++ b/src/wifi.hpp @@ -24,28 +24,14 @@ SOFTWARE. #ifndef SRC_WIFI_HPP_ #define SRC_WIFI_HPP_ -#if defined (ESP8266) -#include -#else // defined (ESP32) -#include -#include -#endif - #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; -extern "C" void tcp_abort(struct tcp_pcb* pcb); class WifiConnection { private: - // WIFI - WiFiClient _client; - WiFiClientSecure _secureClient; - // OTA bool _newFirmware = false; bool parseFirmwareVersionString(int (&num)[3], const char* version); @@ -67,16 +53,6 @@ class WifiConnection { void startPortal(); void loop(); - WiFiClient& getWifiClient() { return _client; } - WiFiClientSecure& getWifiClientSecure() { return _secureClient; } - void closeWifiClient() { - _client.stop(); - _secureClient.stop(); - - // Cleanup memory allocated by open tcp connetions. - while (tcp_tw_pcbs) tcp_abort(tcp_tw_pcbs); - } - // OTA bool updateFirmware(); bool checkFirmwareVersion();