Skip to content

Conversation

@tylerkron
Copy link
Contributor

@tylerkron tylerkron commented Nov 6, 2025

User description

Summary

Implements the ability to import device logging sessions from SD card files into the application database, addressing issue #126.

Changes

  • BinaryMessageConsumer: New consumer for downloading binary files from the device
  • SdCardLogParser: Parser for protobuf-encoded SD card log files
  • LoggingSessionImporter: Service to import parsed logs into the database
  • AbstractStreamingDevice: Extended with DownloadSdCardFileAsync method and SD card download message handler
  • DeviceLogsView/ViewModel: Added import UI and command with progress tracking

How it Works

  1. User selects a file from the SD card file list (via USB connection)
  2. Clicks "Import File" button
  3. Application downloads the binary log file from the device
  4. Parser extracts protobuf messages and converts them to DataSamples
  5. Importer creates a new LoggingSession and saves all samples to the database
  6. User receives confirmation with session details

Key Features

  • Progress feedback during download and import
  • Proper SD/LAN interface switching (SD and LAN share SPI bus)
  • Timestamp preservation from log files
  • Batch database operations for performance
  • Error handling and user feedback

Testing

  • Successfully builds
  • Manual testing required (USB device with SD card files needed)

Related Issues

Closes #126

🤖 Generated with Claude Code


PR Type

Enhancement


Description

  • Implements SD card log file import functionality with binary download support

  • Adds BinaryMessageConsumer for streaming binary data from device

  • Creates SdCardLogParser to extract protobuf-encoded samples from log files

  • Implements LoggingSessionImporter service for database persistence

  • Extends device with DownloadSdCardFileAsync method and UI controls


Diagram Walkthrough

flowchart LR
  A["User selects SD card file"] --> B["Click Import button"]
  B --> C["Download binary file via USB"]
  C --> D["Parse protobuf messages"]
  D --> E["Extract data samples"]
  E --> F["Create logging session"]
  F --> G["Save to database"]
  G --> H["Show completion message"]
Loading

File Walkthrough

Relevant files
Enhancement
BinaryMessage.cs
New binary message class for device data                                 

Daqifi.Desktop.IO/Messages/BinaryMessage.cs

  • New message class implementing IInboundMessage interface
  • Stores binary data received from device
  • Includes null validation in constructor
+24/-0   
BinaryMessageConsumer.cs
Binary data consumer for file downloads                                   

Daqifi.Desktop.IO/Messages/Consumers/BinaryMessageConsumer.cs

  • New consumer class for streaming binary file downloads from device
  • Implements buffered reading with 8KB chunks and 100MB file size limit
  • Handles timeout detection with no-data counter mechanism
  • Thread-safe binary data accumulation using MemoryStream
  • Sends complete binary data as BinaryMessage upon completion
+150/-0 
AbstractStreamingDevice.cs
Add SD card file download capability to device                     

Daqifi.Desktop/Device/AbstractStreamingDevice.cs

  • Added SdCardDownload message handler type to enum
  • Added _downloadedFileData and _downloadTaskCompletionSource fields for
    download state
  • Implemented HandleSdCardDownloadMessageReceived method to process
    binary data
  • Added DownloadSdCardFileAsync public method with USB validation,
    timeout handling, and interface switching
  • Properly restores LAN interface after download completion
+118/-1 
IStreamingDevice.cs
Add download method to device interface                                   

Daqifi.Desktop/Device/IStreamingDevice.cs

  • Added DownloadSdCardFileAsync method signature to interface
  • Returns Task for asynchronous binary file download
+1/-0     
LoggingSessionImporter.cs
Service for importing logs to database                                     

Daqifi.Desktop/Services/LoggingSessionImporter.cs

  • New service class for importing SD card logs into application database
  • Parses binary data using SdCardLogParser
  • Creates new LoggingSession with auto-incremented ID
  • Saves samples in batches of 1000 for performance optimization
  • Provides progress reporting through IProgress callback
  • Includes comprehensive error handling and logging
+168/-0 
SdCardLogParser.cs
Parser for protobuf SD card log files                                       

Daqifi.Desktop/Services/SdCardLogParser.cs

  • New parser class for protobuf-encoded SD card log files
  • Implements protobuf message boundary detection with variable length
    scanning
  • Extracts analog channel samples with scaling using device channel
    configuration
  • Extracts digital channel samples with bit-level decoding
  • Handles device timestamp rollover and calculates accurate message
    timestamps
  • Maintains per-device timestamp state for accurate time calculations
+274/-0 
DeviceLogsViewModel.cs
Add import command and file selection to view model           

Daqifi.Desktop/ViewModels/DeviceLogsViewModel.cs

  • Added SelectedFile observable property for file selection
  • Added ImportFileCommand relay command with can-execute validation
  • Implemented ImportFileAsync method handling download, import, and
    progress reporting
  • Updated property change handlers to refresh command state
  • Integrated LoggingSessionImporter service with progress callbacks
  • Added user feedback dialogs for success and error scenarios
+64/-0   
DeviceLogsView.xaml
Add import button and file selection UI                                   

Daqifi.Desktop/View/DeviceLogsView.xaml

  • Added fourth column to device selection grid for Import button
  • Added SelectedItem binding to ListView for file selection
  • Added new Import File button with icon and tooltip
  • Button binding to ImportFileCommand with enabled state validation
  • Minor formatting adjustments to existing controls
+22/-8   

This commit implements the ability to import device logging sessions from SD card files into the application database, as requested in issue #126.

Changes:
- Created BinaryMessageConsumer for downloading binary files from device
- Implemented SdCardLogParser to parse protobuf-encoded SD card log files
- Added LoggingSessionImporter service to import logs into the database
- Extended AbstractStreamingDevice with DownloadSdCardFileAsync method
- Added SD card download message handler (HandleSdCardDownloadMessageReceived)
- Updated DeviceLogsViewModel with import command and progress tracking
- Enhanced DeviceLogsView with Import button and file selection

The implementation:
- Downloads binary log files from the SD card via USB connection
- Parses protobuf messages to extract analog and digital channel data
- Creates a new logging session with all imported samples
- Provides progress feedback during the import process
- Properly handles SD/LAN interface switching

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@tylerkron tylerkron requested a review from a team as a code owner November 6, 2025 04:03
@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Nov 6, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Memory exhaustion

Description: Unbounded read loop buffers the entire download into memory (up to 100 MB) before
dispatch, which can enable memory exhaustion or DoS if a device streams large or
continuous data and the 0.5s idle heuristic fails to terminate.
BinaryMessageConsumer.cs [24-99]

Referred Code
var buffer = new byte[BUFFER_SIZE];
var totalBytesRead = 0;
var noDataCounter = 0;
const int maxNoDataAttempts = 50; // 0.5 seconds of no data before giving up

while (Running && !_isDisposed)
{
    try
    {
        // Check if we should stop
        if (_isDisposed || !Running || DataStream == null || !DataStream.CanRead)
        {
            break;
        }

        int bytesRead;
        try
        {
            bytesRead = DataStream.Read(buffer, 0, buffer.Length);
        }
        catch


 ... (clipped 55 lines)
Resource leak risk

Description: Uses TaskCompletionSource without timeout safeguards on TrySetResult/Stop ordering and
relies on a 30s cancellation; if device sends unexpected data or keeps streaming, race
conditions could leave consumer running and leak resources.
AbstractStreamingDevice.cs [653-729]

Referred Code
public async Task<byte[]> DownloadSdCardFileAsync(string fileName)
{
    if (ConnectionType != ConnectionType.Usb)
    {
        throw new InvalidOperationException("SD Card access is only available when connected via USB");
    }

    if (string.IsNullOrWhiteSpace(fileName))
    {
        throw new ArgumentException("File name cannot be null or empty", nameof(fileName));
    }

    AppLogger.Information($"Starting download of SD card file: {fileName}");

    try
    {
        var stream = MessageConsumer.DataStream;

        // Stop existing consumer first
        if (MessageConsumer.Running)
        {


 ... (clipped 56 lines)
Algorithmic DoS

Description: Protobuf message boundary detection attempts incremental lengths up to 1024 bytes at every
offset, which may be exploited by crafted data to cause heavy CPU usage (algorithmic
complexity DoS).
SdCardLogParser.cs [96-125]

Referred Code
{
    // Protobuf uses varint encoding, so we need to find the message boundaries
    // We'll try different lengths starting from a reasonable minimum size
    const int minMessageSize = 10; // Minimum reasonable size for a protobuf message
    const int maxMessageSize = 1024; // Maximum expected size for a single message

    for (var length = minMessageSize; length <= maxMessageSize && offset + length <= data.Length; length++)
    {
        try
        {
            var messageBytes = new byte[length];
            Array.Copy(data, offset, messageBytes, 0, length);

            var message = DaqifiOutMessage.Parser.ParseFrom(messageBytes);

            // Validate that this looks like a reasonable message
            if (message.MsgTimeStamp > 0)
            {
                return (message, length);
            }
        }


 ... (clipped 9 lines)
Ticket Compliance
🟡
🎫 #126
🟢 Allow user to import device logging sessions stored on the SD card into the application.
Provide UI to select a device SD card log file and trigger import.
Download the selected binary log file from the device over USB.
Parse protobuf-encoded SD card log files into application data samples while preserving
timestamps.
Create a new logging session in the application database and save imported samples.
Offer progress/feedback during download and import, and user-facing success/error
messages.
Handle SD/LAN interface switching appropriately during SD operations.
End-to-end verification with an actual USB-connected device and SD card to ensure file
download reliability and parser correctness on real data.
Validate that timestamps are accurately preserved across long sessions and rollover
scenarios with real hardware logs.
Confirm UI/UX behavior and responsiveness during long imports, including progress updates
and button enable/disable states.
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

🔴
Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Internal errors exposed: User-facing dialogs display raw exception messages (ex.Message) for refresh and import
failures which may reveal internal details to end users.

Referred Code
        await Application.Current.Dispatcher.InvokeAsync(async () =>
        {
            await ShowMessage("Error", $"Failed to refresh files: {ex.Message}", MessageDialogStyle.Affirmative);
        });
    }
    finally
    {
        IsBusy = false;
        BusyMessage = string.Empty;
    }
}

private async Task ImportFileAsync()
{
    if (SelectedFile == null || SelectedDevice == null || !CanAccessSdCard)
    {
        return;
    }

    try
    {


 ... (clipped 37 lines)
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Action logging: Import operations log high-level progress but do not consistently log user identity or
detailed action outcomes needed for audit trails (e.g., who initiated import, counts
persisted), which may be handled elsewhere.

Referred Code
public async Task<LoggingSession> ImportSdCardLogAsync(
    SdCardFile sdCardFile,
    byte[] binaryData,
    IStreamingDevice device,
    IProgress<ImportProgress>? progress = null)
{
    if (sdCardFile == null)
    {
        throw new ArgumentNullException(nameof(sdCardFile));
    }

    if (binaryData == null || binaryData.Length == 0)
    {
        throw new ArgumentException("Binary data cannot be null or empty", nameof(binaryData));
    }

    if (device == null)
    {
        throw new ArgumentNullException(nameof(device));
    }



 ... (clipped 97 lines)
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Timeout handling: Download routine uses a fixed 30s timeout and immediate consumer stop without visible
cleanup/rollback of interface state on failure which might lead to partial state issues,
though external mechanisms may exist.

Referred Code
public async Task<byte[]> DownloadSdCardFileAsync(string fileName)
{
    if (ConnectionType != ConnectionType.Usb)
    {
        throw new InvalidOperationException("SD Card access is only available when connected via USB");
    }

    if (string.IsNullOrWhiteSpace(fileName))
    {
        throw new ArgumentException("File name cannot be null or empty", nameof(fileName));
    }

    AppLogger.Information($"Starting download of SD card file: {fileName}");

    try
    {
        var stream = MessageConsumer.DataStream;

        // Stop existing consumer first
        if (MessageConsumer.Running)
        {


 ... (clipped 56 lines)
Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
File name logging: Logs include SD card file names and sizes; while useful for debugging, confirm that
filenames cannot include sensitive user data and that this is acceptable under logging
policy.

Referred Code
AppLogger.Information($"Starting download of SD card file: {fileName}");

try
{
    var stream = MessageConsumer.DataStream;

    // Stop existing consumer first
    if (MessageConsumer.Running)
    {
        MessageConsumer.Stop();
    }

    // Reset download state
    _downloadedFileData = null;
    _downloadTaskCompletionSource = new TaskCompletionSource<byte[]>();

    // Create and start a binary message consumer for the download
    MessageConsumer = new IO.Messages.Consumers.BinaryMessageConsumer(stream);
    SetMessageHandler(MessageHandlerType.SdCardDownload);
    MessageConsumer.Start();



 ... (clipped 38 lines)
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Filename validation: DownloadSdCardFileAsync checks for empty strings but does not validate or sanitize
fileName against path traversal or invalid characters, which may be constrained by device
SCPI but is not evident here.

Referred Code
public async Task<byte[]> DownloadSdCardFileAsync(string fileName)
{
    if (ConnectionType != ConnectionType.Usb)
    {
        throw new InvalidOperationException("SD Card access is only available when connected via USB");
    }

    if (string.IsNullOrWhiteSpace(fileName))
    {
        throw new ArgumentException("File name cannot be null or empty", nameof(fileName));
    }

    AppLogger.Information($"Starting download of SD card file: {fileName}");
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Nov 6, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Redesign the import process for streaming

The current implementation loads the entire SD card file into memory before
parsing, which is inefficient for large files. It should be refactored to
process the file as a stream, reading and parsing in chunks to keep memory usage
low.

Examples:

Daqifi.Desktop.IO/Messages/Consumers/BinaryMessageConsumer.cs [23-100]
    {
        var buffer = new byte[BUFFER_SIZE];
        var totalBytesRead = 0;
        var noDataCounter = 0;
        const int maxNoDataAttempts = 50; // 0.5 seconds of no data before giving up

        while (Running && !_isDisposed)
        {
            try
            {

 ... (clipped 68 lines)
Daqifi.Desktop/Services/LoggingSessionImporter.cs [39-74]
    public async Task<LoggingSession> ImportSdCardLogAsync(
        SdCardFile sdCardFile,
        byte[] binaryData,
        IStreamingDevice device,
        IProgress<ImportProgress>? progress = null)
    {
        if (sdCardFile == null)
        {
            throw new ArgumentNullException(nameof(sdCardFile));
        }

 ... (clipped 26 lines)

Solution Walkthrough:

Before:

// AbstractStreamingDevice.cs
async Task<byte[]> DownloadSdCardFileAsync(...) {
    // ...
    MessageConsumer = new BinaryMessageConsumer(stream);
    // ...
    var data = await _downloadTaskCompletionSource.Task; // Waits for the whole file
    return data;
}

// BinaryMessageConsumer.cs
void Run() {
    var _binaryData = new MemoryStream();
    while (reading) {
        _binaryData.Write(buffer, 0, bytesRead); // Accumulate all data
    }
    var data = _binaryData.ToArray(); // Convert whole stream to byte array
    NotifyMessageReceived(new BinaryMessage(data)); // Send one message with all data
}

// LoggingSessionImporter.cs
async Task ImportSdCardLogAsync(byte[] binaryData, ...) {
    var samples = _parser.ParseLogFile(binaryData, device); // Parse all data at once
    // ... save all samples to DB
}

After:

// AbstractStreamingDevice.cs
async Task ImportSdCardFileAsync(string fileName, IProgress<ImportProgress> progress) {
    var stream = MessageConsumer.DataStream;
    var importer = new LoggingSessionImporter();
    await importer.ImportFromStreamAsync(fileName, stream, this, progress);
}

// LoggingSessionImporter.cs
async Task ImportFromStreamAsync(string fileName, Stream stream, ...) {
    // ... create session
    var parser = new SdCardLogParser();
    await foreach (var sample in parser.ParseLogStream(stream, device))
    {
        // Add sample to DbContext and save periodically in batches
    }
}

// SdCardLogParser.cs
async IAsyncEnumerable<DataSample> ParseLogStream(Stream stream, ...) {
    // Read stream in chunks
    while (await stream.ReadAsync(buffer) > 0) {
        // Process buffer, potentially holding state for messages split across chunks
        // yield return sample;
    }
}
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical design flaw where the entire file is loaded into memory, which can cause significant memory issues and crashes with large log files.

High
Possible issue
Ensure device state is always restored

Move the device network interface restoration logic to the finally block in
DownloadSdCardFileAsync to ensure the device state is correctly reset even if
the download fails.

Daqifi.Desktop/Device/AbstractStreamingDevice.cs [704-709]

-// After downloading, restore LAN interface if we're in StreamToApp mode
-if (Mode == DeviceMode.StreamToApp)
-{
-    MessageProducer.Send(ScpiMessageProducer.DisableStorageSd);
-    MessageProducer.Send(ScpiMessageProducer.EnableNetworkLan);
-}
+// This logic is now in the finally block.
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly points out that the device's network interface is not restored on download failure, leaving it in an inconsistent state. Moving the restoration logic to a finally block is a critical fix for device stability.

High
Fix race condition and duplicate processing

To prevent a race condition and duplicate processing, modify the Stop() method
to only signal termination, and let the Run() method handle final data
processing and resource disposal.

Daqifi.Desktop.IO/Messages/Consumers/BinaryMessageConsumer.cs [131-149]

 public override void Stop()
 {
     try
     {
         _isDisposed = true;
-
-        // Process any remaining data before stopping
-        ProcessBinaryData();
-
-        // Clean up
-        _binaryData?.Dispose();
-
         base.Stop();
     }
     catch (Exception ex)
     {
         AppLogger.Error(ex, "Failed to stop BinaryMessageConsumer");
     }
 }
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a race condition and a potential ObjectDisposedException due to ProcessBinaryData() being called from both Run() and Stop(), which could lead to duplicate processing and crashes.

Medium
Use robust protobuf stream parsing

Replace the unreliable brute-force protobuf parsing in TryParseProtobufMessage
with CodedInputStream to robustly handle length-delimited messages from the data
stream, improving parsing efficiency and accuracy.

Daqifi.Desktop/Services/SdCardLogParser.cs [95-125]

 private (DaqifiOutMessage? message, int bytesRead) TryParseProtobufMessage(byte[] data, int offset)
 {
-    // Protobuf uses varint encoding, so we need to find the message boundaries
-    // We'll try different lengths starting from a reasonable minimum size
-    const int minMessageSize = 10; // Minimum reasonable size for a protobuf message
-    const int maxMessageSize = 1024; // Maximum expected size for a single message
+    if (offset >= data.Length)
+    {
+        return (null, 0);
+    }
 
-    for (var length = minMessageSize; length <= maxMessageSize && offset + length <= data.Length; length++)
+    try
     {
-        try
+        using var stream = new MemoryStream(data, offset, data.Length - offset);
+        using var codedStream = new CodedInputStream(stream);
+
+        // Protobuf messages are often prefixed with their length (as a varint).
+        // If not, this will need adjustment based on the actual file format.
+        // Assuming length-prefixed for now as a standard practice.
+        if (codedStream.IsAtEnd) return (null, 0);
+
+        var length = codedStream.ReadLength();
+        if (length == 0 || codedStream.IsAtEnd || codedStream.Position + length > stream.Length)
         {
-            var messageBytes = new byte[length];
-            Array.Copy(data, offset, messageBytes, 0, length);
+            return (null, 0);
+        }
 
-            var message = DaqifiOutMessage.Parser.ParseFrom(messageBytes);
+        var message = DaqifiOutMessage.Parser.ParseFrom(codedStream.ReadBytes(length));
 
-            // Validate that this looks like a reasonable message
-            if (message.MsgTimeStamp > 0)
-            {
-                return (message, length);
-            }
+        // The total bytes read includes the varint length prefix and the message itself.
+        var bytesRead = (int)codedStream.Position;
+
+        // Validate that this looks like a reasonable message
+        if (message.MsgTimeStamp > 0)
+        {
+            return (message, bytesRead);
         }
-        catch
-        {
-            // This length didn't work, try the next
-            continue;
-        }
+    }
+    catch
+    {
+        // Could not parse a message at this offset.
     }
 
     return (null, 0);
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that the brute-force parsing method is unreliable and proposes a more robust solution using CodedInputStream, which would improve parsing reliability. However, it assumes a length-prefixed message format which may not match the actual data format, requiring verification.

Medium
Learned
best practice
Log import exceptions with context

Log the exception with the centralized logger including the exception object to
preserve diagnostic context before notifying the user.

Daqifi.Desktop/ViewModels/DeviceLogsViewModel.cs [204-210]

 catch (Exception ex)
 {
+    AppLogger.Instance.Error(ex, "Failed to import SD card file");
     await Application.Current.Dispatcher.InvokeAsync(async () =>
     {
         await ShowMessage("Import Failed", $"Failed to import file: {ex.Message}", MessageDialogStyle.Affirmative);
     });
 }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Ensure exceptions are logged with full context using the centralized logger to aid troubleshooting.

Low
  • More

@github-actions
Copy link

github-actions bot commented Nov 6, 2025

📊 Code Coverage Report

Summary

Summary
Generated on: 11/6/2025 - 4:06:16 AM
Coverage date: 11/6/2025 - 4:06:02 AM - 11/6/2025 - 4:06:12 AM
Parser: MultiReport (5x Cobertura)
Assemblies: 5
Classes: 124
Files: 157
Line coverage: 11.3% (680 of 6014)
Covered lines: 680
Uncovered lines: 5334
Coverable lines: 6014
Total lines: 18453
Branch coverage: 11.3% (244 of 2156)
Covered branches: 244
Total branches: 2156
Method coverage: Feature is only available for sponsors

Coverage

DAQiFi - 9.9%
Name Line Branch
DAQiFi 9.9% 10.5%
Daqifi.Desktop.App 3% 0%
Daqifi.Desktop.Channel.AbstractChannel 22.7% 25%
Daqifi.Desktop.Channel.AnalogChannel 50% 25%
Daqifi.Desktop.Channel.Channel 11.5% 0%
Daqifi.Desktop.Channel.ChannelColorManager 100% 100%
Daqifi.Desktop.Channel.DataSample 90.4%
Daqifi.Desktop.Channel.DigitalChannel 0% 0%
Daqifi.Desktop.Commands.CompositeCommand 0% 0%
Daqifi.Desktop.Commands.HostCommands 0%
Daqifi.Desktop.Commands.WeakEventHandlerManager 0% 0%
Daqifi.Desktop.Configuration.FirewallConfiguration 90.6% 66.6%
Daqifi.Desktop.Configuration.WindowsFirewallWrapper 64% 68.4%
Daqifi.Desktop.ConnectionManager 40.9% 55.8%
Daqifi.Desktop.Converters.BoolToActiveStatusConverter 0% 0%
Daqifi.Desktop.Converters.BoolToConnectionStatusConverter 0% 0%
Daqifi.Desktop.Converters.BoolToStatusColorConverter 0% 0%
Daqifi.Desktop.Converters.ConnectionTypeToColorConverter 0% 0%
Daqifi.Desktop.Converters.ConnectionTypeToUsbConverter 0% 0%
Daqifi.Desktop.Converters.InvertedBoolToVisibilityConverter 0% 0%
Daqifi.Desktop.Converters.ListToStringConverter 0% 0%
Daqifi.Desktop.Converters.NotNullToVisibilityConverter 0% 0%
Daqifi.Desktop.Converters.OxyColorToBrushConverter 0% 0%
Daqifi.Desktop.Device.AbstractStreamingDevice 4.9% 2.7%
Daqifi.Desktop.Device.DeviceInfoConverter 0% 0%
Daqifi.Desktop.Device.DeviceMessage 0%
Daqifi.Desktop.Device.DeviceTypeDetector 100% 100%
Daqifi.Desktop.Device.HidDevice.HidFirmwareDevice 0%
Daqifi.Desktop.Device.NativeMethods 0%
Daqifi.Desktop.Device.SerialDevice.SerialDeviceHelper 0% 0%
Daqifi.Desktop.Device.SerialDevice.SerialStreamingDevice 7.7% 15%
Daqifi.Desktop.Device.SerialDevice.UsbDevice 0% 0%
Daqifi.Desktop.Device.WiFiDevice.DaqifiStreamingDevice 19.6% 0%
Daqifi.Desktop.DialogService.DialogService 0% 0%
Daqifi.Desktop.DialogService.ServiceLocator 0% 0%
Daqifi.Desktop.DuplicateDeviceCheckResult 100%
Daqifi.Desktop.Exporter.OptimizedLoggingSessionExporter 29.7% 32.9%
Daqifi.Desktop.Exporter.SampleData 0%
Daqifi.Desktop.Helpers.BooleanConverter`1 0% 0%
Daqifi.Desktop.Helpers.BooleanToInverseBoolConverter 0% 0%
Daqifi.Desktop.Helpers.BooleanToVisibilityConverter 0%
Daqifi.Desktop.Helpers.EnumDescriptionConverter 100% 100%
Daqifi.Desktop.Helpers.IntToVisibilityConverter 0% 0%
Daqifi.Desktop.Helpers.MyMultiValueConverter 0%
Daqifi.Desktop.Helpers.NaturalSortHelper 100% 100%
Daqifi.Desktop.Helpers.VersionHelper 98.2% 66.2%
Daqifi.Desktop.Logger.DatabaseLogger 0% 0%
Daqifi.Desktop.Logger.LoggedSeriesLegendItem 0% 0%
Daqifi.Desktop.Logger.LoggingContext 0%
Daqifi.Desktop.Logger.LoggingManager 0% 0%
Daqifi.Desktop.Logger.LoggingSession 26.6% 0%
Daqifi.Desktop.Logger.PlotLogger 0% 0%
Daqifi.Desktop.Logger.SummaryLogger 0% 0%
Daqifi.Desktop.Loggers.FirmwareUpdatationManager 5.8% 0%
Daqifi.Desktop.MainWindow 0% 0%
Daqifi.Desktop.Migrations.InitialSQLiteMigration 0%
Daqifi.Desktop.Migrations.LoggingContextModelSnapshot 0%
Daqifi.Desktop.Models.AddProfileModel 0%
Daqifi.Desktop.Models.DaqifiSettings 86.3% 100%
Daqifi.Desktop.Models.DebugDataCollection 0% 0%
Daqifi.Desktop.Models.DebugDataModel 0% 0%
Daqifi.Desktop.Models.Notifications 0%
Daqifi.Desktop.Models.SdCardFile 0%
Daqifi.Desktop.Services.ImportProgress 0%
Daqifi.Desktop.Services.LoggingSessionImporter 0% 0%
Daqifi.Desktop.Services.SdCardLogParser 0% 0%
Daqifi.Desktop.Services.WindowsPrincipalAdminChecker 0%
Daqifi.Desktop.Services.WpfMessageBoxService 0%
Daqifi.Desktop.UpdateVersion.VersionNotification 0% 0%
Daqifi.Desktop.View.AddChannelDialog 0% 0%
Daqifi.Desktop.View.AddProfileConfirmationDialog 0% 0%
Daqifi.Desktop.View.AddprofileDialog 0% 0%
Daqifi.Desktop.View.ConnectionDialog 0% 0%
Daqifi.Desktop.View.DebugWindow 0% 0%
Daqifi.Desktop.View.DeviceLogsView 0% 0%
Daqifi.Desktop.View.DuplicateDeviceDialog 0% 0%
Daqifi.Desktop.View.ErrorDialog 0% 0%
Daqifi.Desktop.View.ExportDialog 0% 0%
Daqifi.Desktop.View.FirmwareDialog 0% 0%
Daqifi.Desktop.View.Flyouts.ChannelsFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.DevicesFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.FirmwareFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.LiveGraphFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.LoggedSessionFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.NotificationsFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.SummaryFlyout 0% 0%
Daqifi.Desktop.View.Flyouts.UpdateProfileFlyout 0% 0%
Daqifi.Desktop.View.SelectColorDialog 0% 0%
Daqifi.Desktop.View.SettingsDialog 0% 0%
Daqifi.Desktop.View.SuccessDialog 0% 0%
Daqifi.Desktop.ViewModels.AddChannelDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.AddProfileConfirmationDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.AddProfileDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.ConnectionDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.DaqifiViewModel 0% 0%
Daqifi.Desktop.ViewModels.DeviceLogsViewModel 0% 0%
Daqifi.Desktop.ViewModels.DeviceSettingsViewModel 0% 0%
Daqifi.Desktop.ViewModels.DuplicateDeviceDialogViewModel 0%
Daqifi.Desktop.ViewModels.ErrorDialogViewModel 0%
Daqifi.Desktop.ViewModels.ExportDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.FirmwareDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.SelectColorDialogViewModel 0% 0%
Daqifi.Desktop.ViewModels.SettingsViewModel 0%
Daqifi.Desktop.ViewModels.SuccessDialogViewModel 0%
Daqifi.Desktop.WindowViewModelMapping.IWindowViewModelMappingsContract 0%
Daqifi.Desktop.WindowViewModelMapping.WindowViewModelMappings 0%
Daqifi.Desktop.Bootloader - 20.6%
Name Line Branch
Daqifi.Desktop.Bootloader 20.6% 17.3%
Daqifi.Desktop.Bootloader.Crc16 100% 100%
Daqifi.Desktop.Bootloader.Exceptions.FirmwareUpdateException 0%
Daqifi.Desktop.Bootloader.FirmwareDownloader 82% 66.6%
Daqifi.Desktop.Bootloader.Pic32Bootloader 0% 0%
Daqifi.Desktop.Bootloader.Pic32BootloaderMessageConsumer 0% 0%
Daqifi.Desktop.Bootloader.Pic32BootloaderMessageProducer 80.9% 100%
Daqifi.Desktop.Bootloader.WifiFirmwareDownloader 0% 0%
Daqifi.Desktop.Bootloader.WifiModuleUpdater 0% 0%
Daqifi.Desktop.Common - 45.9%
Name Line Branch
Daqifi.Desktop.Common 45.9% 33.3%
Daqifi.Desktop.Common.Loggers.AppLogger 42.1% 33.3%
Daqifi.Desktop.Common.Loggers.NoOpLogger 100%
Daqifi.Desktop.DataModel - 100%
Name Line Branch
Daqifi.Desktop.DataModel 100% ****
Daqifi.Desktop.DataModel.Device.DeviceInfo 100%
Daqifi.Desktop.IO - 17.4%
Name Line Branch
Daqifi.Desktop.IO 17.4% 13.7%
Daqifi.Desktop.IO.Messages.BinaryMessage 0% 0%
Daqifi.Desktop.IO.Messages.Consumers.AbstractMessageConsumer 0% 0%
Daqifi.Desktop.IO.Messages.Consumers.BinaryMessageConsumer 0% 0%
Daqifi.Desktop.IO.Messages.Consumers.MessageConsumer 0% 0%
Daqifi.Desktop.IO.Messages.Consumers.TextMessageConsumer 0% 0%
Daqifi.Desktop.IO.Messages.Decoders.ProtobufDecoder 100% 75%
Daqifi.Desktop.IO.Messages.MessageEventArgs`1 0%
Daqifi.Desktop.IO.Messages.Producers.MessageProducer 81% 80%

Coverage report generated by ReportGeneratorView full report in build artifacts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Import logging session from device to application

2 participants