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? 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> ReadAsync() { var list = new List(); 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(); } }