feat: settings manager with NVS persistence
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
11
src/main.cpp
11
src/main.cpp
@@ -1,6 +1,9 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <M5Unified.h>
|
#include <M5Unified.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
SettingsManager settingsManager;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
auto cfg = M5.config();
|
auto cfg = M5.config();
|
||||||
@@ -15,9 +18,15 @@ void setup() {
|
|||||||
pinMode(PIN_SPK_EN, OUTPUT);
|
pinMode(PIN_SPK_EN, OUTPUT);
|
||||||
digitalWrite(PIN_SPK_EN, LOW);
|
digitalWrite(PIN_SPK_EN, LOW);
|
||||||
|
|
||||||
|
settingsManager.begin();
|
||||||
|
Settings settings = settingsManager.get();
|
||||||
|
|
||||||
|
Serial.printf("[main] Provisioned: %s\n", settingsManager.isProvisioned() ? "yes" : "no");
|
||||||
|
Serial.printf("[main] Immich URL: %s\n", settings.immich_url.c_str());
|
||||||
|
Serial.printf("[main] Interval: %d min\n", settings.interval_min);
|
||||||
Serial.printf("[main] Free heap: %d, PSRAM: %d\n",
|
Serial.printf("[main] Free heap: %d, PSRAM: %d\n",
|
||||||
ESP.getFreeHeap(), ESP.getFreePsram());
|
ESP.getFreeHeap(), ESP.getFreePsram());
|
||||||
Serial.println("[main] Boot complete (skeleton)");
|
Serial.println("[main] Boot complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|||||||
87
src/settings.cpp
Normal file
87
src/settings.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include "settings.h"
|
||||||
|
#include <Preferences.h>
|
||||||
|
|
||||||
|
static const char* NVS_NAMESPACE = "immich_frame";
|
||||||
|
static Preferences prefs;
|
||||||
|
|
||||||
|
void SettingsManager::begin() {
|
||||||
|
prefs.begin(NVS_NAMESPACE, false);
|
||||||
|
Serial.println("[settings] NVS initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings SettingsManager::get() {
|
||||||
|
Settings s;
|
||||||
|
s.wifi_ssid = readString("wifi_ssid");
|
||||||
|
s.wifi_pass = readString("wifi_pass");
|
||||||
|
s.immich_url = readString("immich_url", DEFAULT_IMMICH_URL);
|
||||||
|
s.immich_key = readString("immich_key");
|
||||||
|
s.interval_min = readU8("interval_m", DEFAULT_INTERVAL_MIN);
|
||||||
|
s.cycle_mode = static_cast<CycleMode>(readU8("cycle_mode", DEFAULT_CYCLE_MODE));
|
||||||
|
s.img_quality = static_cast<ImageQuality>(readU8("img_quality", DEFAULT_IMG_QUALITY));
|
||||||
|
s.meta_flags = readU8("meta_flags", DEFAULT_META_FLAGS);
|
||||||
|
s.meta_pos = static_cast<MetaPosition>(readU8("meta_pos", DEFAULT_META_POS));
|
||||||
|
s.led_brightness = readU8("led_bright", DEFAULT_LED_BRIGHTNESS);
|
||||||
|
s.queue_cursor = readU32("queue_cursor", 0);
|
||||||
|
s.albums_json = readString("albums_json", "[]");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::save(const Settings& s) {
|
||||||
|
writeString("wifi_ssid", s.wifi_ssid);
|
||||||
|
writeString("wifi_pass", s.wifi_pass);
|
||||||
|
writeString("immich_url", s.immich_url);
|
||||||
|
writeString("immich_key", s.immich_key);
|
||||||
|
writeU8("interval_m", s.interval_min);
|
||||||
|
writeU8("cycle_mode", static_cast<uint8_t>(s.cycle_mode));
|
||||||
|
writeU8("img_quality", static_cast<uint8_t>(s.img_quality));
|
||||||
|
writeU8("meta_flags", s.meta_flags);
|
||||||
|
writeU8("meta_pos", static_cast<uint8_t>(s.meta_pos));
|
||||||
|
writeU8("led_bright", s.led_brightness);
|
||||||
|
writeU32("queue_cursor", s.queue_cursor);
|
||||||
|
writeString("albums_json", s.albums_json);
|
||||||
|
Serial.println("[settings] All settings saved");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::saveField(const char* key, uint8_t value) {
|
||||||
|
writeU8(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::saveField(const char* key, const char* value) {
|
||||||
|
writeString(key, String(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::factoryReset() {
|
||||||
|
prefs.clear();
|
||||||
|
Serial.println("[settings] Factory reset — rebooting");
|
||||||
|
delay(500);
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SettingsManager::isProvisioned() {
|
||||||
|
String ssid = readString("wifi_ssid");
|
||||||
|
return ssid.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
String SettingsManager::readString(const char* key, const char* defaultValue) {
|
||||||
|
return prefs.getString(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SettingsManager::readU8(const char* key, uint8_t defaultValue) {
|
||||||
|
return prefs.getUChar(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SettingsManager::readU32(const char* key, uint32_t defaultValue) {
|
||||||
|
return prefs.getUInt(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::writeString(const char* key, const String& value) {
|
||||||
|
prefs.putString(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::writeU8(const char* key, uint8_t value) {
|
||||||
|
prefs.putUChar(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SettingsManager::writeU32(const char* key, uint32_t value) {
|
||||||
|
prefs.putUInt(key, value);
|
||||||
|
}
|
||||||
71
src/settings.h
Normal file
71
src/settings.h
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
enum class CycleMode : uint8_t {
|
||||||
|
Random = 0,
|
||||||
|
Chronological = 1,
|
||||||
|
ReverseChronological = 2,
|
||||||
|
FavoritesWeighted = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ImageQuality : uint8_t {
|
||||||
|
Preview = 0,
|
||||||
|
Original = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MetaPosition : uint8_t {
|
||||||
|
Bottom = 0,
|
||||||
|
Top = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Metadata flags bitmask
|
||||||
|
constexpr uint8_t META_DATE = 0x01;
|
||||||
|
constexpr uint8_t META_LOCATION = 0x02;
|
||||||
|
constexpr uint8_t META_PEOPLE = 0x04;
|
||||||
|
constexpr uint8_t META_ALBUM = 0x08;
|
||||||
|
constexpr uint8_t META_CAMERA = 0x10;
|
||||||
|
|
||||||
|
struct Settings {
|
||||||
|
// WiFi
|
||||||
|
String wifi_ssid;
|
||||||
|
String wifi_pass;
|
||||||
|
|
||||||
|
// Immich
|
||||||
|
String immich_url;
|
||||||
|
String immich_key;
|
||||||
|
|
||||||
|
// Slideshow
|
||||||
|
uint8_t interval_min;
|
||||||
|
CycleMode cycle_mode;
|
||||||
|
ImageQuality img_quality;
|
||||||
|
|
||||||
|
// Display
|
||||||
|
uint8_t meta_flags;
|
||||||
|
MetaPosition meta_pos;
|
||||||
|
|
||||||
|
// Device
|
||||||
|
uint8_t led_brightness;
|
||||||
|
uint32_t queue_cursor;
|
||||||
|
String albums_json;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SettingsManager {
|
||||||
|
public:
|
||||||
|
void begin();
|
||||||
|
Settings get();
|
||||||
|
void save(const Settings& s);
|
||||||
|
void saveField(const char* key, uint8_t value);
|
||||||
|
void saveField(const char* key, const char* value);
|
||||||
|
void factoryReset();
|
||||||
|
bool isProvisioned();
|
||||||
|
|
||||||
|
private:
|
||||||
|
String readString(const char* key, const char* defaultValue = "");
|
||||||
|
uint8_t readU8(const char* key, uint8_t defaultValue = 0);
|
||||||
|
uint32_t readU32(const char* key, uint32_t defaultValue = 0);
|
||||||
|
void writeString(const char* key, const String& value);
|
||||||
|
void writeU8(const char* key, uint8_t value);
|
||||||
|
void writeU32(const char* key, uint32_t value);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user