Refactor timerWakeCycle() to fetch a single random photo per wake using cycle-mode-aware server-side filtering via Immich's POST /api/search/random endpoint. Changes: - Add fetchOneRandomAssetId() to ImmichClient with support for isFavorite, takenAfter, takenBefore filter parameters - Add timer_last_date NVS field for chronological cursor persistence - Implement probabilistic filter selection per cycle mode: - Random: unfiltered size=1 - Chronological/ReverseChronological: date cursor in NVS - FavoritesWeighted: 66% favorites, 33% unfiltered - WeightedChronological: 66% recent (30d), 33% unfiltered - WeightedReverseChronological: 66% older (30d), 33% unfiltered - Add retry loop with filter relaxation on empty results - Initialize hardware RTC (RX8130CE) firmware-wide: - Seed system clock from RTC at boot (immediate time) - NTP sync after WiFi connect, write back to RTC - Add time_utils.h with isoNow(), isoNowMinus30d(), hasValidTime() Normal mode (PhotoQueue + displayTask) is completely untouched. Co-authored-by: Cursor <cursoragent@cursor.com>
106 lines
3.7 KiB
C++
106 lines
3.7 KiB
C++
#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.date_fmt = readString("date_fmt", "%Y-%m-%d");
|
|
s.time_fmt = readString("time_fmt", "%H:%M:%S");
|
|
s.pipeline_mode = readU8("pipe_mode", DEFAULT_PIPELINE_MODE);
|
|
s.dither_noise = readU8("dith_noise", DEFAULT_DITHER_NOISE);
|
|
s.meta_translucent = readU8("meta_trans", 0);
|
|
s.led_brightness = readU8("led_bright", DEFAULT_LED_BRIGHTNESS);
|
|
s.show_battery = readU8("show_batt", 1);
|
|
s.queue_cursor = readU32("queue_cursor", 0);
|
|
s.albums_json = readString("albums_json", "[]");
|
|
s.timer_last_date = readString("timer_date", "");
|
|
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));
|
|
writeString("date_fmt", s.date_fmt);
|
|
writeString("time_fmt", s.time_fmt);
|
|
writeU8("pipe_mode", s.pipeline_mode);
|
|
writeU8("dith_noise", s.dither_noise);
|
|
writeU8("meta_trans", s.meta_translucent);
|
|
writeU8("led_bright", s.led_brightness);
|
|
writeU8("show_batt", s.show_battery);
|
|
writeU32("queue_cursor", s.queue_cursor);
|
|
writeString("albums_json", s.albums_json);
|
|
writeString("timer_date", s.timer_last_date);
|
|
Serial.println("[settings] All settings saved");
|
|
}
|
|
|
|
void SettingsManager::saveField(const char* key, uint8_t value) {
|
|
writeU8(key, value);
|
|
}
|
|
|
|
void SettingsManager::saveField(const char* key, uint32_t value) {
|
|
writeU32(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);
|
|
}
|