Added support for .gz compressed SPIFFS files.

Using wrapper for millis() via library --wrap option, returns xTaskGetTicksCount() instead of the very dubious int64_t/1000 of default millis(), especially when it gets BIG.
This commit is contained in:
Ray Jones 2019-07-15 19:56:36 +10:00
parent 1f28bb7d5d
commit 16ee16f97f
16 changed files with 319 additions and 53 deletions

View file

@ -119,7 +119,7 @@
const int FirmwareRevision = 23;
const int FirmwareSubRevision = 6;
const char* FirmwareDate = "3 Jul 2019";
const char* FirmwareDate = "15 Jul 2019";
#ifdef ESP32
@ -197,6 +197,7 @@ unsigned long moderator;
bool bUpdateDisplay = false;
bool bHaveWebClient = false;
bool bBTconnected = false;
long BootTime;
hw_timer_t *watchdogTimer = NULL;
@ -269,6 +270,35 @@ void interruptReboot()
esp_restart();
}
//**************************************************************************************************
//** **
//** WORKAROUND for crap ESP32 millis() standard function **
//** **
//**************************************************************************************************
//
// Substitute shitfull ESP32 millis() with a true and proper ms counter
// The standard millis() on ESP32 is actually micros()/1000.
// This wraps every 71.5 minutes in a **very non linear fashion**.
//
// The FreeRTOS Tick Counter however does increment each ms, and rolls naturally past 0 every 49days.
// With this proper linear behaviour you can use valid timeout calcualtions even through wrap around.
// This elegance breaks using the standard library function, leading to many weird and obtuse issues.
//
// *** IMPORTANT ***
//
// You **MUST** use --wrap millis in the linker command, or -Wl,--wrap,millis in the GCC command.
// platformio.ini file for this project defines the latter as a build_flags entry.
//
// The linker will now link to __wrap_millis() instead of millis() for *any* usage of millis().
// Best of all this includes any library usages of millis() :-D
// If you really must call the shitty ESP32 Arduino millis(), you must call __real_millis()
// from your dubious code ;-) - basically DON'T do this.
extern "C" unsigned long __wrap_millis() {
return xTaskGetTickCount();
}
void setup() {
// ensure cyclic mode is disabled after power on
@ -332,6 +362,7 @@ void setup() {
initMQTTJSONmoderator(); // prevents JSON for MQTT unless requested
initIPJSONmoderator(); // prevents JSON for IP unless requested
initTimerJSONmoderator(); // prevents JSON for timers unless requested
initSysModerator();
KeyPad.begin(keyLeft_pin, keyRight_pin, keyCentre_pin, keyUp_pin, keyDown_pin);
@ -344,6 +375,7 @@ void setup() {
const BTCDateTime& now = Clock.get();
if(now.day() != 0xa5)
bNoClock = false;
BootTime = Clock.get().secondstime();
ScreenManager.begin(bNoClock);
@ -452,7 +484,7 @@ void loop()
CommState.is(CommStates::HeaterRx2) ) {
if(RxTimeElapsed >= moderator) {
moderator += 10;
moderator += 10;
if(bReportRecyleEvents) {
DebugPort.printf("%ldms - ", RxTimeElapsed);
}
@ -496,7 +528,7 @@ void loop()
doStreaming(); // do wifi, BT tx etc when NOT in midst of handling blue wire
// this especially avoids E-07 faults due to larger data transfers
moderator = 50;
moderator = 50;
#if RX_LED == 1
digitalWrite(LED_Pin, LOW);
@ -520,7 +552,7 @@ void loop()
}
#if SUPPORT_OEM_CONTROLLER == 1
if(BlueWireData.available() && (RxTimeElapsed > RX_DATA_TIMOUT+10)) {
if(BlueWireData.available() && (RxTimeElapsed > (RX_DATA_TIMOUT+10))) {
if(bReportOEMresync) {
DebugPort.printf("Re-sync'd with OEM Controller. %ldms Idle time.\r\n", RxTimeElapsed);
@ -719,7 +751,7 @@ void loop()
// update temperature reading,
// synchronised with serial reception as interrupts do get disabled in the OneWire library
tDelta = timenow - lastTemperatureTime;
if(tDelta > MIN_TEMPERATURE_INTERVAL) { // maintain a minimum holdoff period
if(tDelta > MIN_TEMPERATURE_INTERVAL) { // maintain a minimum holdoff period
lastTemperatureTime = millis(); // reset time to observe temeprature
if(TempSensor.readTemperature(fTemperature)) {
@ -928,7 +960,7 @@ void checkDisplayUpdate()
{
// only update OLED when not processing blue wire
if(ScreenManager.checkUpdate()) {
lastAnimationTime = millis() + 100;
lastAnimationTime = millis() + 100;
ScreenManager.animate();
ScreenManager.refresh(); // always refresh post major update
}
@ -936,7 +968,7 @@ void checkDisplayUpdate()
long tDelta = millis() - lastAnimationTime;
if(tDelta >= 100) {
lastAnimationTime = millis() + 100;
lastAnimationTime = millis() + 100;
if(ScreenManager.animate())
ScreenManager.refresh();
}
@ -1436,4 +1468,9 @@ void updateFilteredData()
FilteredSamples.GlowVolts.update(HeaterFrame2.getGlowPlug_Voltage());
FilteredSamples.GlowAmps.update(HeaterFrame2.getGlowPlug_Current());
FilteredSamples.Fan.update(HeaterFrame2.getFan_Actual());
}
int sysUptime()
{
return Clock.get().secondstime() - BootTime;
}

View file

@ -21,4 +21,6 @@ upload_flags =
--port=3232
monitor_speed = 115200
extra_scripts = post:add_CRC.py
; replace shitty Arduino millis with a linear time version
build_flags = -Wl,--wrap,millis

View file

@ -119,7 +119,7 @@
const int FirmwareRevision = 23;
const int FirmwareSubRevision = 6;
const char* FirmwareDate = "3 Jul 2019";
const char* FirmwareDate = "15 Jul 2019";
#ifdef ESP32
@ -197,6 +197,7 @@ unsigned long moderator;
bool bUpdateDisplay = false;
bool bHaveWebClient = false;
bool bBTconnected = false;
long BootTime;
hw_timer_t *watchdogTimer = NULL;
@ -269,6 +270,35 @@ void interruptReboot()
esp_restart();
}
//**************************************************************************************************
//** **
//** WORKAROUND for crap ESP32 millis() standard function **
//** **
//**************************************************************************************************
//
// Substitute shitfull ESP32 millis() with a true and proper ms counter
// The standard millis() on ESP32 is actually micros()/1000.
// This wraps every 71.5 minutes in a **very non linear fashion**.
//
// The FreeRTOS Tick Counter however does increment each ms, and rolls naturally past 0 every 49days.
// With this proper linear behaviour you can use valid timeout calcualtions even through wrap around.
// This elegance breaks using the standard library function, leading to many weird and obtuse issues.
//
// *** IMPORTANT ***
//
// You **MUST** use --wrap millis in the linker command, or -Wl,--wrap,millis in the GCC command.
// platformio.ini file for this project defines the latter as a build_flags entry.
//
// The linker will now link to __wrap_millis() instead of millis() for *any* usage of millis().
// Best of all this includes any library usages of millis() :-D
// If you really must call the shitty ESP32 Arduino millis(), you must call __real_millis()
// from your dubious code ;-) - basically DON'T do this.
extern "C" unsigned long __wrap_millis() {
return xTaskGetTickCount();
}
void setup() {
// ensure cyclic mode is disabled after power on
@ -332,6 +362,7 @@ void setup() {
initMQTTJSONmoderator(); // prevents JSON for MQTT unless requested
initIPJSONmoderator(); // prevents JSON for IP unless requested
initTimerJSONmoderator(); // prevents JSON for timers unless requested
initSysModerator();
KeyPad.begin(keyLeft_pin, keyRight_pin, keyCentre_pin, keyUp_pin, keyDown_pin);
@ -344,6 +375,7 @@ void setup() {
const BTCDateTime& now = Clock.get();
if(now.day() != 0xa5)
bNoClock = false;
BootTime = Clock.get().secondstime();
ScreenManager.begin(bNoClock);
@ -452,7 +484,7 @@ void loop()
CommState.is(CommStates::HeaterRx2) ) {
if(RxTimeElapsed >= moderator) {
moderator += 10;
moderator += 10;
if(bReportRecyleEvents) {
DebugPort.printf("%ldms - ", RxTimeElapsed);
}
@ -496,7 +528,7 @@ void loop()
doStreaming(); // do wifi, BT tx etc when NOT in midst of handling blue wire
// this especially avoids E-07 faults due to larger data transfers
moderator = 50;
moderator = 50;
#if RX_LED == 1
digitalWrite(LED_Pin, LOW);
@ -520,7 +552,7 @@ void loop()
}
#if SUPPORT_OEM_CONTROLLER == 1
if(BlueWireData.available() && (RxTimeElapsed > RX_DATA_TIMOUT+10)) {
if(BlueWireData.available() && (RxTimeElapsed > (RX_DATA_TIMOUT+10))) {
if(bReportOEMresync) {
DebugPort.printf("Re-sync'd with OEM Controller. %ldms Idle time.\r\n", RxTimeElapsed);
@ -719,7 +751,7 @@ void loop()
// update temperature reading,
// synchronised with serial reception as interrupts do get disabled in the OneWire library
tDelta = timenow - lastTemperatureTime;
if(tDelta > MIN_TEMPERATURE_INTERVAL) { // maintain a minimum holdoff period
if(tDelta > MIN_TEMPERATURE_INTERVAL) { // maintain a minimum holdoff period
lastTemperatureTime = millis(); // reset time to observe temeprature
if(TempSensor.readTemperature(fTemperature)) {
@ -928,7 +960,7 @@ void checkDisplayUpdate()
{
// only update OLED when not processing blue wire
if(ScreenManager.checkUpdate()) {
lastAnimationTime = millis() + 100;
lastAnimationTime = millis() + 100;
ScreenManager.animate();
ScreenManager.refresh(); // always refresh post major update
}
@ -936,7 +968,7 @@ void checkDisplayUpdate()
long tDelta = millis() - lastAnimationTime;
if(tDelta >= 100) {
lastAnimationTime = millis() + 100;
lastAnimationTime = millis() + 100;
if(ScreenManager.animate())
ScreenManager.refresh();
}
@ -1436,4 +1468,9 @@ void updateFilteredData()
FilteredSamples.GlowVolts.update(HeaterFrame2.getGlowPlug_Voltage());
FilteredSamples.GlowAmps.update(HeaterFrame2.getGlowPlug_Current());
FilteredSamples.Fan.update(HeaterFrame2.getFan_Actual());
}
int sysUptime()
{
return Clock.get().secondstime() - BootTime;
}

View file

@ -23,7 +23,6 @@
#define __BLUETOOTHABSTRACT_H__
#include "../Utility/UtilClasses.h"
//#include "../Utility/DebugPort.h"
#include "../Utility/helpers.h"
class CProtocol;

View file

@ -427,7 +427,7 @@ void WiFiManager::stopWebPortal() {
boolean WiFiManager::configPortalHasTimeout(){
if(_configPortalTimeout == 0 || (_apClientCheck && (WiFi_softap_num_stations() > 0))){
if(millis() - timer > 30000){
if(millis() - timer > 30000){
timer = millis();
DEBUG_WM(DEBUG_VERBOSE,"NUM CLIENTS: " + (String)WiFi_softap_num_stations());
}
@ -443,7 +443,7 @@ boolean WiFiManager::configPortalHasTimeout(){
} else if(_debugLevel > 0) {
// log timeout
if(_debug){
uint16_t logintvl = 30000; // how often to emit timeing out counter logging
uint32_t logintvl = 30000; // how often to emit timing out counter logging
if((millis() - timer) > logintvl){
timer = millis();
DEBUG_WM(DEBUG_VERBOSE,F("Portal Timeout In"),(String)((_configPortalStart + _configPortalTimeout-millis())/1000) + (String)F(" seconds"));
@ -861,7 +861,7 @@ uint8_t WiFiManager::waitForConnectResult(uint16_t timeout) {
DEBUG_WM(DEBUG_VERBOSE,timeout,F("ms timeout, waiting for connect..."));
uint8_t status = WiFi.status();
while(millis() < timeoutmillis) {
while((millis() - timeoutmillis) < 0) {
status = WiFi.status();
// @todo detect additional states, connect happens, then dhcp then get ip, there is some delay here, make sure not to timeout if waiting on IP
if (status == WL_CONNECTED || status == WL_CONNECT_FAILED) {

View file

@ -81,7 +81,7 @@
#endif
#define WEBSOCKETS_TCP_TIMEOUT (2000)
#define WEBSOCKETS_TCP_TIMEOUT (2000)
#define NETWORK_ESP8266_ASYNC (0)
#define NETWORK_ESP8266 (1)

View file

@ -54,7 +54,7 @@ void esp32FOTA::execOTA()
unsigned long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 5000)
if (millis() - timeout > 5000)
{
Serial.println("Client Timeout !");
client.stop();

View file

@ -520,14 +520,14 @@ CScreenManager::keyHandler(uint8_t event)
if(event & keyReleased) {
_dim(false);
_DimTime_ms = (millis() + abs(dimTime)) | 1;
_MenuTimeout = millis() + NVstore.getUserSettings().menuTimeout;
_MenuTimeout = (millis() + NVstore.getUserSettings().menuTimeout) | 1;
}
return; // initial press when dimmed is always thrown away
}
// _dim(false);
_DimTime_ms = (millis() + abs(dimTime)) | 1;
_MenuTimeout = millis() + NVstore.getUserSettings().menuTimeout;
_MenuTimeout = (millis() + NVstore.getUserSettings().menuTimeout) | 1;
// call key handler for active screen
if(_menu >= 0)

View file

@ -200,7 +200,6 @@ CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster)
break;
}
}
// m_TxFrame.setThermostatMode(NVstore.getThermostatMode());
m_TxFrame.Controller.OperatingVoltage = NVstore.getHeaterTuning().sysVoltage;
m_TxFrame.Controller.FanSensor = NVstore.getHeaterTuning().fanSensor;

View file

@ -23,9 +23,9 @@
class CTxManage
{
const int m_nStartDelay = 20;
const int m_nFrameTime = 14;
const int m_nFrontPorch = 2;
const int m_nStartDelay = 20;
const int m_nFrameTime = 14;
const int m_nFrontPorch = 2;
public:
CTxManage(int TxGatePin, HardwareSerial& serial);

View file

@ -22,6 +22,7 @@
#include "BTC_JSON.h"
#include "DebugPort.h"
#include "NVStorage.h"
#include "../RTC/Clock.h"
#include "../RTC/BTCDateTime.h"
#include "../RTC/Timers.h"
#include "../RTC/TimerManager.h"
@ -39,9 +40,17 @@ int timerConflict = 0;
CModerator MQTTmoderator;
CModerator IPmoderator;
CModerator GPIOmoderator;
CModerator SysModerator;
void validateTimer(int ID);
void Expand(std::string& str);
bool makeJSONString(CModerator& moderator, char* opStr, int len);
bool makeJSONStringEx(CModerator& moderator, char* opStr, int len);
bool makeJSONTimerString(int channel, char* opStr, int len);
bool makeJSONStringGPIO( CModerator& moderator, char* opStr, int len);
bool makeJSONStringSysInfo(CModerator& moderator, char* opStr, int len);
bool makeJSONStringMQTT(CModerator& moderator, char* opStr, int len);
bool makeJSONStringIP(CModerator& moderator, char* opStr, int len);
void interpretJsonCommand(char* pLine)
{
@ -183,6 +192,10 @@ void interpretJsonCommand(char* pLine)
else if(strcmp("IQuery", it->key) == 0) {
IPmoderator.reset(); // force IP params to be sent
}
// system info
else if(strcmp("SQuery", it->key) == 0) {
SysModerator.reset(); // force MQTT params to be sent
}
// MQTT parameters
else if(strcmp("MQuery", it->key) == 0) {
MQTTmoderator.reset(); // force MQTT params to be sent
@ -399,6 +412,34 @@ bool makeJSONStringMQTT(CModerator& moderator, char* opStr, int len)
return bSend;
}
bool makeJSONStringSysInfo(CModerator& moderator, char* opStr, int len)
{
StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack
JsonObject& root = jsonBuffer.createObject(); // create object to add JSON commands to
bool bSend = false; // reset should send flag
const BTCDateTime& now = Clock.get();
char str[32];
sprintf(str, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
bSend |= moderator.addJson("Time", str, root);
sprintf(str, "%d %s %d", now.day(), now.monthStr(), now.year());
bSend |= moderator.addJson("Date", str, root);
bSend |= moderator.addJson("UpTime", sysUptime(), root);
bSend |= moderator.addJson("SysVer", getVersionStr(), root);
bSend |= moderator.addJson("SysDate", getVersionDate(), root);
bSend |= moderator.addJson("SysFreeMem", ESP.getFreeHeap(), root);
// bSend |= moderator.addJson("TickCount", millis(), root); // ms!
if(bSend) {
root.printTo(opStr, len);
}
return bSend;
}
bool makeJSONStringIP(CModerator& moderator, char* opStr, int len)
{
StaticJsonBuffer<800> jsonBuffer; // create a JSON buffer on the stack
@ -501,7 +542,7 @@ void updateJSONclients(bool report)
}
}
// report MQTT params
// report IP params
{
if(makeJSONStringIP(IPmoderator, jsonStr, sizeof(jsonStr))) {
if (report) {
@ -514,6 +555,19 @@ void updateJSONclients(bool report)
}
}
// report System info
{
if(makeJSONStringSysInfo(SysModerator, jsonStr, sizeof(jsonStr))) {
if (report) {
DebugPort.printf("JSON send: %s\r\n", jsonStr);
}
sendWebSocketString( jsonStr );
std::string expand = jsonStr;
Expand(expand);
getBluetoothClient().send( expand.c_str() );
}
}
{
if(makeJSONStringGPIO(GPIOmoderator, jsonStr, sizeof(jsonStr))) {
if (report) {
@ -539,6 +593,7 @@ void resetJSONmoderator()
#endif
initMQTTJSONmoderator();
initIPJSONmoderator();
initSysModerator();
GPIOmoderator.reset();
}
@ -554,6 +609,12 @@ void initIPJSONmoderator()
makeJSONStringIP(IPmoderator, jsonStr, sizeof(jsonStr));
}
void initSysModerator()
{
char jsonStr[800];
makeJSONStringSysInfo(SysModerator, jsonStr, sizeof(jsonStr));
}
void initTimerJSONmoderator()
{
char jsonStr[800];

View file

@ -27,16 +27,11 @@
extern char defaultJSONstr[64];
bool makeJSONString(CModerator& moderator, char* opStr, int len);
bool makeJSONStringEx(CModerator& moderator, char* opStr, int len);
bool makeJSONTimerString(int channel, char* opStr, int len);
bool makeJSONStringGPIO( CModerator& moderator, char* opStr, int len);
void updateJSONclients(bool report);
bool makeJSONStringMQTT(CModerator& moderator, char* opStr, int len);
bool makeJSONStringIP(CModerator& moderator, char* opStr, int len);
void initMQTTJSONmoderator();
void initIPJSONmoderator();
void initTimerJSONmoderator();
void initSysModerator();
template<class T>
const char* createJSON(const char* name, T value)

View file

@ -106,6 +106,7 @@ void TModerator<T>::reset(const char* name)
}
class CModerator {
TModerator<uint32_t> u32Moderator;
TModerator<int> iModerator;
TModerator<float> fModerator;
TModerator<uint8_t> ucModerator;
@ -115,6 +116,12 @@ public:
bool addJson(const char* name, int value, JsonObject& root) {
return iModerator.addJson(name, value, root);
};
bool addJson(const char* name, uint32_t value, JsonObject& root) {
return u32Moderator.addJson(name, value, root);
};
bool addJson(const char* name, unsigned long value, JsonObject& root) {
return u32Moderator.addJson(name, value, root);
};
// float values
bool addJson(const char* name, float value, JsonObject& root) {
return fModerator.addJson(name, value, root);
@ -133,12 +140,14 @@ public:
fModerator.reset();
ucModerator.reset();
szModerator.reset();
u32Moderator.reset();
};
void reset(const char* name) {
iModerator.reset(name);
fModerator.reset(name);
ucModerator.reset(name);
szModerator.reset(name);
u32Moderator.reset(name);
};
};

View file

@ -82,6 +82,7 @@ extern float getBatteryVoltage();
extern float getGlowVolts();
extern float getGlowCurrent();
extern float getFanSpeed();
extern int sysUptime();
extern void ShowOTAScreen(int percent=0, eOTAmodes updateType=eOTAnormal);

View file

@ -46,6 +46,7 @@ extern const char* stdHeader;
extern const char* formatIndex;
extern const char* updateIndex;
extern const char* formatDoneContent;
extern const char* rebootIndex;
File fsUploadFile; // a File object to temporarily store the received file
int SPIFFSupload = 0;
@ -71,11 +72,14 @@ void onErase();
void onFormatSPIFFS();
void onFormatNow();
void onFormatDone();
void onReboot();
void onDoReboot();
void onWMConfig();
void onResetWifi();
void onUploadBegin();
void onUploadCompletion();
void onUploadProgression();
void onRename();
void build404Response(String& content, String file);
void build500Response(String& content, String file);
@ -121,7 +125,12 @@ void initWebServer(void) {
});
server.on("/formatnow", HTTP_POST, onFormatNow); // access via POST is legal, but only if bFormatAccess == true
// NOTE: this serves the default home page, and favicon.ico
server.on("/reboot", HTTP_GET, onReboot); // access via POST is legal, but only if bFormatAccess == true
server.on("/reboot", HTTP_POST, onDoReboot); // access via POST is legal, but only if bFormatAccess == true
server.on("/rename", HTTP_POST, onRename); // access via POST is legal, but only if bFormatAccess == true
// NOTE: this serves the default home page, and favicon.ico
server.onNotFound([]()
{ // If the client requests any URI
if (!handleFileRead(server.uri())) { // send it if it exists
@ -153,6 +162,8 @@ String getContentType(String filename) { // convert the file extension to the MI
else if (filename.endsWith(".js")) return "application/javascript";
else if (filename.endsWith(".ico")) return "image/x-icon";
else if (filename.endsWith(".bin")) return "application/octet-stream";
else if (filename.endsWith(".zip")) return "application/x-zip";
else if (filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
@ -160,7 +171,10 @@ bool handleFileRead(String path) { // send the right file to the client (if it e
DebugPort.println("handleFileRead: " + path);
if (path.endsWith("/")) path += "index.html"; // If a folder is requested, send the index file
String contentType = getContentType(path); // Get the MIME type
if (SPIFFS.exists(path)) { // If the file exists
String pathWithGz = path + ".gz";
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) { // If the file exists as a compressed archive, or normal
if (SPIFFS.exists(pathWithGz)) // If the compressed file exists
path += ".gz";
File file = SPIFFS.open(path, "r"); // Open it
if(!checkFile(file)) { // check it is readable
file.close(); // if not, close the file
@ -200,6 +214,7 @@ button {
background-color: #016ABC;
color: #fff;
border-radius: 25px;
height: 30px;
}
.del {
color: white;
@ -209,7 +224,7 @@ button {
height: 30px;
width: 30px;
}
.fmt {
.redbutton {
color: white;
font-weight: bold;
background-color: red;
@ -226,6 +241,12 @@ th {
}
}
</style>
<script>
function _(el) {
return document.getElementById(el);
}
</script>
)=====";
const char* updateIndex = R"=====(
@ -269,10 +290,6 @@ var ws;
var timeDown;
var timeUp;
function _(el) {
return document.getElementById(el);
}
function onWebSocket(event) {
var response = JSON.parse(event.data);
var key;
@ -352,6 +369,19 @@ function onErase(fn) {
}
}
function onRename(fn) {
var newname = prompt("Enter new file name", fn);
if(newname != null && newname != "") {
var formdata = new FormData();
formdata.append("oldname", fn);
formdata.append("newname", newname);
var ajax = new XMLHttpRequest();
ajax.open("POST", "/rename");
ajax.send(formdata);
setTimeout(function () { location.reload(); }, 500);
}
}
function onBrowseChange() {
_("uploaddiv").hidden = false;
_("upload").hidden = false;
@ -359,7 +389,7 @@ function onBrowseChange() {
_("loaded_n_total").hidden = false;
_("spacer").hidden = false;
var file = _("file1").files[0];
document.getElementById('filename').innerHTML = file.name;
_('filename').innerHTML = file.name;
}
function onformatClick() {
@ -538,6 +568,7 @@ void listSPIFFS(const char * dirname, uint8_t levels, String& HTMLreport, int wi
<th style="width:200px">Name</th>
<th style="width:60px">Size</th>
<th></th>
<th></th>
</tr>
)=====";
File file = root.openNextFile();
@ -548,6 +579,7 @@ void listSPIFFS(const char * dirname, uint8_t levels, String& HTMLreport, int wi
addTableData(HTMLreport, file.name());
addTableData(HTMLreport, "");
addTableData(HTMLreport, "");
addTableData(HTMLreport, "");
sprintf(msg, " DIR : %s", file.name());
DebugPort.println(msg);
@ -558,18 +590,28 @@ void listSPIFFS(const char * dirname, uint8_t levels, String& HTMLreport, int wi
} else {
String fn = file.name();
String ers;
if(withHTMLanchors == 2)
String rename;
if(withHTMLanchors == 2) {
rename = "<button class='rename' onClick=onRename('" + fn + "')>Rename</button>";
ers = "<input class='del' type='button' value='X' onClick=onErase('" + fn + "')>";
}
if(withHTMLanchors) {
String fn2;
if(fn.endsWith(".html") || fn.endsWith(".htm")) {
String fn2(fn);
fn = "<a href=\"" + fn2 + "\">" + fn2 + "</a>";
fn2 = fn;
}
else if(fn.endsWith(".html.gz") || fn.endsWith(".htm.gz")) {
fn2 = fn.substring(0, fn.length()-3);
}
if(fn2.length() != 0) {
fn = "<a href=\"" + fn2 + "\">" + file.name() + "</a>";
}
}
String sz; sz += int(file.size());
addTableData(HTMLreport, "");
addTableData(HTMLreport, fn);
addTableData(HTMLreport, sz);
addTableData(HTMLreport, rename);
addTableData(HTMLreport, ers);
sprintf(msg, " FILE: %s SIZE: %d", fn.c_str(), file.size());
@ -662,7 +704,7 @@ void onUploadBegin()
listSPIFFS("/", 2, SPIFFSinfo, 2);
String content = stdHeader;
content += updateIndex + SPIFFSinfo;
content += "<p><button class='fmt' onclick='onformatClick()'>Format SPIFFS</button>";
content += "<p><button class='redbutton' onclick='onformatClick()'>Format SPIFFS</button>";
content += "</body></html>";
server.send(200, "text/html", content );
#else
@ -741,7 +783,7 @@ void onUploadProgression()
Update.printError(DebugPort);
}
}
DebugPort.setDebugOutput(false);
// DebugPort.setDebugOutput(false);
bUpdateAccessed = false;
} else {
DebugPort.printf("Update Failed Unexpectedly (likely broken connection): status=%d\r\n", upload.status);
@ -826,7 +868,7 @@ function init() {
function onFormat() {
var formdata = new FormData();
if(confirm('Do you really want to reformat the SPIFFS partition ?')) {
document.getElementById('throb').innerHTML = 'FORMATTING - Please wait';
_('throb').innerHTML = 'FORMATTING - Please wait';
formdata.append('confirm', 'yes');
setTimeout(function () { location.reload(); }, 200);
}
@ -844,7 +886,7 @@ function onFormat() {
<body onload="javascript:init()">
<h1>Format SPIFFS partition</h1>
<h3 class='throb' id='throb'>CAUTION! This will erase all web content</h1>
<p><button class='fmt' onClick='onFormat()'>Format</button><br>
<p><button class='redbutton' onClick='onFormat()'>Format</button><br>
<p><a href='/update'><button>Cancel</button></a>
</body>
</html>
@ -868,6 +910,71 @@ void onFormatNow()
}
}
void onReboot()
{
DebugPort.println("WEB: GET /reboot");
String content = stdHeader;
content += rebootIndex;
server.send(200, "text/html", content );
}
void onDoReboot()
{
// HTTP POST handler, do not need to return a web page!
DebugPort.println("WEB: POST /reboot");
String confirm = server.arg("reboot"); // get request argument value by name
if(confirm == "yes") { // confirm user agrees, and we did pass thru /formatspiffs first
DebugPort.println("Rebooting via /reboot");
ESP.restart();
}
}
const char* rebootIndex = R"=====(
<style>
body {
background-color: orangered;
}
</style>
<script>
function onReboot() {
if(confirm('Do you really want to reboot the Afterburner ?')) {
setTimeout(function () { location.assign('/'); }, 2000);
var formdata = new FormData();
formdata.append('reboot', 'yes');
var ajax = new XMLHttpRequest();
ajax.open("POST", "/reboot");
ajax.send(formdata);
_('info').hidden = false;
}
else {
location.assign('/');
}
}
</script>
<title>Afterburner Reboot</title>
</head>
<body>
<h1>Reboot Afterburner</h1>
<p>
<h3 class='throb' id='info' hidden>Rebooting - will re-direct to root index</h3>
<button class='redbutton' onClick='onReboot()'>Reboot</button>
&nbsp;&nbsp;&nbsp;&nbsp;<a href='/'><button>Cancel</button></a>
</body>
</html>
)=====";
void onRename()
{
// HTTP POST handler, do not need to return a web page!
DebugPort.println("WEB: POST /reboot");
String oldname = server.arg("oldname"); // get request argument value by name
String newname = server.arg("newname"); // get request argument value by name
if(oldname != "" && newname != "") {
DebugPort.printf("Renaming %s to %s\r\n", oldname.c_str(), newname.c_str());
SPIFFS.rename(oldname.c_str(), newname.c_str());
}
}
/***************************************************************************************
@ -919,7 +1026,7 @@ content += R"=====(" </i></b> exists, but cannot be streamed?
<hr>
<p>Recommended remedy is to re-format the SPIFFS partition, then reload the web content files.
<br>Latest web content can be downloaded from <a href="http://www.mrjones.id.au/afterburner/firmware.html" target="_blank">http://www.mrjones.id.au/afterburner/firmware.html</a> <i>(opens in new page)</i>.
<p>To format the SPIFFS partition, press <button class='fmt' onClick=location.assign('/formatspiffs')>Format SPIFFS</button>
<p>To format the SPIFFS partition, press <button class='redbutton' onClick=location.assign('/formatspiffs')>Format SPIFFS</button>
<p>You will then need to upload each file of the web content by using the subsequent "<b>Upload</b>" button.
<hr>
<h4 class="throb">Please ensure you unzip the web page content, then upload all the files contained.</h4>

View file

@ -47,6 +47,7 @@ int TRIG_PIN; // pin that triggers the configuration portal
unsigned restartServer = 0; // set to time of portal reconfig - will cause reboot a while later
char MACstr[2][20]; // MACstr[0] STA, MACstr[1] = AP
int wifiButtonState = 0;
unsigned long WifiReconnectHoldoff = 0;
extern CScreenManager ScreenManager;
@ -87,8 +88,10 @@ bool initWifi(int initpin,const char *failedssid, const char *failedpassword)
DebugPort.println("Attempting to start STA mode (or config portal) via WifiManager...");
wm.setHostname(failedssid);
wm.setDebugOutput(true);
wm.setConfigPortalTimeout(20);
wm.setConfigPortalBlocking(false);
wm.setWiFiAutoReconnect(true);
wm.setSaveParamsCallback(saveParamsCallback); // ensure our webserver gets awoken when IP config changes to STA
wm.setAPCallback(APstartedCallback);
wm.setEnableConfigPortal(shouldBootIntoConfigPortal());
@ -143,6 +146,26 @@ void doWiFiManager()
{
wm.process();
/* if(WiFi.status() != WL_CONNECTED) {
if(WifiReconnectHoldoff) {
long tDelta = millis() - WifiReconnectHoldoff;
if(tDelta >= 0) {
WifiReconnectHoldoff = 0;
WiFi.disconnect();
WiFi.mode(WIFI_AP_STA);
wifi_config_t conf;
esp_wifi_get_config(WIFI_IF_STA, &conf);
WiFi.begin((char*)conf.sta.ssid, (char*)conf.sta.password);
}
}
else {
WifiReconnectHoldoff = millis() + 10000;
}
}
else {
WifiReconnectHoldoff = 0;
}*/
#if USE_PORTAL_TRIGGER_PIN == 1
// manage handling of pin to enter WiFManager config portal
// we typically use the BOOT pin for this (pins.h)
@ -270,21 +293,17 @@ void APstartedCallback(WiFiManager*)
const char* getWifiAPAddrStr()
{
// noInterrupts();
IPAddress IPaddr = WiFi.softAPIP(); // use stepping stone - function returns an automatic stack var - LAME!
static char APIPaddr[16];
sprintf(APIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]);
// interrupts();
return APIPaddr;
}
const char* getWifiSTAAddrStr()
{
// noInterrupts();
IPAddress IPaddr = WiFi.localIP(); // use stepping stone - function returns an automatic stack var - LAME!
static char STAIPaddr[16];
sprintf(STAIPaddr, "%d.%d.%d.%d", IPaddr[0], IPaddr[1], IPaddr[2], IPaddr[3]);
// interrupts();
return STAIPaddr;
}