Cause: - Preadjustment Completion and TBF Q3 calibration results required configurable database persistence. - Both write operations required diagnostics and simulation support. Solution: 1. Added independent database writer configurations - Added PreadjustmentCompletionWriter and Q3CalibrationWriter to gci_config. - Support SQL commands, stored procedures and parameter mappings. - Added SQL table creation and verification scripts. 2. Added Preadjustment Completion storage - Store PCB ID, meter size, amplitude settings, temperature offsets, zero-flow offsets, timestamp and overall result. - Use captured Completion readout values. - Preserve the original HTTP reporting. - Report SQL connection and write status in the corresponding slot diagnostics. 3. Added Q3 calibration storage - Forward TBF results through GCI Bridge to the GCI database API. - Store signed deviations and written calibration factors for all three paths. - Write to SQL after successful calibration register writes and StoreCalibration. - Include PCB ID and UTC timestamp. 4. Added simulation support - Generate sample Completion and Q3 records for simulated slots. - Perform real SQL writes when the corresponding writer is enabled. - Log connection progress, write outcomes and generated record IDs. 5. Separated calibration and database outcomes - Preserve meter operation results when database storage fails. - Expose database write status independently. 6. Increased revision - Updated revision from 3.9.3146.108 to 3.9.3146.109. Validation: - Confirmed successful SQL storage for simulated Completion. - Confirmed successful Q3 calibration result storage. ToDo: - Use the GCI Q3 storage API as the foundation for future migration of Q3 calibration from the direct TBF communication branch to GCI.
AppDiagnostic.Logging
Reusable NLog target for sending structured diagnostic events from multiple
.NET Framework processes to AppDiagnostic.exe through a local named pipe.
Producer integration
Reference this project from the producer application and add the extension and target to its NLog configuration:
<extensions>
<add assembly="AppDiagnostic.Logging" />
</extensions>
<targets>
<target name="appDiagnostic"
xsi:type="AppDiagnostic"
layout="${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="appDiagnostic" />
</rules>
The target writes to a bounded background queue. Producer threads are not blocked while the diagnostic viewer is unavailable. Queued messages are sent after the viewer becomes available; new messages are discarded when the queue limit is reached.
The receiver can read messages with:
DiagnosticLogEntry entry =
DiagnosticMessageSerializer.ReadFramed(namedPipeServerStream);