Proper std::string moderator, using mapped value for JSON output. Secure web upload with user/pass
This commit is contained in:
parent
39aba4819f
commit
c1bcc83e8b
|
@ -293,7 +293,7 @@ bool makeJSONStringMQTT(CModerator& moderator, char* opStr, int len)
|
|||
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
|
||||
|
||||
bool bSend = false; // reset should send flag
|
||||
const sMQTTparams& info = NVstore.getMQTTinfo();
|
||||
sMQTTparams info = NVstore.getMQTTinfo();
|
||||
|
||||
bSend |= moderator.addJson("MEn", info.enabled, root);
|
||||
bSend |= moderator.addJson("MPort", info.port, root);
|
||||
|
|
|
@ -98,30 +98,32 @@ CTimerModerator::reset(int timer)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
const char*
|
||||
CStringModerator::shouldSend(const char* name, const char* value)
|
||||
{
|
||||
bool retval = true;
|
||||
std::string sValue = value;
|
||||
auto it = Memory.find(name);
|
||||
if(it != Memory.end()) {
|
||||
retval = it->second != sValue;
|
||||
if(it->second == sValue)
|
||||
return NULL; // unchanged
|
||||
it->second = sValue;
|
||||
return it->second.c_str();
|
||||
}
|
||||
else {
|
||||
Memory[name] = sValue;
|
||||
return (Memory[name] = sValue).c_str();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
CStringModerator::addJson(const char* name, const char* value, JsonObject& root)
|
||||
{
|
||||
bool retval;
|
||||
if( retval = shouldSend(name, value) ) {
|
||||
root.set(name, value);
|
||||
const char* toSend = shouldSend(name, value); // returns pointer to mapped value - persistent!!!!
|
||||
if(toSend) {
|
||||
root.set(name, toSend); // use std::string held in this class's Memory - can trust this is persistent!
|
||||
return true;
|
||||
}
|
||||
return retval;
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -39,10 +39,11 @@ public:
|
|||
void reset(int channel);
|
||||
};
|
||||
|
||||
|
||||
class CStringModerator {
|
||||
std::map<const char*, std::string> Memory;
|
||||
public:
|
||||
bool shouldSend(const char* name, const char* value);
|
||||
const char* shouldSend(const char* name, const char* value);
|
||||
bool addJson(const char* name, const char* value, JsonObject& root);
|
||||
void reset();
|
||||
void reset(const char* name);
|
||||
|
@ -109,30 +110,18 @@ class CModerator {
|
|||
CStringModerator szModerator;
|
||||
public:
|
||||
// integer values
|
||||
bool shouldSend(const char* name, int value) {
|
||||
return iModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, int value, JsonObject& root) {
|
||||
return iModerator.addJson(name, value, root);
|
||||
};
|
||||
// float values
|
||||
bool shouldSend(const char* name, float value) {
|
||||
return fModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, float value, JsonObject& root) {
|
||||
return fModerator.addJson(name, value, root);
|
||||
};
|
||||
// unsigned char values
|
||||
bool shouldSend(const char* name, unsigned char value) {
|
||||
return ucModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, unsigned char value, JsonObject& root) {
|
||||
return ucModerator.addJson(name, value, root);
|
||||
};
|
||||
// const char* values
|
||||
bool shouldSend(const char* name, const char* value) {
|
||||
return szModerator.shouldSend(name, value);
|
||||
};
|
||||
bool addJson(const char* name, const char* value, JsonObject& root) {
|
||||
return szModerator.addJson(name, value, root);
|
||||
};
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include <SPIFFS.h>
|
||||
#endif
|
||||
|
||||
extern void ShowOTAScreen(int percent=0);
|
||||
|
||||
extern WiFiManager wm;
|
||||
|
||||
WebServer server(80);
|
||||
|
@ -41,6 +43,7 @@ WebSocketsServer webSocket = WebSocketsServer(81);
|
|||
|
||||
bool bRxWebData = false; // flags for OLED animation
|
||||
bool bTxWebData = false;
|
||||
bool bUpdateAccessed = false; // flag used to ensure web update always starts via /update. direct accesses to /updatenow will FAIL
|
||||
|
||||
const int led = 13;
|
||||
|
||||
|
@ -138,9 +141,29 @@ void handleBTCNotFound() {
|
|||
}
|
||||
|
||||
const char* serverIndex = "<form method='POST' action='/updatenow' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form>";
|
||||
const char* rootIndex = R"=====(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML Meta Tag</title>
|
||||
<meta http-equiv = "refresh" content = "0; url = /" />
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to root URL</p>
|
||||
</body>
|
||||
</html>
|
||||
)=====";
|
||||
|
||||
void initWebServer(void) {
|
||||
|
||||
Update
|
||||
.onProgress([](unsigned int progress, unsigned int total) {
|
||||
int percent = (progress / (total / 100));
|
||||
DebugPort.printf("Progress: %u%%\r", percent);
|
||||
DebugPort.handle(); // keep telnet spy alive
|
||||
ShowOTAScreen(percent);
|
||||
|
||||
});
|
||||
|
||||
if (MDNS.begin("BTCHeater")) {
|
||||
DebugPort.println("MDNS responder started");
|
||||
|
@ -152,40 +175,66 @@ void initWebServer(void) {
|
|||
server.on("/resetwifi", handleReset);
|
||||
server.on("/formatspiffs", handleFormat);
|
||||
|
||||
server.on("/tst", HTTP_GET, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", rootIndex);
|
||||
});
|
||||
// magical code shaemlessly lifted from Arduino WebUpdate example, slightly modified in paths
|
||||
// this allows pushing new firmware to the ESP via OTA from a WEB BROWSER!
|
||||
// added authentication and a sequencing flag to ensure this is not bypassed
|
||||
//
|
||||
// Initial launch page
|
||||
server.on("/update", HTTP_GET, []() {
|
||||
if (!server.authenticate("ray", "PW")) {
|
||||
return server.requestAuthentication();
|
||||
}
|
||||
bUpdateAccessed = true;
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", serverIndex);
|
||||
});
|
||||
server.on("/updatenow", HTTP_GET, []() { // handle attempts to just browse the /updatenow path - force redirect to root
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", rootIndex);
|
||||
});
|
||||
// actual guts that manages the new firmware upload
|
||||
server.on("/updatenow", HTTP_POST, []() {
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
|
||||
ESP.restart();
|
||||
server.send(200, "text/plain", (Update.hasError()) ? "FAIL - Afterburner will reboot shortly" : "OK - Afterburner will reboot shortly");
|
||||
delay(1000);
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/html", rootIndex); // req browser to redirect to root
|
||||
delay(100);
|
||||
ESP.restart(); // reboot
|
||||
}, []() {
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
DebugPort.setDebugOutput(true);
|
||||
DebugPort.printf("Update: %s\n", upload.filename.c_str());
|
||||
if (!Update.begin()) { //start with max available size
|
||||
Update.printError(DebugPort);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Update.printError(DebugPort);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
if (Update.end(true)) { //true to set the size to the current progress
|
||||
DebugPort.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||
if(bUpdateAccessed) { // only allow progression via /update, directly accessing /updatenow will fail
|
||||
HTTPUpload& upload = server.upload();
|
||||
if (upload.status == UPLOAD_FILE_START) {
|
||||
DebugPort.setDebugOutput(true);
|
||||
DebugPort.printf("Update: %s\n", upload.filename.c_str());
|
||||
if (!Update.begin()) { //start with max available size
|
||||
Update.printError(DebugPort);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_WRITE) {
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
Update.printError(DebugPort);
|
||||
}
|
||||
} else if (upload.status == UPLOAD_FILE_END) {
|
||||
if (Update.end(true)) { //true to set the size to the current progress
|
||||
DebugPort.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
|
||||
} else {
|
||||
Update.printError(DebugPort);
|
||||
}
|
||||
DebugPort.setDebugOutput(false);
|
||||
bUpdateAccessed = false;
|
||||
} else {
|
||||
Update.printError(DebugPort);
|
||||
DebugPort.printf("Update Failed Unexpectedly (likely broken connection): status=%d\n", upload.status);
|
||||
bUpdateAccessed = false;
|
||||
}
|
||||
DebugPort.setDebugOutput(false);
|
||||
} else {
|
||||
DebugPort.printf("Update Failed Unexpectedly (likely broken connection): status=%d\n", upload.status);
|
||||
}
|
||||
else {
|
||||
server.sendHeader("Connection", "close"); // attempt to POST without using /update - force redirect to root
|
||||
server.send(200, "text/html", rootIndex);
|
||||
bUpdateAccessed = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -38,7 +38,8 @@ void hard_restart() {
|
|||
|
||||
void initOTA(){
|
||||
// ArduinoOTA.setHostname("myesp32");
|
||||
ArduinoOTA.setHostname("BTCOTA");
|
||||
ArduinoOTA.setHostname("AfterburnerOTA");
|
||||
// ArduinoOTA.setPassword("TESTO123");
|
||||
|
||||
ArduinoOTA
|
||||
.onStart([]() {
|
||||
|
|
Loading…
Reference in a new issue