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
<PackageReference Include="Oakrey.Applications.FileParsing.DBC" Version="1.0.1" />
<PackageVersion Include="Oakrey.Applications.FileParsing.DBC" Version="1.0.1" />
<PackageReference Include="Oakrey.Applications.FileParsing.DBC" />
paket add Oakrey.Applications.FileParsing.DBC --version 1.0.1
#r "nuget: Oakrey.Applications.FileParsing.DBC, 1.0.1"
#:package Oakrey.Applications.FileParsing.DBC@1.0.1
#addin nuget:?package=Oakrey.Applications.FileParsing.DBC&version=1.0.1
#tool nuget:?package=Oakrey.Applications.FileParsing.DBC&version=1.0.1
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.DBClibrary - DbcMatrix Support: Returns structured CAN database with messages, signals, and metadata
- Extended Browsing: Integrates with
FileBrowsing.Extendedfor 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
- Open your project in Visual Studio.
- Navigate to Tools > NuGet Package Manager > Manage NuGet Packages for Solution....
- Search for
Oakrey.Applications.FileParsing.DBCand 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
FileParsedobservable - 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
- Author: Oakrey
- Company: Oakrey
- License: MIT
- Repository: Git Repository
- Project URL: Project Website
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 | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows7.0 is compatible. |
-
net10.0-windows7.0
- Oakrey.Applications.FileBrowsing.Extended (>= 1.0.1)
- Oakrey.Applications.FileParsing (>= 1.0.1)
- Oakrey.DBC (>= 3.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.