BUG FIX: Web update was broken due to watchdog timeout - added onProgress to FOTA - all good now

Returned to compact timer icon, press centre button to see start/stop times in base menus
Version info screen refactored to show available version number
New splash screen now presented upon display for a short time after upload or rename to /splash.bmp
This commit is contained in:
Ray Jones 2019-08-03 12:42:49 +10:00
parent ac091fa6d8
commit 08d0307fc8
20 changed files with 317 additions and 140 deletions

View file

@ -7,7 +7,6 @@
#include <Arduino.h>
#include "esp32fota.h"
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>
@ -146,6 +145,7 @@ void esp32FOTA::execOTA()
if ( _onComplete != NULL) {
if(!_onComplete(contentLength)) {
Serial.println("ESP32FOTA: OnComplete handler returned false");
Update.abort();
}
}
@ -259,10 +259,12 @@ bool esp32FOTA::execHTTPcheck()
if (plversion > _firwmareVersion && fwtype == _firwmareType)
{
_newVersion = plversion;
return true;
}
else
{
_newVersion = 0;
return false;
}
@ -289,6 +291,16 @@ String esp32FOTA::getDeviceID()
return thisID;
}
/**
* onProgress, set a callback called during upload, passed directly thru to OTA Updater class
* @access public
* @param {[type]} void (*func)(size_t, size_t)
*/
void esp32FOTA::onProgress( std::function<void(size_t, size_t)> func ) {
Update.onProgress(func);
}
/**
* onComplete, set a callback after upload is completed, but not yet verified
* @access public

View file

@ -19,14 +19,17 @@ public:
bool execHTTPcheck();
bool useDeviceID;
String checkURL;
void onProgress( std::function<void(size_t, size_t)> func );
void onComplete( std::function<bool(int)> func );
void onSuccess( std::function<void()> func );
void onFail( std::function<void()> func );
int getNewVersion() { return _newVersion; };
private:
String getHeaderValue(String header, String headerName);
String getDeviceID();
String _firwmareType;
int _firwmareVersion;
int _newVersion;
String _host;
String _bin;
int _port;

View file

@ -123,8 +123,8 @@
#define RX_DATA_TIMOUT 50
const int FirmwareRevision = 30;
const int FirmwareSubRevision = 1;
const char* FirmwareDate = "30 Jul 2019";
const int FirmwareSubRevision = 2;
const char* FirmwareDate = "3 Aug 2019";
#ifdef ESP32
@ -1434,6 +1434,7 @@ void feedWatchdog()
DebugPort.printf("WD time = %lld\r\n", timeRem); // print longer WD intervals
timerWrite(watchdogTimer, 0); //reset timer (feed watchdog)
timerAlarmWrite(watchdogTimer, 15000000, false); //set time in uS must be fed within this time or reboot
}

View file

@ -109,6 +109,7 @@ CBasicScreen::show()
}
}
if((_showModeTime == 0) && _showSetModeTime) {
showHeaderDetail(true);
long tDelta = millis() - _showSetModeTime;
if(tDelta < 0) {
switch(_feedbackType) {
@ -143,6 +144,7 @@ CBasicScreen::show()
}
if((_showModeTime == 0) && (_showSetModeTime == 0)) {
showRunState();
showHeaderDetail(false);
}
return true;
}

View file

@ -47,6 +47,8 @@ CClockScreen::CClockScreen(C128x64_OLED& display, CScreenManager& mgr) : CScreen
bool
CClockScreen::show()
{
showHeaderDetail(true);
CScreenHeader::show(false);
const BTCDateTime& now = Clock.get();

View file

@ -82,6 +82,8 @@ CDetailedScreen::CDetailedScreen(C128x64_OLED& display, CScreenManager& mgr) : C
bool
CDetailedScreen::show()
{
showHeaderDetail(_showTarget != 0);
CScreenHeader::show(false);
int runstate = getHeaterInfo().getRunStateEx();

View file

@ -73,6 +73,7 @@
CScreenHeader::CScreenHeader(C128x64_OLED& disp, CScreenManager& mgr) : CScreen(disp, mgr)
{
_colon = false;
_hdrDetail = false;
}
bool
@ -100,6 +101,14 @@ CScreenHeader::show(bool erase)
return true;
}
void crackVer(char* msg, int newVer)
{
int major = (int)(newVer * 0.01);
int minor = newVer - major*100;
float prtMajor = major * 0.1;
sprintf(msg, "V%.1f.%d", prtMajor, minor);
}
// Animate IN/OUT arrows against the WiFi icon, according to actual web server traffic:
// an IN (down) arrow is drawn if incoming data has been detected.
// an OUT (up) arrow is drawn if outgoing data has been sent.
@ -120,62 +129,72 @@ CScreenHeader::animate()
// animate timer icon,
// inserting an update icon if new firmware available from internet web server
_animateCount++;
_batteryCount++;
WRAPUPPERLIMIT(_animateCount, 9, 0);
WRAPUPPERLIMIT(_batteryCount, 5, 0);
if(isUpdateAvailable(true)) {
WRAPUPPERLIMIT(_animateCount, 11, 0);
int newVer = isUpdateAvailable(true);
if(newVer) {
int xPos = X_TIMER_ICON - 3;
int yPos = Y_TIMER_ICON;
char msg[16];
CTransientFont AF(_display, &miniFontInfo); // temporarily use a mini font
switch(_animateCount) {
case 0:
case 2:
_display.fillRect(xPos, yPos, TimerIconInfo.width+3, TimerIconInfo.height, BLACK);
_display.fillRect(xPos-2, yPos+12, 21, 5, BLACK); // erase annotation
break;
case 1:
_drawBitmap(xPos+6, yPos, UpdateIconInfo);
crackVer(msg, newVer);
_printMenuText(xPos+19, yPos+12, msg, false, eRightJustify);
break;
case 2:
_display.fillRect(xPos, yPos, TimerIconInfo.width+3, TimerIconInfo.height, BLACK);
break;
case 3:
_display.fillRect(xPos-8, yPos+12, 30, 5, BLACK); // erase version annotation
default:
showTimers();
break;
}
}
else {
int xPos = X_BATT_ICON;
int yPos = Y_BATT_ICON;
showTimers();
}
switch(_batteryCount) {
case 0:
// establish battery icon flash pattern
// > 0.5 over LVC - solid
// < 0.5 over LVC - slow flash
// < LVC - fast flash
_batteryWarn = SmartError.checkVolts(FilteredSamples.FastipVolts.getValue(), FilteredSamples.FastGlowAmps.getValue(), false);
_batteryCount++;
WRAPUPPERLIMIT(_batteryCount, 5, 0);
int xPos = X_BATT_ICON;
int yPos = Y_BATT_ICON;
switch(_batteryCount) {
case 0:
// establish battery icon flash pattern
// > 0.5 over LVC - solid
// < 0.5 over LVC - slow flash
// < LVC - fast flash
_batteryWarn = SmartError.checkVolts(FilteredSamples.FastipVolts.getValue(), FilteredSamples.FastGlowAmps.getValue(), false);
showBatteryIcon(getBatteryVoltage(true));
break;
case 1:
if(_batteryWarn == 2)
_display.fillRect(xPos, yPos, BatteryIconInfo.width, BatteryIconInfo.height, BLACK);
break;
case 2:
if(_batteryWarn == 2)
showBatteryIcon(getBatteryVoltage(true));
break;
case 1:
if(_batteryWarn == 2)
_display.fillRect(xPos, yPos, BatteryIconInfo.width, BatteryIconInfo.height, BLACK);
break;
case 2:
if(_batteryWarn == 2)
showBatteryIcon(getBatteryVoltage(true));
break;
case 3:
if(_batteryWarn) // works for either < LVC, or < LVC+0.5
_display.fillRect(xPos, yPos, BatteryIconInfo.width, BatteryIconInfo.height, BLACK);
break;
case 4:
if(_batteryWarn == 2)
showBatteryIcon(getBatteryVoltage(true));
break;
case 5:
if(_batteryWarn == 2)
_display.fillRect(xPos, yPos, BatteryIconInfo.width, BatteryIconInfo.height, BLACK);
break;
break;
case 3:
if(_batteryWarn) // works for either < LVC, or < LVC+0.5
_display.fillRect(xPos, yPos, BatteryIconInfo.width, BatteryIconInfo.height, BLACK);
break;
case 4:
if(_batteryWarn == 2)
showBatteryIcon(getBatteryVoltage(true));
break;
case 5:
if(_batteryWarn == 2)
_display.fillRect(xPos, yPos, BatteryIconInfo.width, BatteryIconInfo.height, BLACK);
break;
}
}
showWifiIcon();
@ -295,21 +314,36 @@ CScreenHeader::showBatteryIcon(float voltage)
int
CScreenHeader::showTimers()
{
int nextTimer = CTimerManager::getNextTimer();
int nextTimer = CTimerManager::getNextTimer(); // timer ID and repeat flag info of next scheduled timer
if(nextTimer) {
int xPos = X_TIMER_ICON;
_drawBitmap(xPos, Y_TIMER_ICON, LargeTimerIconInfo);
if(nextTimer & 0x80)
_drawBitmap(xPos-3, Y_TIMER_ICON, VerticalRepeatIconInfo);
CTransientFont AF(_display, &miniFontInfo); // temporarily use a mini font
if((nextTimer & 0x0f) >= 10)
_display.setCursor(xPos+4, Y_TIMER_ICON+8);
else
_display.setCursor(xPos+6, Y_TIMER_ICON+8);
_display.print(nextTimer & 0x0f);
_drawBitmap(xPos, Y_TIMER_ICON, TimerIconInfo);
if(nextTimer & 0x80)
_drawBitmap(xPos-3, Y_TIMER_ICON, verticalRepeatIconInfo);
if(_hdrDetail) {
sTimer timerInfo;
char msg[8];
int activeTimer = CTimerManager::getActiveTimer();
if(activeTimer) {
CTimerManager::getTimer((activeTimer - 1) & 0xf, timerInfo);
sprintf(msg, "%02d:%02d", timerInfo.stop.hour, timerInfo.stop.min);
_drawBitmap(xPos-5, Y_TIMER_ICON+12, miniStopIconInfo, WHITE, BLACK);
}
else {
CTimerManager::getTimer((nextTimer - 1) & 0xf, timerInfo);
sprintf(msg, "%02d:%02d", timerInfo.start.hour, timerInfo.start.min);
_drawBitmap(xPos-5, Y_TIMER_ICON+12, miniStartIconInfo, WHITE, BLACK);
}
CTransientFont AF(_display, &miniFontInfo); // temporarily use a mini font
_printMenuText(xPos-1, Y_TIMER_ICON+12, msg);
}
else {
_display.fillRect(X_TIMER_ICON-5, Y_TIMER_ICON+12, 21, 5, BLACK); // erase annotation
}
return 1;
}
_display.fillRect(X_TIMER_ICON-3, Y_TIMER_ICON, TimerIconInfo.width+3, TimerIconInfo.height, BLACK); // erase icon
_display.fillRect(X_TIMER_ICON-5, Y_TIMER_ICON+12, 21, 5, BLACK); // erase annotation
return 0;
}

View file

@ -44,6 +44,7 @@ class CScreenHeader : public CScreen {
sScreenholdoff _UpAnnotation;
sScreenholdoff _DnAnnotation;
bool _colon;
bool _hdrDetail;
uint8_t _animateCount;
uint8_t _batteryCount;
uint8_t _batteryWarn;
@ -53,6 +54,7 @@ protected:
void showBatteryIcon(float voltage);
int showTimers();
virtual void showTime(); // x location depends upon how many timers are active
void showHeaderDetail(bool state) { _hdrDetail = state; };
public:
CScreenHeader(C128x64_OLED& disp, CScreenManager& mgr);
bool show(bool erase);

View file

@ -76,6 +76,8 @@ struct sBMPhdr {
};
#pragma pack (pop)
extern CScreenManager ScreenManager;
////////////////////////////////////////////////////////////////////////////////////////////////
// splash creen created using image2cpp http://javl.github.io/image2cpp/
// Settings:
@ -248,7 +250,7 @@ void loadSplashScreen(uint8_t* image)
}
}
void storeSplashScreenFile()
void checkSplashScreenUpdate()
{
if(SPIFFS.exists("/splash.bmp")) { // If a splash.bmp file was uploaded
File file = SPIFFS.open("/splash.bmp", "rb"); // Open it
@ -327,8 +329,10 @@ void storeSplashScreenFile()
} while(0);
file.close();
SPIFFS.remove("/splash.bmp");
ScreenManager.showSplash();
delay(2000);
}
}
@ -378,18 +382,7 @@ CScreenManager::begin(bool bNoClock)
#endif
// replace adafruit splash screen
_pDisplay->clearDisplay();
uint8_t splash[1024];
loadSplashScreen(splash);
_pDisplay->drawBitmap(0, 0, splash, 128, 64, WHITE);
// _pDisplay->drawBitmap(0, 0, DieselSplash, 128, 64, WHITE);
_pDisplay->setCursor(90, 56);
CTransientFont AF(*_pDisplay, &segoeUI_Italic_7ptFontInfo); // temporarily use a midi font
_pDisplay->setTextColor(WHITE);
_pDisplay->print(getVersionStr());
// Show initial display buffer contents on the screen --
_pDisplay->display();
showSplash();
delay(2000);
@ -767,3 +760,19 @@ CScreenManager::_dim(bool state)
_pDisplay->dim(state);
}
void
CScreenManager::showSplash()
{
_pDisplay->clearDisplay();
uint8_t splash[1024];
loadSplashScreen(splash);
_pDisplay->drawBitmap(0, 0, splash, 128, 64, WHITE);
// _pDisplay->drawBitmap(0, 0, DieselSplash, 128, 64, WHITE);
_pDisplay->setCursor(90, 56);
CTransientFont AF(*_pDisplay, &segoeUI_Italic_7ptFontInfo); // temporarily use a midi font
_pDisplay->setTextColor(WHITE);
_pDisplay->print(getVersionStr());
// Show initial display buffer contents on the screen --
_pDisplay->display();
}

View file

@ -69,6 +69,7 @@ public:
void showOTAMessage(int percent, eOTAmodes updateType);
void clearDisplay();
void bumpTimeout();
void showSplash();
};
#endif // __SCREEN_MANAGER_H__

View file

@ -82,25 +82,43 @@ CVersionInfoScreen::show()
// animation of update available via animate() if firmware update is available on web server
_showTitle("Version Information");
_drawBitmap(13, 12, FirmwareIconInfo);
_printMenuText(46, 15, getVersionStr());
_printMenuText(46, 26, getVersionDate());
_drawBitmap(23, 34, HardwareIconInfo);
_drawBitmap(8, 12, FirmwareIconInfo);
_printMenuText(41, 15, getVersionStr());
_printMenuText(41, 26, getVersionDate());
int newVer = isUpdateAvailable();
// if(newVer) {
// char msg[32];
// int major = (int)(newVer * 0.01);
// int minor = newVer - major*100;
// float prtMajor = major * 0.1;
// sprintf(msg, "V%.1f.%d", prtMajor, minor);
// _printMenuText(128, 15, msg, false, eRightJustify);
// }
_drawBitmap(18, 34, HardwareIconInfo);
int PCB = getBoardRevision();
sprintf(msg, "V%.1f", float(PCB)*0.1f);
_printMenuText(46, 38, msg);
_printMenuText(41, 38, msg);
if(PCB == 20) {
_printMenuText(108, 38, "Analog", false, eCentreJustify);
_display.drawLine(88, 42, 127, 42, WHITE);
}
if(PCB == 22) {
_printMenuText(114, 38, "GPIO", false, eCentreJustify);
_display.drawLine(94, 42, 121, 42, WHITE);
}
_printMenuText(_display.xCentre(), 53, " \021 \020 ", true, eCentreJustify);
if(_rowSel == 1 && isUpdateAvailable()) {
if(_rowSel == 1 && newVer) {
// prompt 'Get Update' for new firmware available and first UP press from home
_printMenuText(_display.xCentre(), 53, "Get Update", false, eCentreJustify);
char msg[32];
int major = (int)(newVer * 0.01);
int minor = newVer - major*100;
float prtMajor = major * 0.1;
sprintf(msg, "Get V%.1f.%d update", prtMajor, minor);
_printMenuText(_display.xCentre(), 53, " ", true, eCentreJustify);
_printMenuText(_display.xCentre(), 53, msg, false, eCentreJustify);
}
else {
_printMenuText(_display.xCentre(), 53, " \021 \020 ", true, eCentreJustify);
_printMenuText(_display.xCentre(), 53, "Exit", false, eCentreJustify);
}
}
@ -114,12 +132,12 @@ CVersionInfoScreen::show()
}
else if(_rowSel == 20) {
// firmware update confirmation screen
_printInverted(_display.xCentre(), 0, " Firmware update ", true, eCentreJustify);
_showTitle("Firmware update");
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
_printMenuText(_display.xCentre(), 43, "confirm download", false, eCentreJustify);
}
else {
_printInverted(_display.xCentre(), 0, " Factory Default ", true, eCentreJustify);
_showTitle("Factory Default");
if(_rowSel == 10) {
// factory default confirmation screen
_printMenuText(_display.xCentre(), 35, "Press UP to", false, eCentreJustify);
@ -149,12 +167,27 @@ CVersionInfoScreen::animate()
if(_rowSel <= 1 && isUpdateAvailable()) {
// show ascending up arrow if firmware update is available on web server
_animateCount++;
WRAPUPPERLIMIT(_animateCount, 5, 0);
int ypos = 11 + 15 - 7 - _animateCount;
WRAPUPPERLIMIT(_animateCount, 3, 0);
/* int ypos = 11 + 16 - 7 - _animateCount;
_display.fillRect(0, 11, 10, 21, BLACK);
_display.drawBitmap(2, ypos, WifiOutIconInfo.pBitmap, WifiOutIconInfo.width, 7, WHITE); // upload arrow - from web to afterburner
_display.fillRect(1, 11, 7, 2, WHITE); // top bar
_drawBitmap(0, 11+16, WWWIconInfo); // www icon
_display.fillRect(1, 12, 7, 2, WHITE); // top bar
_drawBitmap(0, 11+17, WWWIconInfo); // www icon*/
int newVer = isUpdateAvailable();
if((_animateCount & 0x02) && newVer) {
char msg[32];
int major = (int)(newVer * 0.01);
int minor = newVer - major*100;
float prtMajor = major * 0.1;
sprintf(msg, "V%.1f.%d", prtMajor, minor);
_printMenuText(128, 15, msg, false, eRightJustify);
_drawBitmap(118, 24, UpdateIconInfo);
}
else {
_display.fillRect(82, 15, 46, 7, BLACK);
_display.fillRect(118, 24, 9, 10, BLACK);
}
}
return true;
}

View file

@ -420,8 +420,6 @@ const uint8_t repeatIcon [] PROGMEM = {
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x02, // #
0x00, 0x02, // #
0xf0, 0x04, // #### #
@ -430,12 +428,27 @@ const uint8_t repeatIcon [] PROGMEM = {
0x98, 0x30, // # # ##
0x07, 0xc0 // #####
};
const BITMAP_INFO RepeatIconInfo(15, 15, repeatIcon);
const BITMAP_INFO RepeatIconInfo(15, 13, repeatIcon);
// 'repeat', 5x11px
const uint8_t verticalRepeatIcon [] PROGMEM = {
0x78, // ####
0x38, // ###
0x38, // ###
0x48, // # #
0x80, // #
0x80, // #
0x80, // #
0x80, // #
0x80, // #
0x40, // #
0x40, // #
0x20, // #
};
const BITMAP_INFO verticalRepeatIconInfo(5, 11, verticalRepeatIcon);
// 'timerID1', 15x15px
const uint8_t timerID1Icon [] PROGMEM = {
0x00, 0x00, //
0x00, 0x00, //
0x07, 0xc0, // #####
0x09, 0x20, // # # #
0x11, 0x10, // # # #
@ -450,7 +463,7 @@ const uint8_t timerID1Icon [] PROGMEM = {
0x00, 0x00, //
0x00, 0x00 //
};
const BITMAP_INFO TimerId1IconInfo(15, 15, timerID1Icon);
const BITMAP_INFO TimerId1IconInfo(15, 13, timerID1Icon);
// 'timerID2', 15x15px
const uint8_t timerID2Icon [] PROGMEM = {
@ -474,23 +487,19 @@ const BITMAP_INFO TimerId2IconInfo(15, 15, timerID2Icon);
// 'timer', 15x15px
const uint8_t timerIcon [] PROGMEM = {
0x00, 0x00, //
0x00, 0x00, //
0x07, 0xc0, // #####
0x09, 0x20, // # # #
0x11, 0x10, // # # #
0x21, 0x08, // # # #
0x21, 0x08, // # # #
0x21, 0x08, // # #### #
0x21, 0xE8, // # #### #
0x20, 0x08, // # #
0x20, 0x08, // # #
0x10, 0x10, // # #
0x08, 0x20, // # #
0x07, 0xc0, // #####
0x00, 0x00, //
0x00, 0x00 //
};
const BITMAP_INFO TimerIconInfo(15, 15, timerIcon);
const BITMAP_INFO TimerIconInfo(15, 11, timerIcon);
// 'large timer', 15x15px
const uint8_t largeTimerIcon[] PROGMEM =
@ -513,7 +522,7 @@ const uint8_t largeTimerIcon[] PROGMEM =
};
const BITMAP_INFO LargeTimerIconInfo(15, 15, largeTimerIcon);
const uint8_t PROGMEM verticalRepeatIcon [] =
const uint8_t PROGMEM verticalLargeRepeatIcon [] =
{
0x78, // ####
0x38, // ###
@ -531,7 +540,7 @@ const uint8_t PROGMEM verticalRepeatIcon [] =
0x20, // #
0x20, // #
};
const BITMAP_INFO VerticalRepeatIconInfo(5, 15, verticalRepeatIcon);
const BITMAP_INFO VerticalRepeatLargeIconInfo(5, 15, verticalLargeRepeatIcon);
const uint8_t PROGMEM GPIO1OFFIcon[] =
{
@ -687,6 +696,16 @@ const uint8_t PROGMEM startIcon[] =
};
const BITMAP_INFO StartIconInfo(5, 9, startIcon);
const uint8_t PROGMEM miniStartIcon[] =
{
0x80, // #
0xC0, // ##
0xE0, // ###
0xC0, // ##
0x80, // #
};
const BITMAP_INFO miniStartIconInfo(3, 5, miniStartIcon);
const uint8_t PROGMEM stopIcon[] =
{
@ -701,6 +720,16 @@ const uint8_t PROGMEM stopIcon[] =
};
const BITMAP_INFO StopIconInfo(6, 8, stopIcon);
const uint8_t PROGMEM miniStopIcon[] =
{
0x00, //
0xE0, // ###
0xE0, // ###
0xE0, // ###
0x00, //
};
const BITMAP_INFO miniStopIconInfo(3, 5, miniStopIcon);
const uint8_t PROGMEM displayTimeoutIcon[] =
{
0xFF, 0xE1, 0xFF, // ########### #########

View file

@ -73,8 +73,9 @@ extern const BITMAP_INFO RepeatIconInfo;
extern const BITMAP_INFO TimerId1IconInfo;
extern const BITMAP_INFO TimerId2IconInfo;
extern const BITMAP_INFO TimerIconInfo;
extern const BITMAP_INFO verticalRepeatIconInfo;
extern const BITMAP_INFO LargeTimerIconInfo;
extern const BITMAP_INFO VerticalRepeatIconInfo;
extern const BITMAP_INFO VerticalLargeRepeatIconInfo;
extern const BITMAP_INFO CrossLgIconInfo;
extern const BITMAP_INFO CrossIconInfo
@ -94,9 +95,11 @@ extern const BITMAP_INFO BulbOffIconInfo;
// Bitmap for start
extern const BITMAP_INFO StartIconInfo;
extern const BITMAP_INFO miniStartIconInfo;
// Bitmap sizes for stop
extern const BITMAP_INFO StopIconInfo;
extern const BITMAP_INFO miniStopIconInfo;
// Bitmap for displayTimeout
extern const BITMAP_INFO DisplayTimeoutIconInfo;

View file

@ -165,6 +165,9 @@ const uint8_t miniFontBitmaps[] PROGMEM =
0x88, // # #
0x70, // ###
// @81 ':' (1 pixel wide)
0x50, // # #
};
// Character descriptors for a 3x5 font
@ -183,7 +186,7 @@ const FONT_CHAR_INFO miniFontDescriptors[] PROGMEM =
{3, 5, 22}, // '7'
{3, 5, 25}, // '8'
{3, 5, 28}, // '9'
{0, 0, 0}, // ':'
{1, 5, 81}, // ':'
{0, 0, 0}, // ';'
{0, 0, 0}, // '<'
{0, 0, 0}, // '='

View file

@ -71,6 +71,7 @@ DebugPort.println("Using millis() based psuedo \"Real Time Clock\"");
update();
CTimerManager::createMap();
CTimerManager::findNextTimer(_currentTime.hour(), _currentTime.minute(), _currentTime.dayOfTheWeek());
}
const BTCDateTime&

View file

@ -34,22 +34,25 @@
#include "../Utility/NVStorage.h"
#include "../Utility/helpers.h"
uint8_t CTimerManager::weekMap[7][CTimerManager::_dayMinutes]; // b[7] = repeat flag, b[3..0] = timer ID
// main array to hold information of which timer is active at any particular minute of the week
// LSBs are used for the timerID + 1
// MSB is set if the timer repeats
uint8_t CTimerManager::_weekMap[7][CTimerManager::_dayMinutes]; // b[7] = repeat flag, b[3..0] = timer ID
int CTimerManager::activeTimer = 0;
int CTimerManager::activeDow = 0;
int CTimerManager::nextTimer = 0;
int CTimerManager::nextStart = 0;
bool CTimerManager::timerChanged = false;
int CTimerManager::_activeTimer = 0;
int CTimerManager::_activeDow = 0;
int CTimerManager::_nextTimer = 0;
int CTimerManager::_nextStart = 0;
bool CTimerManager::_timerChanged = false;
#define SET_MAPS() { \
if(pTimerMap) { \
pTimerMap[dayMinute] |= activeday; \
pTimerMap[dayMinute] |= activeday; \
if(pTimerIDs) \
pTimerIDs[dayMinute] |= timerBit; \
} \
else { \
weekMap[dow][dayMinute] = recordTimer; \
_weekMap[dow][dayMinute] = recordTimer; \
} \
}
@ -64,7 +67,7 @@ CTimerManager::createMap(int timerMask, uint16_t* pTimerMap, uint16_t* pTimerIDs
}
else {
DebugPort.println("Erasing weekMap");
memset(weekMap, 0, _dayMinutes*7*sizeof(uint8_t));
memset(_weekMap, 0, _dayMinutes*7*sizeof(uint8_t));
}
for(int timerID=0; timerID < 14; timerID++) {
@ -202,12 +205,12 @@ CTimerManager::condenseMap(uint8_t timerMap[7][120])
uint8_t condense = 0;
for(int subInterval = 0; subInterval < 12; subInterval++, dayMinute++) {
if(!condense)
condense = weekMap[dow][dayMinute];
condense = _weekMap[dow][dayMinute];
}
timerMap[dow][opIndex++] = condense;
}
}
timerChanged = false;
_timerChanged = false;
}
int
@ -220,26 +223,26 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow)
int retval = 0;
int dayMinute = (hour * 60) + minute;
int newID = weekMap[dow][dayMinute];
if(activeTimer != newID) {
int newID = _weekMap[dow][dayMinute];
if(_activeTimer != newID) {
DebugPort.printf("Timer ID change detected: %d", activeTimer & 0x0f);
if(activeTimer & 0x80) DebugPort.print("(repeating)");
DebugPort.printf("Timer ID change detected: %d", _activeTimer & 0x0f);
if(_activeTimer & 0x80) DebugPort.print("(repeating)");
DebugPort.printf(" -> %d", newID & 0x0f);
if(newID & 0x80) DebugPort.print("(repeating)");
DebugPort.println("");
if(activeTimer) {
if(_activeTimer) {
// deal with expired timer
DebugPort.println("Handling expired timer cleanup");
if(activeTimer & 0x80) {
if(_activeTimer & 0x80) {
DebugPort.println("Expired timer repeats, leaving definition alone");
}
else { // non repeating timer
// delete one shot timer - note that this may require ticking off each day as they appear
DebugPort.printf("Expired timer does not repeat - Cancelling %d\r\n", activeTimer);
int ID = activeTimer & 0x0f;
DebugPort.printf("Expired timer does not repeat - Cancelling %d\r\n", _activeTimer);
int ID = _activeTimer & 0x0f;
if(ID) {
ID--;
sTimer timer;
@ -250,8 +253,8 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow)
timer.enabled = 0; // ouright cancel anyday timer
}
else {
DebugPort.printf("Cancelling specific day idx %d\r\n", activeDow);
timer.enabled &= ~(0x01 << activeDow); // cancel specific day that started the timer
DebugPort.printf("Cancelling specific day idx %d\r\n", _activeDow);
timer.enabled &= ~(0x01 << _activeDow); // cancel specific day that started the timer
}
NVstore.setTimerInfo(ID, timer);
NVstore.save();
@ -263,7 +266,7 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow)
if(newID) {
DebugPort.println("Start of timer interval, starting heater");
requestOn();
activeDow = dow; // dow when timer interval start was detected
_activeDow = dow; // dow when timer interval start was detected
retval = 1;
}
else {
@ -271,7 +274,7 @@ CTimerManager::manageTime(int _hour, int _minute, int _dow)
requestOff();
retval = 2;
}
activeTimer = newID;
_activeTimer = newID;
}
findNextTimer(hour, minute, dow);
return retval;
@ -284,10 +287,10 @@ CTimerManager::findNextTimer(int hour, int minute, int dow)
int limit = 24*60*7;
while(limit--) {
if(weekMap[dow][dayMinute] & 0x0f) {
nextTimer = weekMap[dow][dayMinute];
nextStart = dow*_dayMinutes + dayMinute;
return nextTimer;
if(_weekMap[dow][dayMinute] & 0x0f) {
_nextTimer = _weekMap[dow][dayMinute];
_nextStart = dow*_dayMinutes + dayMinute;
return _nextTimer;
}
dayMinute++;
if(dayMinute == _dayMinutes) {
@ -296,16 +299,23 @@ CTimerManager::findNextTimer(int hour, int minute, int dow)
WRAPUPPERLIMIT(dow, 6, 0);
}
}
nextTimer = 0;
_nextTimer = 0;
return 0;
}
int
CTimerManager::getNextTimer()
{
return nextTimer;
return _nextTimer;
}
int
CTimerManager::getActiveTimer()
{
return _activeTimer;
}
void
CTimerManager::getTimer(int idx, sTimer& timerInfo)
{
@ -320,7 +330,7 @@ CTimerManager::setTimer(sTimer& timerInfo)
NVstore.save();
createMap();
manageTime(0,0,0);
timerChanged = true;
_timerChanged = true;
return 1;
}
return 0;
@ -341,7 +351,7 @@ CTimerManager::conflictTest(int ID)
}
createMap();
manageTime(0,0,0);
timerChanged = true;
_timerChanged = true;
return conflictID;
}

View file

@ -48,17 +48,18 @@ public:
static int manageTime(int hour, int minute, int dow);
static int findNextTimer(int hour, int minute, int dow);
static int getNextTimer();
static int getActiveTimer();
static void getTimer(int idx, sTimer& timerInfo);
static int setTimer(sTimer& timerInfo);
static bool hasTimerChanged() { return timerChanged; };
static bool hasTimerChanged() { return _timerChanged; };
private:
static int activeTimer;
static int activeDow;
static int prevState;
static int nextTimer;
static int nextStart;
static uint8_t weekMap[7][_dayMinutes]; // b[7] = repeat flag, b[3..0] = timer ID
static bool timerChanged;
static int _activeTimer;
static int _activeDow;
static int _prevState;
static int _nextTimer;
static int _nextStart;
static uint8_t _weekMap[7][_dayMinutes]; // b[7] = repeat flag, b[3..0] = timer ID
static bool _timerChanged;
};
#endif //__TIMERMANAGER_H__

View file

@ -72,7 +72,7 @@ extern bool setGPIOout(int channel, bool state);
extern bool getGPIOout(int channel);
extern bool toggleGPIOout(int channel);
extern void feedWatchdog();
extern bool isUpdateAvailable(bool test=true);
extern int isUpdateAvailable(bool test=true);
extern void checkFOTA();
extern void setUploadSize(long val);
extern void getGPIOinfo(sGPIO& info);

View file

@ -49,7 +49,7 @@ extern const char* updateIndex;
extern const char* formatDoneContent;
extern const char* rebootIndex;
extern void storeSplashScreenFile();
extern void checkSplashScreenUpdate();
sBrowserUpload BrowserUpload;
WebServer server(80);
@ -695,7 +695,7 @@ void onUploadCompletion()
// completion functionality
if(BrowserUpload.isSPIFFSupload()) {
if(BrowserUpload.isOK()) {
storeSplashScreenFile();
checkSplashScreenUpdate();
DebugPort.println("WEB: SPIFFS OK");
server.send(200, "text/plain", "OK - File uploaded to SPIFFS");
// javascript reselects the /update page!
@ -988,6 +988,7 @@ void onRename()
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());
checkSplashScreenUpdate();
}
}

View file

@ -31,9 +31,13 @@
#include "../Utility/MODBUS-CRC16.h"
#include "esp_ota_ops.h"
#define TESTFOTA
bool CheckFirmwareCRC(int filesize);
bool CheckFirmwareCRC0(int filesize);
void onSuccess();
void onWebProgress(size_t progress, size_t total);
esp32FOTA FOTA("afterburner-fota-http", int(getVersion()*1000));
unsigned long FOTAtime = millis() + 60000; // initial check in a minutes time
@ -113,9 +117,14 @@ void DoOTA()
// FOTAtime = millis() + 600000; // 10 minutes
FOTAtime = millis() + 3600000; // 1 hour
if ((WiFi.status() == WL_CONNECTED)) { // bug workaround in FOTA where execHTTPcheck does not return false in this condition
FOTA.onProgress(onWebProgress); // important - keeps watchdog fed
FOTA.onComplete(CheckFirmwareCRC0); // upload complete, but not yet verified
FOTA.onSuccess(onSuccess);
#ifdef TESTFOTA
FOTA.checkURL = "http://www.mrjones.id.au/afterburner/fota/fotatest.json";
#else
FOTA.checkURL = "http://www.mrjones.id.au/afterburner/fota/fota.json";
#endif
DebugPort.println("Checking for new firmware...");
if(FOTA.execHTTPcheck()) {
DebugPort.println("New firmware available on web server!");
@ -133,10 +142,16 @@ void DoOTA()
}
};
bool isUpdateAvailable(bool test)
int isUpdateAvailable(bool test)
{
if(test) {
return FOTAauth == 1;
// return FOTAauth == 1;
if(FOTAauth == 1) {
return FOTA.getNewVersion();
}
else {
return 0;
}
}
else
{
@ -228,3 +243,16 @@ void onSuccess()
{
forceBootInit();
}
void onWebProgress(size_t progress, size_t total)
{
feedWatchdog();
int percent = (progress / (total / 100));
static int prevPC = 0;
if(percent != prevPC) {
prevPC = percent;
DebugPort.printf("Progress: %u%%\r", percent);
DebugPort.handle(); // keep telnet spy alive
ShowOTAScreen(percent, eOTAWWW);
}
}