fix(network): persist WiFi config before applying it (closes #352) - #391
Conversation
UpdateNetworkConfigurationAsync sent LAN:APPLY before LAN:SAVE. APPLY restarts the WiFi module, so the trailing SAVE could be lost to that restart, leaving the device applied-but-not-persisted: the new config live now, gone on the next power cycle. Reorder to persist-first — stage, enable LAN, SAVE, then APPLY last: before: SET… -> APPLY -> delay -> SD off -> LAN on -> SAVE after: SET… -> SD off -> LAN on -> SAVE -> APPLY -> delay The firmware persists the *staged* runtime settings, not just the live ones (SCPI_LANSettingsSave memcpy's BOARDRUNTIME_WIFI_SETTINGS to NVM), so saving first is valid. LAN:ENAbled writes isEnabled into that same struct and restarts nothing, so it moves ahead of the save to be persisted — and ahead of the apply, since the firmware only fires a module REINIT when isEnabled is set. APPLY is now last, so no command can be lost to the restart. This keeps reconfiguration working over WiFi/TCP rather than gating it to USB. The connection still drops when switching networks — that is inherent to leaving the network carrying the control link, not a fault — but the config is already in NVM by then, so the device comes back on the new network with the settings intact. Documented as the expected contract so callers reconnect rather than treat the drop as an error. Bench-validated on an Nq1 (WINC1500 fw 19.7.7): - staged SSID + SAVE, no APPLY at all -> survived a cold boot - full new sequence with a successful APPLY (all commands 0,"No error") -> survived a real module REINIT plus a power cycle - APPLY does not write NVM, so applying after saving cannot clobber it - device restored to its original configuration afterwards Tests: 3 ordering regressions (save-before-apply over USB and WiFi, and apply-is-final). All three fail against the old ordering. Full suite 1838 passed / 2 skipped on net9.0 + net10.0, 0-warning Release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PR Summary by QodoPersist WiFi config before LAN:APPLY to survive module restart (#352)
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1.
|
Qodo review: UpdateNetworkConfigurationAsync could throw OperationCanceledException from the post-apply Task.Delay even though LAN:SAVE and LAN:APPLY had already gone out, so the device may have durably changed networks. It also skipped the _networkConfiguration update on that path, leaving callers with a "canceled" result and stale local state describing a device that had in fact moved. Cancellation is now a pre-commit concern: - ThrowIfCancellationRequested immediately before LAN:SAVE — the last point where abandoning is harmless, since everything staged until then lives only in the device's runtime settings, unpersisted and unapplied. - After the apply, cancelling ends the restart wait but does not fail the call, and local state is updated either way. Persist-first made this sharper: with both the save and the apply ahead of the delay, a cancel there reported failure for an operation the device had fully committed. Tests: cancel-before-commit asserts neither SAVE nor APPLY is sent; cancel-during-restart-wait asserts the call completes and NetworkConfiguration reflects the committed values. Both fail against the pre-fix code (TaskCanceledException, and SAVE sent despite the cancel). Full suite 1840 passed / 2 skipped on net9.0 + net10.0, 0-warning Release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 3141551 |
Qodo review: the comment at the pre-save cancellation check claimed "nothing persisted, nothing applied", but the SD disable and LAN enable immediately above it have already reached the device — Core uses those same commands elsewhere to switch interfaces live. Read literally the comment implies cancelling there is side-effect-free, which could mislead later changes or tests. Reword to separate what cancelling before LAN:SAVE actually buys — nothing persisted, no module restart, device still serving its existing configuration — from what it does not: the staged credentials, the LAN enable flag and the SD disable are already in the device's runtime state, and a later LAN:APPLY from any caller would pick them up. Kept the check where it is rather than moving it earlier, as the review offered as an option. Moving it ahead of the SD/LAN commands would not make cancellation side-effect-free either — the credentials above are staged by then too. Persistence and restart are the boundary that actually matters; the top-of-method check is the only one preceding every Send, and that is now said outright instead of implied. Comment-only; no behavior change. Full suite 1840 passed / 2 skipped on net9.0 + net10.0, 0-warning Release. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit e5e5d7e |
Summary
Alternative to #376, which fixes #352 by gating network reconfiguration to USB. This fixes it by reordering two commands, keeping WiFi reconfiguration working.
The field case that motivated this: switching a DAQiFi from one hotspot to another out in the field, with no USB cable to hand.
The premise #376 rests on doesn't hold
#376 treats the dropped control connection as the defect. But if you move a device onto a different network, the connection carrying your commands must die — that is the operation succeeding, not a race to be avoided. #376 makes that impossible-to-avoid outcome unreachable by forbidding the workflow.
The real defect is narrower: Core saves last, so the save is what gets lost.
Why persist-first is valid (firmware-verified)
#352 and #376 both flagged persist-first as depending on unverified firmware semantics. It's now verified, in the firmware source and on hardware:
LAN:SAVEpersists the staged settings, not the active ones.SCPI_LANSettingsSavememcpy'sBOARDRUNTIME_WIFI_SETTINGSstraight to NVM with no dependency onAPPLYhaving run.LAN:ENAbledwritesisEnabledinto that same struct and restarts nothing, so it moves ahead of the save (to be persisted) and ahead of the apply (the firmware only fires a REINIT whenisEnabledis set).APPLYenqueues a REINIT event, andSaveToNvmis a local flash write. Once the command reaches the device, persistence completes on-device regardless of the connection.APPLYnever writes NVM, so applying after saving cannot clobber what was saved.Bench validation
On an Nq1 (WINC1500 fw 19.7.7), over USB:
SAVE, noAPPLYat all, cold bootAPPLY(every command0,"No error"), rebootOne note for anyone reproducing:
APPLYreturns-200when the device is in standby (SYSTem:POWer:STATe? -> 0) because the radio isn't initialized. Power up first. That is unrelated to this change — but it does reinforce the ordering, sinceAPPLYis the step that can fail and it no longer has the save riding behind it.Behavior change
Reconfiguration over WiFi/TCP now works instead of being rejected. Over WiFi the control connection is expected to drop when the target network changes; the config is already in NVM, so the device returns on the new network with settings intact. Documented on both
INetworkConfigurableand the implementation so callers reconnect rather than treat the drop as an error. Over USB the observable sequence is unchanged apart from the ordering.Tests
Three ordering regressions — save-before-apply over USB, the same over a WiFi transport, and apply-is-the-final-command (guards against a future trailing command being appended into the restart window). All three fail against the old ordering, with the diagnostic showing
SAVEat index 7 behindAPPLYat index 4._OverWifi_StillReEnablesLanfrom #347 is kept and still passes — #376 had to delete it.Full suite 1838 passed / 2 skipped on net9.0 + net10.0; 0-warning Release on both TFMs.
Note
Opened for review, not merging. If this approach is preferred, #376 should be closed as superseded — the two are mutually exclusive.
🤖 Generated with Claude Code