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:
parent
1f28bb7d5d
commit
16ee16f97f
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -23,7 +23,6 @@
|
|||
#define __BLUETOOTHABSTRACT_H__
|
||||
|
||||
#include "../Utility/UtilClasses.h"
|
||||
//#include "../Utility/DebugPort.h"
|
||||
#include "../Utility/helpers.h"
|
||||
|
||||
class CProtocol;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -81,7 +81,7 @@
|
|||
#endif
|
||||
|
||||
|
||||
#define WEBSOCKETS_TCP_TIMEOUT (2000)
|
||||
#define WEBSOCKETS_TCP_TIMEOUT (2000)
|
||||
|
||||
#define NETWORK_ESP8266_ASYNC (0)
|
||||
#define NETWORK_ESP8266 (1)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
<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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue