Oakrey.Applications.FileParsing.DBC 1.0.1

dotnet add package Oakrey.Applications.FileParsing.DBC --version 1.0.1
                    
NuGet\Install-Package Oakrey.Applications.FileParsing.DBC -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Oakrey.Applications.FileParsing.DBC" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Oakrey.Applications.FileParsing.DBC" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Oakrey.Applications.FileParsing.DBC" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Oakrey.Applications.FileParsing.DBC --version 1.0.1
                    
#r "nuget: Oakrey.Applications.FileParsing.DBC, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Oakrey.Applications.FileParsing.DBC@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Oakrey.Applications.FileParsing.DBC&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Oakrey.Applications.FileParsing.DBC&version=1.0.1
                    
Install as a Cake Tool

Oakrey.Applications.FileParsing.DBC

A specialized file parsing library for DBC (CAN database) files, built on the FileParsing framework. Provides automatic parsing of DBC files into DbcMatrix objects with reactive updates, file browsing integration, and extended file management capabilities.

Features

DBC File Parsing

  • Automatic Parsing: Parses DBC files using Oakrey.DBC library
  • DbcMatrix Support: Returns structured CAN database with messages, signals, and metadata
  • Extended Browsing: Integrates with FileBrowsing.Extended for file operations
  • Template Support: Includes default DBC template for creating new files

File Management Integration

  • Create New DBC Files: Create files from customizable templates
  • File Browsing: Browse and select DBC files in directories
  • Reactive Updates: Observable pattern for file change notifications
  • Auto-Load Support: Optionally load DBC files at application startup

CAN Database Access

  • Messages: Access CAN message definitions
  • Signals: Work with signal definitions and parameters
  • Network Nodes: Retrieve ECU and node information
  • Attributes: Access extended attributes and metadata

Settings Integration

  • Persistent Configuration: Settings automatically saved and restored
  • Auto-Load Control: Enable/disable automatic file loading
  • Last Selected File: Remembers last opened DBC file

Built on FileParsing Framework

  • Extends FileParsingServiceBase<DbcMatrix>
  • Inherits all file parsing framework features
  • Consistent API with other file parsers

Installation

You can install the package via NuGet Package Manager, Package Manager Console or the .NET CLI.

NuGet Package Manager

  1. Open your project in Visual Studio.
  2. Navigate to Tools > NuGet Package Manager > Manage NuGet Packages for Solution....
  3. Search for Oakrey.Applications.FileParsing.DBC and click Install.

.NET CLI

Run the following command in your terminal:

dotnet add package Oakrey.Applications.FileParsing.DBC

Package Manager Console

Run the following command in your Package Manager Console:

Install-Package Oakrey.Applications.FileParsing.DBC

Prerequisites

This package requires:

  • Oakrey.Applications.FileParsing - Base file parsing framework
  • Oakrey.Applications.FileBrowsing.Extended - Extended file browsing with templates
  • Oakrey.DBC - DBC file parsing library (DbcMatrix)

Usage Examples

Basic Dependency Injection Setup

using Microsoft.Extensions.DependencyInjection;
using Oakrey.Applications.FileBrowsing.Extended;
using Oakrey.Applications.FileParsing.DBC;
using Oakrey.Applications.UserPrompts.Windows;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Register user prompts (required)
        services.AddUserPromptsService();
        
        // Register extended file browsing for DBC files
        services.AddSingleton<IFileExtendedBrowsingServiceSettings, 
                             DbcExtendedFileBrowsingServiceSettings>();
        services.AddSingleton<IFileBrowsingService, IExtendedFileBrowsingService,
                             ExtendedFileBrowsingService>();
        
        // Register DBC parsing service settings
        services.AddSingleton<ISettingsService<DbcServiceSettings>, 
                             SettingsService<DbcServiceSettings>>();
        services.AddSingleton<IDbcServiceSettings, DbcServiceSettings>();
        
        // Register DBC parsing service
        services.AddSingleton<IDbcService, DbcService>();
    }
}

Creating DBC File Browsing Settings

using Oakrey.Applications.FileBrowsing;
using Oakrey.Applications.FileBrowsing.Extended;
using Oakrey.Applications.Settings;

public class DbcExtendedFileBrowsingServiceSettings 
    : FileBrowsingServiceSettingsBase, IFileExtendedBrowsingServiceSettings
{
    public DbcExtendedFileBrowsingServiceSettings(
        ISettingsService<DbcExtendedFileBrowsingServiceSettings> settingsService)
        : base(settingsService)
    {
    }

    public override string FileExtension => "dbc";
    public override string SearchPattern => "*.dbc";
    
    // Template loaded from external file or defined inline
    public string NewFileTemplate
    {
        get
        {
            string templatePath = Path.Combine(
                AppDomain.CurrentDomain.BaseDirectory, 
                "dbcNew.txt");
            
            if (File.Exists(templatePath))
            {
                return File.ReadAllText(templatePath);
            }
            
            // Fallback template
            return "VERSION \"\"\n\nNS_ :\n\nBS_:\n\nBU_:\n";
        }
    }
}

Using the DBC Service

using Oakrey.Applications.FileParsing.DBC;
using Oakrey.DBC;

public class CanManager
{
    private readonly IDbcService _dbcService;

    public CanManager(IDbcService dbcService)
    {
        _dbcService = dbcService;
        
        // Subscribe to DBC file changes
        _dbcService.FileParsed.Subscribe(OnDbcFileParsed);
    }

    private void OnDbcFileParsed(DbcMatrix? dbcMatrix)
    {
        if (dbcMatrix != null)
        {
            Console.WriteLine($"DBC file loaded: {_dbcService.FilePath}");
            Console.WriteLine($"Messages: {dbcMatrix.Messages.Count}");
            Console.WriteLine($"Nodes: {dbcMatrix.Nodes.Count}");
            
            // Process the DBC database
            ProcessCanDatabase(dbcMatrix);
        }
        else
        {
            Console.WriteLine("No DBC file loaded");
        }
    }

    public void ProcessCanDatabase(DbcMatrix matrix)
    {
        // Access CAN messages
        foreach (var message in matrix.Messages)
        {
            Console.WriteLine($"Message: {message.Name} (ID: 0x{message.Id:X})");
            
            // Access signals in the message
            foreach (var signal in message.Signals)
            {
                Console.WriteLine($"  Signal: {signal.Name}");
                Console.WriteLine($"    Start Bit: {signal.StartBit}");
                Console.WriteLine($"    Length: {signal.Length} bits");
                Console.WriteLine($"    Factor: {signal.Factor}");
                Console.WriteLine($"    Offset: {signal.Offset}");
            }
        }
    }
}

Accessing Current DBC Matrix

public class CanDataProcessor
{
    private readonly IDbcService _dbcService;

    public CanDataProcessor(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public void ProcessCanMessage(uint canId, byte[] data)
    {
        // Access current DBC matrix
        if (_dbcService.Instance == null)
        {
            Console.WriteLine("No DBC file loaded");
            return;
        }

        var dbcMatrix = _dbcService.Instance;
        
        // Find message by CAN ID
        var message = dbcMatrix.Messages.FirstOrDefault(m => m.Id == canId);
        
        if (message == null)
        {
            Console.WriteLine($"Message ID 0x{canId:X} not found in DBC");
            return;
        }

        Console.WriteLine($"Processing message: {message.Name}");
        
        // Decode signals
        foreach (var signal in message.Signals)
        {
            double value = DecodeSignal(signal, data);
            double physicalValue = value * signal.Factor + signal.Offset;
            
            Console.WriteLine($"  {signal.Name}: {physicalValue} {signal.Unit}");
        }
    }

    private double DecodeSignal(Signal signal, byte[] data)
    {
        // Implement signal decoding logic based on start bit, length, byte order
        // This is a simplified example
        ulong rawValue = 0;
        
        for (int i = 0; i < signal.Length; i++)
        {
            int bitPos = signal.StartBit + i;
            int byteIndex = bitPos / 8;
            int bitIndex = bitPos % 8;
            
            if (byteIndex < data.Length)
            {
                if ((data[byteIndex] & (1 << bitIndex)) != 0)
                {
                    rawValue |= (1UL << i);
                }
            }
        }
        
        return rawValue;
    }
}

WPF ViewModel Integration

using Oakrey.Applications.FileParsing.DBC;
using System.ComponentModel;
using System.Windows.Input;
using CommunityToolkit.Mvvm.Input;

public class DbcViewModel : INotifyPropertyChanged
{
    private readonly IDbcService _dbcService;
    private DbcMatrix? _currentMatrix;

    public DbcViewModel(IDbcService dbcService)
    {
        _dbcService = dbcService;
        
        // Subscribe to DBC file changes
        _dbcService.FileParsed.Subscribe(OnDbcParsed);
        
        // Initialize with current matrix
        _currentMatrix = _dbcService.Instance;
        
        LoadFileCommand = new AsyncRelayCommand<string>(LoadFileAsync);
        RefreshCommand = new RelayCommand(Refresh);
    }

    public DbcMatrix? CurrentMatrix
    {
        get => _currentMatrix;
        set
        {
            if (_currentMatrix != value)
            {
                _currentMatrix = value;
                OnPropertyChanged(nameof(CurrentMatrix));
                OnPropertyChanged(nameof(IsFileLoaded));
                OnPropertyChanged(nameof(MessageCount));
                OnPropertyChanged(nameof(NodeCount));
            }
        }
    }

    public bool IsFileLoaded => _dbcService.IsFilePathCorrect;
    
    public string CurrentFilePath => _dbcService.FilePath;
    
    public int MessageCount => CurrentMatrix?.Messages.Count ?? 0;
    
    public int NodeCount => CurrentMatrix?.Nodes.Count ?? 0;
    
    public List<string> MessageNames => 
        CurrentMatrix?.Messages.Select(m => m.Name).ToList() ?? new List<string>();

    public IAsyncRelayCommand<string> LoadFileCommand { get; }
    public ICommand RefreshCommand { get; }

    private void OnDbcParsed(DbcMatrix? matrix)
    {
        CurrentMatrix = matrix;
        OnPropertyChanged(nameof(CurrentFilePath));
    }

    private async Task LoadFileAsync(string? filePath)
    {
        if (!string.IsNullOrEmpty(filePath))
        {
            var fileInfo = new FileInfo(filePath);
            await _dbcService.LoadFile(fileInfo);
        }
    }

    private void Refresh()
    {
        CurrentMatrix = _dbcService.Instance;
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Manual File Loading

public class DbcFileLoader
{
    private readonly IDbcService _dbcService;

    public DbcFileLoader(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public async Task<DbcMatrix?> LoadDbcFileAsync(string filePath)
    {
        var fileInfo = new FileInfo(filePath);
        
        if (!fileInfo.Exists)
        {
            Console.WriteLine($"DBC file not found: {filePath}");
            return null;
        }

        // Manually load the file
        var dbcMatrix = await _dbcService.LoadFile(fileInfo);
        
        if (dbcMatrix != null)
        {
            Console.WriteLine($"Loaded DBC file: {filePath}");
            Console.WriteLine($"Messages: {dbcMatrix.Messages.Count}");
            Console.WriteLine($"Signals: {dbcMatrix.Messages.Sum(m => m.Signals.Count)}");
            return dbcMatrix;
        }

        return null;
    }

    public async Task<DbcMatrix?> LoadWithCancellationAsync(
        string filePath, 
        CancellationToken cancellationToken)
    {
        var fileInfo = new FileInfo(filePath);
        
        try
        {
            var dbcMatrix = await _dbcService.LoadFile(fileInfo, cancellationToken);
            
            if (dbcMatrix != null && !cancellationToken.IsCancellationRequested)
            {
                return dbcMatrix;
            }
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Load operation cancelled");
        }

        return null;
    }
}

Pre-Loading at Application Startup

using Oakrey.Applications;

public class ApplicationStartup
{
    private readonly IDbcService _dbcService;

    public ApplicationStartup(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public async Task InitializeAsync(CancellationToken cancellationToken)
    {
        // Pre-load DBC file if AutoLoad is enabled
        if (_dbcService is IPreLoadable preLoadable)
        {
            await preLoadable.Preload(cancellationToken);
            
            if (_dbcService.Instance != null)
            {
                Console.WriteLine("DBC file pre-loaded successfully");
                Console.WriteLine($"File: {_dbcService.FilePath}");
                Console.WriteLine($"Messages: {_dbcService.Instance.Messages.Count}");
            }
        }
    }
}

Working with CAN Messages and Signals

public class CanMessageAnalyzer
{
    private readonly IDbcService _dbcService;

    public CanMessageAnalyzer(IDbcService dbcService)
    {
        _dbcService = dbcService;
    }

    public void AnalyzeMessage(string messageName)
    {
        if (_dbcService.Instance == null)
        {
            Console.WriteLine("No DBC file loaded");
            return;
        }

        var message = _dbcService.Instance.Messages
            .FirstOrDefault(m => m.Name == messageName);

        if (message == null)
        {
            Console.WriteLine($"Message '{messageName}' not found");
            return;
        }

        Console.WriteLine($"Message: {message.Name}");
        Console.WriteLine($"  CAN ID: 0x{message.Id:X}");
        Console.WriteLine($"  DLC: {message.Length} bytes");
        Console.WriteLine($"  Transmitter: {message.Transmitter}");
        Console.WriteLine($"  Signals: {message.Signals.Count}");
        Console.WriteLine();

        foreach (var signal in message.Signals)
        {
            Console.WriteLine($"  Signal: {signal.Name}");
            Console.WriteLine($"    Start Bit: {signal.StartBit}");
            Console.WriteLine($"    Length: {signal.Length} bits");
            Console.WriteLine($"    Byte Order: {signal.ByteOrder}");
            Console.WriteLine($"    Value Type: {signal.ValueType}");
            Console.WriteLine($"    Factor: {signal.Factor}");
            Console.WriteLine($"    Offset: {signal.Offset}");
            Console.WriteLine($"    Min: {signal.Minimum}");
            Console.WriteLine($"    Max: {signal.Maximum}");
            Console.WriteLine($"    Unit: {signal.Unit}");
            Console.WriteLine($"    Receivers: {string.Join(", ", signal.Receivers)}");
            Console.WriteLine();
        }
    }

    public void ListAllMessages()
    {
        if (_dbcService.Instance == null)
        {
            Console.WriteLine("No DBC file loaded");
            return;
        }

        Console.WriteLine("CAN Messages:");
        Console.WriteLine("ID       | Name                | DLC | Signals");
        Console.WriteLine("---------|---------------------|-----|--------");

        foreach (var message in _dbcService.Instance.Messages.OrderBy(m => m.Id))
        {
            Console.WriteLine($"0x{message.Id:X3}    | {message.Name,-19} | {message.Length}   | {message.Signals.Count}");
        }
    }

    public void ListAllNodes()
    {
        if (_dbcService.Instance == null)
        {
            Console.WriteLine("No DBC file loaded");
            return;
        }

        Console.WriteLine("Network Nodes:");
        foreach (var node in _dbcService.Instance.Nodes)
        {
            Console.WriteLine($"  - {node}");
        }
    }
}

Complete Application Example

using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Oakrey.Applications.FileBrowsing.Extended;
using Oakrey.Applications.FileParsing.DBC;
using Oakrey.Applications.UserPrompts.Windows;

public partial class App : Application
{
    private IServiceProvider _serviceProvider;

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var services = new ServiceCollection();
        
        // Register user prompts
        services.AddUserPromptsService();
        
        // Register extended file browsing for DBC files
        services.AddSingleton<ISettingsService<DbcExtendedFileBrowsingServiceSettings>, 
                             SettingsService<DbcExtendedFileBrowsingServiceSettings>>();
        services.AddSingleton<IFileExtendedBrowsingServiceSettings, 
                             DbcExtendedFileBrowsingServiceSettings>();
        services.AddSingleton<IFileBrowsingService, IExtendedFileBrowsingService,
                             ExtendedFileBrowsingService>();
        
        // Register DBC parsing service
        services.AddSingleton<ISettingsService<DbcServiceSettings>, 
                             SettingsService<DbcServiceSettings>>();
        services.AddSingleton<IDbcServiceSettings, DbcServiceSettings>();
        services.AddSingleton<IDbcService, DbcService>();
        
        // Register application services
        services.AddTransient<CanManager>();
        services.AddTransient<MainViewModel>();
        
        _serviceProvider = services.BuildServiceProvider();
        
        // Pre-load DBC file
        var dbcService = _serviceProvider.GetRequiredService<IDbcService>();
        if (dbcService is IPreLoadable preLoadable)
        {
            Task.Run(() => preLoadable.Preload(CancellationToken.None)).Wait();
        }
        
        var mainWindow = new MainWindow
        {
            DataContext = _serviceProvider.GetRequiredService<MainViewModel>()
        };
        
        mainWindow.Show();
    }
}

API Reference

IDbcService

Extends IFileParsingService<DbcMatrix>:

Property Type Description
Instance DbcMatrix? Currently parsed DBC file
FileParsed IObservable<DbcMatrix?> Observable for file parse events
FilePath string Path of the currently selected file
IsFilePathCorrect bool True if file was parsed successfully

DbcMatrix Structure

From Oakrey.DBC:

Property Type Description
Messages List<Message> CAN message definitions
Nodes List<string> Network nodes (ECUs)
Version string DBC version information

Message Structure

Property Type Description
Name string Message name
Id uint CAN identifier
Length int Data length code (bytes)
Transmitter string Transmitting node
Signals List<Signal> Signal definitions

Signal Structure

Property Type Description
Name string Signal name
StartBit int Start bit position
Length int Signal length in bits
ByteOrder ByteOrder Motorola or Intel
ValueType ValueType Signed or Unsigned
Factor double Scaling factor
Offset double Offset value
Minimum double Minimum value
Maximum double Maximum value
Unit string Physical unit
Receivers List<string> Receiving nodes

IDbcServiceSettings

Extends IAutoLoadServiceSettings:

Property Type Description
AutoLoad bool Enable automatic loading on startup

DBC Template File

The package includes a default DBC template (dbcNew.txt) with:

  • VERSION header
  • Namespace definitions
  • Network nodes (BU_)
  • Sample messages with signals
  • Attributes and metadata

You can customize this template for your specific CAN network.

Features in Detail

Automatic Parsing

  • Uses DbcMatrix.Created() from Oakrey.DBC
  • Async parsing for large files
  • Full DBC specification support

Error Handling

  • File not found errors shown to user
  • Parse errors displayed with user-friendly messages
  • Graceful handling of malformed DBC files

Reactive Updates

  • Subscribe to FileParsed observable
  • Get notified when files are parsed or selection changes
  • Always have access to current DbcMatrix

Integration

  • Works seamlessly with FileBrowsing.Extended service
  • Automatic reparsing on file selection change
  • Persistent settings for last selected file
  • Template support for creating new DBC files

When to Use

Use FileParsing.DBC when:

  • You need to parse and monitor DBC CAN database files
  • You want automatic reloading when files change
  • You need reactive updates for CAN database changes
  • You want persistent file selection across sessions
  • You need integration with file browsing and management UI

Use Oakrey.DBC directly when:

  • You only need one-time DBC file reading
  • You don't need change tracking or observables
  • You're working with non-UI scenarios

Requirements

  • .NET 10 or higher
  • Oakrey.Applications.FileParsing
  • Oakrey.Applications.FileBrowsing.Extended
  • Oakrey.DBC (DbcMatrix parser)

Project Information

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests to improve the package.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 95 3/13/2026
1.0.0 99 3/11/2026