Skip to content

Commit

Permalink
Save values of diagram while rebooting
Browse files Browse the repository at this point in the history
Prevent loosing diagram values when performing a reboot or firmware update.
  • Loading branch information
StefanOberhumer committed May 9, 2024
1 parent 1f1227f commit 0587870
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 3 deletions.
1 change: 1 addition & 0 deletions include/Display_Graphic.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class DisplayGraphicClass {
void setLanguage(const uint8_t language);
void setDiagramMode(DiagramMode_t mode);
void setStartupDisplay();
void prepareDtuRestart();

DisplayGraphicDiagramClass& Diagram();

Expand Down
5 changes: 5 additions & 0 deletions include/Display_Graphic_Diagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ class DisplayGraphicDiagramClass {

void updatePeriod();

void prepareDtuRestart();

private:
void averageLoop();
void dataPointLoop();

void backupGraphValuesBeforeRestart();
void restoreGraphValuesAfterRestart(bool& delayUpdateTasks);

uint32_t getSecondsPerDot();

Task _averageTask;
Expand Down
7 changes: 7 additions & 0 deletions src/Display_Graphic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,11 @@ void DisplayGraphicClass::setStatus(const bool turnOn)
_displayTurnedOn = turnOn;
}

void DisplayGraphicClass::prepareDtuRestart() {
if (isValidDisplay()) {
setStatus(false);
_diagram.prepareDtuRestart();
}
}

DisplayGraphicClass Display;
79 changes: 77 additions & 2 deletions src/Display_Graphic_Diagram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,42 @@
#include "Configuration.h"
#include "Datastore.h"
#include <algorithm>
#include <Preferences.h>


// Expected time after a restart all inverters are ready
#define EXPECTED_SECS_INVERTERS_AVAILABLE_AFTER_RESTART 60


DisplayGraphicDiagramClass::DisplayGraphicDiagramClass()
: _averageTask(1 * TASK_SECOND, TASK_FOREVER, std::bind(&DisplayGraphicDiagramClass::averageLoop, this))
, _dataPointTask(TASK_IMMEDIATE, TASK_FOREVER, std::bind(&DisplayGraphicDiagramClass::dataPointLoop, this))
{
}


void DisplayGraphicDiagramClass::init(Scheduler& scheduler, U8G2* display)
{
bool delayUpdateTasks;

_display = display;

restoreGraphValuesAfterRestart(delayUpdateTasks);

scheduler.addTask(_averageTask);
_averageTask.enable();
if (delayUpdateTasks) {
_averageTask.restartDelayed(EXPECTED_SECS_INVERTERS_AVAILABLE_AFTER_RESTART * TASK_SECOND);
} else {
_averageTask.enable();
}

scheduler.addTask(_dataPointTask);
updatePeriod();
_dataPointTask.enable();
if (delayUpdateTasks) {
_dataPointTask.restartDelayed(EXPECTED_SECS_INVERTERS_AVAILABLE_AFTER_RESTART * TASK_SECOND);
} else {
_dataPointTask.enable();
}
}

void DisplayGraphicDiagramClass::averageLoop()
Expand Down Expand Up @@ -134,3 +153,59 @@ void DisplayGraphicDiagramClass::redraw(uint8_t screenSaverOffsetX, uint8_t xPos
graphPosX + i / scaleFactorX, horizontal_line_y - std::max<int16_t>(0, _graphValues[i] / scaleFactorY - 0.5));
}
}

void DisplayGraphicDiagramClass::backupGraphValuesBeforeRestart()
{
auto prefs = Preferences();

if (!prefs.begin("OPENDtuGraphVal")) {
return;
}
_dataPointTask.disable();
// TODO([email protected])
// Find an easy way to wait till a possible current execution of _dataPointTask has ended
// Or: Use a mutex here and in dataPointLoop()
// For now: I assume restarting is very rare and we validate everything in restoreGraphValuesAfterRestart()
prefs.putUChar("count", _graphValuesCount);
prefs.putBytes("vars", &_graphValues[0], sizeof(_graphValues));
prefs.end();
}

void DisplayGraphicDiagramClass::restoreGraphValuesAfterRestart(bool& delayUpdateTasks)
{
auto prefs = Preferences();

delayUpdateTasks = false;

if (!prefs.begin("OPENDtuGraphVal")) {
return;
}
_graphValuesCount = prefs.getUChar("count", _graphValuesCount);
if (_graphValuesCount >= std::size(_graphValues)) {
_graphValuesCount = std::size(_graphValues) - 1;
}
prefs.getBytes("vars", &_graphValues[0], sizeof(_graphValues));
prefs.clear(); // clear - so only after a Utils::restartDtu() the variables are available
prefs.end();

// Check if it was a restart due software reset
if (esp_reset_reason() != ESP_RST_SW) {
_graphValuesCount = 0;
return;
}

// Delaying the data collection makes no sense if a dot is less than the time we need
// to query all the inverters after a reboot.
// At 60secs this equals a diagram period of ~7680sec (2h8m) on a 128 dot display
_chartWidth = _display->getDisplayWidth(); // assume diagram use the whole display
if (getSecondsPerDot() <= EXPECTED_SECS_INVERTERS_AVAILABLE_AFTER_RESTART) {
return;
}

delayUpdateTasks = (_graphValuesCount != 0);
}

void DisplayGraphicDiagramClass::prepareDtuRestart()
{
backupGraphValuesBeforeRestart();
}
2 changes: 1 addition & 1 deletion src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int Utils::getTimezoneOffset()
void Utils::restartDtu()
{
LedSingle.turnAllOff();
Display.setStatus(false);
Display.prepareDtuRestart();
yield();
delay(1000);
yield();
Expand Down

0 comments on commit 0587870

Please sign in to comment.