aethersdr / aethersdr/AetherSDR
Cross-session persistence of NRS level (and other firmware-default-on-recall settings)
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 221
- Forks
- 117
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 299
Description
Context
PR #2917 (merged 2026-05-23) added within-session cache + re-push of `speex_nr_level` (NRS) so a profile-global recall doesn't snap the user's choice back to the firmware default of 50. That fixes the reported behavior in #2849.
It does NOT survive an app restart: `m_nrsLevelUser` and `m_nrsLevelUserOverride` are in-memory only. After AetherSDR is restarted:
- User reconnects to the radio
- Radio sends `speex_nr_level=50` (firmware default, since `profile global` doesn't persist it)
- `m_nrsLevelUserOverride == false` (initial state) → no re-push → NRS sits at 50
- User has to manually reset NRS to their preferred value each session
Proposal
Persist the user's NRS level (and the override flag) per-radio in AppSettings so the in-session cache also survives across restarts.
Suggested storage shape
Per the AppSettings refactor memo, prefer one nested-JSON value under one key rather than flat per-slice keys:
```
SliceUserOverrides = {
"": {
"slice-0": { "nrsLevel": 30 },
"slice-1": { "nrsLevel": 22 }
}
}
```
Keyed by radio serial so two different physical radios on the same operator workstation don't share overrides.
Loading flow
On `SliceModel` construction or first `applyStatus` with serial available:
- Look up the radio+slice tuple in `SliceUserOverrides`
- If a cached value exists, set `m_nrsLevelUser` and `m_nrsLevelUserOverride = true`
- The existing applyStatus re-push logic handles the rest — radio echoes 50 on first status, we re-push the cached value
Saving flow
In `setNrsLevel`, write the new value to the JSON map and `AppSettings::save()`.
Why this is worth doing
NRS isn't the only setting Flex firmware fails to persist across `profile global` recall. The same pattern (in-memory override + applyStatus re-push) is already used for `rtty_mark`. If we keep adding these per-setting workarounds, building one shared persistence layer for them all is cleaner than N copies of the cache-and-re-push code.
The current PR #2917 fix is good for one-shot bug closure (#2849), but the next user report along the lines of "X also resets on profile recall" would benefit from infrastructure already being in place.
Why this can wait
- The reported bug (#2849) is fixed within a session — that's the primary complaint
- No multi-setting demand yet — adding the persistence layer for one knob alone is overengineering
- The AppSettings refactor is on the roadmap independently; this work would benefit from landing on top of the nested-JSON-under-one-key infrastructure rather than ahead of it
Effort
If the AppSettings nested-JSON infrastructure is already done: ~2 hours (storage + load + save + manual test of restart-survival).
If not: ~half day, including the small per-setting persistence layer that can be reused for `rtty_mark` and future similar workarounds.
References
- #2917 — in-session NRS fix (merged)
- #2849 — original bug report
- `project_appsettings_refactor.md` memory — nested-JSON-under-one-key target shape
- `src/models/SliceModel.cpp` — existing `rtty_mark` workaround as reference precedent
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with project_appsettings_refactor.md and the AppSettings implementation to confirm whether nested JSON storage is available. Then read src/models/SliceModel.cpp, especially the existing rtty_mark workaround, setNrsLevel, and applyStatus flow. Done means NRS overrides are stored per radio and slice, restored after restart, and verified with a manual restart-survival test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- desktop
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- Half a day
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100