using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Aging.Infrastructure.Contracts; using CanSimulator; using log4net; namespace Aging.Infrastructure.Drivers { /// /// CAN 通讯驱动适配器。 /// 封装 CanSimulator,实现统一的 IDeviceDriver 接口。 /// 命令格式约定: /// 发送: "SEND:frameId:data" 如 "SEND:0x100:01 02 03 04" /// 查询: /// "RECV" - 获取接收邮箱中的下一帧 /// "RECV_ALL" - 获取接收邮箱中的所有帧 /// "STATUS" - 获取节点/总线状态 /// "FILTER:id:mask" - 设置接收滤波器 /// "FILTER_CLEAR" - 清除所有滤波器 /// "PROMISCUOUS" - 设置混杂模式(接收所有帧) /// "LOG" - 获取总线日志 /// "BUS_STATUS" - 获取总线状态摘要 /// public sealed class CanDriverAdapter : IDeviceDriver { private static readonly ILog Log = LogManager.GetLogger(typeof(CanDriverAdapter)); /// /// 全局 CAN 总线模拟器实例(所有 CAN 驱动共享) /// private static readonly Dictionary _sharedBuses = new(); private static readonly object _busLock = new(); private readonly string _ip; // 总线名称(用 ip 字段映射) private readonly int _port; // 节点编号(用 port 字段映射) private CanBusSimulator? _bus; private CanNode? _node; private bool _disposed; private readonly Stopwatch _latencyStopwatch = new(); private double _lastLatencyMs; private string _lastError = string.Empty; private DateTime? _lastErrorTime; private int _reconnectCount; /// /// 接收到的帧缓存(用于 RECV 查询) /// private readonly Queue _recvBuffer = new(); /// public string DeviceId { get; } /// public bool IsConnected => _node != null && _node.IsActive; /// public event EventHandler? ConnectionChanged; /// /// 初始化 CAN 驱动适配器 /// /// 设备唯一标识符 /// 总线名称(如 CAN_BUS_1) /// 节点编号(用于区分同一总线上的不同设备) public CanDriverAdapter(string deviceId, string busName, int nodeIndex) { DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId)); _ip = busName ?? "CAN_BUS_1"; _port = nodeIndex; } /// /// 获取或创建共享总线 /// private CanBusSimulator GetOrCreateBus(string busName) { lock (_busLock) { if (!_sharedBuses.TryGetValue(busName, out var bus)) { bus = new CanBusSimulator(busName); _sharedBuses[busName] = bus; Log.Info($"[CAN] 创建新的虚拟总线: {busName}"); } return bus; } } /// public Task ConnectAsync(CancellationToken ct) { ThrowIfDisposed(); Log.Info($"[CAN] 设备 {DeviceId} 正在连接到总线 {_ip} (节点: {_port})..."); try { // 获取或创建共享总线 _bus = GetOrCreateBus(_ip); // 如果总线未启动,自动启动 if (_bus.State != CanBusState.Running) { _bus.Start(); } // 注册节点 string nodeId = $"{DeviceId}_node{_port}"; _node = _bus.RegisterNode(nodeId, DeviceId); // 设置默认滤波器(接收所有帧) _node.SetPromiscuousMode(); // 激活节点 _node.Activate(); // 订阅接收事件 _node.FrameReceived += OnFrameReceived; _lastError = string.Empty; Log.Info($"[CAN] 设备 {DeviceId} 已成功连接到总线 {_ip} (节点: {_node.NodeId})"); OnConnectionChanged(true, "连接成功"); } catch (Exception ex) { _lastError = ex.Message; _lastErrorTime = DateTime.Now; Log.Error($"[CAN] 设备 {DeviceId} 连接异常: {ex.Message}", ex); _node?.Deactivate(); _node = null; throw; } return Task.CompletedTask; } /// public Task DisconnectAsync() { ThrowIfDisposed(); Log.Info($"[CAN] 设备 {DeviceId} 正在断开连接..."); try { if (_node != null) { _node.FrameReceived -= OnFrameReceived; _node.Deactivate(); _bus?.UnregisterNode(_node.NodeId); _node = null; } Log.Info($"[CAN] 设备 {DeviceId} 已断开连接"); OnConnectionChanged(false, "主动断开"); } catch (Exception ex) { _lastError = ex.Message; _lastErrorTime = DateTime.Now; Log.Error($"[CAN] 设备 {DeviceId} 断开连接异常: {ex.Message}", ex); _node = null; } return Task.CompletedTask; } /// public Task SendCommandAsync(string command, CancellationToken ct) { ThrowIfDisposed(); if (!IsConnected) throw new InvalidOperationException("[CAN] 设备未连接"); _latencyStopwatch.Restart(); try { Log.Debug($"[CAN] 设备 {DeviceId} 发送命令: {command}"); // 解析命令格式: "SEND:frameId:data" string[] parts = command.Split(':'); if (parts.Length < 3) { throw new ArgumentException($"[CAN] 命令格式错误,应为 SEND:frameId:data,实际: {command}"); } string operation = parts[0].ToUpper(); if (operation != "SEND") { throw new ArgumentException($"[CAN] 不支持的操作类型: {operation},应为 SEND"); } // 解析帧 ID string frameIdStr = parts[1]; uint frameId = CanFrame.ParseFrameId(frameIdStr); // 解析数据 string dataStr = parts[2]; byte[] data = CanFrame.ParseData(dataStr); // 验证数据长度 if (data.Length > 8) { throw new ArgumentException($"[CAN] 数据长度超限: {data.Length} 字节(最大 8 字节)"); } // 创建并发送帧 var frame = new CanFrame { FrameId = frameId, Format = frameId > 0x7FF ? CanFrameFormat.Extended : CanFrameFormat.Standard, Type = CanFrameType.Data, Data = data }; _node!.SendFrame(frame); _latencyStopwatch.Stop(); _lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds; string response = $"OK:TX:{frame.FrameIdHex}:{frame.Dlc}"; Log.Debug($"[CAN] 设备 {DeviceId} 发送成功 (延迟 {_lastLatencyMs:F2}ms): {response}"); return Task.FromResult(response); } catch (Exception ex) { _latencyStopwatch.Stop(); _lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds; _lastError = ex.Message; _lastErrorTime = DateTime.Now; Log.Error($"[CAN] 设备 {DeviceId} 发送命令失败: {ex.Message}", ex); throw; } } /// public Task QueryAsync(string query, CancellationToken ct) { ThrowIfDisposed(); if (!IsConnected) throw new InvalidOperationException("[CAN] 设备未连接"); _latencyStopwatch.Restart(); try { Log.Debug($"[CAN] 设备 {DeviceId} 查询: {query}"); string[] parts = query.Split(':'); string operation = parts[0].ToUpper(); string response; switch (operation) { case "RECV": response = HandleRecv(); break; case "RECV_ALL": response = HandleRecvAll(); break; case "STATUS": response = HandleStatus(); break; case "FILTER": response = HandleFilter(parts); break; case "FILTER_CLEAR": _node!.ClearFilters(); response = "OK:滤波器已清除"; break; case "PROMISCUOUS": _node!.SetPromiscuousMode(); response = "OK:混杂模式已启用"; break; case "AUTO_RESPONSE": response = HandleAutoResponse(parts); break; case "RESPONSE_DELAY": response = HandleResponseDelay(parts); break; case "LOG": response = HandleLog(); break; case "BUS_STATUS": response = _bus?.GetStatusSummary() ?? "总线未初始化"; break; default: throw new ArgumentException($"[CAN] 不支持的查询类型: {operation}"); } _latencyStopwatch.Stop(); _lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds; Log.Debug($"[CAN] 设备 {DeviceId} 查询响应: {response} (延迟 {_lastLatencyMs:F2}ms)"); return Task.FromResult(response); } catch (Exception ex) { _latencyStopwatch.Stop(); _lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds; _lastError = ex.Message; _lastErrorTime = DateTime.Now; Log.Error($"[CAN] 设备 {DeviceId} 查询失败: {ex.Message}", ex); throw; } } /// /// 处理 RECV 查询 - 获取下一帧 /// private string HandleRecv() { // 先从缓冲区取 if (_recvBuffer.Count > 0) { var frame = _recvBuffer.Dequeue(); return $"RECV:{frame.FrameIdHex}:{frame.DataHex}:{frame.Timestamp:HH:mm:ss.fff}"; } // 从节点邮箱取 if (_node!.TryDequeueReceived(out var frame2)) { return $"RECV:{frame2!.FrameIdHex}:{frame2.DataHex}:{frame2.Timestamp:HH:mm:ss.fff}"; } return "RECV:EMPTY"; } /// /// 处理 RECV_ALL 查询 - 获取所有帧 /// private string HandleRecvAll() { var frames = new List(); // 先取缓冲区 while (_recvBuffer.Count > 0) { var f = _recvBuffer.Dequeue(); frames.Add($"{f.FrameIdHex}:{f.DataHex}"); } // 再取节点邮箱 var mailbox = _node!.PeekReceiveMailbox(); _node.ClearReceiveMailbox(); foreach (var f in mailbox) { frames.Add($"{f.FrameIdHex}:{f.DataHex}:{f.Timestamp:HH:mm:ss.fff}"); } return frames.Count > 0 ? $"RECV_ALL:{frames.Count}:{string.Join("|", frames)}" : "RECV_ALL:0"; } /// /// 处理 STATUS 查询 /// private string HandleStatus() { var nodeStatus = _node?.GetStatusSummary() ?? "节点未初始化"; var busStatus = _bus?.GetStatusSummary() ?? "总线未初始化"; return $"STATUS:{nodeStatus}|{busStatus}"; } /// /// 处理 FILTER 设置 /// private string HandleFilter(string[] parts) { if (parts.Length < 3) { throw new ArgumentException("[CAN] FILTER 命令格式错误,应为 FILTER:id:mask"); } uint filterId = CanFrame.ParseFrameId(parts[1]); uint mask = CanFrame.ParseFrameId(parts[2]); _node!.AddFilter(new AcceptanceFilter { FilterId = filterId, Mask = mask, IsExtended = filterId > 0x7FF }); return $"OK:滤波器已添加 ID=0x{filterId:X3}, Mask=0x{mask:X3}"; } /// /// 处理 AUTO_RESPONSE 命令 /// 格式: AUTO_RESPONSE:on|off /// private string HandleAutoResponse(string[] parts) { if (parts.Length < 2) { // 查询当前状态 bool current = _node!.AutoResponseEnabled; return $"AUTO_RESPONSE:{(current ? "ON" : "OFF")}"; } string mode = parts[1].Trim().ToUpper(); switch (mode) { case "ON": case "1": case "TRUE": case "ENABLE": _node!.AutoResponseEnabled = true; Log.Info($"[CAN] 设备 {DeviceId} 启用自动响应模式"); return "OK:自动响应模式已启用"; case "OFF": case "0": case "FALSE": case "DISABLE": _node!.AutoResponseEnabled = false; Log.Info($"[CAN] 设备 {DeviceId} 禁用自动响应模式"); return "OK:自动响应模式已禁用"; default: throw new ArgumentException($"[CAN] AUTO_RESPONSE 参数错误: {mode},应为 on/off"); } } /// /// 处理 RESPONSE_DELAY 命令 /// 格式: RESPONSE_DELAY:毫秒数 /// private string HandleResponseDelay(string[] parts) { if (parts.Length < 2) { // 查询当前延迟 return $"RESPONSE_DELAY:{_node!.AutoResponseDelayMs}ms"; } if (!int.TryParse(parts[1].Trim(), out int delayMs) || delayMs < 0) { throw new ArgumentException($"[CAN] RESPONSE_DELAY 参数错误: {parts[1]},应为非负整数(毫秒)"); } _node!.AutoResponseDelayMs = delayMs; Log.Info($"[CAN] 设备 {DeviceId} 设置响应延迟: {delayMs}ms"); return $"OK:响应延迟已设置为 {delayMs}ms"; } /// /// 处理 LOG 查询 /// private string HandleLog() { var log = _bus?.GetBusLog(50) ?? new List(); if (log.Count == 0) return "LOG:EMPTY"; var entries = log.Select(f => $"[{f.Timestamp:HH:mm:ss.fff}]{f.SourceNodeId}>{f.FrameIdHex}:{f.DataHex}"); return $"LOG:{log.Count}:{string.Join("|", entries)}"; } /// /// 帧接收事件(公开给外部订阅) /// public event EventHandler? DriverFrameReceived; /// /// 帧接收事件处理 /// private void OnFrameReceived(object? sender, CanFrame frame) { // 放入接收缓冲区(用于 RECV/RECV_ALL 查询) while (_recvBuffer.Count >= 1000) { _recvBuffer.Dequeue(); } _recvBuffer.Enqueue(frame); // 触发公开事件(用于即时显示) DriverFrameReceived?.Invoke(this, frame); } /// public DeviceDriverStatus GetStatus() { return new DeviceDriverStatus { IsConnected = IsConnected, IsHealthy = IsConnected && string.IsNullOrEmpty(_lastError), LastError = _lastError, LastErrorTime = _lastErrorTime, LatencyMs = _lastLatencyMs, ReconnectCount = _reconnectCount }; } /// public void Dispose() { if (_disposed) return; _disposed = true; try { if (_node != null) { _node.FrameReceived -= OnFrameReceived; _node.Deactivate(); _bus?.UnregisterNode(_node.NodeId); } } catch (Exception ex) { Log.Error($"[CAN] 设备 {DeviceId} 释放资源异常: {ex.Message}", ex); } } /// /// 触发所有总线和节点(用于测试清理) /// public static void ResetAllBuses() { lock (_busLock) { foreach (var bus in _sharedBuses.Values) { bus.Dispose(); } _sharedBuses.Clear(); Log.Info("[CAN] 所有虚拟总线已重置"); } } /// /// 触发所有总线实例(供外部查询) /// public static IReadOnlyDictionary GetAllBuses() { lock (_busLock) { return new Dictionary(_sharedBuses); } } /// /// 触发连接状态变化事件 /// private void OnConnectionChanged(bool isConnected, string reason) { ConnectionChanged?.Invoke(this, new DeviceConnectionEventArgs { DeviceId = DeviceId, IsConnected = isConnected, Reason = reason }); if (!isConnected) { _reconnectCount++; } } /// /// 检查是否已释放 /// private void ThrowIfDisposed() { if (_disposed) throw new ObjectDisposedException(nameof(CanDriverAdapter)); } } }