CanRead/BlazorApp/Services/Windows/PcanCanService.cs
2026-01-23 11:20:08 +07:00

95 lines
2.4 KiB
C#

using BlazorApp.Models;
using BlazorApp.Services.Interfaces;
using Peak.Can.Basic.BackwardCompatibility;
namespace BlazorApp.Services.Windows
{
public class PcanCanService : ICanService, IDisposable
{
private const ushort PCAN_USBBUS1 = 0x51;
private CancellationTokenSource? _cts;
private bool _initialized;
public event Action<CanMessage>? OnMessageReceived;
public Task InitAsync()
{
if (_initialized) return Task.CompletedTask;
var status = PCANBasic.Initialize(
PCAN_USBBUS1,
TPCANBaudrate.PCAN_BAUD_250K
);
if (status != TPCANStatus.PCAN_ERROR_OK)
throw new Exception($"PCAN init failed: {status}");
_initialized = true;
return Task.CompletedTask;
}
public Task<List<CanMessage>> ReadAsync()
{
var list = new List<CanMessage>();
TPCANMsg msg;
TPCANTimestamp ts;
if (PCANBasic.Read(PCAN_USBBUS1, out msg, out ts)
== TPCANStatus.PCAN_ERROR_OK)
{
list.Add(Map(msg));
}
return Task.FromResult(list);
}
public void StartStream()
{
if (_cts != null) return;
_cts = new CancellationTokenSource();
Task.Run(() =>
{
while (!_cts.IsCancellationRequested)
{
TPCANMsg msg;
TPCANTimestamp ts;
var result = PCANBasic.Read(
PCAN_USBBUS1,
out msg,
out ts
);
if (result == TPCANStatus.PCAN_ERROR_OK)
OnMessageReceived?.Invoke(Map(msg));
else
Thread.Sleep(1);
}
});
}
public void StopStream()
{
_cts?.Cancel();
_cts = null;
if (_initialized)
{
PCANBasic.Uninitialize(PCAN_USBBUS1);
_initialized = false;
}
}
private static CanMessage Map(TPCANMsg msg) => new()
{
Id = msg.ID,
Length = msg.LEN,
Data = msg.DATA,
Timestamp = DateTime.Now
};
public void Dispose() => StopStream();
}
}