Skip to content

Commit ede19b7

Browse files
committed
Yacht Devices Binary CAN format support
1 parent a4b8dac commit ede19b7

File tree

3 files changed

+121
-9
lines changed

3 files changed

+121
-9
lines changed

FileFormats.cs

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Diagnostics;
1+
using System.Diagnostics;
42
using System.Globalization;
53
using System.IO;
6-
using System.Linq;
74
using System.Text;
85
using System.Text.RegularExpressions;
9-
using System.Threading.Tasks;
106
using System.Windows;
117
using static NMEA2000Analyzer.MainWindow;
128

@@ -22,13 +18,20 @@ public enum FileFormat
2218
CanDump1,
2319
CanDump2,
2420
YDWG,
21+
YDBinary,
2522
PCANView
2623
}
2724

2825
public static FileFormat DetectFileFormat(string filePath)
2926
{
3027
try
3128
{
29+
if (IsBinaryYDFormat(filePath))
30+
{
31+
Debug.WriteLine("Binary CAN format detected");
32+
return FileFormat.YDBinary;
33+
}
34+
3235
var lines = File.ReadLines(filePath).Take(10).ToList(); // Read the first few lines
3336

3437
foreach (var line in lines)
@@ -407,5 +410,110 @@ public static List<Nmea2000Record> LoadPCANView(string filePath)
407410
return records;
408411
}
409412

413+
private static bool IsBinaryYDFormat(string filePath)
414+
{
415+
try
416+
{
417+
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
418+
using (var reader = new BinaryReader(fs))
419+
{
420+
if (fs.Length < 16) return false; // File must be at least one record (16 bytes) long
421+
422+
byte[] firstRecord = reader.ReadBytes(16);
423+
424+
if (firstRecord.Length < 16) return false;
425+
426+
// Check if position 4-7 (Message Identifier) is 0xFFFFFFFF (Service Record)
427+
uint messageId = BitConverter.ToUInt32(firstRecord, 4);
428+
if (messageId != 0xFFFFFFFF)
429+
return false;
430+
431+
// Check if data field (position 8-15) contains "YDVR v05"
432+
string dataString = Encoding.ASCII.GetString(firstRecord, 8, 8).TrimEnd('\0');
433+
return dataString.StartsWith("YDVR v05");
434+
}
435+
}
436+
catch
437+
{
438+
return false;
439+
}
440+
}
441+
442+
public static List<Nmea2000Record> LoadYDBinary(string filePath)
443+
{
444+
var records = new List<Nmea2000Record>();
445+
446+
try
447+
{
448+
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
449+
using (var reader = new BinaryReader(fs))
450+
{
451+
while (reader.BaseStream.Position < reader.BaseStream.Length)
452+
{
453+
byte[] recordBytes = reader.ReadBytes(16);
454+
if (recordBytes.Length < 16) break; // Ensure full record read
455+
456+
// Extract fields from the binary record
457+
ushort header = BitConverter.ToUInt16(recordBytes, 0);
458+
ushort timeInMs = BitConverter.ToUInt16(recordBytes, 2);
459+
uint messageId = BitConverter.ToUInt32(recordBytes, 4);
460+
byte[] data = recordBytes.Skip(8).Take(8).ToArray();
461+
462+
// Decode header fields
463+
bool is11BitId = (header & 0x8000) != 0;
464+
bool isTx = (header & 0x4000) != 0;
465+
int dataLength = ((header >> 12) & 0x07) + 1; // Values 0-7 map to 1-8 bytes
466+
int interfaceId = (header & 0x0800) != 0 ? 1 : 0;
467+
int timestampMinutes = header & 0x03FF; // 10-bit timestamp in minutes
468+
469+
// Convert timestamp
470+
string timestamp = $"{timestampMinutes:D4}:{timeInMs:D5}"; // Example format: "0345:01234"
471+
472+
// Extract PGN, Source, Destination
473+
uint pgn;
474+
int source, destination, priority;
475+
476+
if (is11BitId)
477+
{
478+
// 11-bit identifier case (usually not PGN-based)
479+
pgn = messageId & 0x07FF;
480+
source = -1;
481+
destination = -1;
482+
priority = -1;
483+
}
484+
else
485+
{
486+
// 29-bit identifier
487+
priority = (int)((messageId >> 26) & 0x07);
488+
pgn = (messageId >> 8) & 0x1FFFF; // Extract PGN (middle 18 bits)
489+
destination = (int)((messageId >> 8) & 0xFF);
490+
source = (int)(messageId & 0xFF);
491+
}
492+
493+
// Format data bytes as a space-separated hex string
494+
string dataHex = string.Join(" ", data.Take(dataLength).Select(b => $"0x{b:X2}"));
495+
496+
// Create the record
497+
var record = new Nmea2000Record
498+
{
499+
Timestamp = timestamp,
500+
Priority = priority.ToString(),
501+
PGN = pgn.ToString(),
502+
Source = source.ToString(),
503+
Destination = destination.ToString(),
504+
Data = dataHex
505+
};
506+
507+
records.Add(record);
508+
}
509+
}
510+
}
511+
catch (Exception ex)
512+
{
513+
MessageBox.Show($"Failed to load binary CAN file: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
514+
}
515+
516+
return records;
517+
}
410518
}
411519
}

MainWindow.xaml.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private async void OpenMenuItem_ClickAsync(object sender, RoutedEventArgs e)
8484
// Open file picker dialog
8585
OpenFileDialog openFileDialog = new OpenFileDialog
8686
{
87-
Filter = "(*.csv, *.log, *.txt, *.dump)|*.csv;*.log;*.txt;*.dump|All Files (*.*)|*.*",
87+
Filter = "(*.csv, *.can, *.log, *.txt, *.dump)|*.csv;*.can;*.log;*.txt;*.dump|All Files (*.*)|*.*",
8888
Title = "Open File"
8989
};
9090

@@ -117,6 +117,9 @@ private async void OpenMenuItem_ClickAsync(object sender, RoutedEventArgs e)
117117
case FileFormats.FileFormat.PCANView:
118118
_Data = await Task.Run(() => FileFormats.LoadPCANView(filePath));
119119
break;
120+
case FileFormats.FileFormat.YDBinary:
121+
_Data = await Task.Run(() => FileFormats.LoadYDBinary(filePath));
122+
break;
120123
default:
121124
MessageBox.Show("Unsupported or unknown file format.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
122125
return;

NMEA2000Analyzer.csproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<UseWPF>true</UseWPF>
99
<PackageReadmeFile>README.md</PackageReadmeFile>
1010
<SignAssembly>False</SignAssembly>
11-
<AssemblyVersion>1.1.0</AssemblyVersion>
12-
<FileVersion>1.1.0</FileVersion>
11+
<AssemblyVersion>1.1.2</AssemblyVersion>
12+
<FileVersion>1.1.2</FileVersion>
1313
<Version />
1414
</PropertyGroup>
1515

@@ -74,6 +74,7 @@
7474

7575
<ItemGroup>
7676
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
77+
<PackageReference Include="Peak.PCANBasic.NET" Version="4.10.0.964" />
7778
</ItemGroup>
7879

7980
<ItemGroup>
@@ -83,4 +84,4 @@
8384
</None>
8485
</ItemGroup>
8586

86-
</Project>
87+
</Project>

0 commit comments

Comments
 (0)