Refactored to free up heap for SSL

This commit is contained in:
Magnus Persson 2022-02-02 13:23:16 +01:00
parent 9bea54b703
commit 545f274a47
12 changed files with 237 additions and 205 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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,14 +241,14 @@ 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);
#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;
}

View File

@ -37,9 +37,16 @@ SOFTWARE.
#include <wifi.hpp>
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

View File

@ -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; }
};
@ -185,7 +188,6 @@ extern PerfLogging myPerfLogging;
// Global instance created
extern SerialDebug mySerial;
extern ErrorFileLog myLastErrors;
extern BatteryVoltage myBatteryVoltage;
#endif // SRC_HELPER_HPP_

View File

@ -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:

View File

@ -32,40 +32,14 @@ SOFTWARE.
#include <pushtarget.hpp>
#include <wifi.hpp>
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=" +
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=" +
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,14 +191,30 @@ void PushTarget::sendHttp(TemplatingEngine& engine, int index) {
doc = engine.create(TemplatingEngine::TEMPLATE_HTTP2);
}
if (serverPath.startsWith("https://")) {
myWifi.getWifiClientSecure().setInsecure();
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
if (isSecure) {
Log.notice(F("PUSH: HTTP, SSL enabled without validation." CR));
http.begin(myWifi.getWifiClientSecure(), serverPath);
wifiSecure.setInsecure();
httpSecure.begin(wifiSecure, serverPath);
if (index == 0) {
addHttpHeader(httpSecure, myConfig.getHttpHeader(0));
addHttpHeader(httpSecure, myConfig.getHttpHeader(1));
} else {
http.begin(myWifi.getWifiClient(), serverPath);
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));
@ -233,32 +223,33 @@ void PushTarget::sendHttp(TemplatingEngine& engine, int index) {
addHttpHeader(http, myConfig.getHttp2Header(1));
}
#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);
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)"));
}
if (isSecure) {
httpSecure.end();
wifiSecure.stop();
} else {
http.end();
myWifi.closeWifiClient();
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,7 +300,8 @@ 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 +
ErrorFileLog errLog;
errLog.addEntry("PUSH: MQTT push on " + topic +
" failed error=" + String(mqtt.lastError()));
}
@ -319,7 +310,12 @@ void PushTarget::sendMqtt(TemplatingEngine& engine) {
}
mqtt.disconnect();
myWifi.closeWifiClient();
if (isSecure) {
wifiSecure.stop();
} else {
wifi.stop();
}
tcp_cleanup();
}
// EOF

View File

@ -28,30 +28,29 @@ SOFTWARE.
#if defined(ESP8266)
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#else // defined (ESP32)
#include <HTTPClient.h>
#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

View File

@ -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,7 +389,8 @@ 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());
@ -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.");
}

View File

@ -23,11 +23,14 @@ SOFTWARE.
*/
#if defined(ESP8266)
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>
#include <ESP8266httpUpdate.h>
#else // defined (ESP32)
#include <HTTPClient.h>
#include <HTTPUpdate.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#endif
#include <incbin.h>
@ -192,7 +195,8 @@ 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 " +
ErrorFileLog errLog;
errLog.addEntry("WIFI: Failed to connect to wifi " +
String(WiFi.status()));
WiFi.disconnect();
Serial.print(CR);
@ -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 " +
case HTTP_UPDATE_FAILED: {
ErrorFileLog errLog;
errLog.addEntry("WIFI: OTA update failed " +
String(ESPhttpUpdate.getLastError()));
break;
} 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 " +
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;
}

View File

@ -24,28 +24,14 @@ SOFTWARE.
#ifndef SRC_WIFI_HPP_
#define SRC_WIFI_HPP_
#if defined (ESP8266)
#include <ESP8266WiFi.h>
#else // defined (ESP32)
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#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();