using Model.Models; using Prism.Events; using System; using System.Collections.Generic; using System.Linq; using System.Text; using UIShare.PubEvent; using ZLGUSBCANFD; namespace UIShare.GlobalVariable { /// /// CAN 信号广播器(全局单例): /// 统一订阅 GlobalInfo.CanPool 中所有已实例化的 ZLGCANFD 设备, /// 将 DBC 解码后的信号值广播给所有引用该 CAN 设备的作用域, /// 并同步检查各作用域 ValueLimitList 的超限报警。 /// public class CANSignalBroadcaster : IDisposable { private readonly IEventAggregator _eventAggregator; private readonly GlobalInfo _globalInfo; private bool _disposed; /// 已订阅解码事件的 CANFD 实例 → 委托 映射 private readonly Dictionary> _handlers = new(); public CANSignalBroadcaster(GlobalInfo globalInfo, IEventAggregator eventAggregator) { _globalInfo = globalInfo; _eventAggregator = eventAggregator; } /// /// 扫描 GlobalInfo.CanPool 中已创建的 CANFD 实例并订阅解码事件。 /// 幂等:已订阅的实例不会重复订阅。 /// public void Discover() { if (_disposed) return; foreach (var kvp in _globalInfo.CanPool) { string fingerprint = kvp.Key; var lazy = kvp.Value; if (!lazy.IsValueCreated || lazy.Value == null) continue; var canfd = lazy.Value; if (_handlers.ContainsKey(canfd)) continue; // 使用闭包捕获指纹,回调时即可区分不同 CAN 卡 Action handler = (channel, msg) => OnDbcMessageDecoded(fingerprint, channel, msg); canfd.OnDbcMessageDecoded += handler; _handlers[canfd] = handler; } } /// /// 启动广播器(目前 Discover 已完成订阅,此处保留以兼容 HardwareDataBroadcaster 的使用模式)。 /// public void Start() { Discover(); } /// /// DBC 解码回调:提取所有信号,向引用该 CAN 设备的作用域广播,并检查报警。 /// private void OnDbcMessageDecoded(string canFingerprint, uint channel, ZDBC.DBCMessage msg) { if (_disposed) return; string signalFingerprint = BuildFingerprint(canFingerprint, channel); var now = DateTime.Now; // 获取引用该 CAN 设备的所有作用域 var scopes = GetScopesForFingerprint(canFingerprint); if (scopes.Count == 0) return; for (int i = 0; i < msg.nSignalCount; i++) { var signal = msg.vSignals[i]; string signalName = Encoding.Default.GetString(signal.strName).TrimEnd('\0'); if (string.IsNullOrEmpty(signalName)) continue; double physicalValue = signal.nRawvalue * signal.nFactor + signal.nOffset; string methodName = BuildMethodName(msg.nID, signalName); foreach (var scope in scopes) { _eventAggregator.GetEvent().Publish(new HardwareReportArgs { Scope = scope, HardwareFingerprint = signalFingerprint, MethodName = methodName, Value = physicalValue, Time = now }); string MonitorStatus = ValueLimitAlarmHelper.CheckAlarm(scope, signalFingerprint, methodName, physicalValue, _globalInfo); if (MonitorStatus != "" && MonitorStatus != "未报警") { _eventAggregator.GetEvent().Publish((scope,canFingerprint, MonitorStatus)); } } } } /// 获取指定硬件指纹当前被哪些作用域引用 private List GetScopesForFingerprint(string fingerprint) { if (_globalInfo.DeviceAndScopeDic.TryGetValue(fingerprint, out var lazy)) { var scopeList = lazy.Value; lock (scopeList) return scopeList.ToList(); } return new List(); } /// /// 生成 CAN 信号的 DisplayName 格式:"{MessageName}.{SignalName}" /// public static string BuildDisplayName(string messageName, string signalName) { return $"{messageName}.{signalName}"; } /// /// 生成 CAN 信号的 MethodName 格式:"{MessageId:X}.{SignalName}" /// public static string BuildMethodName(uint messageId, string signalName) { return $"{messageId:X}.{signalName}"; } /// /// 生成 CAN 信号的 Fingerprint 格式:"{canDeviceFingerprint}:{channel}" /// canDeviceFingerprint 来自 DeviceManager.ExtractHardwareFingerprint,如 "CAN:0" /// public static string BuildFingerprint(string canDeviceFingerprint, uint channel) { return $"{canDeviceFingerprint}:{channel}"; } public void Dispose() { if (_disposed) return; _disposed = true; foreach (var kvp in _handlers) { if (kvp.Key != null) kvp.Key.OnDbcMessageDecoded -= kvp.Value; } _handlers.Clear(); } } }