feat(firmware): kick LAN:APPLY once on -200 LAN-not-initialized (closes #203) - #324
Conversation
…LanNotInitialized reason (closes #203) CheckWifiFirmwareStatusAsync's chip-info retry loop only covered the transient post-reboot startup window (#144); a steady-state case where LAN:ENAbled?=1 but the WINC1500 state machine hasn't reached INITIALIZED (SCPI -200) exhausted the retry budget and forced a needless multi-minute reflash. GetLanChipInfoAsync now surfaces that specific condition via LanNotInitializedException, the retry loop sends a single gated LAN:APPLY to nudge the state machine and keeps retrying, and WifiFirmwareStatus.Reason reports LanNotInitialized distinctly from the generic ChipInfoUnavailable if it still doesn't recover.
PR Summary by QodoFix WiFi probe: kick LAN:APPLY once on SCPI -200 (LAN not initialized)
AI Description
Diagram
High-Level Assessment
Files changed (8)
|
Code Review by Qodo
Context used 1.
|
…eason doc Addresses Qodo review on #324: the not-initialized recovery kick must observe cancellation before its state-changing Send, matching the existing WINC power-on guard. Also corrects WifiFirmwareStatusReason.LanNotInitialized's docs, which overstated that APPLY was always attempted before this reason is returned.
LoadNetworkConfigurationAsync and FactoryResetNetworkAsync observed the cancellation token only at method entry, so a cancellation requested between the entry guard and the state-changing Send could still emit the command. Add a second ThrowIfCancellationRequested immediately before each Send, matching the cancellation-guard pattern accepted in #324. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
CheckWifiFirmwareStatusAsync's bounded chip-info retry (added in feat(firmware): split WiFi update planning from execution (closes #143) #198 for Retry LAN chip-info probing during WiFi update startup #144) only covers the transient post-PIC32-reboot window. A distinct steady-state failure —LAN:ENAbled? = 1in saved settings but the WINC1500 state machine not yetINITIALIZED— makesGETChipInfo?return SCPI-200instead of JSON, exhausting the retry budget and forcing a needless multi-minute WiFi reflash even when firmware is already current.DaqifiStreamingDevice.GetLanChipInfoAsyncnow throws a newLanNotInitializedExceptionwhen it detects that specific-200line (reusing the existingIsScpiErrorLine/TryParseScpiErrorCodehelpers), instead of silently returningnulllike any other unparseable response.FirmwareUpdateService's retry loop catches that exception distinctly, sendsSYSTem:COMMunicate:LAN:APPLYonce per probe (newKickLanApplyOnNotInitializedoption, defaulttrue, mirroring thePowerOnWifiModuleBeforeProbepattern from feat(firmware): power on WINC before chip-info probe in CheckWifiFirmwareStatusAsync #320), and keeps retrying within the existing budget.WifiFirmwareStatus.Reasonreports the newWifiFirmwareStatusReason.LanNotInitializedinstead of the genericChipInfoUnavailable— same conservative "proceed with flash" behavior for callers, better diagnostics.This implements options 1+3 from the issue (the issue's own text notes they "pair naturally" — option 3 alone wouldn't have fixed the actual reflash bug, and option 2 pushes the fix onto callers who'd have to remember to call it).
Test plan
dotnet test— full suite passes (1495/1497, 2 pre-existing skips unrelated to this change)-200detection at theDaqifiStreamingDevice.GetLanChipInfoAsynclayer (GetLanChipInfoAsyncTests.cs), and end-to-end retry/kick/reason behavior at theFirmwareUpdateServicelayer (kick sent exactly once, recovers toUpToDate, reportsLanNotInitializedon exhaustion, respects the new option flag)GetLanChipInfoAsyncstill succeeds normally post-fix, confirming no regression on the healthy path. Attempted to reproduce the exact-200steady-state via a fresh power cycle; it did not reproduce this run (the condition is timing-dependent per the issue itself), so the recovery path itself is validated by the deterministic unit tests above rather than live on hardware this session.Closes #203.