Added Stop/Start thermostat mode
FuelUsage & FuelRate added as basic MQTT status topics
This commit is contained in:
parent
24d8a4a7f1
commit
775f235ba8
22 changed files with 292 additions and 103 deletions
|
@ -32,6 +32,7 @@ extra_scripts = post:add_CRC.py
|
|||
; replace shitty Arduino millis with a linear time version
|
||||
build_flags =
|
||||
-Wl,--wrap,millis
|
||||
-DHTTPS_LOGLEVEL=2
|
||||
debug_tool = esp-prog
|
||||
;upload_protocol = esp-prog
|
||||
debug_init_break =
|
|
@ -134,7 +134,7 @@
|
|||
const int FirmwareRevision = 32;
|
||||
const int FirmwareSubRevision = 0;
|
||||
const int FirmwareMinorRevision = 6;
|
||||
const char* FirmwareDate = "26 Apr 2020";
|
||||
const char* FirmwareDate = "12 May 2020";
|
||||
|
||||
/*
|
||||
* Macro to check the outputs of TWDT functions and trigger an abort if an
|
||||
|
@ -158,6 +158,7 @@ const char* FirmwareDate = "26 Apr 2020";
|
|||
bool validateFrame(const CProtocol& frame, const char* name);
|
||||
void checkDisplayUpdate();
|
||||
void checkDebugCommands();
|
||||
void manageStopStartMode();
|
||||
void manageCyclicMode();
|
||||
void manageFrostMode();
|
||||
void manageHumidity();
|
||||
|
@ -315,10 +316,10 @@ void checkBlueWireEvents()
|
|||
}
|
||||
|
||||
// trap being in state 0 with a heater error - cancel user on memory to avoid unexpected cyclic restarts
|
||||
if(RTC_Store.getCyclicEngaged() && (BlueWireRxData.getRunState() == 0) && (BlueWireRxData.getErrState() > 1)) {
|
||||
if(RTC_Store.getUserStart() && (BlueWireRxData.getRunState() == 0) && (BlueWireRxData.getErrState() > 1)) {
|
||||
DebugPort.println("Forcing cyclic cancel due to error induced shutdown");
|
||||
// DebugPort.println("Forcing cyclic cancel due to error induced shutdown");
|
||||
RTC_Store.setCyclicEngaged(false);
|
||||
RTC_Store.setUserStart(false);
|
||||
}
|
||||
|
||||
pHourMeter->monitor(BlueWireRxData);
|
||||
|
@ -553,8 +554,7 @@ void setup() {
|
|||
|
||||
RTC_Store.begin();
|
||||
FuelGauge.init(RTC_Store.getFuelGauge());
|
||||
// bCyclicEngaged = RTC_Store.getCyclicEngaged();
|
||||
DebugPort.printf("Previous cyclic active = %d\r\n", RTC_Store.getCyclicEngaged()); // state flag required for cyclic mode to persist properly after a WD reboot :-)
|
||||
DebugPort.printf("Previous user start = %d\r\n", RTC_Store.getUserStart()); // state flag required for cyclic mode to persist properly after a WD reboot :-)
|
||||
|
||||
pHourMeter = new CHourMeter(persistentRunTime, persistentGlowTime); // persistent vars passed by reference so they can be valid after SW reboots
|
||||
pHourMeter->init(bESP32PowerUpInit || RTC_Store.getBootInit()); // ensure persistent memory variable are reset after powerup, or OTA update
|
||||
|
@ -665,6 +665,7 @@ bool checkTemperatureSensors()
|
|||
manageCyclicMode();
|
||||
manageFrostMode();
|
||||
manageHumidity();
|
||||
manageStopStartMode();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -679,10 +680,31 @@ bool checkTemperatureSensors()
|
|||
return false;
|
||||
}
|
||||
|
||||
void manageStopStartMode()
|
||||
{
|
||||
if(NVstore.getUserSettings().ThermostatMethod == 4 && RTC_Store.getUserStart() ) {
|
||||
float deltaT = getTemperatureSensor() - CDemandManager::getDegC();
|
||||
float thresh = NVstore.getUserSettings().ThermostatWindow/2;
|
||||
int heaterState = getHeaterInfo().getRunState(); // native heater state
|
||||
if(deltaT > thresh) {
|
||||
if(heaterState > 0 && heaterState <= 5) {
|
||||
DebugPort.printf("STOP START MODE: Stopping heater, deltaT > +%.1f\r\n", thresh);
|
||||
heaterOff(); // over temp - request heater stop
|
||||
}
|
||||
}
|
||||
if(deltaT < -thresh) {
|
||||
if(heaterState == 0) {
|
||||
DebugPort.printf("STOP START MODE: Restarting heater, deltaT <%.1f\r\n", thresh);
|
||||
heaterOn(); // under temp, start heater again
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void manageCyclicMode()
|
||||
{
|
||||
const sCyclicThermostat& cyclic = NVstore.getUserSettings().cyclic;
|
||||
if(cyclic.Stop && RTC_Store.getCyclicEngaged()) { // cyclic mode enabled, and user has started heater
|
||||
if(cyclic.Stop && RTC_Store.getUserStart()) { // cyclic mode enabled, and user has started heater
|
||||
int stopDeltaT = cyclic.Stop + 1; // bump up by 1 degree - no point invoking at 1 deg over!
|
||||
float deltaT = getTemperatureSensor() - CDemandManager::getDegC();
|
||||
// DebugPort.printf("Cyclic=%d bUserOn=%d deltaT=%d\r\n", cyclic, bUserON, deltaT);
|
||||
|
@ -725,7 +747,7 @@ void manageFrostMode()
|
|||
RTC_Store.setFrostOn(true);
|
||||
DebugPort.printf("FROST MODE: Starting heater, < %d`C\r\n", engage);
|
||||
if(NVstore.getUserSettings().FrostRise == 0)
|
||||
RTC_Store.setCyclicEngaged(true); // enable cyclic mode if user stop
|
||||
RTC_Store.setUserStart(true); // enable cyclic mode if user stop
|
||||
heaterOn();
|
||||
}
|
||||
}
|
||||
|
@ -735,7 +757,7 @@ void manageFrostMode()
|
|||
DebugPort.printf("FROST MODE: Stopping heater, > %d`C\r\n", engage+rise);
|
||||
heaterOff();
|
||||
RTC_Store.setFrostOn(false); // cancel active frost mode
|
||||
RTC_Store.setCyclicEngaged(false); // for cyclic mode
|
||||
RTC_Store.setUserStart(false); // for cyclic mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -768,7 +790,7 @@ requestOn()
|
|||
}
|
||||
bool LVCOK = 2 != SmartError.checkVolts(FilteredSamples.FastipVolts.getValue(), FilteredSamples.FastGlowAmps.getValue());
|
||||
if(hasHtrData() && LVCOK) {
|
||||
RTC_Store.setCyclicEngaged(true); // for cyclic mode
|
||||
RTC_Store.setUserStart(true); // for cyclic mode
|
||||
RTC_Store.setFrostOn(false); // cancel frost mode
|
||||
// only start if below appropriate temperature threshold, raised for cyclic mode
|
||||
// int denied = checkStartTemp();
|
||||
|
@ -795,7 +817,7 @@ void requestOff()
|
|||
{
|
||||
DebugPort.println("Stop Request!");
|
||||
heaterOff();
|
||||
RTC_Store.setCyclicEngaged(false); // for cyclic mode
|
||||
RTC_Store.setUserStart(false); // for cyclic mode
|
||||
RTC_Store.setFrostOn(false); // cancel active frost mode
|
||||
CTimerManager::cancelActiveTimer();
|
||||
}
|
||||
|
@ -1022,9 +1044,9 @@ int getSmartError()
|
|||
return SmartError.getError();
|
||||
}
|
||||
|
||||
bool isCyclicActive()
|
||||
bool isCyclicStopStartActive()
|
||||
{
|
||||
return RTC_Store.getCyclicEngaged() && NVstore.getUserSettings().cyclic.isEnabled();
|
||||
return RTC_Store.getUserStart() && (NVstore.getUserSettings().cyclic.isEnabled() || NVstore.getUserSettings().ThermostatMethod == 4);
|
||||
}
|
||||
|
||||
void setupGPIO()
|
||||
|
|
|
@ -292,6 +292,7 @@ CScreenManager::CScreenManager()
|
|||
_pRebootScreen = NULL;
|
||||
_bDimmed = false;
|
||||
_bReload = true;
|
||||
_OTAholdoff = 0;
|
||||
}
|
||||
|
||||
CScreenManager::~CScreenManager()
|
||||
|
@ -471,9 +472,25 @@ CScreenManager::_loadScreens()
|
|||
showSplash();
|
||||
}
|
||||
|
||||
bool
|
||||
CScreenManager::_checkOTAholdoff()
|
||||
{
|
||||
if(_OTAholdoff) {
|
||||
long tDelta = millis() - _OTAholdoff;
|
||||
if(tDelta < 0)
|
||||
return false;
|
||||
_pDisplay->clearDisplay();
|
||||
_pDisplay->display(); // blank screen
|
||||
_OTAholdoff = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool
|
||||
CScreenManager::checkUpdate()
|
||||
{
|
||||
if(!_checkOTAholdoff())
|
||||
return false;
|
||||
|
||||
if(_bReload)
|
||||
_loadScreens();
|
||||
|
||||
|
@ -585,6 +602,9 @@ CScreenManager::reqUpdate()
|
|||
bool
|
||||
CScreenManager::animate()
|
||||
{
|
||||
if(!_checkOTAholdoff())
|
||||
return false;
|
||||
|
||||
if(_pRebootScreen)
|
||||
return false;
|
||||
|
||||
|
@ -733,6 +753,7 @@ CScreenManager::showOTAMessage(int percent, eOTAmodes updateType)
|
|||
static int prevPercent = -1;
|
||||
|
||||
if(percent != prevPercent) {
|
||||
DebugPort.printf("%d%%\r\n", percent);
|
||||
prevPercent = percent;
|
||||
_pDisplay->clearDisplay();
|
||||
if(percent < 0)
|
||||
|
@ -759,6 +780,7 @@ CScreenManager::showOTAMessage(int percent, eOTAmodes updateType)
|
|||
}
|
||||
_pDisplay->display();
|
||||
}
|
||||
_OTAholdoff = millis() + 1000;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -33,6 +33,7 @@ class CScreenManager {
|
|||
std::vector<std::vector<CScreen*>> _Screens;
|
||||
CRebootScreen* _pRebootScreen;
|
||||
C128x64_OLED* _pDisplay;
|
||||
unsigned long _OTAholdoff;
|
||||
int _menu;
|
||||
int _subMenu;
|
||||
int _rootMenu;
|
||||
|
@ -49,6 +50,7 @@ class CScreenManager {
|
|||
void _dim(bool state);
|
||||
void _loadScreens();
|
||||
void _unloadScreens();
|
||||
bool _checkOTAholdoff();
|
||||
public:
|
||||
enum eUIMenuSets { RootMenuLoop, TimerMenuLoop, UserSettingsLoop, SystemSettingsLoop, TuningMenuLoop, BranchMenu };
|
||||
enum eUIRootMenus { DetailedControlUI, BasicControlUI, ClockUI, ModeUI, GPIOInfoUI, TrunkUI };
|
||||
|
|
|
@ -90,6 +90,7 @@ CThermostatModeScreen::show()
|
|||
case 1: modeStr = "Deadband"; break;
|
||||
case 2: modeStr = "Linear Hz"; break;
|
||||
case 3: modeStr = "Ext thermostat"; break;
|
||||
case 4: modeStr = "Stop Start"; break;
|
||||
}
|
||||
if(modeStr)
|
||||
_printMenuText(Column, Line3, modeStr, _rowSel == 4);
|
||||
|
@ -170,6 +171,9 @@ CThermostatModeScreen::animate()
|
|||
case 3:
|
||||
pMsg = " The heater runs according to GPIO input #2: Open:minimum, Closed:maximum. ";
|
||||
break;
|
||||
case 4:
|
||||
pMsg = " The heater is stopped then started according to the defined window. ";
|
||||
break;
|
||||
}
|
||||
if(pMsg)
|
||||
_scrollMessage(56, pMsg, _scrollChar);
|
||||
|
@ -287,7 +291,6 @@ CThermostatModeScreen::keyHandler(uint8_t event)
|
|||
void
|
||||
CThermostatModeScreen::_adjust(int dir)
|
||||
{
|
||||
int wrap;
|
||||
switch(_rowSel) {
|
||||
case 1:
|
||||
_cyclicMode.Stop += dir;
|
||||
|
@ -304,12 +307,14 @@ CThermostatModeScreen::_adjust(int dir)
|
|||
case 4: // thermostat mode
|
||||
_thermoMode += dir;
|
||||
#if USE_JTAG == 0
|
||||
wrap = GPIOin.usesExternalThermostat() ? 3 : 2;
|
||||
if(_thermoMode == 3 && !GPIOin.usesExternalThermostat())
|
||||
_thermoMode += dir;
|
||||
#else
|
||||
//CANNOT USE GPIO WITH JTAG DEBUG
|
||||
wrap = 2;
|
||||
// CANNOT USE GPIO WITH JTAG DEBUG
|
||||
if(_thermoMode == 3
|
||||
_thermoMode += dir;
|
||||
#endif
|
||||
WRAPLIMITS(_thermoMode, 0, wrap);
|
||||
WRAPLIMITS(_thermoMode, 0, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -328,7 +328,7 @@ CProtocol::setSystemVoltage(float fVal)
|
|||
int CProtocolPackage::getRunStateEx() const
|
||||
{
|
||||
int runstate = getRunState();
|
||||
if(isCyclicActive()) {
|
||||
if(isCyclicStopStartActive()) {
|
||||
// special states for cyclic suspended
|
||||
switch(runstate) {
|
||||
case 0: runstate = 10; break; // standby, awaiting temperature drop
|
||||
|
@ -405,7 +405,7 @@ const char* ErrstatesEx [] PROGMEM = {
|
|||
"E-09: Temp sense", // [10] E-09
|
||||
"E-10: Ignition fail", // [11] E-10 SmartError manufactured state - sensing runstate 2 -> >5
|
||||
"E-11: Failed 1st ignite", // [12] E-11 SmartError manufactured state - sensing runstate 2 -> 3
|
||||
"E-12 Excess fuel shutdown", // [13] E-12 SmartError manufactured state - excess fuel consumed
|
||||
"E-12: Excess fuel shutdown", // [13] E-12 SmartError manufactured state - excess fuel consumed
|
||||
"Unknown error?" // mystery code!
|
||||
};
|
||||
|
||||
|
|
|
@ -290,6 +290,12 @@ CTxManage::PrepareFrame(const CProtocol& basisFrame, bool isBTCmaster)
|
|||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_TxFrame.setThermostatModeProtocol(0); // direct heater to use Hz Mode
|
||||
m_TxFrame.setTemperature_Actual(0); // must force actual to 0 for Hz mode
|
||||
m_TxFrame.setHeaterDemand(m_TxFrame.getTemperature_Max()); // maximum Hz
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ CRTC_Store::CRTC_Store()
|
|||
_fuelgauge = 0;
|
||||
_demandDegC = 22;
|
||||
_demandPump = 22;
|
||||
_CyclicEngaged = false;
|
||||
_userStart = false;
|
||||
_BootInit = true;
|
||||
_RunTime = 0;
|
||||
_GlowTime = 0;
|
||||
|
@ -65,7 +65,7 @@ CRTC_Store::begin()
|
|||
// RTC lost power - reset internal NV values to defaults
|
||||
DebugPort.println("CRTC_Store::begin() RTC lost power, re-initialising NV aspect");
|
||||
_demandPump = _demandDegC = 22;
|
||||
_CyclicEngaged = false;
|
||||
_userStart = false;
|
||||
setFuelGauge(0);
|
||||
setDesiredTemp(_demandDegC);
|
||||
setDesiredPump(_demandPump);
|
||||
|
@ -127,16 +127,16 @@ CRTC_Store::setBootInit(bool val)
|
|||
}
|
||||
|
||||
bool
|
||||
CRTC_Store::getCyclicEngaged()
|
||||
CRTC_Store::getUserStart()
|
||||
{
|
||||
_ReadAndUnpackByte4();
|
||||
return _CyclicEngaged;
|
||||
return _userStart;
|
||||
}
|
||||
|
||||
void
|
||||
CRTC_Store::setCyclicEngaged(bool active)
|
||||
CRTC_Store::setUserStart(bool active)
|
||||
{
|
||||
_CyclicEngaged = active;
|
||||
_userStart = active;
|
||||
_PackAndSaveByte4();
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,20 @@ CRTC_Store::getFrostOn()
|
|||
return _frostOn;
|
||||
}
|
||||
|
||||
void
|
||||
CRTC_Store::setSpare(bool state)
|
||||
{
|
||||
_spare = state;
|
||||
_PackAndSaveByte5();
|
||||
}
|
||||
|
||||
bool
|
||||
CRTC_Store::getSpare()
|
||||
{
|
||||
_ReadAndUnpackByte5();
|
||||
return _spare;
|
||||
}
|
||||
|
||||
void
|
||||
CRTC_Store::resetRunTime()
|
||||
{
|
||||
|
@ -221,17 +235,17 @@ CRTC_Store::_ReadAndUnpackByte4()
|
|||
uint8_t NVval = 0;
|
||||
Clock.readData((uint8_t*)&NVval, 1, 4);
|
||||
_demandDegC = NVval & 0x3f;
|
||||
_CyclicEngaged = (NVval & 0x80) != 0;
|
||||
_userStart = (NVval & 0x80) != 0;
|
||||
_BootInit = (NVval & 0x40) != 0;
|
||||
_accessed[1] = true;
|
||||
DebugPort.printf("RTC_Store - read byte4: degC=%d, CyclicOn=%d, BootInit=%d\r\n", _demandDegC, _CyclicEngaged, _BootInit);
|
||||
DebugPort.printf("RTC_Store - read byte4: degC=%d, UserStart=%d, BootInit=%d\r\n", _demandDegC, _userStart, _BootInit);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRTC_Store::_PackAndSaveByte4()
|
||||
{
|
||||
uint8_t NVval = (_CyclicEngaged ? 0x80 : 0x00)
|
||||
uint8_t NVval = (_userStart ? 0x80 : 0x00)
|
||||
| (_BootInit ? 0x40 : 0x00)
|
||||
| (_demandDegC & 0x3f);
|
||||
Clock.saveData((uint8_t*)&NVval, 1, 4);
|
||||
|
@ -245,6 +259,7 @@ CRTC_Store::_ReadAndUnpackByte5()
|
|||
Clock.readData((uint8_t*)&NVval, 1, 5);
|
||||
_demandPump = NVval & 0x3f;
|
||||
_frostOn = (NVval & 0x40) != 0;
|
||||
_spare = (NVval & 0x80) != 0;
|
||||
_accessed[2] = true;
|
||||
DebugPort.printf("RTC_Store - read byte5: pump=%d\r\n", _demandPump);
|
||||
}
|
||||
|
@ -255,6 +270,7 @@ CRTC_Store::_PackAndSaveByte5()
|
|||
{
|
||||
uint8_t NVval = (_demandPump & 0x3f);
|
||||
NVval |= _frostOn ? 0x40 : 0;
|
||||
NVval |= _spare ? 0x80 : 0;
|
||||
|
||||
Clock.saveData((uint8_t*)&NVval, 1, 5);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,10 @@ class CRTC_Store {
|
|||
float _fuelgauge; // Byte0..Byte3
|
||||
uint8_t _demandDegC; // Byte4[0..5]
|
||||
bool _BootInit; // Byte4[6]
|
||||
bool _CyclicEngaged; // Byte4[7]
|
||||
bool _userStart; // Byte4[7]
|
||||
uint8_t _demandPump; // Byte5[0..5]
|
||||
bool _frostOn; // Byte5[6]
|
||||
bool _spare; // Byte5[7]
|
||||
uint8_t _RunTime; // Byte6[0..4]
|
||||
uint8_t _GlowTime; // Byte6[5..7]
|
||||
void _ReadAndUnpackByte4();
|
||||
|
@ -51,12 +52,12 @@ public:
|
|||
void resetGlowTime();
|
||||
bool incRunTime();
|
||||
bool incGlowTime();
|
||||
void setCyclicEngaged(bool _CyclicEngaged);
|
||||
void setUserStart(bool state);
|
||||
void setBootInit(bool val = true);
|
||||
float getFuelGauge();
|
||||
uint8_t getDesiredTemp();
|
||||
uint8_t getDesiredPump();
|
||||
bool getCyclicEngaged();
|
||||
bool getUserStart();
|
||||
bool getBootInit();
|
||||
int getRunTime();
|
||||
int getGlowTime();
|
||||
|
@ -64,6 +65,8 @@ public:
|
|||
int getMaxRunTime() const { return 32; };
|
||||
void setFrostOn(bool state);
|
||||
bool getFrostOn();
|
||||
void setSpare(bool state);
|
||||
bool getSpare();
|
||||
};
|
||||
|
||||
extern CRTC_Store RTC_Store;
|
||||
|
|
|
@ -283,7 +283,6 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow)
|
|||
}
|
||||
}
|
||||
else {
|
||||
// if(!RTC_Store.getFrostOn() && !RTC_Store.getCyclicEngaged())
|
||||
if(!RTC_Store.getFrostOn())
|
||||
requestOff();
|
||||
retval = 2;
|
||||
|
|
|
@ -415,17 +415,13 @@ void updateJSONclients(bool report)
|
|||
char jsonStr[800];
|
||||
{
|
||||
if(makeJSONString(JSONmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
}
|
||||
// update extended params
|
||||
{
|
||||
if(makeJSONStringEx(JSONmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
}
|
||||
// update timer parameters
|
||||
|
@ -433,9 +429,7 @@ void updateJSONclients(bool report)
|
|||
for(int tmr=0; tmr<14; tmr++)
|
||||
{
|
||||
if(makeJSONTimerString(tmr, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println("Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
bNewTimerInfo = true;
|
||||
}
|
||||
}
|
||||
|
@ -451,43 +445,33 @@ void updateJSONclients(bool report)
|
|||
root.set("TimerRefresh", 1);
|
||||
root.printTo(jsonStr, 800);
|
||||
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
|
||||
// report MQTT params
|
||||
{
|
||||
if(makeJSONStringMQTT(MQTTJSONmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
}
|
||||
|
||||
// report IP params
|
||||
{
|
||||
if(makeJSONStringIP(IPmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
}
|
||||
|
||||
// report System info
|
||||
{
|
||||
if(makeJSONStringSysInfo(SysModerator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if(makeJSONStringGPIO(GPIOmoderator, jsonStr, sizeof(jsonStr))) {
|
||||
if (report) DebugPort.printf(" %ld JSON send: %s", millis(), jsonStr);
|
||||
sendJSONtext(jsonStr);
|
||||
if (report) DebugPort.println(" Done");
|
||||
sendJSONtext(jsonStr, report);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,7 +492,7 @@ void resetAllJSONmoderators()
|
|||
GPIOmoderator.reset();
|
||||
// create and send a validation code (then client knows AB is capable of reboot over JSON)
|
||||
doJSONreboot(0);
|
||||
sendJSONtext("{\"LoadWebContent\":\"Supported\"}");
|
||||
sendJSONtext("{\"LoadWebContent\":\"Supported\"}", false);
|
||||
}
|
||||
|
||||
void initJSONMQTTmoderator()
|
||||
|
@ -562,8 +546,10 @@ void Expand(std::string& str)
|
|||
}
|
||||
}
|
||||
|
||||
void sendJSONtext(const char* jsonStr)
|
||||
void sendJSONtext(const char* jsonStr, bool report)
|
||||
{
|
||||
if (report) DebugPort.printf("JSON send: %s\r\n", jsonStr);
|
||||
|
||||
#ifdef REPORT_JSONSENDS
|
||||
std::string dest;
|
||||
DebugPort.print("1");
|
||||
|
@ -601,11 +587,11 @@ void doJSONreboot(uint16_t PIN)
|
|||
char jsonStr[20];
|
||||
sprintf(jsonStr, "{\"Reboot\":\"%04d\"}", validate);
|
||||
|
||||
sendJSONtext( jsonStr );
|
||||
sendJSONtext( jsonStr, false );
|
||||
}
|
||||
else if(PIN == validate) {
|
||||
strcpy(jsonStr, "{\"Reboot\":\"-1\"}");
|
||||
sendJSONtext( jsonStr );
|
||||
sendJSONtext( jsonStr, false );
|
||||
|
||||
// initate reboot
|
||||
const char* content[2];
|
||||
|
|
|
@ -41,7 +41,7 @@ void resetJSONSysModerator();
|
|||
void resetJSONMQTTmoderator();
|
||||
void validateTimer(int ID);
|
||||
void doJSONreboot(uint16_t code);
|
||||
void sendJSONtext(const char* JSONstr);
|
||||
void sendJSONtext(const char* JSONstr, bool report);
|
||||
|
||||
template<class T>
|
||||
const char* createJSON(const char* name, T value)
|
||||
|
|
|
@ -452,11 +452,13 @@ sUserSettings::load()
|
|||
validatedLoad("thermostat", useThermostat, 1, u8inBounds, 0, 1);
|
||||
validatedLoad("thermoMethod", ThermostatMethod, 0, u8inBounds, 0, 255);
|
||||
// catch and migrate old combined method & window
|
||||
if(ThermostatMethod & 0xFC) {
|
||||
float defVal = float(ThermostatMethod>>2) * 0.1f;
|
||||
validatedLoad("thermoWindow", ThermostatWindow, defVal, 0.2f, 10.0f);
|
||||
preferences.putUChar("thermoMethod", ThermostatMethod & 0x03); // strip old window
|
||||
}
|
||||
// if(ThermostatMethod & 0xFC) {
|
||||
// float defVal = float(ThermostatMethod>>2) * 0.1f;
|
||||
// validatedLoad("thermoWindow", ThermostatWindow, defVal, 0.2f, 10.0f);
|
||||
// preferences.putUChar("thermoMethod", ThermostatMethod & 0x03); // strip old window
|
||||
// }
|
||||
if(ThermostatMethod > 4)
|
||||
ThermostatMethod = 0;
|
||||
validatedLoad("thermoWindow", ThermostatWindow, 1.0f, 0.2f, 10.f);
|
||||
DebugPort.printf("2) Window = %f\r\n", ThermostatWindow);
|
||||
validatedLoad("frostOn", FrostOn, 0, u8inBounds, 0, 10);
|
||||
|
|
|
@ -310,7 +310,7 @@ struct sUserSettings : public CESP32_NVStorage {
|
|||
long menuTimeout;
|
||||
long ExtThermoTimeout;
|
||||
uint8_t degF;
|
||||
uint8_t ThermostatMethod; // 0: standard heater, 1: Narrow Hysterisis, 2:Managed Hz mode
|
||||
uint8_t ThermostatMethod; // 0: standard heater, 1: Narrow Hysterisis, 2:Managed Hz mode, 3: External contact, 4: Stop/Start
|
||||
float ThermostatWindow;
|
||||
uint8_t FrostOn;
|
||||
uint8_t FrostRise;
|
||||
|
@ -333,7 +333,7 @@ struct sUserSettings : public CESP32_NVStorage {
|
|||
retval &= INBOUNDS(menuTimeout, 0, 300000); // 5 mins
|
||||
retval &= INBOUNDS(ExtThermoTimeout, 0, 3600000); // 1 hour
|
||||
retval &= (degF == 0) || (degF == 1);
|
||||
retval &= ThermostatMethod <= 3; // only modes 0, 1 or 2, 3
|
||||
retval &= ThermostatMethod <= 4; // only modes 0, 1, 2, 3 or 4
|
||||
retval &= INBOUNDS(ThermostatWindow, 0.2f, 10.f);
|
||||
retval &= useThermostat < 2;
|
||||
retval &= INBOUNDS(wifiMode, 0, 3);
|
||||
|
|
|
@ -131,11 +131,11 @@ void DecodeCmd(const char* cmd, String& payload)
|
|||
if(payload.toInt()) {
|
||||
CDemandManager::eStartCode result = requestOn();
|
||||
switch(result) {
|
||||
case CDemandManager::eStartOK: sendJSONtext("{\"StartString\":\"\"}"); break;
|
||||
case CDemandManager::eStartTooWarm: sendJSONtext("{\"StartString\":\"Ambient too warm!\"}"); break;
|
||||
case CDemandManager::eStartSuspend: sendJSONtext("{\"StartString\":\"Immediate Cyclic suspension!\"}"); break;
|
||||
case CDemandManager::eStartLVC: sendJSONtext("{\"StartString\":\"Battery below LVC!\"}"); break;
|
||||
case CDemandManager::eStartLowFuel: sendJSONtext("{\"StartString\":\"Fuel Empty!\"}"); break;
|
||||
case CDemandManager::eStartOK: sendJSONtext("{\"StartString\":\"\"}", true); break;
|
||||
case CDemandManager::eStartTooWarm: sendJSONtext("{\"StartString\":\"Ambient too warm!\"}", true); break;
|
||||
case CDemandManager::eStartSuspend: sendJSONtext("{\"StartString\":\"Immediate Cyclic suspension!\"}", true); break;
|
||||
case CDemandManager::eStartLVC: sendJSONtext("{\"StartString\":\"Battery below LVC!\"}", true); break;
|
||||
case CDemandManager::eStartLowFuel: sendJSONtext("{\"StartString\":\"Fuel Empty!\"}", true); break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -185,7 +185,7 @@ void DecodeCmd(const char* cmd, String& payload)
|
|||
else if(strcmp("ThermostatMethod", cmd) == 0) {
|
||||
sUserSettings settings = NVstore.getUserSettings();
|
||||
settings.ThermostatMethod = payload.toInt();
|
||||
if(INBOUNDS(settings.ThermostatMethod, 0, 3))
|
||||
if(INBOUNDS(settings.ThermostatMethod, 0, 4))
|
||||
NVstore.setUserSettings(settings);
|
||||
}
|
||||
else if(strcmp("ThermostatWindow", cmd) == 0) {
|
||||
|
|
|
@ -48,7 +48,7 @@ extern bool hasOEMLCDcontroller();
|
|||
extern bool hasHtrData();
|
||||
extern int getBlueWireStat();
|
||||
extern int getSmartError();
|
||||
extern bool isCyclicActive();
|
||||
extern bool isCyclicStopStartActive();
|
||||
extern float getVersion();
|
||||
const char* getVersionStr(bool beta=false);
|
||||
extern const char* getVersionDate();
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
#include "../Utility/BTC_JSON.h"
|
||||
#include "../Utility/TempSense.h"
|
||||
#include "../Utility/DemandManager.h"
|
||||
#include "../Utility/FuelGauge.h"
|
||||
#include "../Utility/BoardDetect.h"
|
||||
#include "../Utility/NVStorage.h"
|
||||
#include <FreeRTOS.h>
|
||||
|
||||
extern void DecodeCmd(const char* cmd, String& payload);
|
||||
|
@ -348,9 +351,15 @@ void updateMQTT()
|
|||
pubTopic("InputVoltage", getBatteryVoltage(false));
|
||||
pubTopic("GlowVoltage", getGlowVolts());
|
||||
pubTopic("GlowCurrent", getGlowCurrent());
|
||||
if(getBoardRevision() != BRD_V2_GPIO_NOALG && getBoardRevision() != BRD_V3_GPIO_NOALG) { // has GPIO support
|
||||
sGPIO info;
|
||||
getGPIOinfo(info);
|
||||
pubTopic("GPanlg", info.algVal * 100 / 4096);
|
||||
}
|
||||
pubTopic("FuelUsage", FuelGauge.Used_mL());
|
||||
float fuelRate = getHeaterInfo().getPump_Actual() * NVstore.getHeaterTuning().pumpCal * 60 * 60;
|
||||
pubTopic("FuelRate", fuelRate);
|
||||
|
||||
}
|
||||
|
||||
void refreshMQTT()
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
#define USE_EMBEDDED_WEBUPDATECODE
|
||||
#define HTTPS_LOGLEVEL 2
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "BTCWifi.h"
|
||||
|
@ -53,7 +54,7 @@
|
|||
#include <WebsocketHandler.hpp>
|
||||
#include <FreeRTOS.h>
|
||||
#include "../OLED/ScreenManager.h"
|
||||
// #include "../Utility/ABpreferences.h"
|
||||
#include "esp_task_wdt.h"
|
||||
|
||||
// Max clients to be connected to the JSON handler
|
||||
#define MAX_CLIENTS 4
|
||||
|
@ -77,6 +78,7 @@ void streamFileCoreSSL(const size_t fileSize, const String & fileName, const Str
|
|||
void processWebsocketQueue();
|
||||
|
||||
QueueHandle_t webSocketQueue = NULL;
|
||||
QueueHandle_t JSONcommandQueue = NULL;
|
||||
TaskHandle_t handleWebServerTask;
|
||||
#if USE_HTTPS == 1
|
||||
SSLCert* pCert;
|
||||
|
@ -121,6 +123,8 @@ void doDefaultWebHandler(HTTPRequest * req, HTTPResponse * res);
|
|||
void build404Response(HTTPRequest * req, String& content, String file);
|
||||
void build500Response(String& content, String file);
|
||||
bool checkAuthentication(HTTPRequest * req, HTTPResponse * res, int credID=0);
|
||||
bool addRxJSONcommand(const char* str);
|
||||
bool checkRxJSONcommand();
|
||||
|
||||
|
||||
// As websockets are more complex, they need a custom class that is derived from WebsocketHandler
|
||||
|
@ -176,14 +180,31 @@ JSONHandler::onMessage(WebsocketInputStreambuf * inbuf) {
|
|||
|
||||
bRxWebData = true;
|
||||
|
||||
char cmd[256];
|
||||
memset(cmd, 0, 256);
|
||||
if(msg.length() < 256) {
|
||||
strcpy(cmd, msg.c_str());
|
||||
// TODO: use a queue to hand over message
|
||||
interpretJsonCommand(cmd); // send to the main heater controller decode routine
|
||||
}
|
||||
// use a queue to hand over messages - ensures any commands that affect the I2C bus
|
||||
// (typ. various RTC operations) are performed in line with all other accesses
|
||||
addRxJSONcommand(msg.c_str());
|
||||
}
|
||||
|
||||
bool addRxJSONcommand(const char* str)
|
||||
{
|
||||
if(JSONcommandQueue) {
|
||||
char *pMsg = new char[strlen(str)+1];
|
||||
strcpy(pMsg, str);
|
||||
xQueueSend(JSONcommandQueue, &pMsg, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool checkRxJSONcommand()
|
||||
{
|
||||
char* pMsg = NULL;
|
||||
if(xQueueReceive(JSONcommandQueue, &pMsg, 0)) {
|
||||
interpretJsonCommand(pMsg);
|
||||
delete[] pMsg;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -470,10 +491,10 @@ void initWebServer(void) {
|
|||
|
||||
DebugPort.println("HTTPS started");
|
||||
|
||||
JSONcommandQueue = xQueueCreate(50, sizeof(char*) );
|
||||
|
||||
// setup task to handle webserver
|
||||
webSocketQueue = xQueueCreate(50, sizeof(char*) );
|
||||
|
||||
bStopWebServer = false;
|
||||
xTaskCreate(SSLloopTask,
|
||||
"Web server task",
|
||||
|
@ -512,6 +533,8 @@ void SSLloopTask(void *) {
|
|||
bool doWebServer(void)
|
||||
{
|
||||
GetWebContent.manage();
|
||||
BrowserUpload.queueProcess(); // manage data queued from web update
|
||||
checkRxJSONcommand();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1061,9 +1084,6 @@ void onWMConfig(HTTPRequest * req, httpsserver::HTTPResponse * res)
|
|||
newMode.eraseCreds = false;
|
||||
newMode.delay = 500;
|
||||
scheduleWMreboot(newMode);
|
||||
|
||||
// delay(500);
|
||||
// wifiEnterConfigPortal(true, false, 10000);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1077,8 +1097,6 @@ void onResetWifi(HTTPRequest * req, httpsserver::HTTPResponse * res)
|
|||
newMode.eraseCreds = true;
|
||||
newMode.delay = 500;
|
||||
scheduleWMreboot(newMode);
|
||||
// delay(500);
|
||||
// wifiEnterConfigPortal(true, true, 3000);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1118,7 +1136,7 @@ void processWebsocketQueue()
|
|||
// DebugPort.println("->");
|
||||
}
|
||||
}
|
||||
delete pMsg;
|
||||
delete[] pMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1461,19 +1479,40 @@ void onUploadProgression(HTTPRequest * req, httpsserver::HTTPResponse * res)
|
|||
}
|
||||
|
||||
while (!parser->endOfField()) {
|
||||
|
||||
// file upload and writing to SPIFFS is not a happy combination as the web server is running at an elevated level here
|
||||
// best to pass the data to the normal Arduino processing task via a queue, but maintain synchronism with the processing
|
||||
// by spinning here until ready.
|
||||
while(!BrowserUpload.Ready()) {
|
||||
taskYIELD();
|
||||
}
|
||||
|
||||
esp_task_wdt_reset();
|
||||
upload.currentSize = parser->read(upload.buf, HTTP_UPLOAD_BUFLEN);
|
||||
sts = BrowserUpload.fragment(upload, res);
|
||||
|
||||
BrowserUpload.queueFragment(upload); // let user task process the fresh data
|
||||
|
||||
while(!BrowserUpload.Ready()) {
|
||||
taskYIELD();
|
||||
}
|
||||
esp_task_wdt_reset();
|
||||
|
||||
// sts = BrowserUpload.fragment(upload, res);
|
||||
sts = BrowserUpload.queueResult();
|
||||
|
||||
if(sts < 0) {
|
||||
if(pUpdateHandler) {
|
||||
sprintf(JSON, "{\"updateProgress\":%d}", sts);
|
||||
pUpdateHandler->send(JSON, WebsocketHandler::SEND_TYPE_TEXT);
|
||||
}
|
||||
DebugPort.printf("Upload code %d\r\n", sts);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// upload still in progress?
|
||||
if(BrowserUpload.bUploadActive) { // show progress unless a write error has occured
|
||||
DebugPort.print(".");
|
||||
// DebugPort.printf(" p%d ", uxTaskPriorityGet(NULL));
|
||||
// DebugPort.print(".");
|
||||
if(upload.totalSize) {
|
||||
// feed back bytes received over web socket for progressbar update on browser (via javascript)
|
||||
if(pUpdateHandler) {
|
||||
|
@ -1481,13 +1520,14 @@ void onUploadProgression(HTTPRequest * req, httpsserver::HTTPResponse * res)
|
|||
pUpdateHandler->send(JSON, WebsocketHandler::SEND_TYPE_TEXT);
|
||||
}
|
||||
}
|
||||
// show percentage on OLED
|
||||
/* // show percentage on OLED
|
||||
int percent = 0;
|
||||
if(_SuppliedFileSize)
|
||||
percent = 100 * upload.totalSize / _SuppliedFileSize;
|
||||
#if USE_SSL_LOOP_TASK != 1
|
||||
ShowOTAScreen(percent, eOTAbrowser); // browser update
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ void doOTA()
|
|||
if ((WiFi.status() == WL_CONNECTED)) // bug workaround in FOTA where execHTTPcheck does not return false in this condition
|
||||
{
|
||||
#endif
|
||||
FOTA.onProgress(onWebProgress); // important - keeps watchdog fed
|
||||
FOTA.onProgress(NULL); // important - keeps watchdog fed
|
||||
FOTA.onComplete(CheckFirmwareCRC); // upload complete, but not yet verified
|
||||
FOTA.onSuccess(onSuccess);
|
||||
#ifdef TESTFOTA
|
||||
|
@ -137,16 +137,20 @@ void doOTA()
|
|||
if(FOTA.execHTTPcheck()) {
|
||||
DebugPort.println("New firmware available on web server!");
|
||||
if(FOTAauth == 2) { // user has authorised update (was == 1 before auth.)
|
||||
FOTA.onProgress(onWebProgress); // important - keeps watchdog fed
|
||||
FOTA.execOTA(); // go ahead and do the update, reading new file from web server
|
||||
FOTA.onProgress(NULL); // avoid rogue web update pop ups during browser update!
|
||||
FOTAauth = 0; // and we're done.
|
||||
}
|
||||
else
|
||||
else {
|
||||
FOTAauth = 1; // flag that new firmware is available
|
||||
}
|
||||
}
|
||||
else {
|
||||
FOTAauth = 0; // cancel
|
||||
}
|
||||
} // Wifi (STA) Connected
|
||||
FOTA.onProgress(NULL);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -161,7 +165,9 @@ void doOTA()
|
|||
// version number is collected asynchronously after initiating the update check
|
||||
if(FOTA.getNewVersion()) {
|
||||
if(FOTAauth == 2) { // user has authorised update (was == 1 before auth.)
|
||||
FOTA.onProgress(onWebProgress); // important - keeps watchdog fed
|
||||
FOTA.execOTA(); // go ahead and do the update, reading new file from web server
|
||||
FOTA.onProgress(NULL); // avoid rogue web update pop ups during browser update!
|
||||
FOTAauth = 0; // and we're done.
|
||||
}
|
||||
else {
|
||||
|
@ -247,8 +253,6 @@ void onWebProgress(size_t progress, size_t total)
|
|||
static int prevPC = 0;
|
||||
if(percent != prevPC) {
|
||||
prevPC = percent;
|
||||
DebugPort.printf("Web progress: %u%%\r\n", percent);
|
||||
DebugPort.handle(); // keep telnet spy alive
|
||||
ShowOTAScreen(percent, eOTAWWW);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#include "BTCota.h"
|
||||
#include "../Utility/helpers.h"
|
||||
|
||||
QueueHandle_t webUpdateQueue = NULL;
|
||||
|
||||
|
||||
void
|
||||
sBrowserUpload::init()
|
||||
{
|
||||
|
@ -103,7 +106,7 @@ sBrowserUpload::begin(String& filename, int filesize)
|
|||
}
|
||||
|
||||
int
|
||||
sBrowserUpload::fragment(HTTPUpload& upload, httpsserver::HTTPResponse * res)
|
||||
sBrowserUpload::doFragment(HTTPUpload& upload, httpsserver::HTTPResponse * res)
|
||||
{
|
||||
if(isSPIFFSupload()) {
|
||||
// SPIFFS update (may be error state)
|
||||
|
@ -129,6 +132,7 @@ sBrowserUpload::fragment(HTTPUpload& upload, httpsserver::HTTPResponse * res)
|
|||
}
|
||||
}
|
||||
else {
|
||||
// DebugPort.print(".");
|
||||
// Firmware update, add new fragment to OTA partition
|
||||
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
||||
// ERROR !
|
||||
|
@ -138,6 +142,13 @@ sBrowserUpload::fragment(HTTPUpload& upload, httpsserver::HTTPResponse * res)
|
|||
if(res)
|
||||
upload.totalSize += upload.currentSize;
|
||||
}
|
||||
// show percentage on OLED
|
||||
int percent = 0;
|
||||
if(SrcFile.size) {
|
||||
percent = 100 * upload.totalSize / SrcFile.size;
|
||||
}
|
||||
ShowOTAScreen(percent, eOTAbrowser); // browser update
|
||||
|
||||
return upload.totalSize;
|
||||
}
|
||||
|
||||
|
@ -187,3 +198,47 @@ sBrowserUpload::isOK() const
|
|||
else
|
||||
return !Update.hasError();
|
||||
}
|
||||
|
||||
bool
|
||||
sBrowserUpload::Ready() const
|
||||
{
|
||||
return _bProcessed;
|
||||
}
|
||||
|
||||
int
|
||||
sBrowserUpload::queueFragment(HTTPUpload& upload)
|
||||
{
|
||||
_bProcessed = false;
|
||||
sUpdateFragment fragment;
|
||||
fragment.pUploadInfo = &upload;
|
||||
xQueueSend(webUpdateQueue, &fragment, 0);
|
||||
return upload.currentSize;
|
||||
}
|
||||
|
||||
bool
|
||||
sBrowserUpload::queueProcess()
|
||||
{
|
||||
sUpdateFragment fragment;
|
||||
if(webUpdateQueue && xQueueReceive(webUpdateQueue, &fragment, 0)) {
|
||||
|
||||
HTTPUpload& upload = *fragment.pUploadInfo;
|
||||
_queueResult = doFragment(upload, (httpsserver::HTTPResponse *)1);
|
||||
_bProcessed = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
sBrowserUpload::queueResult()
|
||||
{
|
||||
return _queueResult;
|
||||
}
|
||||
|
||||
void
|
||||
sBrowserUpload::createQueue()
|
||||
{
|
||||
if(webUpdateQueue == NULL) {
|
||||
webUpdateQueue = xQueueCreate(2, sizeof(sUpdateFragment) );
|
||||
}
|
||||
}
|
|
@ -37,10 +37,16 @@ struct sBrowserUpload{
|
|||
int state;
|
||||
} DstFile;
|
||||
bool bUploadActive;
|
||||
int _queueResult;
|
||||
volatile bool _bProcessed;
|
||||
//methods
|
||||
sBrowserUpload() {
|
||||
reset();
|
||||
createQueue();
|
||||
_bProcessed = true;
|
||||
}
|
||||
void createQueue();
|
||||
|
||||
void reset() {
|
||||
if(DstFile.file) {
|
||||
DstFile.file.close();
|
||||
|
@ -50,10 +56,21 @@ struct sBrowserUpload{
|
|||
}
|
||||
void init();
|
||||
int begin(String& filename, int filesize = -1);
|
||||
int fragment(HTTPUpload& upload, httpsserver::HTTPResponse * res = NULL);
|
||||
int doFragment(HTTPUpload& upload, httpsserver::HTTPResponse * res = NULL);
|
||||
int end(HTTPUpload& upload);
|
||||
bool isSPIFFSupload() const { return DstFile.state != 0; };
|
||||
bool isOK() const;
|
||||
bool Ready() const;
|
||||
int queueFragment(HTTPUpload& upload);
|
||||
bool queueProcess();
|
||||
int queueResult();
|
||||
|
||||
};
|
||||
|
||||
struct sUpdateFragment {
|
||||
// uint16_t len;
|
||||
// uint8_t buf[1500];
|
||||
HTTPUpload *pUploadInfo;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -395,6 +395,6 @@ CGetWebContent::_sendJSON(const char* name)
|
|||
else
|
||||
JSONmsg += name;
|
||||
JSONmsg += "\"}";
|
||||
sendJSONtext(JSONmsg.c_str());
|
||||
sendJSONtext(JSONmsg.c_str(), false);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue