feat(device): wire remaining NVM persistence SCPI commands (closes #207) - #329
Conversation
Expose the firmware's remaining configuration-persistence NVM primitives as thin, typed wrappers — LAN load/factory-reset plus ADC-calibration and voltage-precision save/load — so Core consumers no longer have to reach past the library to persist or restore device settings. Not a generic serialization framework; each command maps 1:1 to a firmware primitive. ScpiMessageProducer: - LoadNetworkLan -> SYSTem:COMMunicate:LAN:LOAD - FactoryResetNetworkLan-> SYSTem:COMMunicate:LAN:FACRESET - SaveAdcCalibration -> CONFigure:ADC:SAVEcal - LoadAdcCalibration -> CONFigure:ADC:LOADcal - SaveVoltagePrecision -> CONFigure:VOLTage:SAVE - LoadVoltagePrecision -> CONFigure:VOLTage:LOAD API surface: - INetworkConfigurable gains LoadNetworkConfigurationAsync() and FactoryResetNetworkAsync(), implemented on DaqifiStreamingDevice next to the existing UpdateNetworkConfigurationAsync (connected-guard + cancellation). - ADC-calibration and voltage-precision save/load land on IStreamingDevice (device-global NVM ops, no new interface, matching the existing Reboot-style fire-and-forget command methods). Tests: - Command-string round-trip per new producer member. - Interface-level tests via a capturing transport: each method sends the right command when connected and throws InvalidOperationException when not (plus a cancellation test for the async network members). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PR Summary by QodoWire NVM persistence SCPI commands for LAN, ADC calibration, and voltage precision
AI Description
Diagram
High-Level Assessment
Files changed (8)
|
Code Review by Qodo
Context used 1.
|
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>
|
Re Qodo's optional finding "Breaking interface expansion": keeping the new members directly on |
Summary
Exposes the firmware's remaining configuration-persistence NVM primitives as thin, typed wrappers, so Core consumers can persist/restore device settings without reimplementing SCPI. Not a generic serialization framework — each command maps 1:1 to a firmware primitive.
Closes #207.
SCPI wiring (
ScpiMessageProducer)LoadNetworkLanSYSTem:COMMunicate:LAN:LOADFactoryResetNetworkLanSYSTem:COMMunicate:LAN:FACRESETSaveAdcCalibrationCONFigure:ADC:SAVEcalLoadAdcCalibrationCONFigure:ADC:LOADcalSaveVoltagePrecisionCONFigure:VOLTage:SAVELoadVoltagePrecisionCONFigure:VOLTage:LOADAPI surface
INetworkConfigurablegainsLoadNetworkConfigurationAsync()andFactoryResetNetworkAsync(), implemented onDaqifiStreamingDevicenext to the existingUpdateNetworkConfigurationAsync(connected-guard + cancellation). These are thin wrappers over the NVM primitives — they repopulate/reset the device's runtime settings but do not themselves re-apply to the live interface (send an apply/reboot afterward); the localNetworkConfigurationsnapshot is intentionally not refreshed. Matches the async shape the interface already establishes.SaveAdcCalibration/LoadAdcCalibration/SaveVoltagePrecision/LoadVoltagePrecisionland onIStreamingDevice— device-global NVM ops, no new interface, matching the existingReboot-style fire-and-forget command methods (per the ticket: "likely on the channel/calibration subsystem, not a new interface").Tests
InvalidOperationExceptionwhen disconnected, plus a cancellation test for the async network members.Bench test
Ran all six commands against a real Nyquist (firmware 3.7.2, USB
/dev/cu.usbmodem1101) and checked the SCPI error queue after each viaDrainErrorQueueAsync:Every command header was accepted — no
-113 "Undefined header"— confirming the command strings match firmware.LoadAdcCalibrationreturned-200 "Execution error": the header is recognized, but the device had no stored calibration to load in that state — a device-state condition, not a command-string defect. (The bench harness issuedLOADbeforeSAVEfor both cal and voltage so anySAVEwrote back values just refreshed from NVM — a no-op persist.)🤖 Generated with Claude Code