增加了CAN调度表发送,但是没有测试成功
This commit is contained in:
@@ -200,7 +200,8 @@ namespace CapMachine.Wpf
|
||||
containerRegistry.RegisterDialog<DialogLimitConfigView, DialogLimitConfigViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogSuperHeatCoolConfigView, DialogSuperHeatCoolConfigViewModel>();
|
||||
containerRegistry.RegisterDialog<DialogLogicRuleView, DialogLogicRuleViewModel>();
|
||||
|
||||
containerRegistry.RegisterDialog<DialogCANSchConfigView, DialogCANSchConfigViewModel>();
|
||||
|
||||
containerRegistry.RegisterDialog<SplashScreenView, SplashScreenViewModel>();
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using NPOI.OpenXmlFormats.Wordprocessing;
|
||||
using Prism.Ioc;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
@@ -549,6 +550,7 @@ namespace CapMachine.Wpf.CanDrive
|
||||
//此时重置NextExecutionTime为当前时间,避免连续的延迟累积
|
||||
// 严重延迟,重新校准
|
||||
NextExecutionTime = Stopwatcher.ElapsedTicks;
|
||||
LogService.Info("定时发送延迟过大,重新校准时间");
|
||||
Console.WriteLine("定时发送延迟过大,重新校准时间");
|
||||
}
|
||||
|
||||
@@ -681,6 +683,180 @@ namespace CapMachine.Wpf.CanDrive
|
||||
#endregion
|
||||
|
||||
|
||||
#region 并行多线程发送报文
|
||||
|
||||
/// <summary>
|
||||
/// 并行精确周期发送CAN数据
|
||||
/// </summary>
|
||||
public void StartParallelPrecisionCycleSendMsg()
|
||||
{
|
||||
// 创建取消标记源
|
||||
var cancellationTokenSource = new CancellationTokenSource();
|
||||
var token = cancellationTokenSource.Token;
|
||||
|
||||
// 保存取消标记,以便在停止时使用
|
||||
CycleSendCts = cancellationTokenSource;
|
||||
|
||||
// 初始化计时基准
|
||||
TicksPerMs = Stopwatch.Frequency / 1000.0;
|
||||
|
||||
// 分组消息,按照消息名称进行分组
|
||||
var groupedMessages = CmdData.GroupBy(x => x.MsgName).ToList();
|
||||
|
||||
// 创建发送任务列表
|
||||
var sendTasks = new List<Task>();
|
||||
|
||||
// 创建线程同步对象,确保DBC操作和发送操作的线程安全
|
||||
object dbcLock = new object();
|
||||
|
||||
// 为每组消息创建单独的发送任务
|
||||
foreach (var messageGroup in groupedMessages)
|
||||
{
|
||||
var msgName = messageGroup.Key;
|
||||
var signals = messageGroup.ToList();
|
||||
|
||||
// 为每个消息组创建一个发送任务
|
||||
var sendTask = Task.Factory.StartNew(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 设置线程优先级
|
||||
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
|
||||
|
||||
// 每个消息使用独立的计时器
|
||||
var messageStopwatch = new Stopwatch();
|
||||
messageStopwatch.Start();
|
||||
|
||||
// 计算该消息的发送周期(可以为不同消息设置不同周期)
|
||||
// 这里可以从配置或参数中获取特定消息的周期
|
||||
long cycleInTicks = (long)(SendCycle * TicksPerMs);
|
||||
long nextExecutionTime = 0;
|
||||
|
||||
while (IsCycleSend && !token.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 计算下一次执行时间
|
||||
nextExecutionTime += cycleInTicks;
|
||||
|
||||
// 获取当前时间
|
||||
long currentTime = messageStopwatch.ElapsedTicks;
|
||||
long delayTicks = nextExecutionTime - currentTime;
|
||||
|
||||
// 精确等待逻辑
|
||||
if (delayTicks > 0)
|
||||
{
|
||||
int delayMs = (int)(delayTicks / TicksPerMs);
|
||||
|
||||
if (delayMs <= 20)
|
||||
{
|
||||
SpinWait.SpinUntil(() => messageStopwatch.ElapsedTicks >= nextExecutionTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(delayMs - 20, token);
|
||||
SpinWait.SpinUntil(() => messageStopwatch.ElapsedTicks >= nextExecutionTime);
|
||||
}
|
||||
}
|
||||
|
||||
// 校准时间,处理严重延迟情况
|
||||
if (messageStopwatch.ElapsedTicks >= nextExecutionTime + cycleInTicks)
|
||||
{
|
||||
nextExecutionTime = messageStopwatch.ElapsedTicks;
|
||||
LogService.Info($"消息{msgName}定时发送延迟过大,重新校准时间");
|
||||
}
|
||||
|
||||
// 使用锁确保DBC操作和发送的线程安全
|
||||
lock (dbcLock)
|
||||
{
|
||||
// 构建CAN消息
|
||||
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
|
||||
|
||||
try
|
||||
{
|
||||
// 为信号赋值
|
||||
foreach (var signal in signals)
|
||||
{
|
||||
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(msgName),
|
||||
new StringBuilder(signal.SignalName), signal.SignalCmdValue);
|
||||
}
|
||||
|
||||
// 同步值到CAN消息
|
||||
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(msgName), msgPtSend);
|
||||
var canMsg = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
|
||||
|
||||
// 直接发送此消息,无需通过队列
|
||||
USB2CAN.CAN_MSG[] canMsgArray = new USB2CAN.CAN_MSG[] { canMsg };
|
||||
int sendedNum = USB2CAN.CAN_SendMsg(DevHandle, WriteCANIndex, canMsgArray, 1);
|
||||
|
||||
// 更新发送状态
|
||||
if (sendedNum >= 0)
|
||||
{
|
||||
// 发送成功
|
||||
IsSendOk = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSendOk = false;
|
||||
LogService.Info($"消息{msgName}发送失败: {sendedNum}");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 确保释放非托管资源
|
||||
Marshal.FreeHGlobal(msgPtSend);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
LogService.Info($"消息{msgName}发送任务被取消");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Info($"消息{msgName}发送异常: {ex.Message}");
|
||||
await Task.Delay(10, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Info($"消息{msgName}发送线程异常: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogService.Info($"消息{msgName}发送线程已退出");
|
||||
}
|
||||
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
|
||||
sendTasks.Add(sendTask);
|
||||
}
|
||||
|
||||
// 创建监控任务,监控所有发送任务的状态
|
||||
CycleSendTask = Task.Factory.StartNew(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// 等待所有任务完成或取消
|
||||
await Task.WhenAll(sendTasks.ToArray());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogService.Info($"并行发送监控任务异常: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
LogService.Info("并行发送任务已全部结束");
|
||||
IsSendOk = false;
|
||||
}
|
||||
}, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
private bool _IsCycleRevice;
|
||||
/// <summary>
|
||||
/// 是否循环接收数据
|
||||
|
||||
@@ -119,16 +119,24 @@ namespace CapMachine.Wpf.CanDrive
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_Init(Int32 DevHandle, Byte CANIndex, ref CANFD_INIT_CONFIG pCanConfig);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_Init2(Int32 DevHandle, Byte CANIndex, Int32 BaudRateNBTBps, Int32 BaudRateDBTBps, Byte EnResistor, Byte ISOCRCEnable);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_StartGetMsg(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_StopGetMsg(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_SendMsg(Int32 DevHandle, Byte CANIndex, CANFD_MSG[] pCanSendMsg, Int32 SendMsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_SendMsgWithTime(Int32 DevHandle, Byte CANIndex, CANFD_MSG[] pCanSendMsg, Int32 SendMsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_GetMsg(Int32 DevHandle, Byte CANIndex, IntPtr pCanGetMsg, Int32 BufferSize);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_ClearMsg(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_SetFilter(Int32 DevHandle, Byte CANIndex, ref CANFD_FILTER_CONFIG pCanFilter, Byte Len);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_FilterList_Init(Int32 DevHandle, Byte CANIndex, UInt32[] pIDList, Byte IDListLen);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_GetDiagnostic(Int32 DevHandle, Byte CANIndex, ref CANFD_DIAGNOSTIC pCanDiagnostic);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_GetBusError(Int32 DevHandle, Byte CANIndex, ref CANFD_BUS_ERROR pCanBusError);
|
||||
@@ -139,7 +147,13 @@ namespace CapMachine.Wpf.CanDrive
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_StartSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte TimePrecMs, Byte OrderSend);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_UpdateSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte MsgIndex, CANFD_MSG[] pCanMsg, Byte MsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_StopSchedule(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int64 CANFD_GetStartTime(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_ResetStartTime(Int32 DevHandle, Byte CANIndex);
|
||||
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CANFD_SetRelay(Int32 DevHandle, Byte RelayState);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using CapMachine.Wpf.Models.Tag;
|
||||
using CapMachine.Core;
|
||||
using CapMachine.Model.CANLIN;
|
||||
using CapMachine.Wpf.Dtos;
|
||||
using CapMachine.Wpf.Models.Tag;
|
||||
using CapMachine.Wpf.Services;
|
||||
using HslCommunication;
|
||||
using ImTools;
|
||||
using NLog;
|
||||
using NPOI.OpenXmlFormats.Wordprocessing;
|
||||
using Prism.Ioc;
|
||||
@@ -35,7 +39,7 @@ namespace CapMachine.Wpf.CanDrive
|
||||
ContainerProvider = containerProvider;
|
||||
HighSpeedDataService = ContainerProvider.Resolve<HighSpeedDataService>();
|
||||
LoggerService = ContainerProvider.Resolve<ILogService>();
|
||||
|
||||
|
||||
//Stopwatch.Frequency表示高精度计时器每秒的计数次数(ticks/秒)每毫秒的ticks数 = 每秒的ticks数 ÷ 1000
|
||||
TicksPerMs = Stopwatch.Frequency / 1000.0;
|
||||
}
|
||||
@@ -488,8 +492,13 @@ namespace CapMachine.Wpf.CanDrive
|
||||
/// </summary>
|
||||
private static Task CycleSendTask { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 定时扫描更新数据 扫描Task
|
||||
/// </summary>
|
||||
private static Task CycleUpdateCmdTask { get; set; }
|
||||
|
||||
StringBuilder ValueSb = new StringBuilder(16);
|
||||
double[] ValueDouble=new double[5];
|
||||
double[] ValueDouble = new double[5];
|
||||
|
||||
private bool _IsSendOk;
|
||||
/// <summary>
|
||||
@@ -785,6 +794,296 @@ namespace CapMachine.Wpf.CanDrive
|
||||
|
||||
#endregion
|
||||
|
||||
#region 调度表发送报文
|
||||
|
||||
private bool _SchEnable;
|
||||
/// <summary>
|
||||
/// 调度表使能
|
||||
/// </summary>
|
||||
public bool SchEnable
|
||||
{
|
||||
get { return _SchEnable; }
|
||||
set
|
||||
{
|
||||
_SchEnable = value;
|
||||
RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 调度表的发送的报文数据
|
||||
/// </summary>
|
||||
private USB2CAN.CAN_MSG[] SchCanMsg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 依据消息的分组
|
||||
/// </summary>
|
||||
private IEnumerable<IGrouping<string, CanCmdData>> GroupMsg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 调度表集合数据
|
||||
/// 总共3个调度表,第一个表里面包含3帧数据,第二个调度表包含6帧数据,第三个调度表包含11帧数据
|
||||
/// Byte[] MsgTabNum = new Byte[3] { 3, 6, 11 };
|
||||
/// </summary>
|
||||
private Byte[] MsgTabNum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 调度表发送的次数集合
|
||||
/// 第一个调度表循环发送数据,第二个调度表循环发送数据,第三个调度表只发送3次
|
||||
/// UInt16[] SendTimes = new UInt16[3] { 0xFFFF, 0xFFFF, 3 };
|
||||
/// </summary>
|
||||
private UInt16[] SendTimes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 预设的调度表的个数 常值
|
||||
/// </summary>
|
||||
private const int MsgTabCount = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 定时更新时间
|
||||
/// </summary>
|
||||
private int UpdateCycle = 500;
|
||||
|
||||
/// <summary>
|
||||
/// CNA 调度表的配置信息
|
||||
/// </summary>
|
||||
public List<CANScheduleConfigDto> ListCANScheduleConfig { get; set; }
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
/// <summary>
|
||||
/// 更新数据
|
||||
/// </summary>
|
||||
public void UpdateValue()
|
||||
{
|
||||
//通过DBC进行对消息赋值
|
||||
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
|
||||
int Index = 0;
|
||||
//循环给MSG赋值数据
|
||||
foreach (var itemMsg in GroupMsg)
|
||||
{
|
||||
foreach (var itemSignal in itemMsg)
|
||||
{
|
||||
itemSignal.SignalCmdValue = random.Next(0, 100);
|
||||
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
|
||||
}
|
||||
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
|
||||
SchCanMsg[Index] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
|
||||
Index++;
|
||||
}
|
||||
|
||||
//通过DBC写入数据后生成CanMsg
|
||||
//将信号值填入CAN消息里面
|
||||
|
||||
//释放申请的临时缓冲区
|
||||
Marshal.FreeHGlobal(msgPtSend);
|
||||
|
||||
|
||||
////总共3个调度表,第一个表里面包含3帧数据,第二个调度表包含6帧数据,第三个调度表包含11帧数据
|
||||
//MsgTabNum = new Byte[1] { 1 };
|
||||
////第一个调度表循环发送数据,第二个调度表循环发送数据,第三个调度表只发送3次
|
||||
//SendTimes = new UInt16[1] { 0xFFFF };
|
||||
//var ret = USB2CAN.CAN_SetSchedule(DevHandle, WriteCANIndex, SchCanMsg, MsgTabNum, SendTimes, 1);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
|
||||
var ret = USB2CAN.CAN_UpdateSchedule(DevHandle, WriteCANIndex, 0, 0, SchCanMsg, 1);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
|
||||
if (ret == USB2CAN.CAN_SUCCESS)
|
||||
{
|
||||
Console.WriteLine("Update CAN Schedule Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Update CAN Schedule Error ret = {0}", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始调度表执行
|
||||
/// </summary>
|
||||
public void StartSchedule()
|
||||
{
|
||||
if (CmdData.Count() == 0) return;
|
||||
|
||||
//依据报文进行分组
|
||||
GroupMsg = CmdData.GroupBy(x => x.MsgName)!;
|
||||
//初始化调度表要发送的消息结构
|
||||
SchCanMsg = new USB2CAN.CAN_MSG[GroupMsg.Count()];
|
||||
for (int i = 0; i < GroupMsg.Count(); i++)
|
||||
{
|
||||
SchCanMsg[i] = new USB2CAN.CAN_MSG();
|
||||
SchCanMsg[i].Data = new Byte[64];
|
||||
}
|
||||
|
||||
//通过DBC进行对消息赋值
|
||||
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
|
||||
int Index = 0;
|
||||
//循环给MSG赋值数据
|
||||
foreach (var itemMsg in GroupMsg)
|
||||
{
|
||||
foreach (var itemSignal in itemMsg)
|
||||
{
|
||||
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
|
||||
}
|
||||
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
|
||||
//每个分组就是一个帧指令/消息数据
|
||||
SchCanMsg[Index] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
|
||||
//分配当前消息帧在集合中的位置信息到ListCANScheduleConfig中,方便实时更新时定位帧的位置
|
||||
if (ListCANScheduleConfig.Any(a=>a.MsgName== itemMsg.Key))
|
||||
{
|
||||
//把帧的位置给ListCANScheduleConfig,方便更新时定位数据
|
||||
ListCANScheduleConfig.FindFirst(a => a.MsgName == itemMsg.Key).MsgIndex = Index;
|
||||
}
|
||||
Index++;
|
||||
}
|
||||
//通过DBC写入数据后生成CanMsg
|
||||
//将信号值填入CAN消息里面
|
||||
//释放申请的临时缓冲区
|
||||
Marshal.FreeHGlobal(msgPtSend);
|
||||
|
||||
|
||||
//Sample:总共3个调度表,第一个表里面包含3帧数据,第二个调度表包含6帧数据,第三个调度表包含11帧数据
|
||||
//约定每帧对应一个调度表,预设5个调度表,每个调度表对应一个帧
|
||||
MsgTabNum = new Byte[MsgTabCount] { 1, 1, 1, 1, 1 };
|
||||
//0xFFFF:调度表循环发送数据,X:调度表循环发送的次数
|
||||
//设置每个调度表的发送方式,约定全部为循环发送
|
||||
SendTimes = new UInt16[MsgTabCount] { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };
|
||||
|
||||
//SchCanMsg:需要发送的消息集合;MsgTabNum:调度表集合数据;SendTimes:发送次数集合数据;调度表个数:MsgTabCount
|
||||
var ret = USB2CAN.CAN_SetSchedule(DevHandle, WriteCANIndex, SchCanMsg, MsgTabNum, SendTimes, MsgTabCount);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
|
||||
if (ret == USB2CAN.CAN_SUCCESS)
|
||||
{
|
||||
Console.WriteLine("Set CAN Schedule Success");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Set CAN Schedule Error ret = {0}", ret);
|
||||
LoggerService.Info($"Set CAN Schedule Error; 返回错误代码:{ret}");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var itemGroupMsg in GroupMsg)
|
||||
{
|
||||
if (itemGroupMsg == null) continue;
|
||||
if (ListCANScheduleConfig.Any(a => a.MsgName!.Contains(itemGroupMsg.Key)))
|
||||
{
|
||||
var CANScheduleConfig = ListCANScheduleConfig.FindFirst(a => a.MsgName!.Contains(itemGroupMsg.Key));
|
||||
//配置表里面包括这个报文消息内容
|
||||
ret = USB2CAN.CAN_StartSchedule(DevHandle, WriteCANIndex, (byte)CANScheduleConfig.SchTabIndex, (byte)CANScheduleConfig.Cycle, (byte)CANScheduleConfig.OrderSend);
|
||||
if (ret == USB2CAN.CAN_SUCCESS)
|
||||
{
|
||||
Console.WriteLine($"Start CAN Schedule 1 Success,SchTabIndex:{(byte)CANScheduleConfig.SchTabIndex}-Cycle:{(byte)CANScheduleConfig.Cycle}-OrderSend:{(byte)CANScheduleConfig.OrderSend}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Start CAN Schedule 1 Error ret = {0}", ret);
|
||||
LoggerService.Info($"Start CAN Schedule 1 Error;消息名称:{CANScheduleConfig.MsgName}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerService.Info($"调度表配置未发现对应的消息报文信息;报文信息{itemGroupMsg.Key}");
|
||||
}
|
||||
}
|
||||
|
||||
//走到这里说明调度表执行的是OK的
|
||||
IsSendOk = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 停止调度表
|
||||
/// </summary>
|
||||
public void StopSchedule()
|
||||
{
|
||||
ret = USB2CAN.CAN_StopSchedule(DevHandle, WriteCANIndex);//启动第一个调度表,表里面的CAN帧并行发送
|
||||
if (ret == USB2CAN.CAN_SUCCESS)
|
||||
{
|
||||
Console.WriteLine("Stop CAN Schedule");
|
||||
LoggerService.Info($"Stop CAN Schedule");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Start CAN Schedule Error ret = {0}", ret);
|
||||
LoggerService.Info($"Stop CAN Schedule");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 循环使用的
|
||||
/// </summary>
|
||||
private int CycleUpdateIndex = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 循环更新调度表的指令数据
|
||||
/// 定时更新数据到调度表中
|
||||
/// </summary>
|
||||
public void StartCycleUpdateCmd()
|
||||
{
|
||||
CycleUpdateCmdTask = Task.Run(async () =>
|
||||
{
|
||||
while (IsCycleSend)
|
||||
{
|
||||
await Task.Delay(UpdateCycle);
|
||||
try
|
||||
{
|
||||
//通过DBC进行对消息赋值
|
||||
IntPtr msgPtSend = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)));
|
||||
CycleUpdateIndex = 0;
|
||||
//循环给MSG赋值数据,顺序是固定的,跟初始时设置是一样的
|
||||
foreach (var itemMsg in GroupMsg)
|
||||
{
|
||||
foreach (var itemSignal in itemMsg)
|
||||
{
|
||||
itemSignal.SignalCmdValue = random.Next(0, 100); //仿真测试数据使用
|
||||
CAN_DBCParser.DBC_SetSignalValue(DBCHandle, new StringBuilder(itemMsg.Key), new StringBuilder(itemSignal.SignalName), itemSignal.SignalCmdValue);
|
||||
}
|
||||
CAN_DBCParser.DBC_SyncValueToCANMsg(DBCHandle, new StringBuilder(itemMsg.Key), msgPtSend);
|
||||
SchCanMsg[CycleUpdateIndex] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure(msgPtSend, typeof(USB2CAN.CAN_MSG));
|
||||
CycleUpdateIndex++;
|
||||
}
|
||||
|
||||
//通过DBC写入数据后生成CanMsg
|
||||
//将信号值填入CAN消息里面
|
||||
|
||||
//释放申请的临时缓冲区
|
||||
Marshal.FreeHGlobal(msgPtSend);
|
||||
|
||||
//配置信息
|
||||
foreach (var itemMsgSchConfig in ListCANScheduleConfig)
|
||||
{
|
||||
//USB2CAN.CAN_MSG[] SchCanMsg1=new CAN_MSG[1];
|
||||
//SchCanMsg1[0] = SchCanMsg[itemMsgSchConfig.MsgIndex];
|
||||
|
||||
// MsgTabIndex CAN调度表索引号 ;MsgIndex 开始更新帧起始索引,若起始索引大于调度表帧数,则将帧添加到调度表后面, ;
|
||||
// pCanMsg 需要更新的CAN帧指针,消息数据 ; MsgNum pCanMsgTab里面包含的有效帧数,一个调度表对应一个帧/消息,即为:1 (byte)(itemMsgSchConfig.MsgIndex+0)
|
||||
var ret = USB2CAN.CAN_UpdateSchedule(DevHandle, WriteCANIndex, (byte)(itemMsgSchConfig.SchTabIndex+0), (byte)0, SchCanMsg, 1);//配置调度表,该函数耗时可能会比较长,但是只需要执行一次即可
|
||||
if (ret == USB2CAN.CAN_SUCCESS)
|
||||
{
|
||||
Console.WriteLine($"Update CAN Schedule Success--SchTabIndex:{(byte)itemMsgSchConfig.SchTabIndex} --MsgIndex:{(byte)(itemMsgSchConfig.MsgIndex)} ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Update CAN Schedule Error ret = {ret}---SchTabIndex:{(byte)itemMsgSchConfig.SchTabIndex} --MsgIndex:{(byte)(itemMsgSchConfig.MsgIndex)}");
|
||||
//return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerService.Info($"时间:{DateTime.Now.ToString()}-【MSG】-{ex.Message}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 循环获取CAN消息
|
||||
@@ -802,24 +1101,25 @@ namespace CapMachine.Wpf.CanDrive
|
||||
USB2CAN.CAN_MSG[] CanMsgBuffer = new USB2CAN.CAN_MSG[128];
|
||||
//申请数据缓冲区
|
||||
IntPtr msgPtRead = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(USB2CAN.CAN_MSG)) * CanMsgBuffer.Length);
|
||||
int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, CanMsgBuffer.Length);
|
||||
//int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, ReadCANIndex, msgPtRead, CanMsgBuffer.Length);
|
||||
int CanNum = USB2CAN.CAN_GetMsgWithSize(DevHandle, 1, msgPtRead, CanMsgBuffer.Length);
|
||||
if (CanNum > 0)
|
||||
{
|
||||
IsReviceOk = true;
|
||||
Console.WriteLine("Read CanMsgNum = {0}", CanNum);
|
||||
//Console.WriteLine("Read CanMsgNum = {0}", CanNum);
|
||||
for (int i = 0; i < CanNum; i++)
|
||||
{
|
||||
//CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)((UInt32)msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_MSG)); //有溢出报错
|
||||
CanMsgBuffer[i] = (USB2CAN.CAN_MSG)Marshal.PtrToStructure((IntPtr)(msgPtRead + i * Marshal.SizeOf(typeof(USB2CAN.CAN_MSG))), typeof(USB2CAN.CAN_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].DataLen; j++)
|
||||
{
|
||||
Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
|
||||
}
|
||||
Console.WriteLine("");
|
||||
//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].DataLen; j++)
|
||||
//{
|
||||
// Console.Write("{0} ", CanMsgBuffer[i].Data[j].ToString("X2"));
|
||||
//}
|
||||
//Console.WriteLine("");
|
||||
|
||||
//报文给高速记录的服务
|
||||
HighSpeedDataService.AppendOrUpdateMsg(new Models.HighSpeed.CommMsg()
|
||||
@@ -833,7 +1133,7 @@ namespace CapMachine.Wpf.CanDrive
|
||||
}
|
||||
else if (CanNum == 0)
|
||||
{
|
||||
IsReviceOk=false;
|
||||
IsReviceOk = false;
|
||||
Console.WriteLine("No CAN data!");
|
||||
}
|
||||
else
|
||||
@@ -841,7 +1141,7 @@ namespace CapMachine.Wpf.CanDrive
|
||||
IsReviceOk = false;
|
||||
Console.WriteLine("Get CAN data error!");
|
||||
}
|
||||
Console.WriteLine("");
|
||||
//Console.WriteLine("");
|
||||
|
||||
//将CAN消息数据填充到信号里面,用DBC解析数据
|
||||
CAN_DBCParser.DBC_SyncCANMsgToValue(DBCHandle, msgPtRead, CanNum);
|
||||
|
||||
@@ -101,14 +101,22 @@ namespace CapMachine.Wpf.CanDrive
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_Init(Int32 DevHandle, Byte CANIndex, ref CAN_INIT_CONFIG pCanConfig);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_Init2(Int32 DevHandle, Byte CANIndex, Int32 BaudRateBps, Byte EnResistor);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_Filter_Init(Int32 DevHandle, Byte CANIndex, ref CAN_FILTER_CONFIG pFilterConfig);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_FilterList_Init(Int32 DevHandle, Byte CANIndex, UInt32[] pIDList, Byte IDListLen);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_StartGetMsg(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_StopGetMsg(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_SendMsg(Int32 DevHandle, Byte CANIndex, CAN_MSG[] pCanSendMsg, UInt32 SendMsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_SendMsgSynch(Int32 DevHandle, Byte CANIndex, CAN_MSG[] pCanSendMsg, UInt32 SendMsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_SendMsgWithTime(Int32 DevHandle, Byte CANIndex, CAN_MSG[] pCanSendMsg, UInt32 SendMsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_GetMsg(Int32 DevHandle, Byte CANIndex, IntPtr pCanGetMsg);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_GetMsgWithSize(Int32 DevHandle, Byte CANIndex, IntPtr pCanGetMsg, Int32 BufferSize);
|
||||
@@ -121,9 +129,17 @@ namespace CapMachine.Wpf.CanDrive
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_StartSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte TimePrecMs, Byte OrderSend);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_UpdateSchedule(Int32 DevHandle, Byte CANIndex, Byte MsgTabIndex, Byte MsgIndex, CAN_MSG[] pCanMsg, Byte MsgNum);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_StopSchedule(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_SetRelay(Int32 DevHandle, Byte RelayState);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_Stop(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int64 CAN_GetStartTime(Int32 DevHandle, Byte CANIndex);
|
||||
[DllImport("USB2XXX.dll")]
|
||||
public static extern Int32 CAN_ResetStartTime(Int32 DevHandle, Byte CANIndex);
|
||||
|
||||
//CAN Bootloader相关函数
|
||||
[DllImport("USB2XXX.dll")]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -43,5 +43,15 @@ namespace CapMachine.Wpf.Dtos
|
||||
get { return _DbcPath; }
|
||||
set { _DbcPath = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private bool _SchEnable;
|
||||
/// <summary>
|
||||
/// 调度表是否启用
|
||||
/// </summary>
|
||||
public bool SchEnable
|
||||
{
|
||||
get { return _SchEnable; }
|
||||
set { _SchEnable = value; RaisePropertyChanged(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
CapMachine.Wpf/Dtos/CANMsgDto.cs
Normal file
27
CapMachine.Wpf/Dtos/CANMsgDto.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CapMachine.Wpf.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// CAN报文和帧
|
||||
/// </summary>
|
||||
public class CANMsgDto:BindableBase
|
||||
{
|
||||
|
||||
private string? _MsgName;
|
||||
/// <summary>
|
||||
/// 消息名称/帧名称
|
||||
/// </summary>
|
||||
public string? MsgName
|
||||
{
|
||||
get { return _MsgName; }
|
||||
set { _MsgName = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
83
CapMachine.Wpf/Dtos/CANScheduleConfigDto.cs
Normal file
83
CapMachine.Wpf/Dtos/CANScheduleConfigDto.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using CapMachine.Model.CANLIN;
|
||||
using Prism.Mvvm;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CapMachine.Wpf.Dtos
|
||||
{
|
||||
/// <summary>
|
||||
/// CANScheduleConfigDto
|
||||
/// </summary>
|
||||
public class CANScheduleConfigDto : BindableBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 主键
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
private string? _MsgName;
|
||||
/// <summary>
|
||||
/// 消息名称/帧名称
|
||||
/// </summary>
|
||||
public string? MsgName
|
||||
{
|
||||
get { return _MsgName; }
|
||||
set { _MsgName = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private int _Cycle;
|
||||
/// <summary>
|
||||
/// 周期
|
||||
/// </summary>
|
||||
public int Cycle
|
||||
{
|
||||
get { return _Cycle; }
|
||||
set { _Cycle = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private int _OrderSend;
|
||||
/// <summary>
|
||||
/// 发送方式
|
||||
/// </summary>
|
||||
public int OrderSend
|
||||
{
|
||||
get { return _OrderSend; }
|
||||
set { _OrderSend = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private int _SchTabIndex;
|
||||
/// <summary>
|
||||
/// 调度表的Index序列
|
||||
/// </summary>
|
||||
public int SchTabIndex
|
||||
{
|
||||
get { return _SchTabIndex; }
|
||||
set { _SchTabIndex = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在更新调度表数据时,我们有一个整体的帧数据指令集合,但是这些帧数据集合,分属于不同的调度表,
|
||||
/// 这个在开始时生成整体的帧数据指令集合才会把这个MsgIndex分配上,这个不需要保存到数据库中,对接使用
|
||||
/// </summary>
|
||||
public int MsgIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 程序的ID
|
||||
/// </summary>
|
||||
public long CanLinConfigProId { get; set; }
|
||||
|
||||
|
||||
private CanLinConfigPro _CanLinConfigPro;
|
||||
/// <summary>
|
||||
/// 所属的程序
|
||||
/// </summary>
|
||||
public CanLinConfigPro CanLinConfigPro
|
||||
{
|
||||
get { return _CanLinConfigPro; }
|
||||
set { _CanLinConfigPro = value; RaisePropertyChanged(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,6 +577,8 @@ namespace CapMachine.Wpf.LinDrive
|
||||
// 严重延迟,重新校准
|
||||
NextExecutionTime = Stopwatcher.ElapsedTicks;
|
||||
Console.WriteLine("定时发送延迟过大,重新校准时间");
|
||||
|
||||
LoggerService.Info("定时发送延迟过大,重新校准时间");
|
||||
}
|
||||
|
||||
// 使用Stopwatch记录实际的执行间隔,而不是DateTime
|
||||
@@ -585,7 +587,6 @@ namespace CapMachine.Wpf.LinDrive
|
||||
|
||||
//Console.WriteLine($"--当前时间(毫秒): {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}");
|
||||
|
||||
|
||||
// 执行发送CAN逻辑
|
||||
{
|
||||
|
||||
|
||||
14
CapMachine.Wpf/MapperProfile/CANScheduleConfigProfile.cs
Normal file
14
CapMachine.Wpf/MapperProfile/CANScheduleConfigProfile.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using AutoMapper;
|
||||
using CapMachine.Model.CANLIN;
|
||||
using CapMachine.Wpf.Dtos;
|
||||
|
||||
namespace CapMachine.Wpf.MapperProfile
|
||||
{
|
||||
public class CANScheduleConfigProfile : Profile
|
||||
{
|
||||
public CANScheduleConfigProfile()
|
||||
{
|
||||
CreateMap<CANScheduleConfig, CANScheduleConfigDto>().ReverseMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using CapMachine.Model.CANLIN;
|
||||
using CapMachine.Wpf.CanDrive;
|
||||
using CapMachine.Wpf.Dtos;
|
||||
using ImTools;
|
||||
using Prism.Ioc;
|
||||
using Prism.Mvvm;
|
||||
@@ -126,6 +127,11 @@ namespace CapMachine.Wpf.Services
|
||||
/// </summary>
|
||||
public List<CanCmdData> CmdData { get; set; } = new List<CanCmdData>();
|
||||
|
||||
/// <summary>
|
||||
/// CNA 调度表的配置信息
|
||||
/// </summary>
|
||||
public List<CANScheduleConfigDto> ListCANScheduleConfig { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 增加发送的指令数据
|
||||
/// </summary>
|
||||
@@ -307,10 +313,39 @@ namespace CapMachine.Wpf.Services
|
||||
{
|
||||
if (CmdData.Count > 0)
|
||||
{
|
||||
ToomossCanDrive.IsCycleSend = true;
|
||||
|
||||
ToomossCanDrive.CmdData = CmdData;
|
||||
//ToomossCanDrive.StartCycleSendMsg();
|
||||
ToomossCanDrive.StartPrecisionCycleSendMsg();
|
||||
ToomossCanDrive.SchEnable = true;
|
||||
|
||||
if (ToomossCanDrive.SchEnable)
|
||||
{
|
||||
|
||||
//使用调度表的话,需要在调度表中配置信息后才可以进行操作
|
||||
var GroupMsg = ToomossCanDrive.CmdData.GroupBy(a => a.MsgName).ToList();
|
||||
foreach (var itemMsg in GroupMsg)
|
||||
{
|
||||
if (!ListCANScheduleConfig.ToList().Any(a => a.MsgName == itemMsg.Key))
|
||||
{
|
||||
System.Windows.MessageBox.Show($"你使能了调度表,但是调度表中没有设置【{itemMsg.Key}】信息,请设置后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ListCANScheduleConfig == null && ListCANScheduleConfig!.Count() == 0)
|
||||
{
|
||||
System.Windows.MessageBox.Show("调度表配置为空数据,请检查!将无法发送数据", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
||||
return;
|
||||
}
|
||||
ToomossCanDrive.ListCANScheduleConfig = ListCANScheduleConfig!;
|
||||
ToomossCanDrive.StartSchedule();
|
||||
ToomossCanDrive.StartCycleUpdateCmd();
|
||||
}
|
||||
else
|
||||
{
|
||||
ToomossCanDrive.StartCycleSendMsg();
|
||||
}
|
||||
|
||||
ToomossCanDrive.IsCycleSend = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -319,7 +354,15 @@ namespace CapMachine.Wpf.Services
|
||||
}
|
||||
else
|
||||
{
|
||||
ToomossCanDrive.IsCycleSend = false;
|
||||
if (ToomossCanDrive.SchEnable)
|
||||
{
|
||||
ToomossCanDrive.IsCycleSend = false;
|
||||
ToomossCanDrive.StopSchedule();
|
||||
}
|
||||
else
|
||||
{
|
||||
ToomossCanDrive.IsCycleSend = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -388,7 +431,7 @@ namespace CapMachine.Wpf.Services
|
||||
//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 0;
|
||||
}
|
||||
|
||||
@@ -182,6 +182,7 @@ namespace CapMachine.Wpf.ViewModels
|
||||
canLinConfigPros = FreeSql.Select<CanLinConfigPro>().Where(a => a.CANLINInfo == CANLIN.CAN)
|
||||
.Include(a => a.CANConfigExd)
|
||||
.IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))//,then=> then.Include(b=>b.LogicRule) //.IncludeMany(a => a.CanLinConfigContents)
|
||||
.IncludeMany(a => a.CanScheduleConfigs)//
|
||||
.ToList();
|
||||
|
||||
ListCanLinConfigPro = new ObservableCollection<CanLinConfigPro>(canLinConfigPros);
|
||||
@@ -225,6 +226,12 @@ namespace CapMachine.Wpf.ViewModels
|
||||
{
|
||||
ListReadCanLinRWConfigDto = new ObservableCollection<CanLinRWConfigDto>(Mapper.Map<List<CanLinRWConfigDto>>(ReadData));
|
||||
}
|
||||
//调度表配置信息
|
||||
if (SelectCanLinConfigPro.CanScheduleConfigs != null && SelectCanLinConfigPro.CanScheduleConfigs.Count() > 0)
|
||||
{
|
||||
ListCANScheduleConfigDto = new ObservableCollection<CANScheduleConfigDto>(Mapper.Map<List<CANScheduleConfigDto>>(SelectCanLinConfigPro.CanScheduleConfigs));
|
||||
}
|
||||
|
||||
|
||||
//匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListCanDbcModel
|
||||
MatchSeletedAndCanDbcModel();
|
||||
@@ -584,6 +591,17 @@ namespace CapMachine.Wpf.ViewModels
|
||||
|
||||
SelectCanLinConfigProConfigName = SelectCanLinConfigPro.ConfigName;
|
||||
|
||||
//调度表配置信息
|
||||
if (SelectCanLinConfigPro.CanScheduleConfigs != null && SelectCanLinConfigPro.CanScheduleConfigs.Count() > 0)
|
||||
{
|
||||
ListCANScheduleConfigDto = new ObservableCollection<CANScheduleConfigDto>(Mapper.Map<List<CANScheduleConfigDto>>(SelectCanLinConfigPro.CanScheduleConfigs));
|
||||
}
|
||||
else
|
||||
{
|
||||
ListCANScheduleConfigDto = new ObservableCollection<CANScheduleConfigDto>();
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
//先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件
|
||||
@@ -868,7 +886,7 @@ namespace CapMachine.Wpf.ViewModels
|
||||
|
||||
private ObservableCollection<CbxItems> _DataBaudRateCbxItems;
|
||||
/// <summary>
|
||||
/// CAN FD 数据波特率
|
||||
/// CAN 数据波特率
|
||||
/// </summary>
|
||||
public ObservableCollection<CbxItems> DataBaudRateCbxItems
|
||||
{
|
||||
@@ -876,6 +894,47 @@ namespace CapMachine.Wpf.ViewModels
|
||||
set { _DataBaudRateCbxItems = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private DelegateCommand<object> _SchEnableCmd;
|
||||
/// <summary>
|
||||
/// 调度表的使能 操作的指令
|
||||
/// </summary>
|
||||
public DelegateCommand<object> SchEnableCmd
|
||||
{
|
||||
set
|
||||
{
|
||||
_SchEnableCmd = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (_SchEnableCmd == null)
|
||||
{
|
||||
_SchEnableCmd = new DelegateCommand<object>((Par) => SchEnableCmdCall(Par));
|
||||
}
|
||||
return _SchEnableCmd;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 调度表的使能信息
|
||||
/// </summary>
|
||||
/// <param name="par"></param>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void SchEnableCmdCall(object par)
|
||||
{
|
||||
var dd = SelectedCANConfigExdDto.SchEnable;
|
||||
var Result = (bool)par;
|
||||
if (Result)
|
||||
{
|
||||
CanDriveService.ToomossCanDrive.SchEnable = true;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
CanDriveService.ToomossCanDrive.SchEnable = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private DelegateCommand<string> _CanOpCmd;
|
||||
/// <summary>
|
||||
/// CAN操作的指令
|
||||
@@ -963,6 +1022,7 @@ namespace CapMachine.Wpf.ViewModels
|
||||
.Set(a => a.DbcPath, SelectedCANConfigExdDto.DbcPath)
|
||||
.Set(a => a.Cycle, SelectedCANConfigExdDto.Cycle)
|
||||
.Set(a => a.BaudRate, SelectedCANConfigExdDto.BaudRate)
|
||||
.Set(a => a.SchEnable, SelectedCANConfigExdDto.SchEnable)
|
||||
.Where(a => a.Id == SelectedCANConfigExdDto.Id)
|
||||
.ExecuteUpdated();
|
||||
}
|
||||
@@ -1024,7 +1084,12 @@ namespace CapMachine.Wpf.ViewModels
|
||||
|
||||
break;
|
||||
case "CycleSend"://循环发送你
|
||||
//循环发送数据
|
||||
|
||||
//有可能加载完毕后不手动改变状态,导致值没有传输,所以这里赋值
|
||||
CanDriveService.ToomossCanDrive.SchEnable = SelectedCANConfigExdDto.SchEnable;
|
||||
//无论有没有调度表,都要把这个配置给CanDriveService
|
||||
CanDriveService.ListCANScheduleConfig = ListCANScheduleConfigDto.ToList();
|
||||
|
||||
CanDriveService.CycleSendMsg();
|
||||
|
||||
//Listen
|
||||
@@ -1099,6 +1164,17 @@ namespace CapMachine.Wpf.ViewModels
|
||||
}
|
||||
|
||||
|
||||
private ObservableCollection<CANScheduleConfigDto> _ListCANScheduleConfigDto;
|
||||
/// <summary>
|
||||
///调度表集合
|
||||
/// </summary>
|
||||
public ObservableCollection<CANScheduleConfigDto> ListCANScheduleConfigDto
|
||||
{
|
||||
get { return _ListCANScheduleConfigDto; }
|
||||
set { _ListCANScheduleConfigDto = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
|
||||
//private string _SelectedWriteName;
|
||||
///// <summary>
|
||||
///// 选中的写入的Name
|
||||
@@ -1244,6 +1320,44 @@ namespace CapMachine.Wpf.ViewModels
|
||||
System.Windows.MessageBox.Show("请选中后再进行【删除】操作?", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
||||
}
|
||||
|
||||
break;
|
||||
case "WriteSch"://调度表
|
||||
|
||||
var data = CanDriveService.CmdData.GroupBy(a => a.MsgName).Select(a => a.Key).ToList();
|
||||
|
||||
if (data != null && data.Count > 0)
|
||||
{
|
||||
//弹窗
|
||||
DialogService.ShowDialog("DialogCANSchConfigView", new DialogParameters() {
|
||||
{"ListMsg", CanDriveService.CmdData.GroupBy(a=>a.MsgName).Select(a=>a.Key).ToList() },
|
||||
{ "ListCANScheduleConfigDto",ListCANScheduleConfigDto},
|
||||
{ "SelectCanLinConfigProId",SelectCanLinConfigPro.Id},
|
||||
|
||||
}, (par) =>
|
||||
{
|
||||
if (par.Result == ButtonResult.OK)
|
||||
{
|
||||
////程序名称
|
||||
ListCANScheduleConfigDto = par.Parameters.GetValue<ObservableCollection<CANScheduleConfigDto>>("ReturnValue");
|
||||
//把更新后的最新值给当前的主集合中
|
||||
SelectCanLinConfigPro.CanScheduleConfigs = Mapper.Map<List<CANScheduleConfig>>(ListCANScheduleConfigDto.ToList());
|
||||
|
||||
}
|
||||
else if (par.Result == ButtonResult.Cancel)
|
||||
{
|
||||
//取消
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
System.Windows.MessageBox.Show("未发现写入的执行的命令数据,无法配置?", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
|
||||
}
|
||||
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
356
CapMachine.Wpf/ViewModels/DialogCANSchConfigViewModel.cs
Normal file
356
CapMachine.Wpf/ViewModels/DialogCANSchConfigViewModel.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
using AutoMapper;
|
||||
using CapMachine.Core;
|
||||
using CapMachine.Model;
|
||||
using CapMachine.Model.CANLIN;
|
||||
using CapMachine.Wpf.Dtos;
|
||||
using CapMachine.Wpf.Services;
|
||||
using Prism.Commands;
|
||||
using Prism.Services.Dialogs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace CapMachine.Wpf.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// CAN 调度表配置
|
||||
/// </summary>
|
||||
public class DialogCANSchConfigViewModel : DialogViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
public DialogCANSchConfigViewModel(IFreeSql freeSql, IMapper mapper)
|
||||
{
|
||||
Title = "调度表 CAN 配置";
|
||||
FreeSql = freeSql;
|
||||
Mapper = mapper;
|
||||
|
||||
|
||||
SendOrderCbxItems = new ObservableCollection<CbxItems>()
|
||||
{
|
||||
new CbxItems(){
|
||||
Key="0",
|
||||
Text="并行",
|
||||
},
|
||||
new CbxItems(){
|
||||
Key="1",
|
||||
Text="顺序",
|
||||
},
|
||||
};
|
||||
|
||||
SchTabIndexCbxItems = new ObservableCollection<CbxItems>()
|
||||
{
|
||||
new CbxItems(){
|
||||
Key="0",
|
||||
Text="0",
|
||||
},
|
||||
new CbxItems(){
|
||||
Key="1",
|
||||
Text="1",
|
||||
},
|
||||
new CbxItems(){
|
||||
Key="2",
|
||||
Text="2",
|
||||
},
|
||||
new CbxItems(){
|
||||
Key="3",
|
||||
Text="3",
|
||||
},
|
||||
new CbxItems(){
|
||||
Key="4",
|
||||
Text="4",
|
||||
},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public IFreeSql FreeSql { get; }
|
||||
public IMapper Mapper { get; }
|
||||
|
||||
private string name;
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
set { name = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private ObservableCollection<CANScheduleConfigDto> _ListCANScheduleConfigDto = new ObservableCollection<CANScheduleConfigDto>();
|
||||
/// <summary>
|
||||
/// CAN 调度表数据集合
|
||||
/// </summary>
|
||||
public ObservableCollection<CANScheduleConfigDto> ListCANScheduleConfigDto
|
||||
{
|
||||
get { return _ListCANScheduleConfigDto; }
|
||||
set { _ListCANScheduleConfigDto = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 消息/帧报文信息集合
|
||||
/// </summary>
|
||||
public List<string> ListMsg { get; set; }
|
||||
|
||||
private ObservableCollection<CbxItems> _MsgCbxItems;
|
||||
/// <summary>
|
||||
/// 消息名称 集合信息
|
||||
/// </summary>
|
||||
public ObservableCollection<CbxItems> MsgCbxItems
|
||||
{
|
||||
get { return _MsgCbxItems; }
|
||||
set { _MsgCbxItems = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选中的程序的Id
|
||||
/// </summary>
|
||||
public long SelectCanLinConfigProId { get; set; }
|
||||
|
||||
private ObservableCollection<CbxItems> _SendOrderCbxItems;
|
||||
/// <summary>
|
||||
/// 发送方式 集合信息
|
||||
/// </summary>
|
||||
public ObservableCollection<CbxItems> SendOrderCbxItems
|
||||
{
|
||||
get { return _SendOrderCbxItems; }
|
||||
set { _SendOrderCbxItems = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
|
||||
private ObservableCollection<CbxItems> _SchTabIndexCbxItems;
|
||||
/// <summary>
|
||||
/// 调度器序号 集合信息
|
||||
/// </summary>
|
||||
public ObservableCollection<CbxItems> SchTabIndexCbxItems
|
||||
{
|
||||
get { return _SchTabIndexCbxItems; }
|
||||
set { _SchTabIndexCbxItems = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
private CANScheduleConfigDto _CurSelectedItem;
|
||||
/// <summary>
|
||||
/// 选中的数据
|
||||
/// </summary>
|
||||
public CANScheduleConfigDto CurSelectedItem
|
||||
{
|
||||
get { return _CurSelectedItem; }
|
||||
set { _CurSelectedItem = value; RaisePropertyChanged(); }
|
||||
}
|
||||
|
||||
|
||||
private DelegateCommand<object> _GridSelectionChangedCmd;
|
||||
/// <summary>
|
||||
/// 选中行数据命令
|
||||
/// </summary>
|
||||
public DelegateCommand<object> GridSelectionChangedCmd
|
||||
{
|
||||
set
|
||||
{
|
||||
_GridSelectionChangedCmd = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (_GridSelectionChangedCmd == null)
|
||||
{
|
||||
_GridSelectionChangedCmd = new DelegateCommand<object>((par) => GridSelectionChangedCmdMethod(par));
|
||||
}
|
||||
return _GridSelectionChangedCmd;
|
||||
}
|
||||
}
|
||||
private void GridSelectionChangedCmdMethod(object par)
|
||||
{
|
||||
//先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件
|
||||
var Selecteddata = par as CANScheduleConfigDto;
|
||||
|
||||
if (Selecteddata != null)
|
||||
{
|
||||
CurSelectedItem = Selecteddata;
|
||||
}
|
||||
}
|
||||
|
||||
//OpCmd
|
||||
private DelegateCommand<string> _OpCmd;
|
||||
/// <summary>
|
||||
/// 增加方法命令
|
||||
/// </summary>
|
||||
public DelegateCommand<string> OpCmd
|
||||
{
|
||||
set
|
||||
{
|
||||
_OpCmd = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (_OpCmd == null)
|
||||
{
|
||||
_OpCmd = new DelegateCommand<string>((Par) => OpCmdCall(Par));
|
||||
}
|
||||
return _OpCmd;
|
||||
}
|
||||
}
|
||||
|
||||
private void OpCmdCall(string Par)
|
||||
{
|
||||
switch (Par)
|
||||
{
|
||||
case "Add":
|
||||
ListCANScheduleConfigDto.Add(new CANScheduleConfigDto
|
||||
{
|
||||
CanLinConfigProId = SelectCanLinConfigProId,
|
||||
Cycle = 100,
|
||||
SchTabIndex = 0,
|
||||
OrderSend = 1,
|
||||
});
|
||||
break;
|
||||
case "Delete":
|
||||
if (CurSelectedItem != null)
|
||||
{
|
||||
//直接删除掉,如果没有ID的话,这就不需要删除了
|
||||
FreeSql.Delete<CANScheduleConfig>(CurSelectedItem.Id).ExecuteAffrows();
|
||||
ListCANScheduleConfigDto.Remove(CurSelectedItem);
|
||||
|
||||
CurSelectedItem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("请选中后再进行【删除】操作?", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private DelegateCommand saveCmd;
|
||||
/// <summary>
|
||||
/// 保存命令
|
||||
/// </summary>
|
||||
public DelegateCommand SaveCmd
|
||||
{
|
||||
set
|
||||
{
|
||||
saveCmd = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (saveCmd == null)
|
||||
{
|
||||
saveCmd = new DelegateCommand(() => SaveCmdMethod());
|
||||
}
|
||||
return saveCmd;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存命令方法
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void SaveCmdMethod()
|
||||
{
|
||||
//检查空的数据
|
||||
foreach (var item in ListCANScheduleConfigDto)
|
||||
{
|
||||
if (string.IsNullOrEmpty(item.MsgName))
|
||||
{
|
||||
MessageBox.Show("请确认消息名称是否正确", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
|
||||
return;
|
||||
}
|
||||
if (item.Cycle == 0)
|
||||
{
|
||||
MessageBox.Show("请确认周期是否正确", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
|
||||
return;
|
||||
}
|
||||
if (item.OrderSend >= 2)
|
||||
{
|
||||
MessageBox.Show("请确认发送方式是否正确", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
|
||||
return;
|
||||
}
|
||||
}
|
||||
//检查重复设置问题
|
||||
bool isRepeat = ListCANScheduleConfigDto.GroupBy(i => i.MsgName).Any(g => g.Count() > 1);
|
||||
if (isRepeat)
|
||||
{
|
||||
MessageBox.Show("请确认是否重复设置", "提示", MessageBoxButton.OK, MessageBoxImage.Hand);
|
||||
return;
|
||||
}
|
||||
|
||||
//检查数据是否正常
|
||||
foreach (var item in ListCANScheduleConfigDto)
|
||||
{
|
||||
FreeSql.InsertOrUpdate<CANScheduleConfig>()
|
||||
.SetSource(Mapper.Map<CANScheduleConfig>(item)).
|
||||
ExecuteAffrows();
|
||||
}
|
||||
|
||||
ListCANScheduleConfigDto = new ObservableCollection<CANScheduleConfigDto>(Mapper.Map<List<CANScheduleConfigDto>>(FreeSql.Select<CANScheduleConfig>().Where(a => a.CanLinConfigProId == SelectCanLinConfigProId).ToList()));
|
||||
|
||||
DialogParameters pars = new DialogParameters
|
||||
{
|
||||
{ "ReturnValue", ListCANScheduleConfigDto }
|
||||
};
|
||||
|
||||
RaiseRequestClose(new DialogResult(ButtonResult.OK, pars));
|
||||
}
|
||||
|
||||
private DelegateCommand cancelCmd;
|
||||
/// <summary>
|
||||
/// 保存命令
|
||||
/// </summary>
|
||||
public DelegateCommand CancelCmd
|
||||
{
|
||||
set
|
||||
{
|
||||
cancelCmd = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (cancelCmd == null)
|
||||
{
|
||||
cancelCmd = new DelegateCommand(() => CancelCmdMethod());
|
||||
}
|
||||
return cancelCmd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 取消命令方法
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private void CancelCmdMethod()
|
||||
{
|
||||
RaiseRequestClose(new DialogResult(ButtonResult.Cancel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口打开时的传递的参数
|
||||
/// </summary>
|
||||
/// <param name="parameters"></param>
|
||||
public override void OnDialogOpened(IDialogParameters parameters)
|
||||
{
|
||||
ListMsg = parameters.GetValue<List<string>>("ListMsg");
|
||||
// 转换为CbxItems集合,都是文本内容
|
||||
MsgCbxItems = new ObservableCollection<CbxItems>(
|
||||
ListMsg.Select(value => new CbxItems
|
||||
{
|
||||
Key = value,
|
||||
Text = value
|
||||
}));
|
||||
|
||||
ListCANScheduleConfigDto = parameters.GetValue<ObservableCollection<CANScheduleConfigDto>>("ListCANScheduleConfigDto");
|
||||
//防止返回的数据为空,就无法增加了
|
||||
if (ListCANScheduleConfigDto == null) ListCANScheduleConfigDto = new ObservableCollection<CANScheduleConfigDto>();
|
||||
//Name = parameters.GetValue<string>("Name");
|
||||
|
||||
SelectCanLinConfigProId = parameters.GetValue<long>("SelectCanLinConfigProId");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -584,10 +584,10 @@
|
||||
<StackPanel
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="-10,0"
|
||||
Margin="-20,0"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,10,0"
|
||||
Margin="0,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="/Assets/Fonts/#iconfont"
|
||||
FontSize="20"
|
||||
@@ -598,7 +598,7 @@
|
||||
Text="报文状态:" />
|
||||
|
||||
<Border
|
||||
Margin="5,12"
|
||||
Margin="0,12"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5">
|
||||
<Border.Style>
|
||||
@@ -620,7 +620,7 @@
|
||||
</Border>
|
||||
|
||||
<Border
|
||||
Margin="10,12"
|
||||
Margin="2,12"
|
||||
BorderThickness="1"
|
||||
CornerRadius="5">
|
||||
<Border.Style>
|
||||
@@ -641,6 +641,25 @@
|
||||
Text="接收" />
|
||||
</Border>
|
||||
|
||||
<TextBlock
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="/Assets/Fonts/#iconfont"
|
||||
FontSize="20"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
Width="90"
|
||||
Style="{StaticResource TextBlockStyle}"
|
||||
Text="启用调度表:" />
|
||||
<ToggleButton
|
||||
Width="40"
|
||||
Margin="5,2"
|
||||
Command="{Binding SchEnableCmd}"
|
||||
CommandParameter="{Binding SelectedCANConfigExdDto.SchEnable}"
|
||||
IsChecked="{Binding SelectedCANConfigExdDto.SchEnable}"
|
||||
Style="{StaticResource MaterialDesignSwitchToggleButton}"
|
||||
ToolTip="启用调度表" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
@@ -701,6 +720,24 @@
|
||||
Margin="0,0,15,0"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Command="{Binding WriteCmd}"
|
||||
CommandParameter="WriteSch"
|
||||
Foreground="White">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="2,0"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="/Assets/Fonts/#iconfont"
|
||||
FontSize="18"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="调度表" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<Button
|
||||
Margin="5,0"
|
||||
Command="{Binding WriteCmd}"
|
||||
|
||||
180
CapMachine.Wpf/Views/DialogCANSchConfigView.xaml
Normal file
180
CapMachine.Wpf/Views/DialogCANSchConfigView.xaml
Normal file
@@ -0,0 +1,180 @@
|
||||
<UserControl
|
||||
x:Class="CapMachine.Wpf.Views.DialogCANSchConfigView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:local="clr-namespace:CapMachine.Wpf.Views"
|
||||
xmlns:localEx="clr-namespace:CapMachine.Wpf"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
Width="1000"
|
||||
Height="800"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<localEx:BindingProxy x:Key="Proxy" Data="{Binding}" />
|
||||
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
|
||||
<Setter Property="FontSize" Value="24" />
|
||||
<Setter Property="Width" Value="218" />
|
||||
</Style>
|
||||
<Style x:Key="myHeaderStyle1" TargetType="{x:Type GridViewColumnHeader}">
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="60" />
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="10,0"
|
||||
Command="{Binding OpCmd}"
|
||||
CommandParameter="Add"
|
||||
FontWeight="Bold"
|
||||
Foreground="#404040"
|
||||
Style="{StaticResource MaterialDesignFlatAccentBgButton}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="/Assets/Fonts/#iconfont"
|
||||
FontSize="14"
|
||||
Foreground="#404040"
|
||||
Text=" " />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="新增" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
<!--<Button
|
||||
Margin="10,0"
|
||||
Command="{Binding CopyCmd}"
|
||||
FontWeight="Bold"
|
||||
Foreground="#404040"
|
||||
Style="{StaticResource MaterialDesignFlatAccentBgButton}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="/Assets/Fonts/#iconfont"
|
||||
FontSize="14"
|
||||
Foreground="#404040"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="复制" />
|
||||
</StackPanel>
|
||||
</Button>-->
|
||||
<Button
|
||||
Margin="10,0"
|
||||
Command="{Binding OpCmd}"
|
||||
CommandParameter="Delete"
|
||||
FontWeight="Bold"
|
||||
Foreground="#404040"
|
||||
Style="{StaticResource MaterialDesignFlatAccentBgButton}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="/Assets/Fonts/#iconfont"
|
||||
FontSize="14"
|
||||
Foreground="#404040"
|
||||
Text="" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="14"
|
||||
Text="删除" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<DataGrid
|
||||
x:Name="MainDatagrid"
|
||||
Margin="5"
|
||||
AutoGenerateColumns="False"
|
||||
CanUserAddRows="False"
|
||||
HeadersVisibility="Column"
|
||||
ItemsSource="{Binding ListCANScheduleConfigDto}"
|
||||
SelectionMode="Extended"
|
||||
SelectionUnit="FullRow">
|
||||
<DataGrid.Columns>
|
||||
<!--<DataGridTextColumn
|
||||
Binding="{Binding Index}"
|
||||
Header="序号"
|
||||
IsReadOnly="True" />-->
|
||||
|
||||
<DataGridTemplateColumn Width="260" Header="消息名">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<ComboBox
|
||||
DisplayMemberPath="Text"
|
||||
ItemsSource="{Binding Source={StaticResource Proxy}, Path=Data.MsgCbxItems}"
|
||||
SelectedValue="{Binding MsgName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Key" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTextColumn
|
||||
Width="100"
|
||||
Binding="{Binding Cycle}"
|
||||
Header="周期" />
|
||||
|
||||
<DataGridTemplateColumn Width="200" Header="发送方式">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<ComboBox
|
||||
DisplayMemberPath="Text"
|
||||
ItemsSource="{Binding Source={StaticResource Proxy}, Path=Data.SendOrderCbxItems}"
|
||||
SelectedValue="{Binding OrderSend, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Key" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
|
||||
<DataGridTemplateColumn Width="160" Header="调度器序号">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<ComboBox
|
||||
DisplayMemberPath="Text"
|
||||
ItemsSource="{Binding Source={StaticResource Proxy}, Path=Data.SchTabIndexCbxItems}"
|
||||
SelectedValue="{Binding SchTabIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
SelectedValuePath="Key" />
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
<!--<DataGridCheckBoxColumn Binding="{Binding IsEnable}" Header="是否启用" />-->
|
||||
</DataGrid.Columns>
|
||||
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="SelectionChanged">
|
||||
<prism:InvokeCommandAction Command="{Binding GridSelectionChangedCmd}" CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="10,10"
|
||||
Command="{Binding SaveCmd}"
|
||||
Content="确定"
|
||||
Foreground="White" />
|
||||
<Button
|
||||
Margin="10,0"
|
||||
Command="{Binding CancelCmd}"
|
||||
Content="取消"
|
||||
Foreground="White" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
CapMachine.Wpf/Views/DialogCANSchConfigView.xaml.cs
Normal file
28
CapMachine.Wpf/Views/DialogCANSchConfigView.xaml.cs
Normal file
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// DialogCANSchConfigView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class DialogCANSchConfigView : UserControl
|
||||
{
|
||||
public DialogCANSchConfigView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user