feat: add DrainErrorQueueAsync for SCPI error queue inspection#185
Conversation
Closes #174. Adds DaqifiDevice.DrainErrorQueueAsync, which pops SYSTem:ERRor? entries from the device until the queue reports "No error" and returns the popped strings to the caller. This complements the existing inline ContainsScpiError check (last-command result) by exposing what is queued on the device, including stale entries from prior sessions. Also adds ScpiMessageProducer.GetSystemError for the SYSTem:ERRor? query message. Implementation notes that diverged from the issue's draft snippet: - An empty reply terminates the loop (returning what's been popped so far) instead of being recorded as an error and continuing. Without this, a transport timeout would cause the loop to append empty strings until maxIterations was exhausted. - Default response timeout matches the existing ExecuteTextCommandAsync default (1000 ms) rather than 200 ms, which was tight enough to cause false terminations on a slightly loaded transport. - When maxIterations is reached without convergence, a warning is traced; callers that want to treat that as a hard failure can compare Count to maxIterations.
Review Summary by QodoAdd DrainErrorQueueAsync for SCPI error queue inspection
WalkthroughsDescription• Adds DrainErrorQueueAsync method to inspect and pop queued SCPI errors • Adds GetSystemError SCPI message producer for SYSTem:ERRor? queries • Implements robust error queue draining with empty-reply termination • Includes 10 comprehensive unit tests covering edge cases and error scenarios Diagramflowchart LR
A["DaqifiDevice"] -->|new method| B["DrainErrorQueueAsync"]
B -->|queries device| C["SYSTem:ERRor?"]
C -->|via| D["ScpiMessageProducer.GetSystemError"]
B -->|returns| E["List of error strings"]
F["Unit Tests"] -->|verify| B
File Changes1. src/Daqifi.Core.Tests/Device/DaqifiDeviceDrainErrorQueueTests.cs
|
Code Review by Qodo
1. Unsynchronized text exchange
|
- Drop overspecified _SkipsLeadingBlankLines test that asserted defensive behavior the line parser doesn't actually exercise. - Tighten 4-line empty-reply comment to 2. - Remove unneeded Connect() in arg-validation test. - Fix SYST:ERR? -> SYSTem:ERRor? doc inconsistency.
Per Qodo review on PR #185: replying to "No error" via substring match could in theory terminate on a real error whose message text happens to contain that phrase. Parse the numeric prefix (0 or +0) before the comma and only terminate on code 0. Adds a test that proves the substring-match behavior is no longer present.
|
Replying to @qodo-code-review's review: Issue 1 — Loose terminator detection: fixed in b4fc3ad. Agreed. Replaced the Issue 2 — Unsynchronized text exchange: valid concern, but out of scope for this PR. Tracked as #186. The lack of locking is in |
Real-hardware verificationTested against a Nyquist Nq1 FW 3.4.4 over USB serial ( What worked
Firmware caveat (FW 3.4.4)On this firmware, errors are reported inline only and are NOT enqueued in
The original issue mentioned What I couldn't prove on this hardware
The mechanical primitives all work; the populated-list path is exercised by the unit tests. |
Closes #174.
Summary
DaqifiDevice.DrainErrorQueueAsync— popsSYSTem:ERRor?entries until the device reports"No error"and returns the popped strings to the caller. This complements the existing inlineContainsScpiErrorcheck (last-command result) by surfacing what's queued on the device, including stale errors from prior commands or sessions.ScpiMessageProducer.GetSystemError(SYSTem:ERRor?) for use by the new method and any future callers.+0,"No error"terminator variant, leading blank lines, trimming, empty-reply termination, command verification, cancellation, and argument validation.Implementation notes (deviations from the issue's draft snippet)
maxIterationswas exhausted.ExecuteTextCommandAsync's default (1000 ms) rather than 200 ms — 200 ms was tight enough to cause false terminations on a slightly loaded transport.maxIterationsis reached without convergence, aTrace.WriteLinewarning is emitted. Callers that want to treat non-convergence as a hard failure can compareCounttomaxIterations.DaqifiDevice(the base class) so all subclasses inherit it without duplication.Test plan
dotnet test --filter DrainErrorQueue— 10/10 passing🤖 Generated with Claude Code