fix: persist PAN ID selection correctly, disconnect radio on Factory Reset - #46
Merged
Merged
Conversation
Switching droids previously only updated the radio's in-RAM ID setting and an in-memory display name — neither survived a power cycle, so the controller wouldn't reliably reconnect to the last-selected droid after a reboot. The droid *list* was already persisted; which one is currently active was not. - droid_persistence.h/.cpp gains saveCurrentSelection()/ loadCurrentSelection()/clearCurrentSelection(), in their own NVS namespace separate from the list — DroidPersistence::save() calls prefs.clear() on the list's namespace every time it changes, which would otherwise wipe the current selection out from under it. - XbeeControl::setPanId() now also sends "WR" after "ID", committing the PAN ID to the module's own flash — a backstop on the radio side, though SnipsController.ino reapplying it at boot is what actually guarantees reconnection regardless of what the module's flash holds. - MenuController: setCurrentDroidName() is now public (SnipsController.ino calls it once at boot to seed the display from a restored selection) and a successful Switch Droid action now also reports through the new consumeCurrentSelectionChanged(), separate from consumeDroidStoreChanged() (list membership vs. current selection are independent — a selected droid stays "current" even if later removed from the list). Factory Reset now also resets the in-memory display name. - SnipsController.ino: reapplies a saved selection at boot (set PAN + rejoin), persists a new one whenever a switch succeeds, and clears the persisted selection on Factory Reset. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Revises the previous commit on this branch after clarifying two points about how XBee modules actually behave: - Once XbeeControl::setPanId() commits a PAN ID via "WR", the module remembers it in its own flash across power cycles on its own — it never changes until setPanId() is called again, and never needs to be re-applied at boot. This makes the DroidPersistence current-selection NVS entries (and the boot-time reapply/rejoin logic) from the previous commit unnecessary — removed entirely. - SnipsController.ino now derives the "Droid Name" complication at boot by querying the module's current PAN ID (XbeeControl::queryPanId(), new) and matching it against the already-loaded droid list, rather than needing its own separate persisted copy of "current selection." Separately: Factory Reset should actually disconnect the radio from whatever droid it was last on, not just forget it locally — otherwise the controller would stay silently joined post-reset, which would be confusing. It now clears the PAN ID to a neutral all-zero value and forces an immediate leave, deliberately without rejoining anything (unlike a normal Switch Droid) — it should sit disconnected until the user explicitly picks a new droid. Nothing else about the radio (SL, etc.) is touched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a real gap found during review of the merged firmware rewrite: switching droids only updated the radio's in-RAM
IDsetting and an in-memory display name — neither survived a power cycle, so the controller wouldn't reliably reconnect to the last-selected droid after a reboot. The droid list was already persisted (droid_persistence.cpp); which one is currently active was not.XbeeControl::setPanId()now also sendsWRafterID, committing the PAN ID to the module's own flash. Per how XBee modules actually behave, this makes the module remember it across power cycles on its own — nothing needs to re-apply it at boot, and it only changes again whensetPanId()is explicitly called for a new droid.XbeeControl::queryPanId()(new): reads back the module's current PAN ID.SnipsController.inouses this once at boot to derive which saved droid (by name) it corresponds to, for the "Droid Name" complication — no separate persistence needed for that either, it's just derived fresh each boot from the list + the radio's own state.This went through two iterations on this branch: the first commit added a full NVS-backed "current selection" persistence layer and a boot-time reapply step, which turned out to be unnecessary once it was confirmed that
WRalone makes the module remember its PAN ID on its own — the second commit simplifies to the design above.Test plan
pio test -e native— all 189 test cases passgcovr --exclude 'src/SnipsController\.ino' --exclude 'src/oled\.cpp' --exclude 'src/rgb_led\.cpp' --exclude 'src/calibration_store\.cpp' --exclude 'src/droid_persistence\.cpp' --exclude 'src/xbee_spi\.cpp' --exclude 'src/xbee_control\.cpp' --exclude 'src/complication_persistence\.cpp' --fail-under-line 90— 98.6% line coveragepio run -e esp32s3— builds successfully🤖 Generated with Claude Code