mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-14 18:37:26 +00:00
leds: persist brightness across reboots and firmware updates
leds.brightness (PWM-capable boards) was RAM-only since it was added: it always reset to ZEPHCORE_LED_DEFAULT_BRIGHTNESS_PCT (10%) on every boot, regardless of what a user had last set it to. New field led_brightness on NodePrefs, following the exact same append-only pattern as leds_radio_mode/leds_hb_mode added just before it: offset 311 in RepeaterDataStore.cpp (repeater/room-server/observer, shared file), offset 174 in ZephyrDataStore.cpp (companion). Both are backward compatible by construction: a prefs file written before this field existed simply leaves it at the initNodePrefs() default (10%), which is exactly the behaviour every already-deployed node has today -- no special-casing needed to keep "10% on a new/not-yet-upgraded node" as the effective default. CommonCLI.cpp's "set leds.brightness" handler now writes the prefs field and calls savePrefs(), same as the leds.radio/leds.hb handlers right above it; "get leds.brightness" now reads from prefs instead of the RAM getter directly, for the same reason those two already do (always in sync, prefs is the source of truth). The four boot call sites (main_companion.cpp, main_repeater.cpp, main_room_server.cpp, main_observer.cpp) each gained a zephcore_led_set_brightness_pct() call seeding the RAM cache from the persisted value, mirroring the existing leds_radio_mode/leds_hb_mode lines right next to them. Verified building for heltec_t096/nrf52840 (companion) and rak3401_1watt (repeater), the two roles/datastores touched by this change.
This commit is contained in:
@@ -995,8 +995,11 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, const char* command, cha
|
||||
} else if (memcmp(config, "leds.brightness", 15) == 0) {
|
||||
/* Separate from "leds" on purpose: keeps the on/off switch a
|
||||
* pure word command and the dimmer a pure number command,
|
||||
* instead of one command parsing both — see led_gate.h. */
|
||||
snprintf(reply, CLI_REPLY_SIZE, "> %u%%", (unsigned)zephcore_led_brightness_pct());
|
||||
* instead of one command parsing both — see led_gate.h. Read
|
||||
* from _prefs, same as leds.radio/leds.hb above, not from the
|
||||
* RAM getter directly -- the two are always in sync, the "set"
|
||||
* handler below writes both together. */
|
||||
snprintf(reply, CLI_REPLY_SIZE, "> %u%%", (unsigned)_prefs->led_brightness);
|
||||
} else if (memcmp(config, "leds", 4) == 0) {
|
||||
snprintf(reply, CLI_REPLY_SIZE, "> %s", _prefs->leds_disabled ? "off" : "on");
|
||||
#ifndef ZEPHCORE_REPEATER
|
||||
@@ -1271,8 +1274,12 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, const char* command, cha
|
||||
} else if (memcmp(config, "leds.brightness ", 16) == 0) {
|
||||
/* Separate from "leds" on purpose: keeps the on/off switch a pure
|
||||
* word command and the dimmer a pure number command, instead of
|
||||
* one command parsing both. RAM-only, see led_gate.h — no
|
||||
* savePrefs() call here. Checked before "leds " below so this
|
||||
* one command parsing both. Persisted (since 1.17.4): a fresh
|
||||
* node still starts at ZEPHCORE_LED_DEFAULT_BRIGHTNESS_PCT (the
|
||||
* append-only prefs format leaves this byte at the
|
||||
* initNodePrefs() default on any file that predates this field),
|
||||
* but once set it survives reboots and firmware updates like
|
||||
* leds.radio/leds.hb above. Checked before "leds " below so this
|
||||
* longer, more specific prefix is never shadowed by it. */
|
||||
const char *val = &config[16];
|
||||
char *endptr = (char *)val;
|
||||
@@ -1282,7 +1289,9 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, const char* command, cha
|
||||
pct < 0 || pct > 100) {
|
||||
strcpy(reply, "Error: must be 0-100");
|
||||
} else {
|
||||
_prefs->led_brightness = (uint8_t)pct;
|
||||
zephcore_led_set_brightness_pct((uint8_t)pct);
|
||||
savePrefs();
|
||||
snprintf(reply, CLI_REPLY_SIZE, "OK - leds.brightness=%ld%%", pct);
|
||||
}
|
||||
} else if (memcmp(config, "leds ", 5) == 0) {
|
||||
|
||||
@@ -96,6 +96,7 @@ struct NodePrefs {
|
||||
uint8_t leds_disabled; // 1 = all LEDs off (heartbeat, unread, LoRa TX)
|
||||
uint8_t leds_radio_mode; // LEDS_RADIO_* — activity LED source (0 = TX, as before)
|
||||
uint8_t leds_hb_mode; // LEDS_HB_* — heartbeat LED behaviour (0 = all, as before)
|
||||
uint8_t led_brightness; // 0-100, PWM-capable boards only; ZEPHCORE_LED_DEFAULT_BRIGHTNESS_PCT on a new node
|
||||
// Power saving
|
||||
uint8_t powersaving_enabled;
|
||||
/* 1 = powersaving_enabled is a real choice. The field was stored but
|
||||
@@ -306,6 +307,7 @@ static inline void sanitizeNodePrefs(NodePrefs* p) {
|
||||
p->leds_disabled = saneBool<uint8_t>(p->leds_disabled, 0);
|
||||
p->leds_radio_mode = saneEnum(p->leds_radio_mode, LEDS_RADIO_MAX);
|
||||
p->leds_hb_mode = saneEnum(p->leds_hb_mode, LEDS_HB_MAX);
|
||||
p->led_brightness = clampPref<uint8_t>(p->led_brightness, 0, 100);
|
||||
p->meshtimesync = saneBool<uint8_t>(p->meshtimesync, 0);
|
||||
/* Fallback must be the initNodePrefs() default (ON). It was 0, so a byte
|
||||
* that was neither 0 nor 1 silently switched adaptive CAD off instead of
|
||||
@@ -414,6 +416,7 @@ static inline void initNodePrefs(NodePrefs* prefs) {
|
||||
prefs->leds_disabled = 0; // LEDs on
|
||||
prefs->leds_radio_mode = LEDS_RADIO_TX; // activity LED on transmit, as before
|
||||
prefs->leds_hb_mode = LEDS_HB_ALL; // heartbeat + unread, as before
|
||||
prefs->led_brightness = ZEPHCORE_LED_DEFAULT_BRIGHTNESS_PCT; // 10%, new node
|
||||
prefs->powersaving_enabled = POWERSAVING_DEFAULT;
|
||||
prefs->powersaving_set = 1;
|
||||
prefs->gps_enabled = 0;
|
||||
|
||||
@@ -187,6 +187,11 @@ bool companionPrefsDecode(NodePrefs &prefs, const uint8_t *buf, size_t len)
|
||||
r.take(&p.tz_offset, 1);
|
||||
r.take(&p.leds_radio_mode, 1);
|
||||
r.take(&p.leds_hb_mode, 1);
|
||||
/* led_brightness (ZephCore extension, since 1.17.4). Absent in files
|
||||
* written before this field existed; the no-op EOF read leaves the
|
||||
* initNodePrefs() default ZEPHCORE_LED_DEFAULT_BRIGHTNESS_PCT (10%),
|
||||
* same value a fresh node already showed before this was persisted. */
|
||||
r.take(&p.led_brightness, 1);
|
||||
r.take(&p.wifi_enabled, 1);
|
||||
r.take(p.wifi_ssid, sizeof(p.wifi_ssid));
|
||||
r.take(p.wifi_pwd, sizeof(p.wifi_pwd));
|
||||
@@ -355,6 +360,11 @@ void serverPrefsDecode(NodePrefs &prefs, const uint8_t *buf, size_t len)
|
||||
r.get(&prefs.tz_offset, sizeof(prefs.tz_offset));
|
||||
r.get(&prefs.leds_radio_mode, sizeof(prefs.leds_radio_mode));
|
||||
r.get(&prefs.leds_hb_mode, sizeof(prefs.leds_hb_mode));
|
||||
/* led_brightness (ZephCore extension, since 1.17.4). Absent in files
|
||||
* written before this field existed; the no-op EOF read leaves the
|
||||
* initNodePrefs() default ZEPHCORE_LED_DEFAULT_BRIGHTNESS_PCT (10%),
|
||||
* same value a fresh node already showed before this was persisted. */
|
||||
r.get(&prefs.led_brightness, sizeof(prefs.led_brightness));
|
||||
|
||||
/* Only the explicit "off" magic disables LEDs; a legacy AGC interval or an
|
||||
* unwritten byte both mean "on". */
|
||||
|
||||
@@ -61,6 +61,7 @@ protected:
|
||||
def("leds_off", _p->leds_disabled);
|
||||
def("leds_radio", _p->leds_radio_mode);
|
||||
def("leds_hb", _p->leds_hb_mode);
|
||||
def("leds_brightness", _p->led_brightness);
|
||||
def("rx_dc", _p->rx_duty_cycle);
|
||||
def("mts", _p->meshtimesync);
|
||||
def("cad_auto", _p->cad_auto);
|
||||
|
||||
@@ -26,6 +26,7 @@ static inline void apply_boot_prefs(const NodePrefs *p, bool gps_time_sync)
|
||||
zephcore_leds_set_disabled(leds_off);
|
||||
zephcore_leds_set_radio_mode(p->leds_radio_mode);
|
||||
zephcore_leds_set_hb_mode(p->leds_hb_mode);
|
||||
zephcore_led_set_brightness_pct(p->led_brightness);
|
||||
LOG_INF("LEDs: %s (from prefs)", leds_off ? "disabled" : "enabled");
|
||||
|
||||
if (gps_time_sync && gps_is_available()) {
|
||||
|
||||
@@ -1092,6 +1092,7 @@ int main(void)
|
||||
zephcore_leds_set_disabled(leds_off);
|
||||
zephcore_leds_set_radio_mode(companion_mesh.prefs.leds_radio_mode);
|
||||
zephcore_leds_set_hb_mode(companion_mesh.prefs.leds_hb_mode);
|
||||
zephcore_led_set_brightness_pct(companion_mesh.prefs.led_brightness);
|
||||
ui_set_heartbeat_led(!leds_off);
|
||||
LOG_INF("LEDs: %s (from prefs)", leds_off ? "disabled" : "enabled");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user