can信号监控曲线添加

This commit is contained in:
hsc
2026-07-10 09:56:59 +08:00
parent 412b56935c
commit 52d486e2b1
7 changed files with 383 additions and 42 deletions

View File

@@ -22,6 +22,7 @@ using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.UIViewModel;
using UIShare.ViewModelBase;
using ZLGUSBCANFD;
namespace MonitorModule.ViewModels
@@ -119,6 +120,8 @@ namespace MonitorModule.ViewModels
/// <summary>事件订阅令牌,用于 Dispose 时取消订阅</summary>
private SubscriptionToken? _subscriptionToken;
private SubscriptionToken? _dbcLoadedToken;
private SubscriptionToken? _dbcUnloadedToken;
// ==========================================
// 批量入库核心结构
@@ -166,6 +169,10 @@ namespace MonitorModule.ViewModels
// 取消 EventAggregator 订阅
if (_subscriptionToken != null)
_eventAggregator.GetEvent<HardwareDataReportedEvent>().Unsubscribe(_subscriptionToken);
if (_dbcLoadedToken != null)
_eventAggregator.GetEvent<DBCLoadedEvent>().Unsubscribe(_dbcLoadedToken);
if (_dbcUnloadedToken != null)
_eventAggregator.GetEvent<DBCUnloadedEvent>().Unsubscribe(_dbcUnloadedToken);
if (_dbFlushTask != null)
{
@@ -332,6 +339,15 @@ namespace MonitorModule.ViewModels
_subscriptionToken = _eventAggregator.GetEvent<HardwareDataReportedEvent>()
.Subscribe(OnHardwareDataReceived, ThreadOption.UIThread);
// 5b. 订阅 DBC 加载/卸载事件,动态发现或清除 CAN 信号
_dbcLoadedToken = _eventAggregator.GetEvent<DBCLoadedEvent>()
.Subscribe(OnDbcLoaded, ThreadOption.UIThread);
_dbcUnloadedToken = _eventAggregator.GetEvent<DBCUnloadedEvent>()
.Subscribe(OnDbcUnloaded, ThreadOption.UIThread);
// 5c. 根据 SystemConfig.ConfigurationList 刷新已加载 DBC 中的 CAN 信号
RefreshConfiguredCanSignals();
// 6. 启动 OxyPlot 视觉刷新定时器
_stopwatch.Start();
_plotRefreshTimer.Start();
@@ -449,7 +465,6 @@ namespace MonitorModule.ViewModels
private void RestoreChannelsFromConfig()
{
if (_systemConfig?.MonitorChannels == null || _systemConfig.MonitorChannels.Count == 0) return;
if (AvailableMethods.Count == 0) return;
int restored = 0;
foreach (var config in _systemConfig.MonitorChannels)
@@ -508,6 +523,188 @@ namespace MonitorModule.ViewModels
StatusMessage = $"已从配置自动恢复 {restored} 个监测通道";
}
}
/// <summary>
/// 根据 SystemConfig.ConfigurationList 刷新所有已加载 DBC 中的 CAN 信号。
/// 只添加 ConfigurationList 中配置且实际存在于 DBC 的信号;不存在则清理。
/// </summary>
private void RefreshConfiguredCanSignals()
{
if (_systemConfig?.ConfigurationList == null || _systemConfig.ConfigurationList.Count == 0) return;
if (_deviceManager?.CANFD?.DBCParser?.MsgDatabase == null) return;
var msgDb = _deviceManager.CANFD.DBCParser.MsgDatabase;
foreach (var channel in _systemConfig.ConfigurationList.Select(c => c.Channel).Distinct())
{
if (channel < 0 || channel >= msgDb.Count) continue;
RefreshCanSignalsForChannel((uint)channel, msgDb[channel]);
}
}
/// <summary>
/// 刷新单个通道的 CAN 信号:以 ConfigurationList 为白名单,对照 DBC 实际存在性。
/// - DBC 中存在 → 加入 AvailableMethods若 MonitorChannels 中也有,则恢复 Channel。
/// - DBC 中不存在 → 从 AvailableMethods 移除;若已在 Channels 中,则删除。
/// </summary>
private void RefreshCanSignalsForChannel(uint channel, List<_Msg_> messages)
{
if (_systemConfig?.ConfigurationList == null) return;
string fingerprint = CANSignalBroadcaster.BuildFingerprint(channel);
var configs = _systemConfig.ConfigurationList.Where(c => c.Channel == (int)channel).ToList();
bool changed = false;
foreach (var cfg in configs)
{
if (string.IsNullOrEmpty(cfg.SignalName)) continue;
string methodName = CANSignalBroadcaster.BuildMethodName((uint)cfg.MessageID, cfg.SignalName);
bool existsInDbc = messages.Any(m =>
m.msg_id == cfg.MessageID &&
m.signal_Name != null &&
m.signal_Name.Contains(cfg.SignalName));
if (existsInDbc)
{
// 加入 AvailableMethods去重
if (!AvailableMethods.Any(m => m.Fingerprint == fingerprint && m.MethodName == methodName))
{
string displayName = CANSignalBroadcaster.BuildDisplayName(cfg.MessageName, cfg.SignalName);
AvailableMethods.Add(new AvailableMethodItem
{
DeviceName = $"CAN{channel}",
Fingerprint = fingerprint,
MethodName = methodName,
DisplayName = displayName,
MethodInfo = null!,
Device = null!
});
changed = true;
}
// 如果 MonitorChannels 中有持久化记录,自动恢复 Channel
var monitorConfig = _systemConfig.MonitorChannels?.FirstOrDefault(m =>
m.Fingerprint == fingerprint && m.MethodName == methodName);
if (monitorConfig != null && !Channels.Any(c =>
c.Fingerprint == fingerprint && c.MethodName == methodName))
{
AddCanChannel(cfg, fingerprint, methodName, monitorConfig.IsDisplayed);
changed = true;
}
}
else
{
// DBC 中不存在:从 AvailableMethods 移除
var methodToRemove = AvailableMethods.FirstOrDefault(m =>
m.Fingerprint == fingerprint && m.MethodName == methodName);
if (methodToRemove != null)
{
AvailableMethods.Remove(methodToRemove);
changed = true;
}
// 如果该信号已经在 Channels或 MonitorChannels删除
var channelToRemove = Channels.FirstOrDefault(c =>
c.Fingerprint == fingerprint && c.MethodName == methodName);
if (channelToRemove != null)
{
if (channelToRemove.Series != null) Plot.Series.Remove(channelToRemove.Series);
Channels.Remove(channelToRemove);
changed = true;
}
}
}
if (changed)
{
Plot.InvalidatePlot(true);
StatusMessage = $"CAN{channel} 已刷新配置信号";
}
}
/// <summary>
/// DBCLoadedEvent 回调DBC 加载后刷新该通道的配置信号。
/// </summary>
private void OnDbcLoaded(DBCLoadedArgs args)
{
if (args.Scope != TestStatus) return;
if (_deviceManager?.CANFD?.DBCParser?.MsgDatabase == null) return;
int channel = (int)args.Channel;
var msgDb = _deviceManager.CANFD.DBCParser.MsgDatabase;
if (channel < 0 || channel >= msgDb.Count) return;
RefreshCanSignalsForChannel(args.Channel, msgDb[channel]);
}
/// <summary>
/// DBCUnloadedEvent 回调:移除对应通道的 CAN 信号AvailableMethods + Channels
/// </summary>
private void OnDbcUnloaded(DBCUnloadedArgs args)
{
if (args.Scope != TestStatus) return;
string fingerprint = CANSignalBroadcaster.BuildFingerprint(args.Channel);
// 从 AvailableMethods 中移除
var toRemoveMethods = AvailableMethods.Where(m => m.Fingerprint == fingerprint).ToList();
foreach (var m in toRemoveMethods)
AvailableMethods.Remove(m);
// 从 Channels 中移除(并清理 Plot
var toRemoveChannels = Channels.Where(c => c.Fingerprint == fingerprint).ToList();
foreach (var c in toRemoveChannels)
{
if (c.Series != null) Plot.Series.Remove(c.Series);
Channels.Remove(c);
}
if (toRemoveMethods.Count > 0 || toRemoveChannels.Count > 0)
{
Plot.InvalidatePlot(true);
StatusMessage = $"CAN{args.Channel} DBC 已卸载,移除 {toRemoveMethods.Count} 个信号";
}
}
/// <summary>
/// 将单个 CAN 信号添加为监测通道。
/// </summary>
private void AddCanChannel(CANSignalConfig cfg, string fingerprint, string methodName, bool isDisplayed)
{
var color = _palette[_colorIndex % _palette.Length];
_colorIndex++;
string displayName = CANSignalBroadcaster.BuildDisplayName(cfg.MessageName, cfg.SignalName);
var channel = new MonitorChannelVM
{
DeviceName = $"CAN{cfg.Channel}",
Fingerprint = fingerprint,
MethodName = methodName,
DisplayName = displayName,
Color = color,
IsMonitored = true,
IsDisplayed = isDisplayed
};
if (channel.IsDisplayed)
{
channel.Series = new LineSeries
{
Title = channel.DisplayName,
Color = color,
StrokeThickness = 1.5
};
Plot.Series.Add(channel.Series);
}
channel.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(MonitorChannelVM.IsDisplayed))
OnChannelDisplayChanged(channel);
};
Channels.Add(channel);
}
#endregion
#region