周立功换同星

This commit is contained in:
“hsc”
2026-07-29 14:20:32 +08:00
parent d8a22a15b1
commit 3bf33bb561
29 changed files with 1913 additions and 3255 deletions

View File

@@ -0,0 +1,581 @@
using Microsoft.Win32;
using Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
using TSMasterCAN;
using UIShare.GlobalVariable;
using UIShare.UIViewModel;
namespace CANModule.ViewModels
{
public class CANViewModel : BindableBase, IDialogAware
{
#region
private string _Title = "同星CAN";
public string Title
{
get { return _Title; }
set { SetProperty(ref _Title, value); }
}
private ObservableCollection<CanMessageShowVM> _CanMessageList = new();
public ObservableCollection<CanMessageShowVM> CanMessageList
{
get { return _CanMessageList; }
set { SetProperty(ref _CanMessageList, value); }
}
private string _DBCChannel = "0";
public string DBCChannel
{
get { return _DBCChannel; }
set { SetProperty(ref _DBCChannel, value); }
}
private bool _IsDirectlySend = false;
public bool IsDirectlySend
{
get { return _IsDirectlySend; }
set { SetProperty(ref _IsDirectlySend, value); }
}
private ObservableCollection<string> _Message;
public ObservableCollection<string> Message
{
get { return _Message; }
set { SetProperty(ref _Message, value); }
}
private ObservableCollection<string> _Signal;
public ObservableCollection<string> Signal
{
get { return _Signal; }
set { SetProperty(ref _Signal, value); }
}
byte channel;
private string _selectedMessage;
public string SelectedMessage
{
get { return _selectedMessage; }
set
{
if (_selectedMessage != value)
{
Signal = new(DBCParse.MsgDatabase[channel].Where(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value).First().signal_Name);
_selectedMessage = value;
RaisePropertyChanged();
}
}
}
private string _selectedSignal;
public string SelectedSignal
{
get { return _selectedSignal; }
set { SetProperty(ref _selectedSignal, value); }
}
private string _signalValue;
public string SignalValue
{
get { return _signalValue; }
set { SetProperty(ref _signalValue, value); }
}
private string _cycleSendInterval;
public string CycleSendInterval
{
get { return _cycleSendInterval; }
set { SetProperty(ref _cycleSendInterval, value); }
}
private string _messageSendChannel = "0";
public string MessageSendChannel
{
get { return _messageSendChannel; }
set { SetProperty(ref _messageSendChannel, value); }
}
public string BLFPath
{
get => _systemConfig?.DefaultBLFFilePath ?? "";
set
{
if (_systemConfig != null && _systemConfig.DefaultBLFFilePath != value)
{
_systemConfig.DefaultBLFFilePath = value;
RaisePropertyChanged();
}
}
}
public string DBCPath
{
get => _systemConfig?.DefaultDBCFilePath ?? "";
set
{
if (_systemConfig != null && _systemConfig.DefaultDBCFilePath != value)
{
_systemConfig.DefaultDBCFilePath = value;
RaisePropertyChanged();
}
}
}
private bool _IsSaved;
public bool IsSaved
{
get { return _IsSaved; }
set { SetProperty(ref _IsSaved, value); }
}
public ObservableCollection<AutoDBCLoadItem> DBCAutoLoadList
{
get => _systemConfig?.DBCAutoLoadList ?? new ObservableCollection<AutoDBCLoadItem>();
}
private AutoDBCLoadItem _SelectedDcAutoLoad;
public AutoDBCLoadItem SelectedDcAutoLoad
{
get { return _SelectedDcAutoLoad; }
set { SetProperty(ref _SelectedDcAutoLoad, value); }
}
private TSMaster.APP_CHANNEL[] _appChannelNames = new[] { TSMaster.APP_CHANNEL.CHN1, TSMaster.APP_CHANNEL.CHN2, TSMaster.APP_CHANNEL.CHN3, TSMaster.APP_CHANNEL.CHN4 };
public TSMaster.APP_CHANNEL[] APP_CHANNEL
{
get { return _appChannelNames; }
set { SetProperty(ref _appChannelNames, value); }
}
private TSMaster.APP_CHANNEL _aIdxChn;
public TSMaster.APP_CHANNEL AIdxChn
{
get { return _aIdxChn; }
set { SetProperty(ref _aIdxChn, value); }
}
private int _aID;
public int AID
{
get { return _aID; }
set { SetProperty(ref _aID, value); }
}
private bool _aIsTx;
public bool AIsTx
{
get { return _aIsTx; }
set { SetProperty(ref _aIsTx, value); }
}
private bool _aIsExt;
public bool AIsExt
{
get { return _aIsExt; }
set { SetProperty(ref _aIsExt, value); }
}
private bool _aIsRemote;
public bool AIsRemote
{
get { return _aIsRemote; }
set { SetProperty(ref _aIsRemote, value); }
}
private byte _aDlc;
public byte ADLC
{
get { return _aDlc; }
set { SetProperty(ref _aDlc, value); }
}
private byte[] _aDataArray;
public byte[] ADataArray
{
get { return _aDataArray; }
set { SetProperty(ref _aDataArray, value); }
}
private bool _aIsFD = true;
public bool AIsFD
{
get { return _aIsFD; }
set { SetProperty(ref _aIsFD, value); }
}
private bool _aIsBRS = false;
public bool AIsBRS
{
get { return _aIsBRS; }
set { SetProperty(ref _aIsBRS, value); }
}
private bool _AutoSetting = true;
public bool AutoSetting
{
get { return _AutoSetting; }
set { SetProperty(ref _AutoSetting, value); }
}
private string _CustomMessage = "[00,11,22,33,AA,BB,CC,DD]";
public string CustomMessage
{
get { return _CustomMessage; }
set { SetProperty(ref _CustomMessage, value); }
}
private float _CustomSendCycleInterval = 0.0f;
public float CustomSendCycleInterval
{
get { return _CustomSendCycleInterval; }
set { SetProperty(ref _CustomSendCycleInterval, value); }
}
private bool _UpdateToDB;
public bool UpdateToDB
{
get { return _UpdateToDB; }
set { SetProperty(ref _UpdateToDB, value); }
}
#endregion
#region
public ICommand SelectBLFPathCommand { get; set; }
public ICommand SaveBLFPathCommand { get; set; }
public ICommand StartTranscirbeCommand { get; set; }
public ICommand EndTranscirbeCommand { get; set; }
public ICommand CloseCommand { get; set; }
public ICommand ConnectCanCommand { get; set; }
public ICommand CloseCanCommand { get; set; }
public ICommand ClearCycleCommand { get; set; }
public ICommand UpLoadDBCCommand { get; set; }
public ICommand ChangeDBCCommand { get; set; }
public ICommand LoadDBCCommand { get; set; }
public ICommand CheckDBCCommand { get; set; }
public ICommand InitTSMasterCommand { get; set; }
public ICommand ReleaseTSMasterCommand { get; set; }
public ICommand LoadMessageCommand { get; set; }
public ICommand SetAndSendMessageCommand { get; set; }
public ICommand DeleteDcAutoLoadCommand { get; set; }
public ICommand SendCustomMessageCommand { get; set; }
#endregion
private IEventAggregator _eventAggregator { get; set; }
private CAN? _canfd;
private SystemConfig? _systemConfig;
private readonly DeviceManager _deviceManager;
private IDialogService _dialogService { get; set; }
CancellationTokenSource cts = new CancellationTokenSource();
public CANViewModel(IContainerProvider containerProvider)
{
_eventAggregator = containerProvider.Resolve<IEventAggregator>();
_systemConfig = containerProvider.Resolve<SystemConfig>();
_deviceManager = containerProvider.Resolve<DeviceManager>();
_canfd = _deviceManager.CANFD;
_dialogService = containerProvider.Resolve<IDialogService>();
SelectBLFPathCommand = new DelegateCommand(SelectBLFPath);
SaveBLFPathCommand = new DelegateCommand(SaveBLFPath);
StartTranscirbeCommand = new DelegateCommand(StartTranscirbe);
EndTranscirbeCommand = new DelegateCommand(EndTranscirbe);
CloseCommand = new DelegateCommand(Close);
ConnectCanCommand = new DelegateCommand(ConnectCan);
CloseCanCommand = new DelegateCommand(CloseCan);
ClearCycleCommand = new DelegateCommand(ClearCycle);
UpLoadDBCCommand = new DelegateCommand(UpLoadDBC);
ChangeDBCCommand = new DelegateCommand(ChangeDBC);
LoadDBCCommand = new DelegateCommand(LoadDBC);
CheckDBCCommand = new DelegateCommand(CheckDBC);
InitTSMasterCommand = new DelegateCommand(InitTSMaster);
ReleaseTSMasterCommand = new DelegateCommand(ReleaseTSMaster);
SetAndSendMessageCommand = new DelegateCommand(SetAndSendMessage);
LoadMessageCommand = new DelegateCommand(LoadMessage);
DeleteDcAutoLoadCommand = new DelegateCommand(DeleteDcAutoLoad);
SendCustomMessageCommand = new DelegateCommand(SendCustomMessage);
}
#region
private void SendCustomMessage()
{
try
{
ADataArray = (CustomMessage);
if (ADataArray.Length > byte.MaxValue) throw new Exception("报文数量超过上限!");
if (AutoSetting)
{
ADLC = (byte)ADataArray.Length;
}
}
catch (Exception ex)
{
_dialogService.ShowDialog("MessageDialog", new DialogParameters
{
{ "message", $"报文转换失败:{ex.Message}" }
});
return;
}
var re = CAN.SendMsg(AIdxChn, AID, AIsTx, AIsExt,
AIsRemote, ADLC, ADataArray, AIsFD, AIsBRS, UpdateToDB, CustomSendCycleInterval);
}
private void DeleteDcAutoLoad()
{
DBCAutoLoadList.Remove(SelectedDcAutoLoad);
ConfigService.Save(_systemConfig);
}
private void LoadMessage()
{
if (int.TryParse(MessageSendChannel, out int channel))
{
Message = new(DBCParse.MsgDatabase[channel].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
}
else
{
}
}
private void SetAndSendMessage()
{
if (int.TryParse(CycleSendInterval, out int sendPeriod) && double.TryParse(SignalValue, out double SValue) && byte.TryParse(MessageSendChannel, out byte c))
{
channel = c;
var message = SelectedMessage.Split(']')[1];
var re = CAN.SetSignalValue(channel, message, SelectedSignal, SValue, IsDirectlySend, sendPeriod);
}
else
{
}
}
private void ReleaseTSMaster()
{
CAN.Release();
}
private void InitTSMaster()
{
var re = CAN.Init("ACP");
}
private void UpLoadDBC()
{
var re = CAN.UnLoadDBC();
}
private void ChangeDBC()
{
var dialog = new OpenFileDialog
{
Title = "更换DBC文件",
Filter = "DBC 文件 (*.dbc)|*.dbc|所有文件 (*.*)|*.*",
DefaultExt = ".dbc",
};
if (dialog.ShowDialog() == true)
{
DBCPath = Path.GetFullPath(dialog.FileName);
ConfigService.Save(_systemConfig);
}
}
private void LoadDBC()
{
if (int.TryParse(DBCChannel, out var channel))
{
var re = CAN.LoadDBC(DBCPath, [channel], out _);
if (re == 0 && IsSaved)
{
var item = DBCAutoLoadList.Where(s => s.DBCChannel == channel).FirstOrDefault();
if (item == null)
{
DBCAutoLoadList.Add(new AutoDBCLoadItem
{
DBCFilePath = DBCPath,
DBCChannel = channel
});
}
else
{
DBCAutoLoadList.Remove(item);
DBCAutoLoadList.Add(new AutoDBCLoadItem
{
DBCFilePath = DBCPath,
DBCChannel = channel
});
}
ConfigService.Save(_systemConfig);
}
}
else
{
}
}
private void CheckDBC()
{
if (int.TryParse(DBCChannel, out var channel))
{
_dialogService.ShowDialog("DBCInfo", new DialogParameters
{
{ "can_Network", DBCParse.can_Network },
{ "MsgDatabase", DBCParse.MsgDatabase[channel] }
});
}
}
private void ClearCycle()
{
var re = CAN.DeleteCyclicMsgs();
}
private void CloseCan()
{
var re = CAN.DisConnect();
}
private void ConnectCan()
{
var re = CAN.Connect();
}
private void EndTranscirbe()
{
var re = CAN.StopLogging();
}
private void StartTranscirbe()
{
var re = CAN.StartLogging(BLFPath);
}
private void SaveBLFPath()
{
_systemConfig.DefaultBLFFilePath = BLFPath;
ConfigService.Save(_systemConfig);
}
private void SelectBLFPath()
{
var dialog = new SaveFileDialog
{
Title = "保存 CAN报文回放 BLF 文件",
Filter = "BLF 文件 (*.blf)|*.blf|所有文件 (*.*)|*.*",
DefaultExt = ".blf",
FileName = "log.blf",
OverwritePrompt = true
};
if (dialog.ShowDialog() == true)
{
BLFPath = Path.GetFullPath(dialog.FileName);
}
}
private void Close()
{
RequestClose.Invoke();
}
#endregion
public byte[] (string s)
{
s = s.Replace("[", string.Empty).Replace("]", string.Empty);
var strs = s.Split(',', StringSplitOptions.RemoveEmptyEntries);
byte[] bytes = new byte[strs.Length];
for (int i = 0; i < strs.Length; i++)
{
bytes[i] = Convert.ToByte(strs[i], 16);
}
return bytes;
}
private async Task Refresh(CancellationToken ct = default)
{
while (ct.IsCancellationRequested == false)
{
var temp = CAN.RealTimeMessages.Select(s => s.Value).ToArray();
foreach (var item in temp)
{
var find = CanMessageList.FirstOrDefault(s => s.ID == item.FIdentifier);
if (find != null)
{
if (find. != item.FIdxChn) find. = item.FIdxChn;
if (find.ID != item.FIdentifier) find.ID = item.FIdentifier;
if (find. != item.FTimeUS) find. = item.FTimeUS;
if (find.FD != item.FIsFD) find.FD = item.FIsFD;
if (find.IsTx != item.FIsTx) find.IsTx = item.FIsTx;
var = find. == item.FDLC;
var = find.Bytes.SequenceEqual(item.FData);
if ( || )
{
find. = item.FDLC;
Array.Copy(item.FData, 0, find.Bytes, 0, 64);
find. = (item.FData.AsSpan(0, find.));
}
}
else
{
var temp = new CanMessageShowVM()
{
= item.FIdxChn,
ID = item.FIdentifier,
= item.FTimeUS,
FD = item.FIsFD,
IsTx = item.FIsTx,
= item.FDLC,
= (item.FData.AsSpan(0, item.FDLC)),
};
Array.Copy(item.FData, 0, temp.Bytes, 0, 64);
Application.Current.Dispatcher.Invoke(() =>
{
CanMessageList.Add(temp);
});
}
}
await Task.Delay(50, ct);
}
}
string (Span<byte> s)
{
if (s == null || s.Length == 0)
return "[]";
var sb = new StringBuilder();
sb.Append('[');
for (int i = 0; i < s.Length; i++)
{
sb.Append("0x");
sb.Append(s[i].ToString("X2"));
if (i < s.Length - 1)
sb.Append(", ");
}
sb.Append(']');
return sb.ToString();
}
#region dialog规范
public DialogCloseListener RequestClose { get; set; }
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
cts.Cancel();
}
public void OnDialogOpened(IDialogParameters parameters)
{
Task.Run(() => Refresh(cts.Token), cts.Token);
}
#endregion
}
}

View File

@@ -1,30 +1,41 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Model;
using TSMasterCAN;
using UIShare.GlobalVariable;
using UIShare.PubEvent;
using UIShare.UIViewModel;
using UIShare.ViewModelBase;
using ZLGUSBCANFD;
namespace CANModule.ViewModels
{
public class CollectCANSignalSettingViewModel : DialogViewModelBase
public class CollectCANSignalSettingViewModel : BindableBase, IDialogAware
{
#region
private ZLGCANFD? _canfd;
private SystemConfig? _systemConfig;
#endregion
#region
public ObservableCollection<CANSignalConfig> ConfigurationList
{
get => _systemConfig?.ConfigurationList ?? new ObservableCollection<CANSignalConfig>();
get => _systemConfig.ConfigurationList;
set
{
if(_systemConfig.ConfigurationList != value)
{
_systemConfig.ConfigurationList = value;
RaisePropertyChanged();
}
}
}
private ObservableCollection<int> _ChannelList;
public ObservableCollection<int> ChannelList
{
get => _ChannelList;
set => SetProperty(ref _ChannelList, value);
}
private ObservableCollection<string> _messageList;
public ObservableCollection<string> MessageList
{
@@ -39,42 +50,23 @@ namespace CANModule.ViewModels
set => SetProperty(ref _signalList, value);
}
private string _title = "信号采集设置";
private string _title= "信号采集设置";
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
private string _selectedMessage;
public string SelectedMessage
{
get => _selectedMessage;
set
{
if (SetProperty(ref _selectedMessage, value))
if (SetProperty(ref _selectedMessage,value))
{
if (!string.IsNullOrEmpty(value) && _canfd != null)
if (value != null && value != "")
{
var db = _canfd.DBCParser.MsgDatabase;
if (MessageChannel >= 0 && MessageChannel < db.Count)
{
var targetMsg = db[MessageChannel]
.FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value);
if (targetMsg != null && targetMsg.signal_Name != null)
{
SignalList = new ObservableCollection<string>(targetMsg.signal_Name);
}
else
{
SignalList = new ObservableCollection<string>();
}
}
}
else
{
SignalList = new ObservableCollection<string>();
SignalList = new(DBCParse.MsgDatabase[MessageChannel].Where(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value).First().signal_Name);
}
}
}
@@ -86,7 +78,6 @@ namespace CANModule.ViewModels
get => _SelectedItem;
set => SetProperty(ref _SelectedItem, value);
}
private string _selectedSignal;
public string SelectedSignal
{
@@ -94,7 +85,7 @@ namespace CANModule.ViewModels
set => SetProperty(ref _selectedSignal, value);
}
private int _MessageChannel=-1;
private int _MessageChannel;
public int MessageChannel
{
get => _MessageChannel;
@@ -103,127 +94,91 @@ namespace CANModule.ViewModels
if (_MessageChannel != value)
{
_MessageChannel = value;
MessageList = new(DBCParse.MsgDatabase[value].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
SignalList = new();
SelectedMessage = null;
SelectedSignal = null;
SignalList = new ObservableCollection<string>();
if (_canfd != null)
{
var db = _canfd.DBCParser.MsgDatabase;
if (db != null && value >= 0 && value < db.Count)
{
MessageList = new ObservableCollection<string>(
db[value].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}")
);
}
else
{
MessageList = new ObservableCollection<string>();
}
}
else
{
MessageList = new ObservableCollection<string>();
}
RaisePropertyChanged();
}
}
}
private int _collectionInterval = 1000;
private int _collectionInterval=1000;
public int CollectionInterval
{
get => _collectionInterval;
set => SetProperty(ref _collectionInterval, value);
}
#endregion
#region
#endregion Properties
public ICommand AddCommand { get; set; }
public ICommand CloseCommand { get; set; }
public ICommand SaveCommand { get; set; }
public ICommand DeleteCommand { get; set; }
#endregion
public CollectCANSignalSettingViewModel(IContainerProvider containerProvider) : base(containerProvider)
public ICommand CloseCommand { get; set; }
public ICommand LoadCommand { get; set; }
public ICommand SaveCommand { get; set; }
public ICommand DeleteCommand { get; set; }
public DialogCloseListener RequestClose { get; set; }
public IEventAggregator _eventAggregator { get; set; }
private SystemConfig _systemConfig;
public CollectCANSignalSettingViewModel(IContainerProvider containerProvider)
{
_eventAggregator=containerProvider.Resolve<IEventAggregator>();
_systemConfig= containerProvider.Resolve<SystemConfig>();
CloseCommand = new DelegateCommand(Close);
AddCommand = new DelegateCommand(Add);
LoadCommand = new DelegateCommand(Load);
SaveCommand = new DelegateCommand(Save);
DeleteCommand = new DelegateCommand(Delete);
}
#region Dialog
public override void OnDialogOpened(IDialogParameters parameters)
{
_systemConfig = parameters.GetValue<SystemConfig>("SystemConfig");
_canfd = _systemConfig?.CANFD;
string title = _systemConfig.Title;
char lastChar = title[title.Length - 1];
// 3. "TestCellX"转int
MessageChannel = int.Parse(lastChar.ToString())-1;
if (MessageChannel >= 4) MessageChannel -= 4;
RaisePropertyChanged(nameof(ConfigurationList));
}
#endregion
#region
private void Delete()
{
if (SelectedItem != null)
{
_systemConfig?.ConfigurationList.Remove(SelectedItem);
}
ConfigurationList.Remove(SelectedItem);
}
private void Save()
{
_eventAggregator.GetEvent<CollectedCANMessageChangedEvent>().Publish();
ConfigService.Save(_systemConfig);
}
private void Load()
{
ChannelList = new ObservableCollection<int>(Enumerable.Range(0, 12));
}
private void Add()
{
if (string.IsNullOrEmpty(SelectedSignal) || string.IsNullOrEmpty(SelectedMessage) || CollectionInterval < 100)
if (string.IsNullOrEmpty(SelectedSignal) || string.IsNullOrEmpty(SelectedMessage)||CollectionInterval<100)
{
return;
}
if (_systemConfig == null) return;
string hexString = ExtractHex(SelectedMessage);
if (string.IsNullOrEmpty(hexString)) return;
int decimalValue = ConvertHexToDecimal(hexString);
if (_systemConfig.ConfigurationList.Any(x => x.SignalName == SelectedSignal && x.Channel == MessageChannel))
if (string.IsNullOrEmpty(hexString))
{
return;
}
_systemConfig.ConfigurationList.Add(new CANSignalConfig
int decimalValue = ConvertHexToDecimal(hexString);
if (ConfigurationList.Where(x => x.SignalName == SelectedSignal&&x.Channel==MessageChannel).FirstOrDefault() != null) return;
ConfigurationList.Add(new CANSignalConfig
{
CollectionID = Guid.NewGuid(),
Channel = MessageChannel,
MethodName = CANSignalBroadcaster.BuildMethodName((uint)decimalValue, SelectedSignal),
Channel = MessageChannel,
MessageName = ExtractMessageName(SelectedMessage),
SignalName = SelectedSignal,
MessageID = decimalValue,
CollectionInterval = CollectionInterval
});
}
private string ExtractHex(string input)
{
int startIndex = input.IndexOf("0x") + 2;
int endIndex = input.IndexOf("]", startIndex);
int endIndex = input.IndexOf("]", startIndex);
if (startIndex >= 2 && endIndex > startIndex)
{
return input.Substring(startIndex, endIndex - startIndex);
}
return string.Empty;
}
private int ConvertHexToDecimal(string hex)
{
try
@@ -232,20 +187,37 @@ namespace CANModule.ViewModels
}
catch (FormatException)
{
return -1;
return -1;
}
}
private string ExtractMessageName(string input)
{
var parts = input.Split(']');
return parts.Length > 1 ? parts[1] : string.Empty;
return parts.Length > 1 ? parts[1] : string.Empty;
}
private void Close()
{
RequestClose.Invoke();
}
#endregion
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
if (DBCParse.MsgDatabase.Count == 0 || DBCParse.MsgDatabase[0].Count==0)
{
}
MessageList = new(DBCParse.MsgDatabase[0].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
}
}
}

View File

@@ -1,29 +1,26 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using UIShare.ViewModelBase;
using ZLGUSBCANFD;
using TSMasterCAN;
using UIShare.UIViewModel;
namespace CANModule.ViewModels
{
public class SelectCanMessageViewModel : DialogViewModelBase
public class SelectCanMessageViewModel : BindableBase, IDialogAware
{
#region
private ZLGCANFD? _canfd;
#endregion
#region
public DialogCloseListener RequestClose { get; set; }
private ObservableCollection<int> _ChannelList;
public ObservableCollection<int> ChannelList
{
get => _ChannelList;
set => SetProperty(ref _ChannelList, value);
}
private ObservableCollection<string> _messageList;
public ObservableCollection<string> MessageList
{
@@ -44,7 +41,6 @@ namespace CANModule.ViewModels
get => _title;
set => SetProperty(ref _title, value);
}
private string _selectedMessage;
public string SelectedMessage
{
@@ -53,27 +49,9 @@ namespace CANModule.ViewModels
{
if (SetProperty(ref _selectedMessage, value))
{
if (!string.IsNullOrEmpty(value) && _canfd != null)
if (value != null && value != "")
{
var db = _canfd.DBCParser.MsgDatabase;
if (MessageChannel >= 0 && MessageChannel < db.Count)
{
var targetMsg = db[MessageChannel]
.FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value);
if (targetMsg != null && targetMsg.signal_Name != null)
{
SignalList = new ObservableCollection<string>(targetMsg.signal_Name);
}
else
{
SignalList = new ObservableCollection<string>();
}
}
}
else
{
SignalList = new ObservableCollection<string>();
SignalList = new(DBCParse.MsgDatabase[MessageChannel].Where(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value).First().signal_Name);
}
}
}
@@ -85,8 +63,7 @@ namespace CANModule.ViewModels
get => _selectedSignal;
set => SetProperty(ref _selectedSignal, value);
}
private int _MessageChannel = -1;
private int _MessageChannel;
public int MessageChannel
{
get => _MessageChannel;
@@ -94,94 +71,84 @@ namespace CANModule.ViewModels
{
if (_MessageChannel != value)
{
_MessageChannel = value;
// 1. 先安全清空旧的选择项和信号列表
_MessageChannel=value;
MessageList = new(DBCParse.MsgDatabase[value].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
SignalList = new();
SelectedMessage = null;
SelectedSignal = null;
SignalList = new ObservableCollection<string>();
// 2. 刷新当前通道的报文列表
if (_canfd != null)
{
var db = _canfd.DBCParser.MsgDatabase;
if (db != null && value >= 0 && value < db.Count)
{
MessageList = new ObservableCollection<string>(
db[value].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}")
);
}
else
{
MessageList = new ObservableCollection<string>();
}
}
else
{
MessageList = new ObservableCollection<string>();
}
RaisePropertyChanged();
}
}
}
#endregion
#region
public ICommand CloseCommand { get; set; }
public ICommand GetSelectedMessageCommand { get; set; }
public ICommand GetSelectedSignalCommand { get; set; }
public ICommand LoadCommand { get; set; }
#endregion
public SelectCanMessageViewModel(IContainerProvider containerProvider) : base(containerProvider)
public DialogCloseListener RequestClose { get; set; }
public SelectCanMessageViewModel()
{
CloseCommand = new DelegateCommand(Close);
GetSelectedMessageCommand = new DelegateCommand(GetSelectedMessage);
GetSelectedSignalCommand = new DelegateCommand(GetSelectedSignal);
LoadCommand = new DelegateCommand(Load);
}
#region Dialog
public override void OnDialogOpened(IDialogParameters parameters)
{
_canfd = parameters.GetValue<ZLGCANFD>("CANFD");
}
#endregion
#region
private void Close()
{
RequestClose.Invoke();
}
private void Load()
{
int maxCh = _canfd?.DBCParser.MaxChannels ?? 4;
ChannelList = new ObservableCollection<int>(Enumerable.Range(0, maxCh));
ChannelList = new ObservableCollection<int>(Enumerable.Range(0, 12));
}
private void GetSelectedSignal()
{
if (!string.IsNullOrEmpty(SelectedSignal))
if (SelectedSignal!=null)
{
Application.Current.Dispatcher.Invoke(() =>
{
Clipboard.SetDataObject(SelectedSignal);
});
}
else
{
}
}
private void GetSelectedMessage()
{
if (!string.IsNullOrEmpty(SelectedMessage) && SelectedMessage.Contains(']'))
if (SelectedSignal != null)
{
Application.Current.Dispatcher.Invoke(() =>
{
Clipboard.SetDataObject(SelectedMessage);
Clipboard.SetDataObject(SelectedMessage.Split("]")[1]);
});
}
else
{
}
}
private void Close()
{
RequestClose.Invoke();
}
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
MessageList = new(DBCParse.MsgDatabase[0].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
}
#endregion
}
}

View File

@@ -1,649 +0,0 @@
using Microsoft.Win32;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using UIShare.GlobalVariable;
using UIShare.UIViewModel;
using UIShare.ViewModelBase;
using ZLGUSBCANFD;
namespace CANModule.ViewModels
{
public class ZLGCANFDViewModel : NavigateViewModelBase
{
#region
private ZLGCANFD? _canfd;
private SystemConfig? _systemConfig;
private CancellationTokenSource? _refreshCts;
private readonly DeviceManager _deviceManager;
#endregion
#region
private string _Title = "周立功CAN";
public string Title
{
get => _Title;
set => SetProperty(ref _Title, value);
}
private ObservableCollection<CanMessageShowVM> _CanMessageList = new();
public ObservableCollection<CanMessageShowVM> CanMessageList
{
get => _CanMessageList;
set => SetProperty(ref _CanMessageList, value);
}
private int _DBCChannel = 0;
public int DBCChannel
{
get => _DBCChannel;
set => SetProperty(ref _DBCChannel, value);
}
private bool _IsDirectlySend = false;
public bool IsDirectlySend
{
get => _IsDirectlySend;
set => SetProperty(ref _IsDirectlySend, value);
}
private ObservableCollection<string> _Message;
public ObservableCollection<string> Message
{
get => _Message;
set => SetProperty(ref _Message, value);
}
private ObservableCollection<string> _Signal;
public ObservableCollection<string> Signal
{
get => _Signal;
set => SetProperty(ref _Signal, value);
}
private byte _channel;
private string _selectedMessage;
public string SelectedMessage
{
get => _selectedMessage;
set
{
if (_selectedMessage != value)
{
if (!string.IsNullOrEmpty(value) && _canfd != null)
{
var db = _canfd.DBCParser.MsgDatabase;
if (_channel >= 0 && _channel < db.Count)
{
var targetMsg = db[(int)_channel]
.FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == value);
if (targetMsg != null && targetMsg.signal_Name != null)
{
Signal = new ObservableCollection<string>(targetMsg.signal_Name);
}
else
{
Signal = new ObservableCollection<string>();
}
}
}
else
{
Signal = new ObservableCollection<string>();
}
_selectedMessage = value;
RaisePropertyChanged();
}
}
}
private string _selectedSignal;
public string SelectedSignal
{
get => _selectedSignal;
set => SetProperty(ref _selectedSignal, value);
}
private string _signalValue;
public string SignalValue
{
get => _signalValue;
set => SetProperty(ref _signalValue, value);
}
private string _cycleSendInterval;
public string CycleSendInterval
{
get => _cycleSendInterval;
set => SetProperty(ref _cycleSendInterval, value);
}
private int _messageSendChannel = 0;
public int MessageSendChannel
{
get => _messageSendChannel;
set => SetProperty(ref _messageSendChannel, value);
}
public string BLFPath
{
get => _systemConfig?.DefaultBLFFilePath ?? "";
set
{
if (_systemConfig != null && _systemConfig.DefaultBLFFilePath != value)
{
_systemConfig.DefaultBLFFilePath = value;
RaisePropertyChanged();
}
}
}
public string DBCPath
{
get => _systemConfig?.DefaultDBCFilePath ?? "";
set
{
if (_systemConfig != null && _systemConfig.DefaultDBCFilePath != value)
{
_systemConfig.DefaultDBCFilePath = value;
RaisePropertyChanged();
}
}
}
private bool _IsSaved;
public bool IsSaved
{
get => _IsSaved;
set => SetProperty(ref _IsSaved, value);
}
public ObservableCollection<AutoDBCLoadItem> DBCAutoLoadList
{
get => _systemConfig?.DBCAutoLoadList ?? new ObservableCollection<AutoDBCLoadItem>();
}
private AutoDBCLoadItem _SelectedDcAutoLoad;
public AutoDBCLoadItem SelectedDcAutoLoad
{
get => _SelectedDcAutoLoad;
set => SetProperty(ref _SelectedDcAutoLoad, value);
}
// ===== 自定义报文发送属性 =====
private APP_CHANNEL[] _appChannelNames = Enum.GetValues<APP_CHANNEL>();
public APP_CHANNEL[] APP_CHANNEL
{
get => _appChannelNames;
set => SetProperty(ref _appChannelNames, value);
}
private APP_CHANNEL _aIdxChn;
public APP_CHANNEL AIdxChn
{
get => _aIdxChn;
set => SetProperty(ref _aIdxChn, value);
}
private int _aID;
public int AID
{
get => _aID;
set => SetProperty(ref _aID, value);
}
private bool _aIsTx;
public bool AIsTx
{
get => _aIsTx;
set => SetProperty(ref _aIsTx, value);
}
private bool _aIsExt;
public bool AIsExt
{
get => _aIsExt;
set => SetProperty(ref _aIsExt, value);
}
private bool _aIsRemote;
public bool AIsRemote
{
get => _aIsRemote;
set => SetProperty(ref _aIsRemote, value);
}
private byte _aDlc;
public byte ADLC
{
get => _aDlc;
set => SetProperty(ref _aDlc, value);
}
private byte[] _aDataArray;
public byte[] ADataArray
{
get => _aDataArray;
set => SetProperty(ref _aDataArray, value);
}
private bool _aIsFD = true;
public bool AIsFD
{
get => _aIsFD;
set => SetProperty(ref _aIsFD, value);
}
private bool _aIsBRS = false;
public bool AIsBRS
{
get => _aIsBRS;
set => SetProperty(ref _aIsBRS, value);
}
private bool _AutoSetting = true;
public bool AutoSetting
{
get => _AutoSetting;
set => SetProperty(ref _AutoSetting, value);
}
private string _CustomMessage = "[00,11,22,33,AA,BB,CC,DD]";
public string CustomMessage
{
get => _CustomMessage;
set => SetProperty(ref _CustomMessage, value);
}
private float _CustomSendCycleInterval = 0.0f;
public float CustomSendCycleInterval
{
get => _CustomSendCycleInterval;
set => SetProperty(ref _CustomSendCycleInterval, value);
}
//private bool _UpdateToDB;
//public bool UpdateToDB
//{
// get => _UpdateToDB;
// set => SetProperty(ref _UpdateToDB, value);
//}
// ===== 连接状态 =====
private bool _IsDeviceOpened;
public bool IsDeviceOpened
{
get => _IsDeviceOpened;
set => SetProperty(ref _IsDeviceOpened, value);
}
private ObservableCollection<int> _ChannelList;
public ObservableCollection<int> ChannelList
{
get => _ChannelList;
set => SetProperty(ref _ChannelList, value);
}
private int _SelectedChannel = -1;
public int SelectedChannel
{
get => _SelectedChannel;
set
{
if (_SelectedChannel != value)
{
_SelectedChannel = value;
if (value >= 0 && _canfd != null)
{
_canfd.((uint)value);
}
RaisePropertyChanged();
}
}
}
#endregion
#region
public ICommand SelectBLFPathCommand { get; set; }
public ICommand SaveBLFPathCommand { get; set; }
public ICommand StartTranscribeCommand { get; set; }
public ICommand EndTranscribeCommand { get; set; }
public ICommand ConnectCanCommand { get; set; }
public ICommand CloseCanCommand { get; set; }
public ICommand ClearCycleCommand { get; set; }
public ICommand UpLoadDBCCommand { get; set; }
public ICommand ChangeDBCCommand { get; set; }
public ICommand LoadDBCCommand { get; set; }
public ICommand LoadMessageCommand { get; set; }
public ICommand SetAndSendMessageCommand { get; set; }
public ICommand DeleteDcAutoLoadCommand { get; set; }
public ICommand SendCustomMessageCommand { get; set; }
public ICommand LoadCommand { get; set; }
#endregion
public ZLGCANFDViewModel(IContainerProvider containerProvider) : base(containerProvider)
{
_systemConfig = containerProvider.Resolve<SystemConfig>();
_deviceManager = containerProvider.Resolve<DeviceManager>();
_canfd = _deviceManager.CANFD;
SelectBLFPathCommand = new DelegateCommand(SelectBLFPath);
SaveBLFPathCommand = new DelegateCommand(SaveBLFPath);
StartTranscribeCommand = new DelegateCommand(StartTranscribe);
EndTranscribeCommand = new DelegateCommand(EndTranscribe);
ConnectCanCommand = new DelegateCommand(ConnectCan);
CloseCanCommand = new DelegateCommand(CloseCan);
ClearCycleCommand = new DelegateCommand(ClearCycle);
UpLoadDBCCommand = new DelegateCommand(UpLoadDBC);
ChangeDBCCommand = new DelegateCommand(ChangeDBC);
LoadDBCCommand = new DelegateCommand(LoadDBC);
SetAndSendMessageCommand = new DelegateCommand(SetAndSendMessage);
LoadMessageCommand = new DelegateCommand(LoadMessage);
DeleteDcAutoLoadCommand = new DelegateCommand(DeleteDcAutoLoad);
SendCustomMessageCommand = new DelegateCommand(SendCustomMessage);
_canfd.OnDbcMessageDecoded += OnDbcMessageDecoded;
LoadCommand = new DelegateCommand(Load);
}
#region Dialog
public override void OnNavigatedTo(NavigationContext navigationContext)
{
if (_canfd != null)
{
}
RaisePropertyChanged(nameof(BLFPath));
RaisePropertyChanged(nameof(DBCPath));
RaisePropertyChanged(nameof(DBCAutoLoadList));
}
public override void OnNavigatedFrom(NavigationContext navigationContext)
{
if (_canfd != null)
{
_canfd.OnDbcMessageDecoded -= OnDbcMessageDecoded;
}
_refreshCts?.Cancel();
}
#endregion
#region
private void Load()
{
int maxCh = _canfd?.DBCParser.MaxChannels ?? 4;
ChannelList = new ObservableCollection<int>(Enumerable.Range(0, maxCh));
}
private void SendCustomMessage()
{
if (_canfd == null) return;
try
{
ADataArray = (CustomMessage);
if (ADataArray.Length > byte.MaxValue) throw new Exception("报文数量超过上限!");
if (AutoSetting)
{
ADLC = (byte)ADataArray.Length;
}
}
catch (Exception ex)
{
ShowErrorMessageBox($"报文转换失败:{ex.Message}", () => { });
return;
}
_canfd.(
(uint)AIdxChn,
AID.ToString(),
ADataArray,
ADLC,
AIsExt,
AIsFD,
AIsBRS);
}
private void DeleteDcAutoLoad()
{
if (SelectedDcAutoLoad != null)
{
DBCAutoLoadList.Remove(SelectedDcAutoLoad);
}
}
private void LoadMessage()
{
if (_canfd == null) return;
if (MessageSendChannel >= 0)
{
var db = _canfd.DBCParser.MsgDatabase;
if (MessageSendChannel < db.Count)
{
Message = new ObservableCollection<string>(
db[MessageSendChannel].Select(s => $"[0x{s.msg_id:X}]{s.msg_name}"));
}
}
}
private void SetAndSendMessage()
{
if (_canfd == null) return;
if (int.TryParse(CycleSendInterval, out int sendPeriod) &&
double.TryParse(SignalValue, out double SValue) &&
MessageSendChannel >= 0)
{
_channel = (byte)MessageSendChannel;
var message = SelectedMessage.Split(']')[1];
// 通过 DBC 查找帧 ID
var db = _canfd.DBCParser.MsgDatabase;
if (MessageSendChannel < db.Count)
{
var targetMsg = db[MessageSendChannel]
.FirstOrDefault(x => $"[0x{x.msg_id:X}]{x.msg_name}" == SelectedMessage);
if (targetMsg != null)
{
_canfd.((uint)MessageSendChannel, targetMsg.msg_id.ToString(), SelectedSignal, SValue, sendPeriod, IsDirectlySend);
}
}
}
}
private void UpLoadDBC()
{
if (_canfd == null) return;
// 释放当前通道的 DBC
if (DBCChannel >= 0)
{
_canfd.DBC((uint)DBCChannel);
}
}
private void ChangeDBC()
{
var dialog = new OpenFileDialog
{
Title = "更换DBC文件",
Filter = "DBC 文件 (*.dbc)|*.dbc|所有文件 (*.*)|*.*",
DefaultExt = ".dbc",
};
if (dialog.ShowDialog() == true)
{
DBCPath = System.IO.Path.GetFullPath(dialog.FileName);
}
}
private void LoadDBC()
{
if (_canfd == null || DBCChannel < 0) return;
bool re = _canfd.DBC文件((uint)DBCChannel, DBCPath);
if (re && IsSaved)
{
var item = DBCAutoLoadList.FirstOrDefault(s => s.DBCChannel == DBCChannel);
if (item == null)
{
DBCAutoLoadList.Add(new AutoDBCLoadItem
{
DBCFilePath = DBCPath,
DBCChannel = DBCChannel
});
}
else
{
DBCAutoLoadList.Remove(item);
DBCAutoLoadList.Add(new AutoDBCLoadItem
{
DBCFilePath = DBCPath,
DBCChannel = DBCChannel
});
}
ConfigService.Save(_systemConfig);
}
}
private void ClearCycle()
{
_canfd?.();
}
private void CloseCan()
{
if (_canfd == null) return;
_canfd.CAN卡设备();
IsDeviceOpened = false;
_refreshCts?.Cancel();
}
private void ConnectCan()
{
if (_canfd == null) return;
bool re = _canfd.();
IsDeviceOpened = re;
if (re)
{
// 启动实时报文刷新
_refreshCts?.Cancel();
_refreshCts = new CancellationTokenSource();
_ = Refresh(_refreshCts.Token);
}
}
private void EndTranscribe()
{
// TODO: BLF 录制功能在 ZLGCANFD 中未实现,暂不支持
ShowInfoMessageBox("BLF 录制功能尚未在此硬件驱动中实现。", () => { });
}
private void StartTranscribe()
{
// TODO: BLF 录制功能在 ZLGCANFD 中未实现,暂不支持
ShowInfoMessageBox("BLF 录制功能尚未在此硬件驱动中实现。", () => { });
}
private void SaveBLFPath()
{
// 路径已直接绑定到 SystemConfig无需额外操作
}
private void SelectBLFPath()
{
var dialog = new SaveFileDialog
{
Title = "保存 CAN报文回放 BLF 文件",
Filter = "BLF 文件 (*.blf)|*.blf|所有文件 (*.*)|*.*",
DefaultExt = ".blf",
FileName = "log.blf",
OverwritePrompt = true
};
if (dialog.ShowDialog() == true)
{
BLFPath = System.IO.Path.GetFullPath(dialog.FileName);
}
}
#endregion
#region
public byte[] (string s)
{
s = s.Replace("[", string.Empty).Replace("]", string.Empty);
var strs = s.Split(',', StringSplitOptions.RemoveEmptyEntries);
byte[] bytes = new byte[strs.Length];
for (int i = 0; i < strs.Length; i++)
{
bytes[i] = Convert.ToByte(strs[i], 16);
}
return bytes;
}
private async Task Refresh(CancellationToken ct = default)
{
while (!ct.IsCancellationRequested)
{
// 通过 OnDbcMessageDecoded 事件已实时更新 CanMessageList
// 此处仅做周期性 UI 刷新触发
await Task.Delay(50, ct);
}
}
private void OnDbcMessageDecoded(uint channel, ZDBC.DBCMessage msg)
{
// DBC 解码后的报文回调
Application.Current.Dispatcher.BeginInvoke(() =>
{
var msgName = System.Text.Encoding.Default.GetString(msg.strName).TrimEnd('\0');
var find = CanMessageList.FirstOrDefault(s => s.ID == (int)msg.nID&& s.==channel);
if (find != null)
{
find. = (byte)channel;
find.ID = (int)msg.nID;
find. = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(); ;
find. = (byte)msg.nSize;
}
else
{
CanMessageList.Add(new CanMessageShowVM
{
= (byte)channel,
ID = (int)msg.nID,
= (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds(),
= (byte)msg.nSize
});
}
});
}
private string (System.Span<byte> s)
{
if (s == null || s.Length == 0)
return "[]";
var sb = new StringBuilder();
sb.Append('[');
for (int i = 0; i < s.Length; i++)
{
sb.Append("0x");
sb.Append(s[i].ToString("X2"));
if (i < s.Length - 1)
sb.Append(", ");
}
sb.Append(']');
return sb.ToString();
}
#endregion
}
}