aethersdr / aethersdr/AetherSDR

Cross-session persistence of NRS level (and other firmware-default-on-recall settings)

Open
#2,985 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement maintainer-review priority: low protocol
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:

  1. User reconnects to the radio
  2. Radio sends `speex_nr_level=50` (firmware default, since `profile global` doesn't persist it)
  3. `m_nrsLevelUserOverride == false` (initial state) → no re-push → NRS sits at 50
  4. 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:

  1. Look up the radio+slice tuple in `SliceUserOverrides`
  2. If a cached value exists, set `m_nrsLevelUser` and `m_nrsLevelUserOverride = true`
  3. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.