diff --git a/CapMachine.Model/CANLIN/CANFdConfigExd.cs b/CapMachine.Model/CANLIN/CANFdConfigExd.cs
new file mode 100644
index 0000000..4425e27
--- /dev/null
+++ b/CapMachine.Model/CANLIN/CANFdConfigExd.cs
@@ -0,0 +1,53 @@
+using FreeSql.DataAnnotations;
+
+namespace CapMachine.Model.CANLIN
+{
+ ///
+ /// CAN和LIN的配置信息数据
+ ///
+ [Table(Name = "CANFdConfigExd")]
+ public class CANFdConfigExd
+ {
+ ///
+ /// 主键
+ ///
+ [Column(IsPrimary = true, IsIdentity = true)]
+ public long Id { get; set; }
+
+ ///
+ /// 数据波特率
+ ///
+ [Column(Name = "DataBaudRate")]
+ public int DataBaudRate { get; set; }
+
+ ///
+ /// 仲裁波特率
+ ///
+ [Column(Name = "ArbBaudRate")]
+ public int ArbBaudRate { get; set; }
+
+ ///
+ /// CAN FD标准 ISO是否启用
+ ///
+ [Column(Name = "ISOEnable")]
+ public bool ISOEnable { get; set; }
+
+ ///
+ /// 终端电阻 是否启用
+ ///
+ [Column(Name = "ResEnable")]
+ public bool ResEnable { get; set; }
+
+ ///
+ /// 周期
+ ///
+ [Column(Name = "Cycle")]
+ public int Cycle { get; set; }
+
+ ///
+ /// Dbc文件路径
+ ///
+ [Column(Name = "DbcPath", IsNullable = false, StringLength = 500)]
+ public string? DbcPath { get; set; }
+ }
+}
diff --git a/CapMachine.Model/CANLIN/CanLinConfigPro.cs b/CapMachine.Model/CANLIN/CanLinConfigPro.cs
index 249ecb8..c78cfd3 100644
--- a/CapMachine.Model/CANLIN/CanLinConfigPro.cs
+++ b/CapMachine.Model/CANLIN/CanLinConfigPro.cs
@@ -45,6 +45,13 @@ namespace CapMachine.Model.CANLIN
public List? CanLinConfigContents { get; set; }
+ ///
+ /// ///////////////////////////////////////////导航属性 LIN 一对一///////////////////////////////////////////////////////
+ ///
+ public long CANFdConfigExdId { get; set; } // 外键字段,必要
+ public CANFdConfigExd CANFdConfigExd { get; set; }
+
+
///
/// ///////////////////////////////////////////导航属性 CAN 一对一///////////////////////////////////////////////////////
///
diff --git a/CapMachine.Model/CANLIN/CanLinEmun.cs b/CapMachine.Model/CANLIN/CanLinEmun.cs
index 42802ed..6fbd82a 100644
--- a/CapMachine.Model/CANLIN/CanLinEmun.cs
+++ b/CapMachine.Model/CANLIN/CanLinEmun.cs
@@ -19,6 +19,11 @@ namespace CapMachine.Model.CANLIN
/// LIN
///
LIN = 2,
+
+ ///
+ /// CANFD
+ ///
+ CANFD = 3,
}
///
diff --git a/CapMachine.Wpf/App.xaml.cs b/CapMachine.Wpf/App.xaml.cs
index de1db20..958243f 100644
--- a/CapMachine.Wpf/App.xaml.cs
+++ b/CapMachine.Wpf/App.xaml.cs
@@ -137,6 +137,7 @@ namespace CapMachine.Wpf
////注册设备服务
//containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
+ containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
@@ -187,6 +188,7 @@ namespace CapMachine.Wpf
containerRegistry.RegisterForNavigation();
containerRegistry.RegisterForNavigation();
containerRegistry.RegisterForNavigation();
+ containerRegistry.RegisterForNavigation();
containerRegistry.RegisterForNavigation();
diff --git a/CapMachine.Wpf/CanDrive/CanFD/DBCParserByFD.cs b/CapMachine.Wpf/CanDrive/CanFD/DBCParserByFD.cs
new file mode 100644
index 0000000..0967da2
--- /dev/null
+++ b/CapMachine.Wpf/CanDrive/CanFD/DBCParserByFD.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.CanDrive.CanFD
+{
+ ///
+ /// 和DBCParser一样,但用于处理USB设备的DBC文件解析。
+ /// DBCParserByFD类用于处理USB设备的DBC文件解析。
+ ///
+ public class DBCParserByFD
+ {
+ public const Int32 DBC_PARSER_OK = 0;//没有错误
+ public const Int32 DBC_PARSER_FILE_OPEN = (-1);//打开文件出错
+ public const Int32 DBC_PARSER_FILE_FORMAT = (-2);//文件格式错误
+ public const Int32 DBC_PARSER_DEV_DISCONNECT = (-3);//设备未连接
+ public const Int32 DBC_PARSER_HANDLE_ERROR = (-4);//LDF Handle错误
+ public const Int32 DBC_PARSER_GET_INFO_ERROR = (-5);//获取解析后的数据出错
+ public const Int32 DBC_PARSER_DATA_ERROR = (-6);//数据处理错误
+ public const Int32 DBC_PARSER_SLAVE_NACK = (-7);//从机未响应数据
+
+ [DllImport("USB2XXX.dll")]
+ public static extern UInt64 DBC_ParserFile(int DevHandle, StringBuilder pDBCFileName);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetMsgQuantity(UInt64 DBCHandle);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetMsgName(UInt64 DBCHandle, int index, StringBuilder pMsgName);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetMsgSignalQuantity(UInt64 DBCHandle, StringBuilder pMsgName);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetMsgSignalName(UInt64 DBCHandle, StringBuilder pMsgName, int index, StringBuilder pSignalName);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetMsgPublisher(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pPublisher);
+ //设置信号值
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_SetSignalValue(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pSignalName, double Value);
+ //获取信号值
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetSignalValue(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pSignalName, double[] pValue);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_GetSignalValueStr(UInt64 DBCHandle, StringBuilder pMsgName, StringBuilder pSignalName, StringBuilder pValueStr);
+
+ //将CAN消息数据填充到信号里面
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_SyncCANMsgToValue(UInt64 DBCHandle, IntPtr pCANMsg, int MsgLen);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_SyncCANFDMsgToValue(UInt64 DBCHandle, IntPtr pCANFDMsg, int MsgLen);
+ //将信号数据填充到CAN消息里面
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_SyncValueToCANMsg(UInt64 DBCHandle, StringBuilder pMsgName, IntPtr pCANMsg);
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 DBC_SyncValueToCANFDMsg(UInt64 DBCHandle, StringBuilder pMsgName, IntPtr pCANFDMsg);
+ }
+}
diff --git a/CapMachine.Wpf/CanDrive/CanFD/ToomossCanFD.cs b/CapMachine.Wpf/CanDrive/CanFD/ToomossCanFD.cs
new file mode 100644
index 0000000..833d7b6
--- /dev/null
+++ b/CapMachine.Wpf/CanDrive/CanFD/ToomossCanFD.cs
@@ -0,0 +1,899 @@
+using CapMachine.Wpf.CanDrive.CanFD;
+using CapMachine.Wpf.Models.Tag;
+using CapMachine.Wpf.Services;
+using NPOI.OpenXmlFormats.Wordprocessing;
+using Prism.Ioc;
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Windows.Interop;
+
+namespace CapMachine.Wpf.CanDrive
+{
+ ///
+ /// Toomoss CANFD
+ ///
+ public class ToomossCanFD : BindableBase
+ {
+ private readonly IContainerProvider ContainerProvider;
+
+ ///
+ /// 实例化函数
+ ///
+ public ToomossCanFD(IContainerProvider containerProvider)
+ {
+ ContainerProvider = containerProvider;
+ HighSpeedDataService = ContainerProvider.Resolve();
+ LogService = ContainerProvider.Resolve();
+ //Stopwatch.Frequency表示高精度计时器每秒的计数次数(ticks/秒)每毫秒的ticks数 = 每秒的ticks数 ÷ 1000
+ TicksPerMs = Stopwatch.Frequency / 1000.0;
+ }
+
+ ///
+ /// HighSpeedDataService 实例
+ ///
+ public HighSpeedDataService HighSpeedDataService { get; set; }
+
+ public ILogService LogService { get; set; }
+
+ ///
+ /// 开始CAN的驱动
+ ///
+ public void StartCanDrive()
+ {
+ try
+ {
+ IsExistsDllFile();
+ ScanDevice();
+ OpenDevice();
+ GetDeviceInfo();
+ GetCANConfig();
+ InitCAN();
+ }
+ catch (Exception ex)
+ {
+ LogService.Error(ex.Message);
+ System.Windows.MessageBox.Show($"{ex.Message}", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ }
+
+ ///
+ /// 开始Dbc文件写入
+ ///
+ public ObservableCollection StartDbc(string DbcPath)
+ {
+ DBC_Parser(DbcPath);
+ return ListCanFdDbcModel;
+ }
+
+ ///
+ /// Dbc消息集合
+ ///
+ public ObservableCollection ListCanFdDbcModel { get; set; } = new ObservableCollection();
+
+
+ #region 公共变量
+
+ ///
+ /// 仲裁波特率
+ ///
+ public uint ArbBaudRate { get; set; } = 500000;
+
+ ///
+ /// 数据波特率
+ ///
+ public uint DataBaudRate { get; set; } = 2000000;
+
+ ///
+ /// CAN FD标准 ISO是否启用
+ ///
+ public bool ISOEnable { get; set; } = true;
+
+ ///
+ /// 终端电阻 是否启用
+ ///
+ public bool ResEnable { get; set; } = true;
+
+ ///
+ /// 更新配置
+ ///
+ public void UpdateConfig(uint arbBaudRate, uint dataBaudRate, bool iSOEnable, bool resEnable, ushort sendCycle)
+ {
+ ArbBaudRate = arbBaudRate;
+ DataBaudRate = dataBaudRate;
+ ISOEnable = iSOEnable;
+ ResEnable = resEnable;
+ SendCycle = sendCycle;
+ }
+
+ ///
+ /// 设备固件信息
+ ///
+ public USB_DEVICEByFD.DEVICE_INFO DevInfo = new USB_DEVICEByFD.DEVICE_INFO();
+
+ ///
+ /// CAN Config
+ ///
+ USB2CANFD.CANFD_INIT_CONFIG CANConfig = new USB2CANFD.CANFD_INIT_CONFIG();
+
+ ///
+ /// 诊断信息
+ ///
+ public USB2CANFD.CANFD_DIAGNOSTIC CurCANFD_DIAGNOSTIC = new USB2CANFD.CANFD_DIAGNOSTIC();
+
+ ///
+ /// CANFD总线错误信息
+ ///
+ public USB2CANFD.CANFD_BUS_ERROR CurCANFD_BUS_ERROR = new USB2CANFD.CANFD_BUS_ERROR();
+
+ ///
+ /// DBC Handle
+ ///
+ public UInt64 DBCHandle { get; set; }
+
+ ///
+ /// 扫描设备Handle集合
+ ///
+ public Int32[] DevHandles { get; set; } = new Int32[20];
+
+ ///
+ /// 扫描设备Handle
+ ///
+ public Int32 DevHandle { get; set; } = 0;
+
+ ///
+ /// Write CAN Index
+ ///
+ public Byte WriteCANIndex { get; set; } = 0;
+
+ ///
+ /// Read CAN Index
+ ///
+ public Byte ReadCANIndex { get; set; } = 0;
+
+
+ private bool _OpenState;
+ ///
+ /// 打开设备的状态
+ ///
+ public bool OpenState
+ {
+ get { return _OpenState; }
+ set { _OpenState = value; RaisePropertyChanged(); }
+ }
+
+ private bool _DbcParserState;
+ ///
+ /// DBC解析的状态
+ ///
+ public bool DbcParserState
+ {
+ get { return _DbcParserState; }
+ set { _DbcParserState = value; RaisePropertyChanged(); }
+ }
+
+ ///
+ /// 扫描到设备个数
+ ///
+ public Int32 DevNum { get; set; }
+
+ public Int32 ret { get; set; }
+
+ public string dllFilePath { get; set; } = "USB2XXX.dll";
+
+
+ ///
+ /// 消息值Pt
+ ///
+ public IntPtr msgPt { get; set; }
+
+ #endregion
+
+ ///
+ /// ******************【1】*********************
+ /// 是否存在Dll文件
+ ///
+ ///
+ public bool IsExistsDllFile()
+ {
+ if (!File.Exists(dllFilePath))
+ {
+ Console.WriteLine("请先将USB2XXX.dll和libusb-1.0.dll文件复制到exe程序文件输出目录下!");
+ Console.WriteLine("dll文件在‘usb2can_lin_pwm_example/sdk/libs/windows’目录下!");
+ Console.WriteLine("程序是32位的就复制‘x86’目录下文件,程序是64位的就复制‘x86_64’目录下文件!");
+ return false;
+ }
+ return true;
+ }
+
+ ///
+ /// ******************【2】*********************
+ /// 扫描查找设备,并将每个设备的唯一设备号存放到数组中,后面的函数需要用到
+ ///
+ ///
+ public bool ScanDevice()
+ {
+ DevNum = USB_DEVICEByFD.USB_ScanDevice(DevHandles);
+ if (DevNum <= 0)
+ {
+ Console.WriteLine("No device connected!");
+
+ return false;
+ }
+ else
+ {
+ Console.WriteLine("Have {0} device connected!", DevNum);
+ DevHandle = DevHandles[0];//获取第一个设备的设备号
+ return true;
+ }
+ }
+
+ ///
+ /// ******************【3】*********************
+ /// 打开设备
+ ///
+ ///
+ public bool OpenDevice()
+ {
+ //打开设备
+ OpenState = USB_DEVICEByFD.USB_OpenDevice(DevHandle);
+ if (!OpenState)
+ {
+ Console.WriteLine("Open device error!");
+ return false;
+ }
+ else
+ {
+ Console.WriteLine("Open device success!");
+ return true;
+ }
+ }
+
+ ///
+ /// ******************【4】*********************
+ /// 获取设备的固件信息
+ ///
+ ///
+ public bool GetDeviceInfo()
+ {
+ //获取固件信息
+ StringBuilder FuncStr = new StringBuilder(256);
+ OpenState = USB_DEVICEByFD.DEV_GetDeviceInfo(DevHandle, ref DevInfo, FuncStr);
+ if (!OpenState)
+ {
+ Console.WriteLine("Get device infomation error!");
+ return false;
+ }
+ else
+ {
+ Console.WriteLine("Firmware Info:");
+ Console.WriteLine(" Name:" + Encoding.Default.GetString(DevInfo.FirmwareName));
+ Console.WriteLine(" Build Date:" + Encoding.Default.GetString(DevInfo.BuildDate));
+ Console.WriteLine(" Firmware Version:v{0}.{1}.{2}", (DevInfo.FirmwareVersion >> 24) & 0xFF, (DevInfo.FirmwareVersion >> 16) & 0xFF, DevInfo.FirmwareVersion & 0xFFFF);
+ Console.WriteLine(" Hardware Version:v{0}.{1}.{2}", (DevInfo.HardwareVersion >> 24) & 0xFF, (DevInfo.HardwareVersion >> 16) & 0xFF, DevInfo.HardwareVersion & 0xFFFF);
+ Console.WriteLine(" Functions:" + DevInfo.Functions.ToString("X8"));
+ Console.WriteLine(" SerialNumber:" + DevInfo.SerialNumber[0] + DevInfo.SerialNumber[1] + DevInfo.SerialNumber[2]);
+ Console.WriteLine(" Functions String:" + FuncStr);
+ StringBuilder DLLBuildDate = new StringBuilder(256);
+ USB_DEVICEByFD.DEV_GetDllBuildTime(DLLBuildDate);
+ Console.WriteLine(" DLL Build Date:" + DLLBuildDate);
+
+ return true;
+ }
+ }
+
+ ///
+ /// ******************【5】*********************
+ /// 获取设备Config配置
+ ///
+ public void GetCANConfig()
+ {
+ //获取CAN波特率参数
+ ret = USB2CANFD.CANFD_GetCANSpeedArg(DevHandle, ref CANConfig, ArbBaudRate, DataBaudRate);
+ if (ret != USB2CANFD.CANFD_SUCCESS)
+ {
+ Console.WriteLine("Get CAN Speed failed!");
+ return;
+ }
+ else
+ {
+ Console.WriteLine("Get CAN Speed Success!");
+ }
+
+ }
+
+ ///
+ /// ******************【6】*********************
+ /// 初始化CAN
+ ///
+ public void InitCAN()
+ {
+ //初始化CAN
+ CANConfig.ISOCRCEnable = ISOEnable == true ? (byte)1 : (byte)0;//使能ISOCRC
+ CANConfig.ResEnable = ResEnable == true ? (byte)1 : (byte)0;//使能终端电阻
+ ret = USB2CANFD.CANFD_Init(DevHandle, WriteCANIndex, ref CANConfig);
+ if (ret != USB2CANFD.CANFD_SUCCESS)
+ {
+ Console.WriteLine("Config CAN failed!");
+ return;
+ }
+ else
+ {
+ Console.WriteLine("WriteCANIndex Config CAN Success!");
+ }
+
+ ret = USB2CANFD.CANFD_Init(DevHandle, ReadCANIndex, ref CANConfig);
+ if (ret != USB2CANFD.CANFD_SUCCESS)
+ {
+ Console.WriteLine("Config CAN failed!");
+ return;
+ }
+ else
+ {
+ Console.WriteLine("ReadCANIndex Config CAN Success!");
+ }
+ Console.WriteLine("");
+ }
+
+ ///
+ /// ******************【7】*********************
+ /// DBC解析
+ ///
+ public void DBC_Parser(string Path)
+ {
+ //解析DBC文件
+ DBCHandle = DBCParserByFD.DBC_ParserFile(DevHandle, new StringBuilder(Path));
+ if (DBCHandle == 0)
+ {
+ Console.WriteLine("Parser DBC File error!");
+ DbcParserState = false;
+ return;
+ }
+ else
+ {
+ Console.WriteLine("Parser DBC File success!");
+ }
+
+ ListCanFdDbcModel.Clear();
+
+ //打印DBC里面报文和信号相关信息
+ int DBCMsgNum = DBCParserByFD.DBC_GetMsgQuantity(DBCHandle);
+ for (int i = 0; i < DBCMsgNum; i++)
+ {
+ StringBuilder MsgName = new StringBuilder(32);
+ DBCParserByFD.DBC_GetMsgName(DBCHandle, i, MsgName);
+ Console.WriteLine("Msg.Name = {0}", MsgName);
+ int DBCSigNum = DBCParserByFD.DBC_GetMsgSignalQuantity(DBCHandle, MsgName);
+ StringBuilder Publisher = new StringBuilder(32);
+ DBCParserByFD.DBC_GetMsgPublisher(DBCHandle, MsgName, Publisher);
+ Console.Write("Signals:");
+ for (int j = 0; j < DBCSigNum; j++)
+ {
+ StringBuilder SigName = new StringBuilder(32);
+ DBCParserByFD.DBC_GetMsgSignalName(DBCHandle, MsgName, j, SigName);
+ Console.Write("{0} ", SigName);
+
+ //增加信息数据
+ ListCanFdDbcModel.Add(new CanDbcModel()
+ {
+ MsgName = MsgName.ToString(),
+ MsgId = "",
+ SignalName = SigName.ToString(),
+ SignalDesc = "",
+ SignalUnit = "",
+ SignalRtValue = "",
+ Publisher = Publisher.ToString()
+ });
+ }
+ Console.WriteLine("");
+ }
+
+ //Dbc解析成功
+ DbcParserState = true;
+ }
+
+ ///
+ /// 发送CAN数据
+ ///
+ public void SendCanMsg(List CmdData)
+ {
+ var GroupMsg = CmdData.GroupBy(x => x.MsgName);
+ USB2CANFD.CANFD_MSG[] CanMsg = new USB2CANFD.CANFD_MSG[GroupMsg.Count()];
+ for (int i = 0; i < GroupMsg.Count(); i++)
+ {
+ CanMsg[i] = new USB2CANFD.CANFD_MSG();
+ CanMsg[i].Data = new Byte[64];
+ }
+
+ IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
+ int Index = 0;
+ //循环给MSG赋值数据
+ foreach (var itemMsg in GroupMsg)
+ {
+ foreach (var itemSignal in itemMsg)
+ {
+ DBCParserByFD.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
+ }
+ DBCParserByFD.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPt);
+ CanMsg[Index] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
+ Index++;
+ }
+
+ //设置信号值
+ //DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), 2412);
+ //DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), 980);
+ //DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), 120);
+
+ //通过DBC写入数据后生成CanMsg
+ //将信号值填入CAN消息里面
+
+
+ //IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
+ //DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_moto_speed"), msgPt);
+ //CanMsg[0] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
+
+ //DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_oil_pressure"), msgPt);
+ //CanMsg[1] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
+
+ //DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_speed_can"), msgPt);
+ //CanMsg[2] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
+
+ //释放申请的临时缓冲区
+ Marshal.FreeHGlobal(msgPt);
+ Console.WriteLine("");
+ //发送CAN数据
+ int SendedNum = USB2CANFD.CANFD_SendMsg(DevHandle, WriteCANIndex, CanMsg, (Int32)CanMsg.Length);
+ if (SendedNum >= 0)
+ {
+ Console.WriteLine("Success send frames:{0}", SendedNum);
+ }
+ else
+ {
+ Console.WriteLine("Send CAN data failed! {0}", SendedNum);
+ }
+ }
+
+
+ #region 精确发送报文数据
+
+ // 添加取消标记源字段用于停止任务
+ private CancellationTokenSource CycleSendCts;
+
+ ///
+ /// 计算每毫秒对应的ticks数(只需计算一次)
+ ///
+ private double TicksPerMs;
+
+ // 类成员变量定义 精确记时用
+ private readonly Stopwatch Stopwatcher = new Stopwatch();
+ private long NextExecutionTime;
+ // 计算需要等待的时间
+ private long CurrentTime;
+ private long DelayTicks;
+ private int DelayMs;
+
+ private static readonly Random _random = new Random();
+
+ ///
+ /// 精确周期发送CAN数据
+ ///
+ public void StartPrecisionCycleSendMsg()
+ {
+ // 创建取消标记源 用于控制任务的取消 允许在需要时通过取消令牌来优雅停止任务
+ var cancellationTokenSource = new CancellationTokenSource();
+ var token = cancellationTokenSource.Token;
+
+ // 保存取消标记,以便在停止时使用
+ CycleSendCts = cancellationTokenSource;//将取消标记源保存到类的成员变量CycleSendCts,这样在外部调用停止方法时可以访问它
+ NextExecutionTime = 0;//初始化NextExecutionTime为0,这个变量用于记录下一次执行的目标时间点
+
+ CycleSendTask = Task.Factory.StartNew(async () =>
+ {
+ try
+ {
+ // 设置当前线程为高优先级
+ Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
+
+ // 初始化完成后开始计时
+ Stopwatcher.Restart();
+ // 预先计算固定值
+ long CycleInTicks = (long)(SendCycle * TicksPerMs);
+ //临时测试用
+ //long lastTicks = Stopwatcher.ElapsedTicks;
+ //IsCycleSend
+ while (IsCycleSend && !token.IsCancellationRequested)
+ {
+ try
+ {
+ // 计算下一次执行时间点 ,将当前设置的发送周期SendCycle(毫秒)转换为Stopwatch的计时单位(tick),累加到NextExecutionTime上
+ NextExecutionTime += CycleInTicks; // 转换为Stopwatch计时单位
+
+ // 获取当前时间点,以Stopwatch的tick为单位
+ CurrentTime = Stopwatcher.ElapsedTicks;
+ //计算需要等待的时间,即目标时间点(NextExecutionTime)与当前时间点(CurrentTime)的差值
+ DelayTicks = NextExecutionTime - CurrentTime;
+
+ // 如果还有等待时间,则等待,只有在目标时间点还未到达时才执行等待
+ if (DelayTicks > 0)
+ {
+ ////此时是需要等待的,那么需要等待多久呢, 将需等待的tick数转换回毫秒
+ DelayMs = (int)(DelayTicks / TicksPerMs);
+ //20这个数据是预估和测试的,可能跟Windows抖动误差就是20ms左右,当然可以不用这个IF()判断,直接SpinWait.SpinUntil(() => Stopwatcher.ElapsedTicks >= NextExecutionTime);但是会导致当前独占一个CPU核心线程
+ //所以设置一个20的阈值,20ms以下的延迟使用SpinWait.SpinUntil进行自旋等待,20ms以上的延迟使用Task.Delay进行异步等待,让CPU不至于一直的独占
+ if (DelayMs <= 20)
+ {
+ SpinWait.SpinUntil(() => Stopwatcher.ElapsedTicks >= NextExecutionTime);
+ }
+ else
+ {
+ ////使用Task.Delay进行异步等待,大部分等待时间通过这种方式完成,避免线程阻塞
+ await Task.Delay(DelayMs - 20, token);
+ //// 使用SpinWait.SpinUntil进行精确的微调等待。自旋等待会占用CPU资源,但能提供更高的定时精度,确保在精确的时间点执行
+ ////上面的Task.Delay可能会因为系统调度等原因导致实际执行时间稍晚于预期,因此在这里使用SpinWait.SpinUntil来确保在精确的时间点执行
+ SpinWait.SpinUntil(() => Stopwatcher.ElapsedTicks >= NextExecutionTime);
+ }
+ }
+
+ // 如果已经超过了计划时间,立即执行并重新校准
+ if (Stopwatcher.ElapsedTicks >= NextExecutionTime + CycleInTicks)
+ {
+ //检测是否发生了严重延迟(超过一个周期)。如果当前时间已经超过了下一次计划时间,则说明系统负载过高或其他原因导致无法按时执行,
+ //此时重置NextExecutionTime为当前时间,避免连续的延迟累积
+ // 严重延迟,重新校准
+ NextExecutionTime = Stopwatcher.ElapsedTicks;
+ Console.WriteLine("定时发送延迟过大,重新校准时间");
+ }
+
+ // 使用Stopwatch记录实际的执行间隔,而不是DateTime
+ //Console.WriteLine($"--实际间隔(ms): {(Stopwatcher.ElapsedTicks - lastTicks) / TicksPerMs:F3}, 目标: {SendCycle}");
+ //lastTicks = Stopwatcher.ElapsedTicks;
+
+ //Console.WriteLine($"--当前时间(毫秒): {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
+
+
+ // 执行发送CAN逻辑
+ {
+
+ var GroupMsg = CmdData.GroupBy(x => x.MsgName);
+ USB2CANFD.CANFD_MSG[] CanMsg = new USB2CANFD.CANFD_MSG[GroupMsg.Count()];
+ for (int i = 0; i < GroupMsg.Count(); i++)
+ {
+ CanMsg[i] = new USB2CANFD.CANFD_MSG();
+ CanMsg[i].Data = new Byte[64];
+ }
+
+ IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
+ int Index = 0;
+
+ //循环给MSG赋值数据
+ foreach (var itemMsg in GroupMsg)
+ {
+ foreach (var itemSignal in itemMsg)
+ {
+ DBCParserByFD.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
+ }
+ DBCParserByFD.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
+ CanMsg[Index] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CANFD.CANFD_MSG));
+ Index++;
+ }
+
+ //通过DBC写入数据后生成CanMsg
+ //将信号值填入CAN消息里面
+
+ //释放申请的临时缓冲区
+ Marshal.FreeHGlobal(msgPtSend);
+ //CanMsg[0].Flags = 5;
+
+ //发送CAN数据
+ int SendedNum = USB2CANFD.CANFD_SendMsg(DevHandle, WriteCANIndex, CanMsg, (Int32)CanMsg.Length);
+
+ if (SendedNum >= 0)
+ {
+ //Console.WriteLine("Success send frames:{0}", SendedNum);
+ IsSendOk = true;
+ }
+ else
+ {
+ //Console.WriteLine("Send CAN data failed! {0}", SendedNum);
+ IsSendOk = false;
+ }
+ }
+
+ }
+ catch (TaskCanceledException)
+ {
+ // 任务被取消,正常退出
+ break;
+ }
+ catch (Exception ex)
+ {
+ LogService.Error(ex.Message);
+ Console.WriteLine($"CAN周期发送异常: {ex.Message}");
+ // 短暂暂停避免异常情况下CPU占用过高
+ await Task.Delay(10, token);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // 确保在任何情况下(正常退出、异常、取消)都会停止计时器
+ Stopwatcher.Stop();
+ LogService.Error(ex.Message);
+ // 清理其他可能的资源
+ Console.WriteLine("CAN周期发送任务已结束,资源已清理");
+ }
+ finally
+ {
+ // 确保在任何情况下(正常退出、异常、取消)都会停止计时器
+ Stopwatcher.Stop();
+ }
+
+ }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
+ }
+
+ ///
+ /// 获取CAN消息数组中指定位置的数据
+ ///
+ /// 源CAN消息数组
+ /// 要获取的数据索引位置
+ /// 返回指定位置数据的新数组
+ private USB2CANFD.CANFD_MSG[] GetCanMsg(USB2CANFD.CANFD_MSG[] sourceCanMsg, int index)
+ {
+ // 参数检查
+ if (sourceCanMsg == null || sourceCanMsg.Length == 0 || index < 0 || index >= sourceCanMsg.Length)
+ {
+ return new USB2CANFD.CANFD_MSG[0];
+ }
+
+ // 创建单个元素的新数组
+ USB2CANFD.CANFD_MSG[] targetMsg = new USB2CANFD.CANFD_MSG[1];
+ targetMsg[0] = sourceCanMsg[index];
+
+ // 由于CANFD_MSG包含数组字段,需要手动初始化数据数组
+ targetMsg[0].Data = new byte[64];
+ // 复制数据
+ Array.Copy(sourceCanMsg[index].Data, targetMsg[0].Data, sourceCanMsg[index].Data.Length);
+
+ return targetMsg;
+ }
+
+ ///
+ /// 修改停止发送的方法
+ ///
+ public void StopCycleSendMsg()
+ {
+ IsCycleSend = false;
+ CycleSendCts?.Cancel();
+ }
+
+ #endregion
+
+
+ private bool _IsCycleRevice;
+ ///
+ /// 是否循环接收数据
+ ///
+ public bool IsCycleRevice
+ {
+ get { return _IsCycleRevice; }
+ set { _IsCycleRevice = value; RaisePropertyChanged(); }
+ }
+
+
+ private bool _IsCycleSend;
+ ///
+ /// 是否循环发送数据
+ ///
+ public bool IsCycleSend
+ {
+ get { return _IsCycleSend; }
+ set { _IsCycleSend = value; RaisePropertyChanged(); }
+ }
+
+ ///
+ /// 循环发送数据
+ ///
+ public ushort SendCycle { get; set; } = 200;
+
+ ///
+ /// 循环接受数据
+ ///
+ public ushort ReviceCycle { get; set; } = 200;
+
+
+ ///
+ /// CycleRevice 扫描Task
+ ///
+ private static Task CycleReviceTask { get; set; }
+
+ ///
+ /// CycleSend 扫描Task
+ ///
+ private static Task CycleSendTask { get; set; }
+
+ StringBuilder ValueSb = new StringBuilder(16);
+ double[] ValueDouble = new double[5];
+
+ private bool _IsSendOk;
+ ///
+ /// 发送报文是否OK
+ ///
+ public bool IsSendOk
+ {
+ get { return _IsSendOk; }
+ set
+ {
+ if (_IsSendOk != value)
+ {
+ RaisePropertyChanged();
+ _IsSendOk = value;
+ }
+ }
+ }
+
+ ///
+ /// 要发送的数据
+ ///
+ public List CmdData { get; set; } = new List();
+
+ ///
+ /// 循环获取CAN消息
+ ///
+ public void StartCycleReviceCanMsg()
+ {
+ CycleReviceTask = Task.Run(async () =>
+ {
+ //var ret = USB2CANFD.CANFD_StartGetMsg(DevHandle, ReadCANIndex);
+ while (IsCycleRevice)
+ {
+ await Task.Delay(ReviceCycle);
+ try
+ {
+ //另外一个CAN通道读取数据
+ USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[128];
+ IntPtr msgPtRead = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);
+ int CanNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, msgPtRead, CanMsgBuffer.Length);
+ if (CanNum > 0)
+ {
+ Console.WriteLine("Read CanMsgNum = {0}", CanNum);
+ for (int i = 0; i < CanNum; i++)
+ {
+ CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(msgPtRead + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
+ Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
+ //Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
+ Console.Write("CanMsg[{0}].Data = ", i);
+ for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
+ {
+ Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
+ }
+ Console.WriteLine("");
+ //报文给高速记录的服务
+ HighSpeedDataService.AppendOrUpdateMsg(new Models.HighSpeed.CommMsg()
+ {
+ Category = "CANFD",
+ MsgInfo = "0x" + CanMsgBuffer[i].ID.ToString("X8"),
+ MsgData = BitConverter.ToString(CanMsgBuffer[i].Data),
+ Time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+ });
+ }
+ }
+ else if (CanNum == 0)
+ {
+ Console.WriteLine("No CAN data!");
+ }
+ else
+ {
+ Console.WriteLine("Get CAN data error!");
+ }
+ Console.WriteLine("");
+
+ //将CAN消息数据填充到信号里面
+ DBCParserByFD.DBC_SyncCANFDMsgToValue(DBCHandle, msgPtRead, CanNum);
+
+ //循环获取消息的数据
+ foreach (var item in ListCanFdDbcModel)
+ {
+ //有配置的名称的,认为是有用的,则需要读取数据
+ //if (!string.IsNullOrEmpty(item.Name))
+ //{
+ //CAN_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), ValueSb);
+ //double[] ValueDouble;
+ DBCParserByFD.DBC_GetSignalValue(DBCHandle, new StringBuilder(item.MsgName), new StringBuilder(item.SignalName), ValueDouble);
+ //item.SignalRtValueSb = ValueSb;
+ item.SignalRtValue = ValueDouble[0].ToString();
+ //Console.Write(ValueSb.ToString());
+ //}
+ }
+
+ //释放数据缓冲区,必须释放,否则程序运行一段时间后会报内存不足
+ Marshal.FreeHGlobal(msgPtRead);
+ Thread.Sleep(10);
+
+ ////获取信号值并打印出来
+ //StringBuilder ValueStr = new StringBuilder(32);
+ //DBCParserByFD.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("TX1"), new StringBuilder("COM_current_Power"), ValueStr);
+ //Console.WriteLine("COM_current_Power = {0}", ValueStr);
+ //DBCParserByFD.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("TX1"), new StringBuilder("COM_Curr_dc"), ValueStr);
+ //Console.WriteLine("COM_Curr_dc = {0}", ValueStr);
+ }
+ catch (Exception ex)
+ {
+ LogService.Error(ex.Message);
+ //LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}");
+ }
+ }
+ });
+ }
+
+ ///
+ /// 接受CAN消息
+ ///
+ public void ReciveCanMsg()
+ {
+ //另外一个CAN通道读取数据
+ USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[10];
+ msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);
+ int CanNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, msgPt, CanMsgBuffer.Length);
+ if (CanNum > 0)
+ {
+ Console.WriteLine("Read CanMsgNum = {0}", CanNum);
+ for (int i = 0; i < CanNum; i++)
+ {
+ CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(msgPt + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
+ Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
+ //Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
+ Console.Write("CanMsg[{0}].Data = ", i);
+ for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
+ {
+ Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
+ }
+ Console.WriteLine("");
+ }
+ }
+ else if (CanNum == 0)
+ {
+ Console.WriteLine("No CAN data!");
+ }
+ else
+ {
+ Console.WriteLine("Get CAN data error!");
+ }
+ Console.WriteLine("");
+
+ //将CAN消息数据填充到信号里面
+ DBCParserByFD.DBC_SyncCANFDMsgToValue(DBCHandle, msgPt, CanNum);
+ //获取信号值并打印出来
+ StringBuilder ValueStr = new StringBuilder(32);
+ DBCParserByFD.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
+ Console.WriteLine("moto_speed = {0}", ValueStr);
+ DBCParserByFD.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
+ Console.WriteLine("oil_pressure = {0}", ValueStr);
+ DBCParserByFD.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
+ Console.WriteLine("speed_can = {0}", ValueStr);
+
+ }
+
+
+ ///
+ /// 关闭设备
+ ///
+ public void CloseDevice()
+ {
+ //关闭设备
+ USB_DEVICEByFD.USB_CloseDevice(DevHandle);
+ OpenState = false;
+ DbcParserState = false;
+ IsCycleRevice = false;
+ IsCycleSend = false;
+ }
+
+ }
+}
diff --git a/CapMachine.Wpf/CanDrive/USB2CANFD.cs b/CapMachine.Wpf/CanDrive/CanFD/USB2CANFD.cs
similarity index 100%
rename from CapMachine.Wpf/CanDrive/USB2CANFD.cs
rename to CapMachine.Wpf/CanDrive/CanFD/USB2CANFD.cs
diff --git a/CapMachine.Wpf/CanDrive/CanFD/USB_DEVICEByFD.cs b/CapMachine.Wpf/CanDrive/CanFD/USB_DEVICEByFD.cs
new file mode 100644
index 0000000..66b11c1
--- /dev/null
+++ b/CapMachine.Wpf/CanDrive/CanFD/USB_DEVICEByFD.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.CanDrive.CanFD
+{
+ ///
+ /// 和USB_DEVICE一样,但用于处理USB设备的CAN FD协议。
+ ///
+ public class USB_DEVICEByFD
+ {
+ //定义电压输出值
+ public const Byte POWER_LEVEL_NONE = 0; //不输出
+ public const Byte POWER_LEVEL_1V8 = 1; //输出1.8V
+ public const Byte POWER_LEVEL_2V5 = 2; //输出2.5V
+ public const Byte POWER_LEVEL_3V3 = 3; //输出3.3V
+ public const Byte POWER_LEVEL_5V0 = 4; //输出5.0V
+ //设备信息定义
+ public struct DEVICE_INFO
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public Byte[] FirmwareName; //固件名称字符串
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
+ public Byte[] BuildDate; //固件编译时间字符串
+ public UInt32 HardwareVersion;//硬件版本号
+ public UInt32 FirmwareVersion;//固件版本号
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public UInt32[] SerialNumber; //适配器序列号
+ public UInt32 Functions; //适配器当前具备的功能
+ }
+ //方法定义
+ /**
+ * @brief 初始化USB设备,并扫描设备连接数,必须调用
+ * @param pDevHandle 每个设备的设备号存储地址
+ * @retval 扫描到的设备数量
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern Int32 USB_ScanDevice(Int32[] pDevHandle);
+ /**
+ * @brief 打开设备,必须调用
+ * @param DevHandle 设备索引号
+ * @retval 打开设备的状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool USB_OpenDevice(Int32 DevHandle);
+ /**
+ * @brief 关闭设备
+ * @param DevHandle 设备索引号
+ * @retval 关闭设备的状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool USB_CloseDevice(Int32 DevHandle);
+ /**
+ * @brief 复位设备程序,复位后需要重新调用USB_ScanDevice,USB_OpenDevice函数
+ * @param DevHandle 设备索引号
+ * @retval 复位设备的状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool USB_ResetDevice(Int32 DevHandle);
+
+ /**
+ * @brief 检测到USB断开连接后,重新连接设备
+ * @param DevHandle 设备号
+ * @retval 重连状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool USB_RetryConnect(Int32 DevHandle);
+
+ /**
+ * @brief 获取设备信息,比如设备名称,固件版本号,设备序号,设备功能说明字符串等
+ * @param DevHandle 设备索引号
+ * @param pDevInfo 设备信息存储结构体指针
+ * @param pFunctionStr 设备功能说明字符串
+ * @retval 获取设备信息的状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_GetDeviceInfo(Int32 DevHandle, ref DEVICE_INFO pDevInfo, StringBuilder pFunctionStr);
+ /**
+ * @brief 擦出用户区数据
+ * @param DevHandle 设备索引号
+ * @retval 用户区数据擦出状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_EraseUserData(Int32 DevHandle);
+
+ /**
+ * @brief 向用户区域写入用户自定义数据,写入数据之前需要调用擦出函数将数据擦出
+ * @param DevHandle 设备索引号
+ * @param OffsetAddr 数据写入偏移地址,起始地址为0x00,用户区总容量为0x10000字节,也就是64KBye
+ * @param pWriteData 用户数据缓冲区首地址
+ * @param DataLen 待写入的数据字节数
+ * @retval 写入用户自定义数据状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_WriteUserData(Int32 DevHandle, Int32 OffsetAddr, byte[] pWriteData, Int32 DataLen);
+
+ /**
+ * @brief 从用户自定义数据区读出数据
+ * @param DevHandle 设备索引号
+ * @param OffsetAddr 数据写入偏移地址,起始地址为0x00,用户区总容量为0x10000字节,也就是64KBye
+ * @param pReadData 用户数据缓冲区首地址
+ * @param DataLen 待读出的数据字节数
+ * @retval 读出用户自定义数据的状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_ReadUserData(Int32 DevHandle, Int32 OffsetAddr, byte[] pReadData, Int32 DataLen);
+
+ /**
+ * @brief 设置可变电压输出引脚输出电压值
+ * @param DevHandle 设备索引号
+ * @param PowerLevel 输出电压值
+ * @retval 设置输出电压状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_SetPowerLevel(Int32 DevHandle, byte PowerLevel);
+ /**
+ * @brief 或者CAN或者LIN的时间戳原始值
+ * @param DevHandle 设备索引号
+ * @param pTimestamp 时间戳指针
+ * @retval 获取时间戳状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_GetTimestamp(Int32 DevHandle, byte BusType, Int32[] pTimestamp);
+
+ /**
+ * @brief 复位CAN/LIN时间戳,需要在初始化CAN/LIN之后调用
+ * @param DevHandle 设备索引号
+ * @retval 复位时间戳状态
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_ResetTimestamp(Int32 DevHandle);
+ /**
+ * @brief 获取dll编译日期
+ * @param pDateTime 输出DLL编译日期字符串
+ * @retval 获取dll编译日期字符串
+ */
+ [DllImport("USB2XXX.dll")]
+ public static extern bool DEV_GetDllBuildTime(StringBuilder pDateTime);
+ }
+}
diff --git a/CapMachine.Wpf/CanDrive/ToomossCanFD.cs b/CapMachine.Wpf/CanDrive/ToomossCanFD.cs
deleted file mode 100644
index a84245b..0000000
--- a/CapMachine.Wpf/CanDrive/ToomossCanFD.cs
+++ /dev/null
@@ -1,511 +0,0 @@
-using CapMachine.Wpf.Models.Tag;
-using NPOI.OpenXmlFormats.Wordprocessing;
-using Prism.Mvvm;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Interop;
-
-namespace CapMachine.Wpf.CanDrive
-{
- ///
- /// Toomoss CAN
- ///
- public class ToomossCanFD : BindableBase
- {
- ///
- /// 实例化函数
- ///
- public ToomossCanFD()
- {
-
- }
-
- ///
- /// 开始CAN的驱动
- ///
- public void StartCanDrive()
- {
- IsExistsDllFile();
- ScanDevice();
- OpenDevice();
- GetDeviceInfo();
- GetCANConfig();
- InitCAN();
-
- }
-
- ///
- /// 开始Dbc文件写入
- ///
- public void StartDbc(string DbcPath)
- {
- DBC_Parser(DbcPath);
- }
-
- ///
- /// Dbc消息集合
- ///
- public ObservableCollection ListCanDbcModel { get; set; } = new ObservableCollection();
-
-
- #region 公共变量
-
- ///
- /// 设备固件信息
- ///
- public USB_DEVICE.DEVICE_INFO DevInfo = new USB_DEVICE.DEVICE_INFO();
-
- ///
- /// CAN Config
- ///
- USB2CANFD.CANFD_INIT_CONFIG CANConfig = new USB2CANFD.CANFD_INIT_CONFIG();
-
- ///
- /// DBC Handle
- ///
- public UInt64 DBCHandle { get; set; }
-
- ///
- /// 扫描设备Handle集合
- ///
- public Int32[] DevHandles { get; set; } = new Int32[20];
-
- ///
- /// 扫描设备Handle
- ///
- public Int32 DevHandle { get; set; } = 0;
- ///
- /// Write CAN Index
- ///
- public Byte WriteCANIndex { get; set; } = 0;
-
- ///
- /// Read CAN Index
- ///
- public Byte ReadCANIndex { get; set; } = 1;
-
-
- private bool _OpenState;
- ///
- /// 打开设备的状态
- ///
- public bool OpenState
- {
- get { return _OpenState; }
- set { _OpenState = value; RaisePropertyChanged(); }
- }
-
-
- ///
- /// 扫描到设备个数
- ///
- public Int32 DevNum { get; set; }
-
- public Int32 ret { get; set; }
-
- public string dllFilePath { get; set; } = "USB2XXX.dll";
-
-
- ///
- /// 消息值Pt
- ///
- public IntPtr msgPt { get; set; }
-
- #endregion
-
- ///
- /// ******************【1】*********************
- /// 是否存在Dll文件
- ///
- ///
- public bool IsExistsDllFile()
- {
- if (!File.Exists(dllFilePath))
- {
- Console.WriteLine("请先将USB2XXX.dll和libusb-1.0.dll文件复制到exe程序文件输出目录下!");
- Console.WriteLine("dll文件在‘usb2can_lin_pwm_example/sdk/libs/windows’目录下!");
- Console.WriteLine("程序是32位的就复制‘x86’目录下文件,程序是64位的就复制‘x86_64’目录下文件!");
- return false;
- }
- return true;
- }
-
- ///
- /// ******************【2】*********************
- /// 扫描查找设备,并将每个设备的唯一设备号存放到数组中,后面的函数需要用到
- ///
- ///
- public bool ScanDevice()
- {
- DevNum = USB_DEVICE.USB_ScanDevice(DevHandles);
- if (DevNum <= 0)
- {
- Console.WriteLine("No device connected!");
-
- return false;
- }
- else
- {
- Console.WriteLine("Have {0} device connected!", DevNum);
- DevHandle = DevHandles[0];//获取第一个设备的设备号
- return true;
- }
- }
-
- ///
- /// ******************【3】*********************
- /// 打开设备
- ///
- ///
- public bool OpenDevice()
- {
- //打开设备
- OpenState = USB_DEVICE.USB_OpenDevice(DevHandle);
- if (!OpenState)
- {
- Console.WriteLine("Open device error!");
- return false;
- }
- else
- {
- Console.WriteLine("Open device success!");
- return true;
- }
- }
-
- ///
- /// ******************【4】*********************
- /// 获取设备的固件信息
- ///
- ///
- public bool GetDeviceInfo()
- {
- //获取固件信息
- StringBuilder FuncStr = new StringBuilder(256);
- OpenState = USB_DEVICE.DEV_GetDeviceInfo(DevHandle, ref DevInfo, FuncStr);
- if (!OpenState)
- {
- Console.WriteLine("Get device infomation error!");
- return false;
- }
- else
- {
- Console.WriteLine("Firmware Info:");
- Console.WriteLine(" Name:" + Encoding.Default.GetString(DevInfo.FirmwareName));
- Console.WriteLine(" Build Date:" + Encoding.Default.GetString(DevInfo.BuildDate));
- Console.WriteLine(" Firmware Version:v{0}.{1}.{2}", (DevInfo.FirmwareVersion >> 24) & 0xFF, (DevInfo.FirmwareVersion >> 16) & 0xFF, DevInfo.FirmwareVersion & 0xFFFF);
- Console.WriteLine(" Hardware Version:v{0}.{1}.{2}", (DevInfo.HardwareVersion >> 24) & 0xFF, (DevInfo.HardwareVersion >> 16) & 0xFF, DevInfo.HardwareVersion & 0xFFFF);
- Console.WriteLine(" Functions:" + DevInfo.Functions.ToString("X8"));
- Console.WriteLine(" Functions String:" + FuncStr);
- StringBuilder DLLBuildDate = new StringBuilder(256);
- USB_DEVICE.DEV_GetDllBuildTime(DLLBuildDate);
- Console.WriteLine(" DLL Build Date:" + DLLBuildDate);
-
- return true;
- }
- }
-
- ///
- /// ******************【5】*********************
- /// 获取设备Config配置
- ///
- public void GetCANConfig()
- {
- //获取CAN波特率参数
- ret = USB2CANFD.CANFD_GetCANSpeedArg(DevHandle, ref CANConfig, 500000, 2000000);
- if (ret != USB2CANFD.CANFD_SUCCESS)
- {
- Console.WriteLine("Get CAN Speed failed!");
- return;
- }
- else
- {
- Console.WriteLine("Get CAN Speed Success!");
- }
-
- }
-
- ///
- /// ******************【6】*********************
- /// 初始化CAN
- ///
- public void InitCAN()
- {
- //初始化CAN
-
- ret = USB2CANFD.CANFD_Init(DevHandle, WriteCANIndex, ref CANConfig);
- if (ret != USB2CANFD.CANFD_SUCCESS)
- {
- Console.WriteLine("Config CAN failed!");
- return;
- }
- else
- {
- Console.WriteLine("WriteCANIndex Config CAN Success!");
- }
-
- ret = USB2CANFD.CANFD_Init(DevHandle, ReadCANIndex, ref CANConfig);
- if (ret != USB2CAN.CAN_SUCCESS)
- {
- Console.WriteLine("Config CAN failed!");
- return;
- }
- else
- {
- Console.WriteLine("ReadCANIndex Config CAN Success!");
- }
- Console.WriteLine("");
- }
-
- ///
- /// ******************【7】*********************
- /// DBC解析
- ///
- public void DBC_Parser(string Path)
- {
- //解析DBC文件
- DBCHandle = CANFD_DBCParser.DBC_ParserFile(DevHandle, new StringBuilder(Path));
- if (DBCHandle == 0)
- {
- Console.WriteLine("Parser DBC File error!");
- return;
- }
- else
- {
- Console.WriteLine("Parser DBC File success!");
- }
-
- ListCanDbcModel.Clear();
-
- //打印DBC里面报文和信号相关信息
- int DBCMsgNum = CANFD_DBCParser.DBC_GetMsgQuantity(DBCHandle);
- for (int i = 0; i < DBCMsgNum; i++)
- {
- StringBuilder MsgName = new StringBuilder(32);
- CANFD_DBCParser.DBC_GetMsgName(DBCHandle, i, MsgName);
- Console.WriteLine("Msg.Name = {0}", MsgName);
- int DBCSigNum = CANFD_DBCParser.DBC_GetMsgSignalQuantity(DBCHandle, MsgName);
- StringBuilder Publisher = new StringBuilder(32);
- CANFD_DBCParser.DBC_GetMsgPublisher(DBCHandle, MsgName, Publisher);
- Console.Write("Signals:");
- for (int j = 0; j < DBCSigNum; j++)
- {
- StringBuilder SigName = new StringBuilder(32);
- CANFD_DBCParser.DBC_GetMsgSignalName(DBCHandle, MsgName, j, SigName);
- Console.Write("{0} ", SigName);
-
- //增加信息数据
- ListCanDbcModel.Add(new CanDbcModel()
- {
- MsgName = MsgName.ToString(),
- MsgId = "",
- SignalName = SigName.ToString(),
- SignalDesc = "",
- SignalUnit = "",
- SignalRtValue = "",
- Publisher = Publisher.ToString()
- });
- }
- Console.WriteLine("");
- }
- }
-
- ///
- /// 发送CAN数据
- ///
- public void SendCanMsg(List CmdData)
- {
- var GroupMsg = CmdData.GroupBy(x => x.MsgName);
- USB2CANFD.CANFD_MSG[] CanMsg = new USB2CANFD.CANFD_MSG[GroupMsg.Count()];
- for (int i = 0; i < GroupMsg.Count(); i++)
- {
- CanMsg[i] = new USB2CANFD.CANFD_MSG();
- CanMsg[i].Data = new Byte[64];
- }
-
- IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
- int Index = 0;
- //循环给MSG赋值数据
- foreach (var itemMsg in GroupMsg)
- {
- foreach (var itemSignal in itemMsg)
- {
- CANFD_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
- }
- CANFD_DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPt);
- CanMsg[Index] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
- Index++;
- }
-
- //设置信号值
- //DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), 2412);
- //DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), 980);
- //DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), 120);
-
- //通过DBC写入数据后生成CanMsg
- //将信号值填入CAN消息里面
-
-
- //IntPtr msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)));
- //DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_moto_speed"), msgPt);
- //CanMsg[0] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
-
- //DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_oil_pressure"), msgPt);
- //CanMsg[1] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
-
- //DBCParser.DBC_SyncValueToCANFDMsg(DBCHandle, new StringBuilder("msg_speed_can"), msgPt);
- //CanMsg[2] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure(msgPt, typeof(USB2CANFD.CANFD_MSG));
-
- //释放申请的临时缓冲区
- Marshal.FreeHGlobal(msgPt);
- Console.WriteLine("");
- //发送CAN数据
- int SendedNum = USB2CANFD.CANFD_SendMsg(DevHandle, WriteCANIndex, CanMsg, (Int32)CanMsg.Length);
- if (SendedNum >= 0)
- {
- Console.WriteLine("Success send frames:{0}", SendedNum);
- }
- else
- {
- Console.WriteLine("Send CAN data failed! {0}", SendedNum);
- }
- }
-
- ///
- /// 是否循环接收数据
- ///
- public bool IsCycleRevice { get; set; }
-
- ///
- /// CycleRevice扫描Task
- ///
- private static Task CycleReviceTask { get; set; }
-
- ///
- /// 循环获取CAN消息
- ///
- public void StartCycleReviceCanMsg()
- {
- CycleReviceTask = Task.Run(async () =>
- {
- while (IsCycleRevice)
- {
- await Task.Delay(1000);
- try
- {
- //另外一个CAN通道读取数据
- USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[10];
- msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);
- int CanNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, msgPt, CanMsgBuffer.Length);
- if (CanNum > 0)
- {
- Console.WriteLine("Read CanMsgNum = {0}", CanNum);
- for (int i = 0; i < CanNum; i++)
- {
- CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(msgPt + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
- Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
- //Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
- Console.Write("CanMsg[{0}].Data = ", i);
- for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
- {
- Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
- }
- Console.WriteLine("");
- }
- }
- else if (CanNum == 0)
- {
- Console.WriteLine("No CAN data!");
- }
- else
- {
- Console.WriteLine("Get CAN data error!");
- }
- Console.WriteLine("");
-
- //将CAN消息数据填充到信号里面
- CANFD_DBCParser.DBC_SyncCANFDMsgToValue(DBCHandle, msgPt, CanNum);
- //获取信号值并打印出来
- StringBuilder ValueStr = new StringBuilder(32);
- CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("TX1"), new StringBuilder("COM_current_Power"), ValueStr);
- Console.WriteLine("COM_current_Power = {0}", ValueStr);
- CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("TX1"), new StringBuilder("COM_Curr_dc"), ValueStr);
- Console.WriteLine("COM_Curr_dc = {0}", ValueStr);
- }
- catch (Exception ex)
- {
- //LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}");
- }
- }
- });
- }
-
- ///
- /// 接受CAN消息
- ///
- public void ReciveCanMsg()
- {
- //另外一个CAN通道读取数据
- USB2CANFD.CANFD_MSG[] CanMsgBuffer = new USB2CANFD.CANFD_MSG[10];
- msgPt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG)) * CanMsgBuffer.Length);
- int CanNum = USB2CANFD.CANFD_GetMsg(DevHandle, ReadCANIndex, msgPt, CanMsgBuffer.Length);
- if (CanNum > 0)
- {
- Console.WriteLine("Read CanMsgNum = {0}", CanNum);
- for (int i = 0; i < CanNum; i++)
- {
- CanMsgBuffer[i] = (USB2CANFD.CANFD_MSG)Marshal.PtrToStructure((IntPtr)(msgPt + i * Marshal.SizeOf(typeof(USB2CANFD.CANFD_MSG))), typeof(USB2CANFD.CANFD_MSG));
- Console.WriteLine("CanMsg[{0}].ID = 0x{1}", i, CanMsgBuffer[i].ID.ToString("X8"));
- //Console.WriteLine("CanMsg[{0}].TimeStamp = {1}",i,CanMsgBuffer[i].TimeStamp);
- Console.Write("CanMsg[{0}].Data = ", i);
- for (int j = 0; j < CanMsgBuffer[i].DLC; j++)
- {
- Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
- }
- Console.WriteLine("");
- }
- }
- else if (CanNum == 0)
- {
- Console.WriteLine("No CAN data!");
- }
- else
- {
- Console.WriteLine("Get CAN data error!");
- }
- Console.WriteLine("");
-
- //将CAN消息数据填充到信号里面
- CANFD_DBCParser.DBC_SyncCANFDMsgToValue(DBCHandle, msgPt, CanNum);
- //获取信号值并打印出来
- StringBuilder ValueStr = new StringBuilder(32);
- CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_moto_speed"), new StringBuilder("moto_speed"), ValueStr);
- Console.WriteLine("moto_speed = {0}", ValueStr);
- CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_oil_pressure"), new StringBuilder("oil_pressure"), ValueStr);
- Console.WriteLine("oil_pressure = {0}", ValueStr);
- CANFD_DBCParser.DBC_GetSignalValueStr(DBCHandle, new StringBuilder("msg_speed_can"), new StringBuilder("speed_can"), ValueStr);
- Console.WriteLine("speed_can = {0}", ValueStr);
-
- }
-
-
- ///
- /// 关闭设备
- ///
- public void CloseDevice()
- {
- //关闭设备
- USB_DEVICE.USB_CloseDevice(DevHandle);
- OpenState = false;
- }
-
- }
-}
diff --git a/CapMachine.Wpf/Dtos/CANFdConfigExdDto.cs b/CapMachine.Wpf/Dtos/CANFdConfigExdDto.cs
new file mode 100644
index 0000000..8d4d873
--- /dev/null
+++ b/CapMachine.Wpf/Dtos/CANFdConfigExdDto.cs
@@ -0,0 +1,77 @@
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.Dtos
+{
+ public class CANFdConfigExdDto : BindableBase
+ {
+ ///
+ /// 主键
+ ///
+ public long Id { get; set; }
+
+ private int _DataBaudRate;
+ ///
+ /// 数据波特率
+ ///
+ public int DataBaudRate
+ {
+ get { return _DataBaudRate; }
+ set { _DataBaudRate = value; RaisePropertyChanged(); }
+ }
+
+ private int _ArbBaudRate;
+ ///
+ /// 仲裁波特率
+ ///
+ public int ArbBaudRate
+ {
+ get { return _ArbBaudRate; }
+ set { _ArbBaudRate = value; RaisePropertyChanged(); }
+ }
+
+ private bool _ISOEnable;
+ ///
+ /// ISO 使能
+ ///
+ public bool ISOEnable
+ {
+ get { return _ISOEnable; }
+ set { _ISOEnable = value; RaisePropertyChanged(); }
+ }
+
+ private bool _ResEnable;
+ ///
+ /// 终端电阻使能
+ ///
+ public bool ResEnable
+ {
+ get { return _ResEnable; }
+ set { _ResEnable = value; RaisePropertyChanged(); }
+ }
+
+ private int _Cycle;
+ ///
+ /// 周期
+ ///
+ public int Cycle
+ {
+ get { return _Cycle; }
+ set { _Cycle = value; RaisePropertyChanged(); }
+ }
+
+ private string? _DbcPath;
+ ///
+ /// Dbc文件路径
+ ///
+ public string? DbcPath
+ {
+ get { return _DbcPath; }
+ set { _DbcPath = value; RaisePropertyChanged(); }
+ }
+ }
+}
diff --git a/CapMachine.Wpf/MapperProfile/CANFdConfigExdProfile.cs b/CapMachine.Wpf/MapperProfile/CANFdConfigExdProfile.cs
new file mode 100644
index 0000000..abafe8f
--- /dev/null
+++ b/CapMachine.Wpf/MapperProfile/CANFdConfigExdProfile.cs
@@ -0,0 +1,19 @@
+using AutoMapper;
+using CapMachine.Model.CANLIN;
+using CapMachine.Wpf.Dtos;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.MapperProfile
+{
+ public class CANFdConfigExdProfile : Profile
+ {
+ public CANFdConfigExdProfile()
+ {
+ CreateMap().ReverseMap();
+ }
+ }
+}
diff --git a/CapMachine.Wpf/Models/CanLinRunStateModel.cs b/CapMachine.Wpf/Models/CanLinRunStateModel.cs
index 2241dcf..12d618e 100644
--- a/CapMachine.Wpf/Models/CanLinRunStateModel.cs
+++ b/CapMachine.Wpf/Models/CanLinRunStateModel.cs
@@ -33,6 +33,10 @@ namespace CapMachine.Wpf.Models
SelectedCanLinMsg = "CAN";
CanLinRunState=true;
break;
+ case CanLinEnum.CANFD:
+ SelectedCanLinMsg = "CANFD";
+ CanLinRunState = true;
+ break;
case CanLinEnum.Lin:
SelectedCanLinMsg = "LIN";
CanLinRunState = true;
diff --git a/CapMachine.Wpf/Models/ComEnum.cs b/CapMachine.Wpf/Models/ComEnum.cs
index 8f7b3e9..b02b82e 100644
--- a/CapMachine.Wpf/Models/ComEnum.cs
+++ b/CapMachine.Wpf/Models/ComEnum.cs
@@ -79,6 +79,11 @@ namespace CapMachine.Wpf.Models
/// Lin
///
Lin = 2,
+
+ ///
+ /// CAN FD
+ ///
+ CANFD = 3,
}
}
}
diff --git a/CapMachine.Wpf/Services/CanFdDriveService.cs b/CapMachine.Wpf/Services/CanFdDriveService.cs
new file mode 100644
index 0000000..bb01213
--- /dev/null
+++ b/CapMachine.Wpf/Services/CanFdDriveService.cs
@@ -0,0 +1,415 @@
+using CapMachine.Model.CANLIN;
+using CapMachine.Wpf.CanDrive;
+using CapMachine.Wpf.Models;
+using CapMachine.Wpf.Models.ProModelPars;
+using ImTools;
+using Prism.Ioc;
+using Prism.Mvvm;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.Services
+{
+ ///
+ /// Can FD驱动服务
+ ///
+ public class CanFdDriveService : BindableBase
+ {
+ public HighSpeedDataService HighSpeedDataService { get; }
+ public LogicRuleService LogicRuleService { get; }
+
+ ///
+ /// 实例化函数
+ ///
+ public CanFdDriveService(HighSpeedDataService highSpeedDataService, IContainerProvider containerProvider, LogicRuleService logicRuleService)
+ {
+ ToomossCanFDDrive = new ToomossCanFD(containerProvider);
+ //高速数据服务
+ HighSpeedDataService = highSpeedDataService;
+ LogicRuleService = logicRuleService;
+
+ //ToomossCanFDDrive.StartCanDrive();
+ }
+
+ ///
+ /// 当前选中的CanLinConfigPro 程序
+ ///
+ public CanLinConfigPro SelectedCanLinConfigPro { get; set; }
+
+
+ ///
+ /// 图莫斯 CAN Drive
+ /// ToomossCanFDDrive
+ ///
+ public ToomossCanFD ToomossCanFDDrive { get; set; }
+
+ ///
+ /// Dbc消息集合
+ /// 包括读取的实时值和数据
+ ///
+ public ObservableCollection ListCanDbcModel { get; set; } = new ObservableCollection();
+
+ ///
+ /// 初始化CAN的配置信息
+ ///
+ public void InitCanConfig(CanLinConfigPro selectedCanLinConfigPro)
+ {
+ //赋值配置数据
+ SelectedCanLinConfigPro = selectedCanLinConfigPro;
+ //为DBC实时数据关联配置的名称
+ foreach (var item in SelectedCanLinConfigPro.CanLinConfigContents)
+ {
+ var FindData = ListCanDbcModel.FindFirst(a => a.SignalName == item.SignalName);
+ if (FindData != null)
+ {
+ FindData.Name = item.Name;
+ }
+ }
+ }
+
+ ///
+ /// 开始DBC 配置文件 加载
+ ///
+ ///
+ public ObservableCollection StartDbc(string Path)
+ {
+ ListCanDbcModel = ToomossCanFDDrive.StartDbc(Path);
+ return ListCanDbcModel;
+ }
+
+
+ #region 程序驱动CAN
+
+ ///
+ /// 转速 指令数据 实例
+ ///
+ private CanCmdData SpeedCanCmdData { get; set; }
+
+ ///
+ /// 功率限制 指令数据 实例
+ ///
+ private CanCmdData PwLimitCanCmdData { get; set; }
+
+ ///
+ /// 使能 指令数据 实例
+ ///
+ private CanCmdData EnableCanCmdData { get; set; }
+
+ ///
+ /// PTC使能 指令数据 实例
+ ///
+ private CanCmdData PTCEnableCanCmdData { get; set; }
+
+ ///
+ /// PTC功率 指令数据 实例
+ ///
+ private CanCmdData PTCPwCanCmdData { get; set; }
+
+ ///
+ /// PTC水流量 指令数据 实例
+ ///
+ private CanCmdData PTCFlowCanCmdData { get; set; }
+
+ ///
+ /// PTC水温 指令数据 实例
+ ///
+ private CanCmdData PTCWaterTempCanCmdData { get; set; }
+
+
+ ///
+ /// 要发送的CAN指令数据
+ /// 在程序配置好后就确定要发送哪些数据
+ ///
+ public List CmdData { get; set; } = new List();
+
+ ///
+ /// 增加发送的指令数据
+ ///
+ ///
+ public void AddCmdData(CanCmdData SendCanCmdData)
+ {
+ //提取常用的实例数据
+ switch (SendCanCmdData.ConfigName)
+ {
+ case "转速":
+ SpeedCanCmdData = SendCanCmdData;
+ break;
+ case "功率限制":
+ PwLimitCanCmdData = SendCanCmdData;
+ break;
+ case "使能":
+ EnableCanCmdData = SendCanCmdData;
+ break;
+ case "Anti_Sleep":
+ //SpeedCanCmdData = SendCanCmdData;
+ break;
+ case "PTC使能":
+ PTCEnableCanCmdData = SendCanCmdData;
+ break;
+ case "PTC功率":
+ PTCPwCanCmdData = SendCanCmdData;
+ break;
+ case "PTC水流量":
+ PTCFlowCanCmdData = SendCanCmdData;
+ break;
+ case "PTC水温":
+ PTCWaterTempCanCmdData = SendCanCmdData;
+ break;
+ default:
+ break;
+ }
+ //添加到发送数据集合
+ CmdData.Add(SendCanCmdData);
+ }
+
+
+ ///
+ /// 更新速度信息
+ /// 默认是启动
+ ///
+ ///
+ public void UpdateSpeedCmdData(double SpeedData)
+ {
+ if (SpeedCanCmdData != null)
+ {
+ if (SpeedCanCmdData.LogicRuleDto == null)
+ {
+ //没有启动逻辑规则处理
+ SpeedCanCmdData.SignalCmdValue = SpeedData;
+ return;
+ }
+
+ SpeedCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(SpeedData, SpeedCanCmdData.LogicRuleDto);
+ }
+ //if (EnableCanCmdData != null)
+ //{
+ // EnableCanCmdData.SignalCmdValue = 1;
+ //}
+ }
+
+ ///
+ /// 更新压缩机使能数据
+ ///
+ ///
+ public void UpdateCapEnableCmdData(bool IsEnable)
+ {
+ if (EnableCanCmdData != null)
+ {
+ EnableCanCmdData.SignalCmdValue = IsEnable ? 1 : 0;
+ }
+ }
+
+
+ ///
+ /// 更新压缩机的功率限制
+ ///
+ ///
+ public void UpdateCapPwLimitCmdData(double PwLimit)
+ {
+ if (PwLimitCanCmdData != null)
+ {
+ if (PwLimitCanCmdData.LogicRuleDto == null)
+ {
+ PwLimitCanCmdData.SignalCmdValue = PwLimit;
+ return;
+ }
+ PwLimitCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(PwLimit, PwLimitCanCmdData.LogicRuleDto!);
+ }
+ }
+
+
+ ///
+ /// 更新 PTC使能信号
+ ///
+ ///
+ public void UpdateCapPTCEnableCmdData(bool IsEnable)
+ {
+ if (PTCEnableCanCmdData != null)
+ {
+ PTCEnableCanCmdData.SignalCmdValue = IsEnable ? 1 : 0;
+ }
+ }
+
+ ///
+ /// 更新 PTC功率 信号
+ ///
+ ///
+ public void UpdateCapPTCPwCmdData(double PTCPw)
+ {
+ if (PTCPwCanCmdData != null)
+ {
+ if (PTCPwCanCmdData.LogicRuleDto == null)
+ {
+ PTCPwCanCmdData.SignalCmdValue = PTCPw;
+ return;
+ }
+ PTCPwCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(PTCPw, PTCPwCanCmdData.LogicRuleDto!);
+ }
+ }
+
+ ///
+ /// 更新 PTC水流量 信号
+ ///
+ ///
+ public void UpdateCapPTCFlowCmdData(double Flow)
+ {
+ if (PTCFlowCanCmdData != null)
+ {
+ if (PTCFlowCanCmdData.LogicRuleDto == null)
+ {
+ PTCFlowCanCmdData.SignalCmdValue = Flow;
+ return;
+ }
+ PTCFlowCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(Flow, PTCFlowCanCmdData.LogicRuleDto!);
+ }
+ }
+
+ ///
+ /// 更新 PTC水温 信号
+ ///
+ ///
+ public void UpdateCapPTCWaterTempCmdData(double WaterTemp)
+ {
+ if (PTCWaterTempCanCmdData != null)
+ {
+ if (PTCWaterTempCanCmdData.LogicRuleDto == null)
+ {
+ PTCWaterTempCanCmdData.SignalCmdValue = WaterTemp;
+ return;
+ }
+ PTCWaterTempCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(WaterTemp, PTCWaterTempCanCmdData.LogicRuleDto!);
+ }
+ }
+
+ ///
+ /// 发送消息给CAN 驱动
+ ///
+ public void SendMsgToCanDrive(double SpeedData)
+ {
+ if (ToomossCanFDDrive.OpenState)
+ {
+ if (CmdData.Count > 0)
+ {
+ //更新速度信息
+ UpdateSpeedCmdData(SpeedData);
+
+ ToomossCanFDDrive.SendCanMsg(CmdData);
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("未发现配置的数据内容", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("未打开CAN通信,无法发送数据", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ }
+
+
+ ///
+ /// 循环发送数据到CAN
+ ///
+ public void CycleSendMsg()
+ {
+ if (ToomossCanFDDrive.OpenState)
+ {
+ if (ToomossCanFDDrive.IsCycleSend == false)
+ {
+ if (CmdData.Count > 0)
+ {
+ ToomossCanFDDrive.IsCycleSend = true;
+ ToomossCanFDDrive.CmdData = CmdData;
+ //ToomossCanFDDrive.StartCycleSendMsg();
+ ToomossCanFDDrive.StartPrecisionCycleSendMsg();
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("未发现配置的数据内容", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ }
+ else
+ {
+ ToomossCanFDDrive.IsCycleSend = false;
+ }
+
+ }
+ }
+
+
+
+ ///
+ ///循环接收数据
+ ///
+ public void CycleReciveMsg()
+ {
+ if (ToomossCanFDDrive.OpenState)
+ {
+ if (ToomossCanFDDrive.IsCycleRevice == false)
+ {
+ if (ListCanDbcModel.Count > 0)
+ {
+ ToomossCanFDDrive.IsCycleRevice = true;
+ ToomossCanFDDrive.StartCycleReviceCanMsg();
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("未发现配置的数据内容", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ }
+ else
+ {
+ ToomossCanFDDrive.IsCycleRevice = false;
+ }
+ }
+ }
+
+
+ ///
+ /// 获取数据值
+ /// 从DBC中获取数据给数据中心集合
+ ///
+ ///
+ ///
+ public double GetDbcValueByName(string Name)
+ {
+ if (!ToomossCanFDDrive.IsCycleRevice) return 0;
+
+ if (ListCanDbcModel.Any(a => a.Name == Name))
+ {
+ //double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue, out double Result1);
+ return double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
+ //return 12.3;
+ }
+ return 0;
+ }
+
+ ///
+ /// 速度的数据的获取
+ /// 获取速度数据值
+ /// 从DBC中获取Speed数据给数据中心集合
+ ///
+ ///
+ ///
+ public double GetDbcSpeedValueBySpeedName(string Name)
+ {
+ if (!ToomossCanFDDrive.IsCycleRevice) return 0;
+
+ if (ListCanDbcModel.Any(a => a.Name == Name))
+ {
+ //double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue, out double Result1);
+ //return double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
+ return double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
+ //return 2300;
+ }
+ return 0;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/CapMachine.Wpf/Services/MachineRtDataService.cs b/CapMachine.Wpf/Services/MachineRtDataService.cs
index bb5ab60..d35a36f 100644
--- a/CapMachine.Wpf/Services/MachineRtDataService.cs
+++ b/CapMachine.Wpf/Services/MachineRtDataService.cs
@@ -42,6 +42,7 @@ namespace CapMachine.Wpf.Services
public ConfigService ConfigService { get; }
public LogicRuleService LogicRuleService { get; }
public CanDriveService CanDriveService { get; }
+ public CanFdDriveService CanFdDriveService { get; }
public LinDriveService LinDriveService { get; }
public SysRunService SysRunService { get; }
@@ -135,7 +136,7 @@ namespace CapMachine.Wpf.Services
///
///
public MachineRtDataService(IEventAggregator eventAggregator, AlarmService alarmService, ConfigService configService, LogicRuleService logicRuleService,
- CanDriveService canDriveService, LinDriveService linDriveService, SysRunService sysRunService)//, AlarmService alarmService
+ CanDriveService canDriveService, CanFdDriveService canFdDriveService, LinDriveService linDriveService, SysRunService sysRunService)//, AlarmService alarmService
{
//ConcurrentDictionary keyValuePairs = new ConcurrentDictionary();
@@ -153,6 +154,7 @@ namespace CapMachine.Wpf.Services
ConfigService = configService;
LogicRuleService = logicRuleService;
CanDriveService = canDriveService;
+ CanFdDriveService = canFdDriveService;
LinDriveService = linDriveService;
SysRunService = sysRunService;
@@ -2604,6 +2606,15 @@ namespace CapMachine.Wpf.Services
//pVModel.EngSrcValue = 0;
}
break;
+ case CanLinEnum.CANFD:
+ //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC 取消XXX
+ if (TagManger.TryGetPVModel(itemCanLinGroup.Key, out MeterValueAttrCell? CanpFDVModel))
+ {
+ CanpFDVModel!.EngValue = CanDriveService.GetDbcSpeedValueBySpeedName("通讯转速");
+ SiemensDrive.Write(CanpFDVModel!.Address!.Replace("W", ""), (short)CanFdDriveService.GetDbcSpeedValueBySpeedName("通讯转速"));
+ //pVModel.EngSrcValue = 0;
+ }
+ break;
case CanLinEnum.Lin:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC 取消XXX
if (TagManger.TryGetPVModel(itemCanLinGroup.Key, out MeterValueAttrCell? LinpVModel))
@@ -2633,6 +2644,12 @@ namespace CapMachine.Wpf.Services
//写入到PLC中
SiemensDrive.Write(pVModel!.Address!.Replace("W", ""), (short)(CanDriveService.GetDbcValueByName(itemCanLinGroup.Value.NameNoUnit) * itemCanLinGroup.Value.Precision));
break;
+ case CanLinEnum.CANFD:
+ //取得压缩机的CANLIN数据到数据集合中
+ pVModel!.EngValue = CanDriveService.GetDbcValueByName(itemCanLinGroup.Value.NameNoUnit);
+ //写入到PLC中
+ SiemensDrive.Write(pVModel!.Address!.Replace("W", ""), (short)(CanFdDriveService.GetDbcValueByName(itemCanLinGroup.Value.NameNoUnit) * itemCanLinGroup.Value.Precision));
+ break;
case CanLinEnum.Lin:
//取得压缩机的CANLIN数据
pVModel!.EngValue = LinDriveService.GetLdfValueByName(itemCanLinGroup.Value.NameNoUnit);
@@ -3100,6 +3117,9 @@ namespace CapMachine.Wpf.Services
case CanLinEnum.Can:
CanDriveService.UpdateCapEnableCmdData((bool)itemStepExd.Value!);
break;
+ case CanLinEnum.CANFD:
+ CanFdDriveService.UpdateCapEnableCmdData((bool)itemStepExd.Value!);
+ break;
case CanLinEnum.Lin:
LinDriveService.UpdateCapEnableCmdData((bool)itemStepExd.Value!);
break;
@@ -3183,6 +3203,15 @@ namespace CapMachine.Wpf.Services
CanDriveService.UpdateSpeedCmdData(SpeedSv);
}
+ //itemTag.Value.EngPvValue = 0;
+ break;
+ case CanLinEnum.CANFD:
+ //获取PLC的SV数据 更新SV的速度值到压缩机
+ if (CanDriveService.CanAutoHand)//自动时步骤的数据可以赋值数据
+ {
+ CanFdDriveService.UpdateSpeedCmdData(SpeedSv);
+ }
+
//itemTag.Value.EngPvValue = 0;
break;
case CanLinEnum.Lin:
diff --git a/CapMachine.Wpf/Services/NavigationMenuService.cs b/CapMachine.Wpf/Services/NavigationMenuService.cs
index f5a02bd..0592641 100644
--- a/CapMachine.Wpf/Services/NavigationMenuService.cs
+++ b/CapMachine.Wpf/Services/NavigationMenuService.cs
@@ -73,6 +73,7 @@ namespace CapMachine.Wpf.Services
//}));
MenuItems.Add(new NavigationItem("", "工艺过程", "MonitorView"));
MenuItems.Add(new NavigationItem("", "CAN配置", "CANConfigView"));
+ MenuItems.Add(new NavigationItem("", "CANFD配置", "CANFDConfigView"));
MenuItems.Add(new NavigationItem("", "LIN配置", "LINConfigView"));
MenuItems.Add(new NavigationItem("", "工艺参数", "ProConfigView"));
MenuItems.Add(new NavigationItem("", "工艺曲线", "RealTimeChartView"));
diff --git a/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs b/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs
new file mode 100644
index 0000000..86d2cf8
--- /dev/null
+++ b/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs
@@ -0,0 +1,1423 @@
+using AutoMapper;
+using CapMachine.Core;
+using CapMachine.Model;
+using CapMachine.Model.CANLIN;
+using CapMachine.Wpf.CanDrive;
+using CapMachine.Wpf.Dtos;
+using CapMachine.Wpf.PrismEvent;
+using CapMachine.Wpf.Services;
+using Ganss.Excel;
+using ImTools;
+using Microsoft.VisualBasic;
+using Microsoft.Win32;
+using NPOI.SS.UserModel.Charts;
+using Prism.Commands;
+using Prism.Events;
+using Prism.Regions;
+using Prism.Services.Dialogs;
+using Syncfusion.Windows.Tools.Controls;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using static CapMachine.Wpf.Models.ComEnum;
+
+namespace CapMachine.Wpf.ViewModels
+{
+ public class CANFDConfigViewModel : NavigationViewModel
+ {
+ public CANFDConfigViewModel(IDialogService dialogService, IFreeSql freeSql,
+ IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService,
+ ComActionService actionService, ILogService logService, LogicRuleService logicRuleService,
+ ConfigService configService, CanFdDriveService canFdDriveService,
+ IMapper mapper, MachineRtDataService machineRtDataService)
+ {
+ //LogService = logService;
+ FreeSql = freeSql;
+ EventAggregator = eventAggregator;
+ RegionManager = regionManager;
+ SysRunService = sysRunService;
+ ComActionService = actionService;
+ LogicRuleService = logicRuleService;
+ LogService = logService;
+ ConfigService = configService;
+ CanFdDriveService = canFdDriveService;
+ Mapper = mapper;
+ this.MachineRtDataService = machineRtDataService;
+
+ //MachineDataService = machineDataService;
+ DialogService = dialogService;
+
+ //仲裁波特率
+ ArbBaudRateCbxItems = new ObservableCollection()
+ {
+ new CbxItems(){ Key="10000",Text="10 Kbps"},
+ new CbxItems(){ Key="20000",Text="20 Kbps"},
+ new CbxItems(){ Key="33000",Text="33 Kbps"},
+ new CbxItems(){ Key="50000",Text="50Kbps"},
+ new CbxItems(){ Key="83000",Text="83 Kbps"},
+ new CbxItems(){ Key="100000",Text="100 Kbps"},
+ new CbxItems(){ Key="125000",Text="125 Kbps"},
+ new CbxItems(){ Key="150000",Text="150 Kbps"},
+ new CbxItems(){ Key="200000",Text="200 Kbps"},
+ new CbxItems(){ Key="250000",Text="250 Kbps"},
+ new CbxItems(){ Key="300000",Text="300 Kbps"},
+ new CbxItems(){ Key="400000",Text="400 Kbps"},
+ new CbxItems(){ Key="500000",Text="500 Kbps"},
+ new CbxItems(){ Key="666000",Text="666 Kbps"},
+ new CbxItems(){ Key="800000",Text="800 Kbps"},
+ new CbxItems(){ Key="1000000",Text="1.0 Mbps"},
+ };
+
+ //数据波特率
+ DataBaudRateCbxItems = new ObservableCollection()
+ {
+ new CbxItems(){ Key="100000",Text="100 Kbps"},
+ new CbxItems(){ Key="125000",Text="125 Kbps"},
+ new CbxItems(){ Key="200000",Text="200 Kbps"},
+ new CbxItems(){ Key="250000",Text="250 Kbps"},
+ new CbxItems(){ Key="400000",Text="400 Kbps"},
+ new CbxItems(){ Key="500000",Text="500 Kbps"},
+ new CbxItems(){ Key="666000",Text="666 Kbps"},
+ new CbxItems(){ Key="800000",Text="800 Kbps"},
+ new CbxItems(){ Key="1000000",Text="1.0 Mbps"},
+
+ new CbxItems(){ Key="1500000",Text="1.5 Mbps"},
+ new CbxItems(){ Key="2000000",Text="2.0 Mbps"},
+ new CbxItems(){ Key="3000000",Text="3.0 Mbps"},
+ new CbxItems(){ Key="4000000",Text="4.0 Mbps"},
+ new CbxItems(){ Key="5000000",Text="5.0 Mbps"},
+ new CbxItems(){ Key="6700000",Text="6.7 Mbps"},
+ new CbxItems(){ Key="8000000",Text="8.0 Mbps"},
+ new CbxItems(){ Key="10000000",Text="10.0 Mbps"},
+ };
+
+ WriteNameCbxItems = new ObservableCollection()
+ {
+ new CbxItems(){ Key="转速",Text="转速"},
+ new CbxItems(){ Key="功率限制",Text="功率限制"},
+ new CbxItems(){ Key="使能",Text="使能"},
+ new CbxItems(){ Key="Anti_Sleep",Text="Anti_Sleep"},
+
+ new CbxItems(){ Key="PTC使能",Text="PTC使能"},
+ new CbxItems(){ Key="PTC功率",Text="PTC功率"},
+ new CbxItems(){ Key="PTC水流量",Text="PTC水流量"},
+ new CbxItems(){ Key="PTC水温",Text="PTC水温"},
+ };
+
+ ReadNameCbxItems = new ObservableCollection()
+ {
+ new CbxItems(){ Key="通讯Cmp转速",Text="通讯Cmp转速"},
+ new CbxItems(){ Key="通讯Cmp母线电压",Text="通讯Cmp母线电压"},
+ new CbxItems(){ Key="通讯Cmp母线电流",Text="通讯Cmp母线电流"},
+ new CbxItems(){ Key="通讯Cmp逆变器温度",Text="通讯Cmp逆变器温度"},
+ new CbxItems(){ Key="通讯Cmp相电流",Text="通讯Cmp相电流"},
+ new CbxItems(){ Key="通讯Cmp功率",Text="通讯Cmp功率"},
+ new CbxItems(){ Key="通讯Cmp芯片温度",Text="通讯Cmp芯片温度"},
+
+ new CbxItems(){ Key="通讯PTC入水温度",Text="通讯PTC入水温度"},
+ new CbxItems(){ Key="通讯PTC出水温度",Text="通讯PTC出水温度"},
+ new CbxItems(){ Key="通讯PTC峰值电流",Text="通讯PTC峰值电流"},
+ new CbxItems(){ Key="通讯PTC母线电流",Text="通讯PTC母线电流"},
+ new CbxItems(){ Key="通讯PTC膜温",Text="通讯PTC膜温"},
+ new CbxItems(){ Key="通讯PTC模块温度",Text="通讯PTC模块温度"},
+ };
+
+ InitLoadCanConfigPro();
+ //初始化写规则下拉框
+ InitWriteRuleCbx();
+ }
+
+
+ ///
+ /// FreeSQL 实例函数
+ ///
+ public IFreeSql FreeSql { get; }
+ public IEventAggregator EventAggregator { get; }
+ public IRegionManager RegionManager { get; }
+ public SysRunService SysRunService { get; }
+ public ComActionService ComActionService { get; }
+ public LogicRuleService LogicRuleService { get; }
+ public ILogService LogService { get; }
+ public ConfigService ConfigService { get; }
+ public CanFdDriveService CanFdDriveService { get; }
+ public IMapper Mapper { get; }
+ private MachineRtDataService MachineRtDataService { get; }
+
+ ///
+ /// 弹窗服务
+ ///
+ public IDialogService DialogService { get; }
+
+ #region 规则
+
+
+ ///
+ /// 逻辑更改事件
+ ///
+ ///
+ ///
+ private void LogicRuleChangeEventCall(string msg)
+ {
+ //InitWriteRuleCbx();
+ }
+
+ ///
+ /// 初始化写规则下拉框
+ ///
+ private void InitWriteRuleCbx()
+ {
+ WriteRuleCbxItems = new ObservableCollection();
+ //选择的读写规则
+ foreach (var itemRule in LogicRuleService.LogicRuleDtos)
+ {
+ WriteRuleCbxItems.Add(new CbxItems()
+ {
+ Key = itemRule.Id.ToString(),
+ Text = itemRule.Name
+ });
+ }
+
+ }
+
+
+ #endregion
+
+ #region CanConfigPro
+
+ ///
+ /// 初始化j加载执行方法
+ ///
+ private void InitLoadCanConfigPro()
+ {
+ //CAN配置集合数据
+ canLinConfigPros = FreeSql.Select().Where(a => a.CANLINInfo == CANLIN.CANFD)
+ .Include(a => a.CANFdConfigExd)
+ .IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))//,then=> then.Include(b=>b.LogicRule)
+ //.IncludeMany(a => a.CanLinConfigContents)
+ .ToList();
+
+ ListCanLinConfigPro = new ObservableCollection(canLinConfigPros);
+ if (SelectCanLinConfigPro != null)
+ {
+ SelectCanLinConfigPro = canLinConfigPros.Where(a => a.Id == SelectCanLinConfigPro.Id).FirstOrDefault()!;
+ //无数据就返回
+ if (SelectCanLinConfigPro == null) return;
+
+ SelectedCANConfigExdDto = Mapper.Map(SelectCanLinConfigPro!.CANFdConfigExd);
+ if (SelectedCANConfigExdDto != null)
+ {
+ //更新波特率等配置信息
+ CanFdDriveService.ToomossCanFDDrive.UpdateConfig((uint)SelectedCANConfigExdDto.ArbBaudRate,
+ (uint)SelectedCANConfigExdDto.DataBaudRate, SelectedCANConfigExdDto.ISOEnable, SelectedCANConfigExdDto.ResEnable, (ushort)SelectedCANConfigExdDto.Cycle);
+ }
+
+ //配置信息
+ var WirteData = SelectCanLinConfigPro.CanLinConfigContents!.Where(a => a.RWInfo == RW.Write).ToList();
+ if (WirteData != null && WirteData.Count > 0)
+ {
+ ListWriteCanLinRWConfigDto = new ObservableCollection(Mapper.Map>(WirteData));
+
+ //加载把当前的配置信息给指令
+ CanFdDriveService.CmdData.Clear();
+ foreach (var item in WirteData)
+ {
+ CanFdDriveService.AddCmdData(new CanCmdData()
+ {
+ ConfigName = item.Name,
+ MsgName = item.MsgFrameName,
+ SignalName = item.SignalName,
+ SignalCmdValue = double.TryParse(item.DefautValue, out double result) == true ? result : 0,
+ LogicRuleDto = Mapper.Map(item.LogicRule),
+ });
+ //CanFdDriveService.CmdData.Add(new CanCmdData()
+ //{
+ // ConfigName = item.Name,
+ // MsgName = item.MsgFrameName,
+ // SignalName = item.SignalName,
+ // SignalCmdValue = double.TryParse(item.DefautValue, out double result) == true ? result : 0,
+ //});
+ }
+ }
+ var ReadData = SelectCanLinConfigPro.CanLinConfigContents!.Where(a => a.RWInfo == RW.Read).ToList();
+ if (ReadData != null && ReadData.Count > 0)
+ {
+ ListReadCanLinRWConfigDto = new ObservableCollection(Mapper.Map>(ReadData));
+ }
+
+ //匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListCanDbcModel
+ MatchSeletedAndCanDbcModel();
+ }
+ }
+
+ ///
+ /// 匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListCanDbcModel
+ /// 为了标注和着色使用
+ ///
+ private void MatchSeletedAndCanDbcModel()
+ {
+ //通过CanLinConfigContents标注ListCanDbcModel的选中状态属性,方便着色
+ if (ListCanDbcModel != null && ListCanDbcModel!.Count() > 0 && SelectCanLinConfigPro.CanLinConfigContents != null && SelectCanLinConfigPro.CanLinConfigContents.Count() > 0)
+ {
+ foreach (var itemCanDbcModel in ListCanDbcModel)
+ {
+ var FindData = SelectCanLinConfigPro.CanLinConfigContents.FindFirst(a => a.SignalName == itemCanDbcModel.SignalName);
+ if (FindData != null)//找到了就标注
+ {
+ switch (FindData.RWInfo)
+ {
+ case RW.Write:
+ itemCanDbcModel.IsSeletedInfo = 1;
+ break;
+ case RW.Read:
+ itemCanDbcModel.IsSeletedInfo = 2;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ //没有找到了就标注为0
+ itemCanDbcModel.IsSeletedInfo = 0;
+ }
+ }
+ }
+ }
+
+
+
+ private bool _IsCanConfigProActive = false;
+ ///
+ /// CAN 配置是否被激活
+ ///
+ public bool IsCanConfigProActive
+ {
+ get { return _IsCanConfigProActive; }
+ set { _IsCanConfigProActive = value; RaisePropertyChanged(); }
+ }
+
+ private bool _IsCANConfigDatagridActive = true;
+ ///
+ /// CANConfigDatagrid是否被触控
+ /// 关联IsCanConfigProActive 取反
+ ///
+ public bool IsCANConfigDatagridActive
+ {
+ get { return _IsCANConfigDatagridActive; }
+ set { _IsCANConfigDatagridActive = value; RaisePropertyChanged(); }
+ }
+
+ private string _SelectCanLinConfigProConfigName;
+ ///
+ /// 选中的 CanLinConfigPro 名称
+ ///
+ public string SelectCanLinConfigProConfigName
+ {
+ get { return _SelectCanLinConfigProConfigName; }
+ set { _SelectCanLinConfigProConfigName = value; RaisePropertyChanged(); }
+ }
+
+
+ private DelegateCommand _CanLinConfigPromdCmd;
+ ///
+ /// CanConfigPro操作的指令
+ ///
+ public DelegateCommand CanLinConfigPromdCmd
+ {
+ set
+ {
+ _CanLinConfigPromdCmd = value;
+ }
+ get
+ {
+ if (_CanLinConfigPromdCmd == null)
+ {
+ _CanLinConfigPromdCmd = new DelegateCommand((Par) => CanLinConfigPromdCmdMethod(Par));
+ }
+ return _CanLinConfigPromdCmd;
+ }
+ }
+ ///
+ /// CanConfigPro操作的指令方法
+ ///
+ ///
+ private void CanLinConfigPromdCmdMethod(string Par)
+ {
+ switch (Par)
+ {
+ case "Add":
+ //弹窗
+ DialogService.ShowDialog("DialogCanLinConfigCreateView", new DialogParameters() { { "Name", "" } }, (par) =>
+ {
+ if (par.Result == ButtonResult.OK)
+ {
+ //程序名称
+ var ReturnValue = par.Parameters.GetValue("Name");
+
+ //加载默认的数据 CANConfigExd
+ var InsertCANConfigExd = FreeSql.Insert(new CANFdConfigExd()
+ {
+ DataBaudRate = 250,
+ ArbBaudRate = 2000,
+ DbcPath = "请配置DBC路径",
+ Cycle = 100,
+ }).ExecuteInserted();
+
+ //返回数据,刷新Chart
+ var InsertData = FreeSql.Insert(new CanLinConfigPro()
+ {
+ ConfigName = ReturnValue,
+ CANLINInfo = CANLIN.CANFD,
+ CANFdConfigExdId = InsertCANConfigExd.FirstOrDefault()!.Id
+ }).ExecuteInserted();
+ if (InsertData != null)
+ {
+ //加载默认的数据 CanLinRWConfig
+ FreeSql.Insert(new CanLinRWConfig()
+ {
+ SignalName = "Speed",
+ DefautValue = "0",
+ Name = "转速",
+ RWInfo = RW.Write,
+ CanLinConfigProId = InsertData.FirstOrDefault().Id
+ }).ExecuteInserted();
+
+ FreeSql.Insert(new CanLinRWConfig()
+ {
+ SignalName = "Vol",
+ DefautValue = "0",
+ Name = "电压",
+ RWInfo = RW.Read,
+ CanLinConfigProId = InsertData.FirstOrDefault().Id
+
+ }).ExecuteInserted();
+ }
+
+ InitLoadCanConfigPro();
+
+ SelectCanLinConfigPro = canLinConfigPros!.Find(a => a.Id == InsertData.FirstOrDefault()!.Id);
+ }
+ else if (par.Result == ButtonResult.Cancel)
+ {
+ //取消
+
+ }
+
+ });
+
+ break;
+ case "Edit":
+ if (SelectCanLinConfigPro != null)
+ {
+ //弹窗
+ DialogService.ShowDialog("DialogCanLinConfigCreateView", new DialogParameters() { { "Name", SelectCanLinConfigPro.ConfigName } }, (par) =>
+ {
+ if (par.Result == ButtonResult.OK)
+ {
+ //程序名称
+ var ReturnValue = par.Parameters.GetValue("Name");
+
+ FreeSql.Update()
+ .Set(a => a.ConfigName, ReturnValue)
+ .Where(a => a.Id == SelectCanLinConfigPro.Id)
+ .ExecuteAffrows();
+
+ InitLoadCanConfigPro();
+
+ SelectCanLinConfigPro = null;
+ }
+ else if (par.Result == ButtonResult.Cancel)
+ {
+ //取消
+
+ }
+
+ });
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("选中后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ break;
+
+ case "Save":
+
+ case "Delete":
+ if (SelectCanLinConfigPro != null)
+ {
+ var repo = FreeSql.GetRepository();
+ repo.DbContextOptions.EnableCascadeSave = true; //关键设置
+
+ var DeleteData = repo.Select
+ .Include(a => a.CANFdConfigExd)
+ .IncludeMany(a => a.CanLinConfigContents)
+ .Where(a => a.Id == SelectCanLinConfigPro.Id)
+ .ToList();
+
+ repo.Delete(DeleteData);
+ foreach (var item in DeleteData)
+ {
+ FreeSql.Delete(item.CANFdConfigExdId).ExecuteAffrows();
+ }
+ InitLoadCanConfigPro();
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("选中后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ break;
+ case "Active":
+
+ //激活到取消的状态的判断
+ if (IsCanConfigProActive == true)
+ {
+ //控件的激活
+ IsCanConfigProActive = !IsCanConfigProActive;
+ //控件的激活配置信息
+ IsCANConfigDatagridActive = !IsCanConfigProActive;
+
+ return;
+ }
+
+ if ((CanFdDriveService.ToomossCanFDDrive.OpenState == true && CanFdDriveService.ToomossCanFDDrive.DbcParserState == true))
+ {
+ if (SelectCanLinConfigPro != null)
+ {
+ //控件的激活
+ IsCanConfigProActive = !IsCanConfigProActive;
+ //控件的激活配置信息
+ IsCANConfigDatagridActive = !IsCanConfigProActive;
+
+ //当前使用的CAN 配置信息
+ CanFdDriveService.InitCanConfig(SelectCanLinConfigPro);
+
+ InitLoadCanConfigPro();
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("选中后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+
+ }
+ else
+ {
+ System.Windows.MessageBox.Show("请确保CAN连接打开和Dbc解析成功后再激活", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ///
+ /// CAN List集合信息
+ ///
+ private List canLinConfigPros = new List();
+
+
+ private ObservableCollection _ListCanLinConfigPro;
+ ///
+ /// CAN 配置程序集合 ObservableCollection
+ ///
+ public ObservableCollection ListCanLinConfigPro
+ {
+ get { return _ListCanLinConfigPro; }
+ set { _ListCanLinConfigPro = value; RaisePropertyChanged(); }
+ }
+
+ ///
+ /// 选中的CanLinConfigPro
+ ///
+ public CanLinConfigPro SelectCanLinConfigPro { get; set; }
+
+ private DelegateCommand