95 lines
2.4 KiB
C#
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();
|
|
}
|
|
}
|