Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 27 additions & 16 deletions usermods/usermod_v2_auto_save/usermod_v2_auto_save.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
// It can be configured to load auto saved preset at startup,
// during the first `loop()`.
//
// By default it will not save the state if an unmodified preset
// is selected (to not duplicate it). You can change this behaviour
// by setting autoSaveIgnorePresets=false
//
// AutoSaveUsermod is standalone, but if FourLineDisplayUsermod
// is installed, it will notify the user of the saved changes.

Expand Down Expand Up @@ -49,6 +53,8 @@ class AutoSaveUsermod : public Usermod {
bool applyAutoSaveOnBoot = false; // do we load auto-saved preset on boot?
#endif

bool autoSaveIgnorePresets = true; // ignore by default to not duplicate presets

// If we've detected the need to auto save, this will be non zero.
unsigned long autoSaveAfter = 0;

Expand All @@ -68,6 +74,7 @@ class AutoSaveUsermod : public Usermod {
static const char _autoSaveAfterSec[];
static const char _autoSavePreset[];
static const char _autoSaveApplyOnBoot[];
static const char _autoSaveIgnorePresets[];

void inline saveSettings() {
char presetNameBuffer[PRESET_NAME_BUFFER_SIZE];
Expand Down Expand Up @@ -122,7 +129,8 @@ class AutoSaveUsermod : public Usermod {
void loop() {
static unsigned long lastRun = 0;
unsigned long now = millis();
if (!autoSaveAfterSec || !enabled || currentPreset>0 || (strip.isUpdating() && now - lastRun < 240)) return; // setting 0 as autosave seconds disables autosave
if (!autoSaveAfterSec || !enabled || (autoSaveIgnorePresets && currentPreset>0) || (strip.isUpdating() && now - lastRun < 240)) return; // setting 0 as autosave seconds disables autosave
lastRun = now;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While reviewing this again, I stumbled over lastRun never being set!? I think the intention probably was this; fine to add this in this MR as well? This got introduced in 0ff4016#diff-e57385253fd04c5e758584aeb14c1398a2ec9febfbb230c376b406b4aaa93ffc

And, sorry, rusty cpp: should lastRun be a static scoped variable here? why not a private member variable?

Copy link
Member

@softhack007 softhack007 Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mtin I think your fix is correct, "lastRun" implements the standard "be nice but not too nice" logic that enforces running the loop() even under high load (strip.isUdating())
A static variable in a function is different from a private class attribute, I think it was chosen here because we needed a persistent value without polluting global namespace.

So not necessary to make it a private member, because we will never have more than one instance of this usermod.

uint8_t currentMode = strip.getMainSegment().mode;
uint8_t currentPalette = strip.getMainSegment().palette;

Expand Down Expand Up @@ -219,10 +227,11 @@ class AutoSaveUsermod : public Usermod {
void addToConfig(JsonObject& root) {
// we add JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}}
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
top[FPSTR(_autoSaveEnabled)] = enabled;
top[FPSTR(_autoSaveAfterSec)] = autoSaveAfterSec; // usermodparam
top[FPSTR(_autoSavePreset)] = autoSavePreset; // usermodparam
top[FPSTR(_autoSaveApplyOnBoot)] = applyAutoSaveOnBoot;
top[FPSTR(_autoSaveEnabled)] = enabled;
top[FPSTR(_autoSaveAfterSec)] = autoSaveAfterSec; // usermodparam
top[FPSTR(_autoSavePreset)] = autoSavePreset; // usermodparam
top[FPSTR(_autoSaveApplyOnBoot)] = applyAutoSaveOnBoot;
top[FPSTR(_autoSaveIgnorePresets)] = autoSaveIgnorePresets;
DEBUG_PRINTLN(F("Autosave config saved."));
}

Expand All @@ -245,12 +254,13 @@ class AutoSaveUsermod : public Usermod {
return false;
}

enabled = top[FPSTR(_autoSaveEnabled)] | enabled;
autoSaveAfterSec = top[FPSTR(_autoSaveAfterSec)] | autoSaveAfterSec;
autoSaveAfterSec = (uint16_t) min(3600,max(10,(int)autoSaveAfterSec)); // bounds checking
autoSavePreset = top[FPSTR(_autoSavePreset)] | autoSavePreset;
autoSavePreset = (uint8_t) min(250,max(100,(int)autoSavePreset)); // bounds checking
applyAutoSaveOnBoot = top[FPSTR(_autoSaveApplyOnBoot)] | applyAutoSaveOnBoot;
enabled = top[FPSTR(_autoSaveEnabled)] | enabled;
autoSaveAfterSec = top[FPSTR(_autoSaveAfterSec)] | autoSaveAfterSec;
autoSaveAfterSec = (uint16_t) min(3600,max(10,(int)autoSaveAfterSec)); // bounds checking
autoSavePreset = top[FPSTR(_autoSavePreset)] | autoSavePreset;
autoSavePreset = (uint8_t) min(250,max(100,(int)autoSavePreset)); // bounds checking
applyAutoSaveOnBoot = top[FPSTR(_autoSaveApplyOnBoot)] | applyAutoSaveOnBoot;
autoSaveIgnorePresets = top[FPSTR(_autoSaveIgnorePresets)] | autoSaveIgnorePresets;
DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINTLN(F(" config (re)loaded."));

Expand All @@ -268,11 +278,12 @@ class AutoSaveUsermod : public Usermod {
};

// strings to reduce flash memory usage (used more than twice)
const char AutoSaveUsermod::_name[] PROGMEM = "Autosave";
const char AutoSaveUsermod::_autoSaveEnabled[] PROGMEM = "enabled";
const char AutoSaveUsermod::_autoSaveAfterSec[] PROGMEM = "autoSaveAfterSec";
const char AutoSaveUsermod::_autoSavePreset[] PROGMEM = "autoSavePreset";
const char AutoSaveUsermod::_autoSaveApplyOnBoot[] PROGMEM = "autoSaveApplyOnBoot";
const char AutoSaveUsermod::_name[] PROGMEM = "Autosave";
const char AutoSaveUsermod::_autoSaveEnabled[] PROGMEM = "enabled";
const char AutoSaveUsermod::_autoSaveAfterSec[] PROGMEM = "autoSaveAfterSec";
const char AutoSaveUsermod::_autoSavePreset[] PROGMEM = "autoSavePreset";
const char AutoSaveUsermod::_autoSaveApplyOnBoot[] PROGMEM = "autoSaveApplyOnBoot";
const char AutoSaveUsermod::_autoSaveIgnorePresets[] PROGMEM = "autoSaveIgnorePresets";

static AutoSaveUsermod autosave;
REGISTER_USERMOD(autosave);