can信号监控曲线添加
This commit is contained in:
@@ -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 命令处理
|
||||
|
||||
Reference in New Issue
Block a user