From 169ea7b93dfaa5a33a22dd466c60a52ee2d17f3c Mon Sep 17 00:00:00 2001 From: Tyrone CT Date: Fri, 11 Jul 2025 23:47:23 +0800 Subject: [PATCH] =?UTF-8?q?CAN=20FD=E5=A2=9E=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CapMachine.Model/CANLIN/CANFdConfigExd.cs | 53 + CapMachine.Model/CANLIN/CanLinConfigPro.cs | 7 + CapMachine.Model/CANLIN/CanLinEmun.cs | 5 + CapMachine.Wpf/App.xaml.cs | 2 + .../CanDrive/CanFD/DBCParserByFD.cs | 57 + CapMachine.Wpf/CanDrive/CanFD/ToomossCanFD.cs | 899 +++++++++++ .../CanDrive/{ => CanFD}/USB2CANFD.cs | 0 .../CanDrive/CanFD/USB_DEVICEByFD.cs | 143 ++ CapMachine.Wpf/CanDrive/ToomossCanFD.cs | 511 ------ CapMachine.Wpf/Dtos/CANFdConfigExdDto.cs | 77 + .../MapperProfile/CANFdConfigExdProfile.cs | 19 + CapMachine.Wpf/Models/CanLinRunStateModel.cs | 4 + CapMachine.Wpf/Models/ComEnum.cs | 5 + CapMachine.Wpf/Services/CanFdDriveService.cs | 415 +++++ .../Services/MachineRtDataService.cs | 31 +- .../Services/NavigationMenuService.cs | 1 + .../ViewModels/CANFDConfigViewModel.cs | 1423 +++++++++++++++++ CapMachine.Wpf/ViewModels/MonitorViewModel.cs | 10 +- CapMachine.Wpf/Views/CANFDConfigView.xaml | 1073 +++++++++++++ CapMachine.Wpf/Views/CANFDConfigView.xaml.cs | 28 + 20 files changed, 4250 insertions(+), 513 deletions(-) create mode 100644 CapMachine.Model/CANLIN/CANFdConfigExd.cs create mode 100644 CapMachine.Wpf/CanDrive/CanFD/DBCParserByFD.cs create mode 100644 CapMachine.Wpf/CanDrive/CanFD/ToomossCanFD.cs rename CapMachine.Wpf/CanDrive/{ => CanFD}/USB2CANFD.cs (100%) create mode 100644 CapMachine.Wpf/CanDrive/CanFD/USB_DEVICEByFD.cs delete mode 100644 CapMachine.Wpf/CanDrive/ToomossCanFD.cs create mode 100644 CapMachine.Wpf/Dtos/CANFdConfigExdDto.cs create mode 100644 CapMachine.Wpf/MapperProfile/CANFdConfigExdProfile.cs create mode 100644 CapMachine.Wpf/Services/CanFdDriveService.cs create mode 100644 CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs create mode 100644 CapMachine.Wpf/Views/CANFDConfigView.xaml create mode 100644 CapMachine.Wpf/Views/CANFDConfigView.xaml.cs 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 _CanConfigProGridSelectionChangedCmd; + /// + /// CAN 配置程序 选中行数据命令 + /// + public DelegateCommand CanConfigProGridSelectionChangedCmd + { + set + { + _CanConfigProGridSelectionChangedCmd = value; + } + get + { + if (_CanConfigProGridSelectionChangedCmd == null) + { + _CanConfigProGridSelectionChangedCmd = new DelegateCommand((par) => CanConfigProGridSelectionChangedCmdMethod(par)); + } + return _CanConfigProGridSelectionChangedCmd; + } + } + private void CanConfigProGridSelectionChangedCmdMethod(object par) + { + if (par == null) + { + return; + } + if (par is SelectionChangedEventArgs) + { + return; + } + + if (par is CanLinConfigPro) + { + SelectCanLinConfigPro = par as CanLinConfigPro; + + //CANConfigExdDto 数据 + 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)); + } + + SelectCanLinConfigProConfigName = SelectCanLinConfigPro.ConfigName; + + return; + } + //先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件 + var Selecteddata = (par as SelectionChangedEventArgs)!.AddedItems[0] as CanLinConfigPro; + + if (Selecteddata != null) + { + SelectCanLinConfigPro = Selecteddata; + + SelectCanLinConfigProConfigName = SelectCanLinConfigPro.ConfigName; + + } + + + } + + + private DelegateCommand _CanConfigProGridPreviewMouseLeftButtonDownCmd; + /// + /// CAN 配置程序 选中行之前的数据命令 Preview + /// 防止CAN 打开后没有关闭就开始切换CAN 配置程序信息 + /// 要关闭后再切换 + /// + public DelegateCommand CanConfigProGridPreviewMouseLeftButtonDownCmd + { + set + { + _CanConfigProGridPreviewMouseLeftButtonDownCmd = value; + } + get + { + if (_CanConfigProGridPreviewMouseLeftButtonDownCmd == null) + { + _CanConfigProGridPreviewMouseLeftButtonDownCmd = new DelegateCommand((par) => CanConfigProGridPreviewMouseLeftButtonDownCmdMethod(par)); + } + return _CanConfigProGridPreviewMouseLeftButtonDownCmd; + } + } + /// + /// 防止CAN 打开后没有关闭就开始切换CAN 配置程序信息 + /// 要关闭后再切换 + /// + /// + private void CanConfigProGridPreviewMouseLeftButtonDownCmdMethod(object par) + { + if (par == null) + { + return; + } + if (par is System.Windows.Input.MouseButtonEventArgs) + { + var handler = par as System.Windows.Input.MouseButtonEventArgs; + + if (!CanFdDriveService.ToomossCanFDDrive.OpenState) + { + // 防止默认的行选择行为发生 + handler.Handled = false; + } + else + { + System.Windows.MessageBox.Show("关闭CAN连接后再点击切换CAN配置", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + handler.Handled = true; + } + } + } + + + #endregion + + #region Dbc操作 + + private ObservableCollection _ListCanDbcModel; + /// + /// Dbc消息集合 + /// + public ObservableCollection ListCanDbcModel + { + get { return _ListCanDbcModel; } + set { _ListCanDbcModel = value; RaisePropertyChanged(); } + } + + //private string _DbcFilePath; + ///// + ///// Dbc文件路径 + ///// + //public string DbcFilePath + //{ + // get { return _DbcFilePath; } + // set { _DbcFilePath = value; RaisePropertyChanged(); } + //} + + + private DelegateCommand _LoadDbcCmd; + /// + /// 下载Dbc文件指令 + /// + public DelegateCommand LoadDbcCmd + { + set + { + _LoadDbcCmd = value; + } + get + { + if (_LoadDbcCmd == null) + { + _LoadDbcCmd = new DelegateCommand(() => LoadDbcCmdMethod()); + } + return _LoadDbcCmd; + } + } + /// + /// 加载Dbc文件信息 + /// + private void LoadDbcCmdMethod() + { + //DbcFilePath + try + { + //var dd = ListQuickMeterStepDto; + + if (SelectCanLinConfigPro != null && SelectedCANConfigExdDto != null) + { + OpenFileDialog OpenFileDialogInfo = new OpenFileDialog(); //new一个方法 + OpenFileDialogInfo.Filter = "(*.dbc;*.dbc)|*.dbc;*.dbc|all|*.*"; //删选、设定文件显示类型 + OpenFileDialogInfo.CheckFileExists = true; + OpenFileDialogInfo.CheckPathExists = true; + + OpenFileDialogInfo.ShowDialog(); //显示打开文件的窗口 + string fileName = OpenFileDialogInfo.FileName; //获得选择的文件路径 + + SelectedCANConfigExdDto.DbcPath = fileName; + } + else + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + + + + //System.Diagnostics.Process.Start(fileName);//打开指定路径下的文件 + } + catch (Exception ex) + { + System.Windows.MessageBox.Show("可能未选择信息", "提示", System.Windows.MessageBoxButton.OKCancel, System.Windows.MessageBoxImage.Hand); + } + } + + + /// + /// 选中的CanDbcModel + /// + public CanDbcModel SelectedCanDbcModel { get; set; } + + private DelegateCommand _DbcGridSelectionChangedCmd; + /// + /// Dbc选中行数据命令 + /// + public DelegateCommand DbcGridSelectionChangedCmd + { + set + { + _DbcGridSelectionChangedCmd = value; + } + get + { + if (_DbcGridSelectionChangedCmd == null) + { + _DbcGridSelectionChangedCmd = new DelegateCommand((par) => DbcGridSelectionChangedCmdMethod(par)); + } + return _DbcGridSelectionChangedCmd; + } + } + private void DbcGridSelectionChangedCmdMethod(object par) + { + if (par == null) + { + return; + } + if (par is CanDbcModel) + { + SelectedCanDbcModel = par as CanDbcModel; + return; + } + + //(par as SelectionChangedEventArgs)!.AddedItems[0] == null + if ((par as SelectionChangedEventArgs)!.AddedItems.Count == 0) + { + return; + } + //先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件 + var Selecteddata = (par as SelectionChangedEventArgs)!.AddedItems[0] as CanDbcModel; + + if (Selecteddata != null) + { + SelectedCanDbcModel = Selecteddata; + + } + } + + + private DelegateCommand _DataGridMenuCmd; + /// + /// DataGridMenu 操作的指令 + /// + public DelegateCommand DataGridMenuCmd + { + set + { + _DataGridMenuCmd = value; + } + get + { + if (_DataGridMenuCmd == null) + { + _DataGridMenuCmd = new DelegateCommand((Par) => DataGridMenuCmdMethod(Par)); + } + return _DataGridMenuCmd; + } + } + /// + /// DataGridMenu 操作的指令 + /// + /// + private void DataGridMenuCmdMethod(string Par) + { + switch (Par) + { + case "Write": + if (SelectedCanDbcModel != null && SelectCanLinConfigPro != null) + { + FreeSql.Insert(new CanLinRWConfig() + { + Name = "", + SignalName = SelectedCanDbcModel.SignalName, + MsgFrameName = SelectedCanDbcModel.MsgName, + CanLinConfigProId = SelectCanLinConfigPro.Id, + DefautValue = "", + RWInfo = RW.Write, + }).ExecuteInserted(); + + InitLoadCanConfigPro(); + } + break; + case "Read": + if (SelectedCanDbcModel != null && SelectCanLinConfigPro != null) + { + FreeSql.Insert(new CanLinRWConfig() + { + Name = "", + SignalName = SelectedCanDbcModel.SignalName, + MsgFrameName = SelectedCanDbcModel.MsgName, + CanLinConfigProId = SelectCanLinConfigPro.Id, + DefautValue = "", + RWInfo = RW.Read, + }).ExecuteInserted(); + + InitLoadCanConfigPro(); + } + break; + default: + break; + } + } + + + + #endregion + + #region CAN操作 + + private CANFdConfigExdDto _SelectedCANConfigExdDto; + /// + /// 选中的CAN操作 + /// + public CANFdConfigExdDto SelectedCANConfigExdDto + { + get { return _SelectedCANConfigExdDto; } + set { _SelectedCANConfigExdDto = value; RaisePropertyChanged(); } + } + + private ObservableCollection _DataBaudRateCbxItems; + /// + /// CAN FD 数据波特率 + /// + public ObservableCollection DataBaudRateCbxItems + { + get { return _DataBaudRateCbxItems; } + set { _DataBaudRateCbxItems = value; RaisePropertyChanged(); } + } + + private ObservableCollection _ArbBaudRateCbxItems; + /// + /// CAN FD 仲裁波特率 + /// + public ObservableCollection ArbBaudRateCbxItems + { + get { return _ArbBaudRateCbxItems; } + set { _ArbBaudRateCbxItems = value; RaisePropertyChanged(); } + } + + private DelegateCommand _CanOpCmd; + /// + /// CAN操作的指令 + /// + public DelegateCommand CanOpCmd + { + set + { + _CanOpCmd = value; + } + get + { + if (_CanOpCmd == null) + { + _CanOpCmd = new DelegateCommand((Par) => CanOpCmdMethod(Par)); + } + return _CanOpCmd; + } + } + /// + /// CAN操作的指令方法 + /// + /// + private void CanOpCmdMethod(string Par) + { + switch (Par) + { + case "Open": + + if (ComActionService.IsCanToDoWork() == false) + { + System.Windows.MessageBox.Show("请关闭LIN连接后才能开启CAN,同一个时刻只能有一个通信驱动压缩机", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } + if (SelectCanLinConfigPro != null && SelectedCANConfigExdDto != null) + { + //打开连接 + CanFdDriveService.ToomossCanFDDrive.StartCanDrive(); + //成功后状态显示 + if (CanFdDriveService.ToomossCanFDDrive.OpenState) + { + //系统使用了CAN + ConfigService.CanLinRunStateModel.CurSysSelectedCanLin = CanLinEnum.CANFD; + } + + //CAN DBC配置 有DBC配置的话,则直接加载DBC信息 + if (!string.IsNullOrEmpty(SelectCanLinConfigPro.CANFdConfigExd.DbcPath)) + { + var DbcData = CanFdDriveService.StartDbc(SelectedCANConfigExdDto.DbcPath); + ListCanDbcModel = DbcData; + + //ListCanDbcModel有数据后就要看看是否有配置信息,有的话就要标注 + //匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListCanDbcModel + MatchSeletedAndCanDbcModel(); + + } + + } + else + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + break; + case "Close": + if (SelectCanLinConfigPro != null && SelectedCANConfigExdDto != null) + { + + CanFdDriveService.ToomossCanFDDrive.CloseDevice(); + //系统取消使用了CAN + ConfigService.CanLinRunStateModel.CurSysSelectedCanLin = CanLinEnum.No; + } + else + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + break; + case "Save": + if (SelectCanLinConfigPro != null && SelectedCANConfigExdDto != null) + { + //保存Can 配置 + if (!string.IsNullOrEmpty(SelectedCANConfigExdDto.DbcPath)) + { + var Update = FreeSql.Update() + .Set(a => a.DbcPath, SelectedCANConfigExdDto.DbcPath) + .Set(a => a.Cycle, SelectedCANConfigExdDto.Cycle) + .Set(a => a.DataBaudRate, SelectedCANConfigExdDto.DataBaudRate) + .Set(a => a.ArbBaudRate, SelectedCANConfigExdDto.ArbBaudRate) + .Set(a => a.ISOEnable, SelectedCANConfigExdDto.ISOEnable) + .Set(a => a.ResEnable, SelectedCANConfigExdDto.ResEnable) + .Where(a => a.Id == SelectedCANConfigExdDto.Id) + .ExecuteUpdated(); + } + + InitLoadCanConfigPro(); + } + else + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + break; + case "Parse": + if (SelectCanLinConfigPro != null && SelectedCANConfigExdDto != null) + { + //打开之后连接 + if (CanFdDriveService.ToomossCanFDDrive.OpenState) + { + //CAN DBC配置 有DBC配置的话,则加载DBC信息 + if (!string.IsNullOrEmpty(SelectedCANConfigExdDto.DbcPath)) + { + var DbcData = CanFdDriveService.StartDbc(SelectedCANConfigExdDto.DbcPath); + + ListCanDbcModel = DbcData; + } + else + { + System.Windows.MessageBox.Show("请选择DBC文件后再操作", "提示", System.Windows.MessageBoxButton.OKCancel, System.Windows.MessageBoxImage.Hand); + } + } + // ListCanDbcModel = new ObservableCollection() + //{ + // new CanDbcModel(){ MsgName="DSDF1",SignalName="FASDFA11",Publisher="DFAD1",SignalDesc="ASDFASD1"}, + // new CanDbcModel(){ MsgName="DSDF2",SignalName="FASDFA22",Publisher="DFAD2",SignalDesc="ASDFASD2"}, + // new CanDbcModel(){ MsgName="DSDF3",SignalName="FASDFA33",Publisher="DFAD3",SignalDesc="ASDFASD3"}, + // new CanDbcModel(){ MsgName="DSDF4",SignalName="FASDFA44",Publisher="DFAD4",SignalDesc="ASDFASD4"}, + // new CanDbcModel(){ MsgName="DSDF5",SignalName="FASDFA55",Publisher="DFAD5",SignalDesc="ASDFASD5"}, + //}; + // return; + + } + else + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + break; + + case "HandSend"://手动发送 + + //手动发送数据 + CanFdDriveService.SendMsgToCanDrive(HandSpeed); + + //CanFdDriveService.ToomossCanFDDrive.SendCanMsg(new List() + //{ + // new CanCmdData(){ MsgName="TX1",SignalName="COM_current_Power",SignalCmdValue=12}, + // new CanCmdData(){ MsgName="TX1",SignalName="COM_Curr_dc",SignalCmdValue=12}, + //}); + + break; + case "CycleSend"://循环发送你 + //循环发送数据 + CanFdDriveService.CycleSendMsg(); + + //Listen + break; + case "CycleRecive": + CanFdDriveService.CycleReciveMsg(); + + //Listen + break; + default: + break; + } + } + + + private double _HandSpeed; + /// + /// 手动转速数据 + /// + public double HandSpeed + { + get { return _HandSpeed; } + set { _HandSpeed = value; RaisePropertyChanged(); } + } + + + #endregion + + + #region 写入和读取操作 + + private ObservableCollection _WriteNameCbxItems; + /// + /// 写入的Name + /// + public ObservableCollection WriteNameCbxItems + { + get { return _WriteNameCbxItems; } + set { _WriteNameCbxItems = value; RaisePropertyChanged(); } + } + + + private ObservableCollection _ReadNameCbxItems; + /// + /// 写入的Name + /// + public ObservableCollection ReadNameCbxItems + { + get { return _ReadNameCbxItems; } + set { _ReadNameCbxItems = value; RaisePropertyChanged(); } + } + + private ObservableCollection _WriteRuleCbxItems; + /// + /// 写入的规格集合 + /// + public ObservableCollection WriteRuleCbxItems + { + get { return _WriteRuleCbxItems; } + set { _WriteRuleCbxItems = value; RaisePropertyChanged(); } + } + + //private string _SelectedWriteName; + ///// + ///// 选中的写入的Name + ///// + //public string SelectedWriteName + //{ + // get { return _SelectedWriteName; } + // set { _SelectedWriteName = value; RaisePropertyChanged(); } + //} + + //private string _SelectedReadName; + ///// + ///// 选中的读取的Name + ///// + //public string SelectedReadName + //{ + // get { return _SelectedReadName; } + // set { _SelectedReadName = value; RaisePropertyChanged(); } + //} + + + private ObservableCollection _ListWriteCanLinRWConfigDto; + /// + /// CAN写入集合数据 + /// + public ObservableCollection ListWriteCanLinRWConfigDto + { + get { return _ListWriteCanLinRWConfigDto; } + set { _ListWriteCanLinRWConfigDto = value; RaisePropertyChanged(); } + } + + /// + /// 选中的CanLinRWConfigDto行 Write + /// + private CanLinRWConfigDto SelectedWriteCanLinRWConfigDto { get; set; } + + private DelegateCommand _WriteGridSelectionChangedCmd; + /// + /// 写入CAN的选中行的命令 + /// + public DelegateCommand WriteGridSelectionChangedCmd + { + set + { + _WriteGridSelectionChangedCmd = value; + } + get + { + if (_WriteGridSelectionChangedCmd == null) + { + _WriteGridSelectionChangedCmd = new DelegateCommand((Par) => WriteGridSelectionChangedCmdMethod(Par)); + } + return _WriteGridSelectionChangedCmd; + } + } + /// + /// 写入CAN的选中行执行方法 + /// + /// + /// + private void WriteGridSelectionChangedCmdMethod(object par) + { + if (par is CanLinRWConfigDto) + { + SelectedWriteCanLinRWConfigDto = par as CanLinRWConfigDto; + } + } + + private DelegateCommand _WriteCmd; + /// + /// 写入操作的指令 + /// + public DelegateCommand WriteCmd + { + set + { + _WriteCmd = value; + } + get + { + if (_WriteCmd == null) + { + _WriteCmd = new DelegateCommand((Par) => WriteCmdMethod(Par)); + } + return _WriteCmd; + } + } + /// + /// 写入操作的指令方法 + /// + /// + private void WriteCmdMethod(string Par) + { + if (SelectCanLinConfigPro == null) + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } + + + switch (Par) + { + case "Add": + //由右侧的右键DBC目录增加 + + break; + case "Edit": + if (ListWriteCanLinRWConfigDto != null && ListWriteCanLinRWConfigDto.Count() > 0) + { + foreach (var item in ListWriteCanLinRWConfigDto) + { + //直接修改 + FreeSql.Update(item.Id) + .Set(a => a.Name, item.Name) + .Set(a => a.LogicRuleId, item.LogicRuleId) + .Set(a => a.DefautValue, item.DefautValue) + .ExecuteAffrows(); + //ListWriteCanLinRWConfigDto.Remove(SelectedWriteCanLinRWConfigDto); + + //SelectedWriteCanLinRWConfigDto = null; + + } + + InitLoadCanConfigPro(); + } + + + + break; + case "Delete": + if (SelectedWriteCanLinRWConfigDto != null) + { + //直接删除掉 + FreeSql.Delete(SelectedWriteCanLinRWConfigDto.Id).ExecuteAffrows(); + ListWriteCanLinRWConfigDto.Remove(SelectedWriteCanLinRWConfigDto); + + SelectedWriteCanLinRWConfigDto = null; + + InitLoadCanConfigPro(); + } + else + { + System.Windows.MessageBox.Show("请选中后再进行【删除】操作?", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + break; + default: + break; + } + } + + + + + + private ObservableCollection _ListReadCanLinRWConfigDto; + /// + /// CAN读取集合数据 + /// + public ObservableCollection ListReadCanLinRWConfigDto + { + get { return _ListReadCanLinRWConfigDto; } + set { _ListReadCanLinRWConfigDto = value; RaisePropertyChanged(); } + } + + /// + /// 选中的CanLinRWConfigDto行 Read + /// + private CanLinRWConfigDto SelectedReadCanLinRWConfigDto { get; set; } + + private DelegateCommand _ReadGridSelectionChangedCmd; + /// + /// 写入CAN的选中行的命令 + /// + public DelegateCommand ReadGridSelectionChangedCmd + { + set + { + _ReadGridSelectionChangedCmd = value; + } + get + { + if (_ReadGridSelectionChangedCmd == null) + { + _ReadGridSelectionChangedCmd = new DelegateCommand((Par) => ReadGridSelectionChangedCmdMethod(Par)); + } + return _ReadGridSelectionChangedCmd; + } + } + /// + /// 读取CAN的选中行执行方法 + /// + /// + /// + private void ReadGridSelectionChangedCmdMethod(object par) + { + if (par is CanLinRWConfigDto) + { + SelectedReadCanLinRWConfigDto = par as CanLinRWConfigDto; + } + } + + + + private DelegateCommand _ReadCmd; + /// + /// 读取操作的指令 + /// + public DelegateCommand ReadCmd + { + set + { + _ReadCmd = value; + } + get + { + if (_ReadCmd == null) + { + _ReadCmd = new DelegateCommand((Par) => ReadCmdMethod(Par)); + } + return _ReadCmd; + } + } + /// + /// 读取操作的指令方法 + /// + /// + private void ReadCmdMethod(string Par) + { + if (SelectCanLinConfigPro == null) + { + System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } + + switch (Par) + { + case "Add": + //由右侧的右键DBC目录增加 + + break; + case "Edit": + if (ListReadCanLinRWConfigDto != null && ListReadCanLinRWConfigDto.Count() > 0) + { + foreach (var item in ListReadCanLinRWConfigDto) + { + //直接修改 + FreeSql.Update(item.Id) + .Set(a => a.Name, item.Name) + .Set(a => a.DefautValue, item.DefautValue) + .ExecuteAffrows(); + //ListReadCanLinRWConfigDto.Remove(SelectedReadCanLinRWConfigDto); + + //SelectedReadCanLinRWConfigDto = null; + + } + + InitLoadCanConfigPro(); + } + + + + break; + case "Delete": + if (SelectedReadCanLinRWConfigDto != null) + { + //直接删除掉 + FreeSql.Delete(SelectedReadCanLinRWConfigDto.Id).ExecuteAffrows(); + ListReadCanLinRWConfigDto.Remove(SelectedReadCanLinRWConfigDto); + + SelectedReadCanLinRWConfigDto = null; + + InitLoadCanConfigPro(); + } + else + { + System.Windows.MessageBox.Show("请选中后再进行【删除】操作?", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + } + + break; + default: + break; + } + } + + #endregion + } +} diff --git a/CapMachine.Wpf/ViewModels/MonitorViewModel.cs b/CapMachine.Wpf/ViewModels/MonitorViewModel.cs index 421e6da..5199abe 100644 --- a/CapMachine.Wpf/ViewModels/MonitorViewModel.cs +++ b/CapMachine.Wpf/ViewModels/MonitorViewModel.cs @@ -27,7 +27,7 @@ namespace CapMachine.Wpf.ViewModels /// /// public MonitorViewModel(ConfigService configService, IEventAggregator eventAggregator, - DataRecordService dataRecordService, SysRunService sysRunService, AlarmService alarmService, PPCService pPCService, CanDriveService canDriveService, LinDriveService linDriveService, + DataRecordService dataRecordService, CanFdDriveService canFdDriveService, SysRunService sysRunService, AlarmService alarmService, PPCService pPCService, CanDriveService canDriveService, LinDriveService linDriveService, ProRuntimeService proRuntimeService, MachineRtDataService machineRtDataService, IDialogService dialogService) { @@ -39,6 +39,7 @@ namespace CapMachine.Wpf.ViewModels AlarmService = alarmService; PPCService = pPCService; CanDriveService = canDriveService; + CanFdDriveService = canFdDriveService; LinDriveService = linDriveService; ProRuntimeService = proRuntimeService; MachineRtDataService = machineRtDataService; @@ -91,6 +92,7 @@ namespace CapMachine.Wpf.ViewModels public AlarmService AlarmService { get; } public PPCService PPCService { get; } public CanDriveService CanDriveService { get; } + public CanFdDriveService CanFdDriveService { get; } public LinDriveService LinDriveService { get; } public ProRuntimeService ProRuntimeService { get; } public MachineRtDataService MachineRtDataService { get; } @@ -344,6 +346,12 @@ namespace CapMachine.Wpf.ViewModels CanDriveService.UpdateCapEnableCmdData(false); //itemTag.Value.EngPvValue = 0; break; + case CanLinEnum.CANFD: + //获取PLC的SV数据 更新SV的速度值到压缩机 + CanFdDriveService.UpdateSpeedCmdData(0); + CanFdDriveService.UpdateCapEnableCmdData(false); + //itemTag.Value.EngPvValue = 0; + break; case CanLinEnum.Lin: //获取PLC的SV数据 更新SV的速度值到压缩机 LinDriveService.UpdateSpeedCmdData(0); diff --git a/CapMachine.Wpf/Views/CANFDConfigView.xaml b/CapMachine.Wpf/Views/CANFDConfigView.xaml new file mode 100644 index 0000000..28032a4 --- /dev/null +++ b/CapMachine.Wpf/Views/CANFDConfigView.xaml @@ -0,0 +1,1073 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CapMachine.Wpf/Views/CANFDConfigView.xaml.cs b/CapMachine.Wpf/Views/CANFDConfigView.xaml.cs new file mode 100644 index 0000000..84a4c0d --- /dev/null +++ b/CapMachine.Wpf/Views/CANFDConfigView.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace CapMachine.Wpf.Views +{ + /// + /// CANFDConfigView.xaml 的交互逻辑 + /// + public partial class CANFDConfigView : UserControl + { + public CANFDConfigView() + { + InitializeComponent(); + } + } +}