diff --git a/CapMachine.Model/CANLIN/CanLinConfigPro.cs b/CapMachine.Model/CANLIN/CanLinConfigPro.cs index eb5521d..48f1f48 100644 --- a/CapMachine.Model/CANLIN/CanLinConfigPro.cs +++ b/CapMachine.Model/CANLIN/CanLinConfigPro.cs @@ -50,6 +50,12 @@ namespace CapMachine.Model.CANLIN ///CAN 的调度表配置模式 public List? CanScheduleConfigs { get; set; } + /// + /// ///////////////////////////////////////////导航属性/////////////////////////////////////////////////////// + /// + ///LIN 的调度表配置模式 + public List? LinScheduleConfigs { get; set; } + /// /// ///////////////////////////////////////////导航属性 LIN 一对一/////////////////////////////////////////////////////// diff --git a/CapMachine.Model/CANLIN/LINConfigExd.cs b/CapMachine.Model/CANLIN/LINConfigExd.cs index f681e0e..6120577 100644 --- a/CapMachine.Model/CANLIN/LINConfigExd.cs +++ b/CapMachine.Model/CANLIN/LINConfigExd.cs @@ -31,5 +31,12 @@ namespace CapMachine.Model.CANLIN /// [Column(Name = "LdfPath", IsNullable = false, StringLength = 500)] public string? LdfPath { get; set; } + + + /// + /// 调度表是否启用 + /// + [Column(Name = "SchEnable")] + public bool SchEnable { get; set; } } } diff --git a/CapMachine.Model/CANLIN/LINScheduleConfig.cs b/CapMachine.Model/CANLIN/LINScheduleConfig.cs new file mode 100644 index 0000000..496ea73 --- /dev/null +++ b/CapMachine.Model/CANLIN/LINScheduleConfig.cs @@ -0,0 +1,53 @@ +using FreeSql.DataAnnotations; + +namespace CapMachine.Model.CANLIN +{ + /// + /// 调度表的配置 + /// 其实这些调度表是在DBC中有的,但是图莫斯的驱动没有读取到这些信息 + /// 那么我们在系统层面进行操作和保存这些信息 + /// + [Table(Name = "LINScheduleConfig")] + public class LINScheduleConfig + { + /// + /// 主键 + /// + [Column(IsPrimary = true, IsIdentity = true)] + public long Id { get; set; } + + /// + /// 消息名称 + /// + [Column(Name = "MsgName")] + public string? MsgName { get; set; } + + /// + /// 消息的周期 + /// + [Column(Name = "Cycle")] + public int Cycle { get; set; } + + /// + /// 调度表的Index + /// LDF中可能有多个调度器 + /// + [Column(Name = "SchTabIndex")] + public int SchTabIndex { get; set; } + + /// + /// 调度表的名称 + /// LDF中可能有多个调度器名称 + /// + [Column(Name = "SchTabName")] + public int SchTabName { get; set; } + + + /// + /// ///////////////////////////////////////////导航属性/////////////////////////////////////////////////////// + /// + + public long CanLinConfigProId { get; set; } + public CanLinConfigPro? CanLinConfigPro { get; set; } + } +} diff --git a/CapMachine.Wpf/App.xaml.cs b/CapMachine.Wpf/App.xaml.cs index 4037639..7fa6444 100644 --- a/CapMachine.Wpf/App.xaml.cs +++ b/CapMachine.Wpf/App.xaml.cs @@ -201,6 +201,7 @@ namespace CapMachine.Wpf containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/CapMachine.Wpf/CapMachine.Wpf.csproj b/CapMachine.Wpf/CapMachine.Wpf.csproj index 38d28f8..16f359b 100644 --- a/CapMachine.Wpf/CapMachine.Wpf.csproj +++ b/CapMachine.Wpf/CapMachine.Wpf.csproj @@ -1,7 +1,7 @@  - WinExe + Exe net6.0-windows enable enable diff --git a/CapMachine.Wpf/Dtos/LINConfigExdDto.cs b/CapMachine.Wpf/Dtos/LINConfigExdDto.cs index 8288ac9..57c1b19 100644 --- a/CapMachine.Wpf/Dtos/LINConfigExdDto.cs +++ b/CapMachine.Wpf/Dtos/LINConfigExdDto.cs @@ -43,5 +43,16 @@ namespace CapMachine.Wpf.Dtos get { return _LdfPath; } set { _LdfPath = value; RaisePropertyChanged(); } } + + private bool _SchEnable; + /// + /// 调度表是否启用 + /// + public bool SchEnable + { + get { return _SchEnable; } + set { _SchEnable = value; RaisePropertyChanged(); } + } + } } diff --git a/CapMachine.Wpf/Dtos/LINScheduleConfigDto.cs b/CapMachine.Wpf/Dtos/LINScheduleConfigDto.cs new file mode 100644 index 0000000..2630129 --- /dev/null +++ b/CapMachine.Wpf/Dtos/LINScheduleConfigDto.cs @@ -0,0 +1,82 @@ +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 +{ + public class LINScheduleConfigDto : BindableBase + { + /// + /// 主键 + /// + public long Id { get; set; } + + private string? _MsgName; + /// + /// 消息名称/帧名称 + /// + public string? MsgName + { + get { return _MsgName; } + set { _MsgName = value; RaisePropertyChanged(); } + } + + private int _Cycle; + /// + /// 周期 + /// + public int Cycle + { + get { return _Cycle; } + set { _Cycle = value; RaisePropertyChanged(); } + } + + + private int _SchTabIndex; + /// + /// 调度表的Index序列 + /// + public int SchTabIndex + { + get { return _SchTabIndex; } + set { _SchTabIndex = value; RaisePropertyChanged(); } + } + + private string? _SchTabName; + /// + /// 调度表的名称 + /// + public string? SchTabName + { + get { return _SchTabName; } + set { _SchTabName = value; RaisePropertyChanged(); } + } + + + /// + /// 在更新调度表数据时,我们有一个整体的帧数据指令集合,但是这些帧数据集合,分属于不同的调度表, + /// 这个在开始时生成整体的帧数据指令集合才会把这个MsgIndex分配上,这个不需要保存到数据库中,对接使用 + /// + public int MsgIndex { get; set; } + + /// + /// 程序的ID + /// + public long CanLinConfigProId { get; set; } + + + private CanLinConfigPro _CanLinConfigPro; + /// + /// 所属的程序 + /// + public CanLinConfigPro CanLinConfigPro + { + get { return _CanLinConfigPro; } + set { _CanLinConfigPro = value; RaisePropertyChanged(); } + } + } +} diff --git a/CapMachine.Wpf/LinDrive/LDFParser.cs b/CapMachine.Wpf/LinDrive/LDFParser.cs index 3334e7f..2f53829 100644 --- a/CapMachine.Wpf/LinDrive/LDFParser.cs +++ b/CapMachine.Wpf/LinDrive/LDFParser.cs @@ -68,6 +68,15 @@ namespace CapMachine.Wpf.LinDrive [DllImport("USB2XXX.dll")] public static extern Int32 LDF_ExeFrameToBus(UInt64 LDFHandle, StringBuilder pFrameName, byte FillBitValue); [DllImport("USB2XXX.dll")] - public static extern Int32 LDF_ExeSchToBus(UInt64 LDFHandle, StringBuilder pSchName, byte FillBitValue); + public static extern Int32 LDF_ExeSchToBus(UInt64 LDFHandle, StringBuilder pSchName, byte FillBitValue); + + [DllImport("USB2XXX.dll")] + public static extern Int32 LDF_SetSchToTable(UInt64 LDFHandle, StringBuilder pSchName, byte FillBitValue); + [DllImport("USB2XXX.dll")] + public static extern Int32 LDF_GetRawMsg(UInt64 LDFHandle, IntPtr pLINMsg, int BufferSize); + [DllImport("USB2XXX.dll")] + public static extern Int32 LDF_StopSchTable(UInt64 LDFHandle); + [DllImport("USB2XXX.dll")] + public static extern Int32 LDF_Release(UInt64 LDFHandle); } } diff --git a/CapMachine.Wpf/LinDrive/ToomossLin.cs b/CapMachine.Wpf/LinDrive/ToomossLin.cs index 0f16459..d325d5b 100644 --- a/CapMachine.Wpf/LinDrive/ToomossLin.cs +++ b/CapMachine.Wpf/LinDrive/ToomossLin.cs @@ -57,7 +57,7 @@ namespace CapMachine.Wpf.LinDrive HighSpeedDataService = ContainerProvider.Resolve(); LoggerService = ContainerProvider.Resolve(); - + //Stopwatch.Frequency表示高精度计时器每秒的计数次数(ticks/秒)每毫秒的ticks数 = 每秒的ticks数 ÷ 1000 TicksPerMs = Stopwatch.Frequency / 1000.0; } @@ -378,7 +378,7 @@ namespace CapMachine.Wpf.LinDrive } - IsReviceOk= true; + IsReviceOk = true; //StringBuilder ValueStr = new StringBuilder(64); //LDFParser.LDF_ExeFrameToBus(LDFHandle, new StringBuilder("ID_DATA"), 1); @@ -614,7 +614,7 @@ namespace CapMachine.Wpf.LinDrive } } - IsSendOk=true; + IsSendOk = true; } } @@ -666,7 +666,61 @@ namespace CapMachine.Wpf.LinDrive #endregion + #region 调度器发送报文 + private bool _SchEnable; + /// + /// 调度表使能 + /// + public bool SchEnable + { + get { return _SchEnable; } + set + { + _SchEnable = value; + RaisePropertyChanged(); + } + } + + /// + /// 调度表数量 + /// + public int SchCount { get; set; } + + + /// + /// 获取调度表数量 + /// + /// + public int GetSchCount() + { + SchCount = LDFParser.LDF_GetSchQuantity(LDFHandle); + return SchCount; + } + + + + public void LinTest() + { + GetSchCount(); + + for (int i = 0; i < SchCount; i++) + { + StringBuilder pSchName = new StringBuilder(); + var Ret = LDFParser.LDF_GetSchName(LDFHandle, i, pSchName); + if (Ret <= 0) + { + Console.WriteLine($"{pSchName.ToString()}"); + } + else + { + Console.WriteLine("执行失败"); + } + } + + } + + #endregion /// /// 关闭设备 diff --git a/CapMachine.Wpf/MapperProfile/LINScheduleConfigProfile.cs b/CapMachine.Wpf/MapperProfile/LINScheduleConfigProfile.cs new file mode 100644 index 0000000..7654552 --- /dev/null +++ b/CapMachine.Wpf/MapperProfile/LINScheduleConfigProfile.cs @@ -0,0 +1,14 @@ +using AutoMapper; +using CapMachine.Model.CANLIN; +using CapMachine.Wpf.Dtos; + +namespace CapMachine.Wpf.MapperProfile +{ + public class LINScheduleConfigProfile : Profile + { + public LINScheduleConfigProfile() + { + CreateMap().ReverseMap(); + } + } +} diff --git a/CapMachine.Wpf/ViewModels/DialogLINSchConfigViewModel.cs b/CapMachine.Wpf/ViewModels/DialogLINSchConfigViewModel.cs new file mode 100644 index 0000000..9a407c0 --- /dev/null +++ b/CapMachine.Wpf/ViewModels/DialogLINSchConfigViewModel.cs @@ -0,0 +1,325 @@ +using AutoMapper; +using CapMachine.Core; +using CapMachine.Model.CANLIN; +using CapMachine.Wpf.Dtos; +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 +{ + public class DialogLINSchConfigViewModel:DialogViewModel + { + public DialogLINSchConfigViewModel(IFreeSql freeSql, IMapper mapper) + { + Title = "调度表 LIN 配置"; + FreeSql = freeSql; + Mapper = mapper; + + //默认只能用1号调度器 + SchTabIndexCbxItems = new ObservableCollection() + { + 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; + /// + /// 名称 + /// + public string Name + { + get { return name; } + set { name = value; RaisePropertyChanged(); } + } + + private ObservableCollection _ListLINScheduleConfigDto = new ObservableCollection(); + /// + /// LIN 调度表数据集合 + /// + public ObservableCollection ListLINScheduleConfigDto + { + get { return _ListLINScheduleConfigDto; } + set { _ListLINScheduleConfigDto = value; RaisePropertyChanged(); } + } + + /// + /// 消息/帧报文信息集合 + /// + public List ListMsg { get; set; } + + private ObservableCollection _MsgCbxItems; + /// + /// 消息名称 集合信息 + /// + public ObservableCollection MsgCbxItems + { + get { return _MsgCbxItems; } + set { _MsgCbxItems = value; RaisePropertyChanged(); } + } + + /// + /// 选中的程序的Id + /// + public long SelectCanLinConfigProId { get; set; } + + + private ObservableCollection _SchTabIndexCbxItems; + /// + /// 调度器序号 集合信息 + /// + public ObservableCollection SchTabIndexCbxItems + { + get { return _SchTabIndexCbxItems; } + set { _SchTabIndexCbxItems = value; RaisePropertyChanged(); } + } + + private LINScheduleConfigDto _CurSelectedItem; + /// + /// 选中的数据 + /// + public LINScheduleConfigDto CurSelectedItem + { + get { return _CurSelectedItem; } + set { _CurSelectedItem = value; RaisePropertyChanged(); } + } + + + private DelegateCommand _GridSelectionChangedCmd; + /// + /// 选中行数据命令 + /// + public DelegateCommand GridSelectionChangedCmd + { + set + { + _GridSelectionChangedCmd = value; + } + get + { + if (_GridSelectionChangedCmd == null) + { + _GridSelectionChangedCmd = new DelegateCommand((par) => GridSelectionChangedCmdMethod(par)); + } + return _GridSelectionChangedCmd; + } + } + private void GridSelectionChangedCmdMethod(object par) + { + //先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件 + var Selecteddata = par as LINScheduleConfigDto; + + if (Selecteddata != null) + { + CurSelectedItem = Selecteddata; + } + } + + //OpCmd + private DelegateCommand _OpCmd; + /// + /// 增加方法命令 + /// + public DelegateCommand OpCmd + { + set + { + _OpCmd = value; + } + get + { + if (_OpCmd == null) + { + _OpCmd = new DelegateCommand((Par) => OpCmdCall(Par)); + } + return _OpCmd; + } + } + + private void OpCmdCall(string Par) + { + switch (Par) + { + case "Add": + ListLINScheduleConfigDto.Add(new LINScheduleConfigDto + { + CanLinConfigProId = SelectCanLinConfigProId, + Cycle = 100, + SchTabIndex = 0, + }); + break; + case "Delete": + if (CurSelectedItem != null) + { + //直接删除掉,如果没有ID的话,这就不需要删除了 + FreeSql.Delete(CurSelectedItem.Id).ExecuteAffrows(); + ListLINScheduleConfigDto.Remove(CurSelectedItem); + + CurSelectedItem = null; + } + else + { + MessageBox.Show("请选中后再进行【删除】操作?", "提示", MessageBoxButton.OK, MessageBoxImage.Hand); + } + break; + default: + break; + } + } + + private DelegateCommand saveCmd; + /// + /// 保存命令 + /// + public DelegateCommand SaveCmd + { + set + { + saveCmd = value; + } + get + { + if (saveCmd == null) + { + saveCmd = new DelegateCommand(() => SaveCmdMethod()); + } + return saveCmd; + } + } + + /// + /// 保存命令方法 + /// + /// + private void SaveCmdMethod() + { + //检查空的数据 + foreach (var item in ListLINScheduleConfigDto) + { + + if (string.IsNullOrEmpty(item.MsgName)) + { + MessageBox.Show("请确认消息名称是否正确", "提示", MessageBoxButton.OK, MessageBoxImage.Hand); + return; + } + if (item.Cycle == 0) + { + MessageBox.Show("请确认周期是否正确", "提示", MessageBoxButton.OK, MessageBoxImage.Hand); + return; + } + } + + + //发送的控制帧都放到同一个调度表中,不需要检查了 + ////检查重复设置问题 + //bool isRepeat = ListLINScheduleConfigDto.GroupBy(i => i.MsgName).Any(g => g.Count() > 1); + //if (isRepeat) + //{ + // MessageBox.Show("请确认是否重复设置", "提示", MessageBoxButton.OK, MessageBoxImage.Hand); + // return; + //} + + //检查数据是否正常 + foreach (var item in ListLINScheduleConfigDto) + { + FreeSql.InsertOrUpdate() + .SetSource(Mapper.Map(item)). + ExecuteAffrows(); + } + + ListLINScheduleConfigDto = new ObservableCollection(Mapper.Map>(FreeSql.Select().Where(a => a.CanLinConfigProId == SelectCanLinConfigProId).ToList())); + + DialogParameters pars = new DialogParameters + { + { "ReturnValue", ListLINScheduleConfigDto } + }; + + RaiseRequestClose(new DialogResult(ButtonResult.OK, pars)); + } + + private DelegateCommand cancelCmd; + /// + /// 保存命令 + /// + public DelegateCommand CancelCmd + { + set + { + cancelCmd = value; + } + get + { + if (cancelCmd == null) + { + cancelCmd = new DelegateCommand(() => CancelCmdMethod()); + } + return cancelCmd; + } + } + + + /// + /// 取消命令方法 + /// + /// + private void CancelCmdMethod() + { + RaiseRequestClose(new DialogResult(ButtonResult.Cancel)); + } + + /// + /// 窗口打开时的传递的参数 + /// + /// + public override void OnDialogOpened(IDialogParameters parameters) + { + ListMsg = parameters.GetValue>("ListMsg"); + // 转换为CbxItems集合,都是文本内容 + MsgCbxItems = new ObservableCollection( + ListMsg.Select(value => new CbxItems + { + Key = value, + Text = value + })); + + ListLINScheduleConfigDto = parameters.GetValue>("ListLINScheduleConfigDto"); + //防止返回的数据为空,就无法增加了 + if (ListLINScheduleConfigDto == null) ListLINScheduleConfigDto = new ObservableCollection(); + //Name = parameters.GetValue("Name"); + + SelectCanLinConfigProId = parameters.GetValue("SelectCanLinConfigProId"); + } + + + } +} + diff --git a/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs b/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs index 87a2edf..7962ad2 100644 --- a/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs @@ -130,6 +130,7 @@ namespace CapMachine.Wpf.ViewModels canLinConfigPros = FreeSql.Select().Where(a => a.CANLINInfo == CANLIN.LIN) .Include(a => a.LINConfigExd) .IncludeMany(a => a.CanLinConfigContents) + .IncludeMany(a => a.LinScheduleConfigs) .ToList(); ListCanLinConfigPro = new ObservableCollection(canLinConfigPros); @@ -182,6 +183,12 @@ namespace CapMachine.Wpf.ViewModels ListReadCanLinRWConfigDto = new ObservableCollection(); } + //调度表配置信息 + if (SelectCanLinConfigPro.CanScheduleConfigs != null && SelectCanLinConfigPro.CanScheduleConfigs.Count() > 0) + { + ListLINScheduleConfigDto = new ObservableCollection(Mapper.Map>(SelectCanLinConfigPro.LinScheduleConfigs)); + } + //匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListLinLdfModel MatchSeletedAndLinLdfModel(); } @@ -543,6 +550,18 @@ namespace CapMachine.Wpf.ViewModels } SelectCanLinConfigProConfigName = SelectCanLinConfigPro.ConfigName; + + //调度表配置信息 + if (SelectCanLinConfigPro.CanScheduleConfigs != null && SelectCanLinConfigPro.CanScheduleConfigs.Count() > 0) + { + ListLINScheduleConfigDto = new ObservableCollection(Mapper.Map>(SelectCanLinConfigPro.LinScheduleConfigs)); + } + else + { + ListLINScheduleConfigDto = new ObservableCollection(); + } + + return; } //先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件 @@ -1030,6 +1049,17 @@ namespace CapMachine.Wpf.ViewModels } + private ObservableCollection _ListLINScheduleConfigDto; + /// + ///调度表集合 + /// + public ObservableCollection ListLINScheduleConfigDto + { + get { return _ListLINScheduleConfigDto; } + set { _ListLINScheduleConfigDto = value; RaisePropertyChanged(); } + } + + //private string _SelectedWriteName; ///// ///// 选中的写入的Name @@ -1174,6 +1204,47 @@ namespace CapMachine.Wpf.ViewModels System.Windows.MessageBox.Show("请选中后再进行【删除】操作?", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); } + break; + case "WriteSch"://调度表 + + LinDriveService.ToomossLinDrive.LinTest(); + + + //var data = LinDriveService.CmdData.GroupBy(a => a.MsgName).Select(a => a.Key).ToList(); + + //if (data != null && data.Count > 0) + //{ + // //弹窗 + // DialogService.ShowDialog("DialogLINSchConfigView", new DialogParameters() { + // {"ListMsg", LinDriveService.CmdData.GroupBy(a=>a.MsgName).Select(a=>a.Key).ToList() }, + // { "ListLINScheduleConfigDto",ListLINScheduleConfigDto}, + // { "SelectCanLinConfigProId",SelectCanLinConfigPro.Id}, + + // }, (par) => + // { + // if (par.Result == ButtonResult.OK) + // { + // ////程序名称 + // ListLINScheduleConfigDto = par.Parameters.GetValue>("ReturnValue"); + // //把更新后的最新值给当前的主集合中 + // SelectCanLinConfigPro.LinScheduleConfigs = Mapper.Map>(ListLINScheduleConfigDto.ToList()); + + // } + // else if (par.Result == ButtonResult.Cancel) + // { + // //取消 + + // } + + // }); + //} + //else + //{ + // System.Windows.MessageBox.Show("未发现写入的执行的命令数据,无法配置?", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + //} + + + break; default: break; diff --git a/CapMachine.Wpf/Views/DialogLINSchConfigView.xaml b/CapMachine.Wpf/Views/DialogLINSchConfigView.xaml new file mode 100644 index 0000000..418343d --- /dev/null +++ b/CapMachine.Wpf/Views/DialogLINSchConfigView.xaml @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +