diff --git a/CapMachine.Wpf/CanDrive/CanCmdData.cs b/CapMachine.Wpf/CanDrive/CanCmdData.cs index 58baba8..610e2b4 100644 --- a/CapMachine.Wpf/CanDrive/CanCmdData.cs +++ b/CapMachine.Wpf/CanDrive/CanCmdData.cs @@ -1,4 +1,5 @@ -using System; +using CapMachine.Wpf.Dtos; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -31,5 +32,17 @@ namespace CapMachine.Wpf.CanDrive /// 没有的话,则给默认值 /// public double SignalCmdValue { get; set; } + + + ///// + ///// 逻辑规则Id + ///// + //public long LogicRuleId { get; set; } + + /// + /// CanLinConfig的逻辑转换规则 + /// 比如:速度下发的数据SV是4000,但是下发到CAN的值是40,可能是其他的逻辑转换规则,这里就是保存其中的逻辑规则 + /// + public LogicRuleDto? LogicRuleDto { get; set; } } } diff --git a/CapMachine.Wpf/PrismEvent/LogicRuleChangeEvent.cs b/CapMachine.Wpf/PrismEvent/LogicRuleChangeEvent.cs new file mode 100644 index 0000000..09ec50c --- /dev/null +++ b/CapMachine.Wpf/PrismEvent/LogicRuleChangeEvent.cs @@ -0,0 +1,14 @@ +using Prism.Events; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CapMachine.Wpf.PrismEvent +{ + class LogicRuleChangeEvent:PubSubEvent + { + + } +} diff --git a/CapMachine.Wpf/Services/CanDriveService.cs b/CapMachine.Wpf/Services/CanDriveService.cs index 7f31f3a..f07cf22 100644 --- a/CapMachine.Wpf/Services/CanDriveService.cs +++ b/CapMachine.Wpf/Services/CanDriveService.cs @@ -20,15 +20,17 @@ namespace CapMachine.Wpf.Services { public HighSpeedDataService HighSpeedDataService { get; } + public LogicRuleService LogicRuleService { get; } /// /// 实例化函数 /// - public CanDriveService(HighSpeedDataService highSpeedDataService, IContainerProvider containerProvider) + public CanDriveService(HighSpeedDataService highSpeedDataService, IContainerProvider containerProvider, LogicRuleService logicRuleService) { ToomossCanDrive = new ToomossCan(containerProvider); //高速数据服务 HighSpeedDataService = highSpeedDataService; + LogicRuleService = logicRuleService; //ToomossCanDrive.StartCanDrive(); } @@ -131,7 +133,6 @@ namespace CapMachine.Wpf.Services CmdData.Add(SendCanCmdData); } - /// /// 更新速度信息 /// 默认是启动 @@ -141,7 +142,18 @@ namespace CapMachine.Wpf.Services { if (SpeedCanCmdData != null) { - SpeedCanCmdData.SignalCmdValue = SpeedData; + //首先是否判断是有斜率 + if (SpeedCanCmdData.LogicRuleDto == null) + { + //没有启动逻辑规则处理 + SpeedCanCmdData.SignalCmdValue = SpeedData; + } + else + { + //LogicRuleService.ApplyExpressionFast(SpeedData, SpeedCanCmdData.LogicRuleDto); + SpeedCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(SpeedData, SpeedCanCmdData.LogicRuleDto); + } + } //if (EnableCanCmdData != null) //{ diff --git a/CapMachine.Wpf/Services/ComActionService.cs b/CapMachine.Wpf/Services/ComActionService.cs index 69e51b8..4b07dbd 100644 --- a/CapMachine.Wpf/Services/ComActionService.cs +++ b/CapMachine.Wpf/Services/ComActionService.cs @@ -117,6 +117,15 @@ namespace CapMachine.Wpf.Services //保存配置信息 //PPCService.SaveSuperHeatCoolConfig(); + //是否改变规格 + var ReturnValue = par.Parameters.GetValue("IsRuleEdit"); + if (ReturnValue) + { + MessageBox.Show("检测到你已经改变了规则,CAN或者LIN配置中如果已经加载规则或者连接的话,则会出现错误,那么你需要重启软件"); + //逻辑可能更改了 + EventAggregator.GetEvent().Publish(""); + } + } else if (par.Result == ButtonResult.Cancel) diff --git a/CapMachine.Wpf/Services/LogicRuleService.cs b/CapMachine.Wpf/Services/LogicRuleService.cs index c46f952..d420068 100644 --- a/CapMachine.Wpf/Services/LogicRuleService.cs +++ b/CapMachine.Wpf/Services/LogicRuleService.cs @@ -42,7 +42,7 @@ namespace CapMachine.Wpf.Services /// Key: 规则名称, Value: 已编译的Lambda表达式 ///private readonly ConcurrentDictionary> _expressionCache; /// - private readonly ConcurrentDictionary _expressionCache; + private readonly ConcurrentDictionary> _expressionCache; ///// ///// 创建包含指定值的参数数组 @@ -60,7 +60,7 @@ namespace CapMachine.Wpf.Services /// private Parameter CreateParameters(double value) { - return new Parameter("value", typeof(double),value); + return new Parameter("value", typeof(double), value); } @@ -76,13 +76,10 @@ namespace CapMachine.Wpf.Services // 初始化集合 LogicRuleDtos = new ObservableCollection(); - _expressionCache = new ConcurrentDictionary(); + _expressionCache = new ConcurrentDictionary>(); // 初始化DynamicExpresso解释器 CurInterpreter = new Interpreter(); - //.Reference(typeof(Math)) // 引用Math类 - // //.SetVariable("Math", typeof(Math)) - //.SetVariable("value", 0.2); try { @@ -228,7 +225,7 @@ namespace CapMachine.Wpf.Services /// 更新规则 /// /// 规则对象 - public void UpdateRule(LogicRule rule) + public void UpdateRule(LogicRule ruleOld,LogicRule rule) { if (string.IsNullOrWhiteSpace(rule.Name)) { @@ -269,8 +266,8 @@ namespace CapMachine.Wpf.Services LogicRuleDtos.Insert(insertIndex - 1, Mapper.Map(rule)); } - - _expressionCache.TryRemove(updatedDto.Name, out _); + //有可能更改的是名称,那么新名称的话在_expressionCache中肯定是找不到的,可以用之前的ruleOld + _expressionCache.TryRemove(ruleOld.Name!, out _); CacheExpression(updatedDto); } } @@ -412,39 +409,6 @@ namespace CapMachine.Wpf.Services return rule; } - /// - /// 应用逻辑转换 - 主要使用方法 - /// - /// 输入值 - /// 规则名称 - /// 转换后的输出值 - public double ApplyLogic(double value, string ruleName) - { - var rule = GetRuleByName(ruleName); - - return ApplyExpression(value, rule); - } - - /// - /// 应用逻辑转换(基于参数类型自动选择规则) - /// - /// 输入值 - /// 参数类型 - /// 转换后的输出值 - public double ApplyLogicByType(double value, string parameterType) - { - var rules = GetRulesByParameterType(parameterType).ToList(); - if (rules.Count == 0) - { - LogService.Warn($"未找到适用于 {parameterType} 的转换规则,将返回原始值"); - return value; - } - - // 如果存在多个规则,取第一个 - var rule = rules.First(); - - return ApplyExpression(value, rule); - } /// /// 将规则表达式预编译并缓存到字典中 @@ -459,13 +423,17 @@ namespace CapMachine.Wpf.Services try { + // ****如下步骤很重要,尝试了很多次才正常运行**** + // 使用已有的CreateParameters方法创建参数声明 var parameter = CreateParameters(0); // 值不重要,只是为了获取参数声明 // 只解析一次,得到 Lambda 对象 var lambda = CurInterpreter.Parse(rule.Expression, parameter); // 只定义参数类型,不传值 + // 编译为强类型委托 + var compiledFunc = lambda.Compile>(); // 存入缓存 - _expressionCache[rule.Name] = lambda; + _expressionCache[rule.Name] = compiledFunc; } catch (Exception ex) { @@ -557,114 +525,54 @@ namespace CapMachine.Wpf.Services /// - /// 临时测试用 + /// 快速的执行数据 /// /// /// /// - public double ApplyExpressionNoCache(double value, LogicRuleDto rule) + public double ApplyExpressionFast(double value, LogicRuleDto rule) { try { + if (!_expressionCache.TryGetValue(rule.Name, out var CurActiveFunc)) + { + CacheExpression(rule); + if (!_expressionCache.TryGetValue(rule.Name, out CurActiveFunc)) + return value; + } - CurInterpreter.SetVariable("value", value); - var lambda = CurInterpreter.Parse(rule.Expression); - return (double)lambda.Invoke(); - - //// 创建全新的解释器实例 - //var localInterpreter = new Interpreter() - // .Reference(typeof(Math)) - // .SetVariable("Math", typeof(Math)); - - //// 直接设置变量值而不是使用参数 - //localInterpreter.SetVariable("value", value); - //// 解析并执行 - //var result = localInterpreter.Eval(rule.Expression); - //Console.WriteLine($"直接执行: 输入={value}, 表达式={rule.Expression}, 结果={result}"); - //return result; + // 直接调用委托,无反射开销 + return CurActiveFunc(value); } - catch (Exception ex) + catch { - LogService.Error($"直接执行表达式失败: {ex.Message}"); return value; } } + /// - /// 批量应用逻辑转换 (高性能版本) + /// 如果需要对多个数据应用相同规则,考虑实现批处理版本: /// - /// 原始值字典(键为参数名称,值为原始值) - /// 转换后的值字典 - public Dictionary ApplyBatchLogic(Dictionary values) + /// + /// + /// + public IEnumerable ApplyExpressionBatch(IEnumerable values, LogicRuleDto rule) { - // 为了性能,预分配容量 - var result = new Dictionary(values.Count); - - // 缓存参数类型到规则的映射,避免重复查询 - var cachedRulesByType = new Dictionary(); - - foreach (var entry in values) + if (!_expressionCache.TryGetValue(rule.Name, out var func)) { - var paramName = entry.Key; - var origValue = entry.Value; - - try - { - // 获取参数类型 - var paramType = DetermineParameterType(paramName); - - // 尝试从缓存获取规则 - if (!cachedRulesByType.TryGetValue(paramType, out var rule)) - { - var rules = GetRulesByParameterType(paramType).ToList(); - if (rules.Count > 0) - { - rule = rules.First(); - cachedRulesByType[paramType] = rule; // 添加到缓存 - } - } - - // 如果找到规则,应用转换 - if (rule != null) - { - var convertedValue = ApplyExpression(origValue, rule); - result.Add(paramName, convertedValue); - } - else - { - result.Add(paramName, origValue); // 没有规则时使用原始值 - } - } - catch (Exception ex) - { - LogService.Error($"处理参数 {paramName} 失败: {ex.Message}"); - result.Add(paramName, origValue); // 出错时使用原始值 - } + CacheExpression(rule); + if (!_expressionCache.TryGetValue(rule.Name, out func)) + return values; } - return result; + // 使用并行处理大量数据 + return values.AsParallel().Select(v => + { + try { return func(v); } + catch { return v; } + }); } - /// - /// 从参数名称确定参数类型 - /// - /// 参数名称 - /// 参数类型 - private string DetermineParameterType(string paramName) - { - // 根据参数名称确定类型的逻辑 - // 这里使用简单的名称匹配,实际项目中可能需要更复杂的映射 - if (paramName.Contains("速度") || paramName.Contains("转速")) - return "转速"; - else if (paramName.Contains("功率") || paramName.Contains("pw") || paramName.Contains("power")) - return "功率"; - else if (paramName.Contains("温度") || paramName.Contains("temp")) - return "温度"; - else if (paramName.Contains("压力") || paramName.Contains("press")) - return "压力"; - - // 默认类型 - return "通用"; - } } } diff --git a/CapMachine.Wpf/Services/MachineRtDataService.cs b/CapMachine.Wpf/Services/MachineRtDataService.cs index f72b880..806f459 100644 --- a/CapMachine.Wpf/Services/MachineRtDataService.cs +++ b/CapMachine.Wpf/Services/MachineRtDataService.cs @@ -2537,6 +2537,8 @@ namespace CapMachine.Wpf.Services /// private OperateResult OperateResultBlockMVRead { get; set; } + private double TestValue = 0.2; + /// /// PLC扫描线程 /// @@ -2704,7 +2706,8 @@ namespace CapMachine.Wpf.Services //程序步骤的写入 ProRunStepWrite(); - Console.WriteLine($"结果:{LogicRuleService.ApplyExpression(random.NextDouble() * 100, LogicRuleService.LogicRuleDtos.FirstOrDefault())}"); + TestValue = TestValue + 0.001; + Console.WriteLine($"结果:{LogicRuleService.ApplyExpressionFast(TestValue, LogicRuleService.LogicRuleDtos[1])}"); //stopwatch.Stop(); //停止Stopwatch //Console.WriteLine("Add Elapsed output runTime:{0}", stopwatch.Elapsed.TotalSeconds.ToString()); diff --git a/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs b/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs index 885486b..06372f0 100644 --- a/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs @@ -53,9 +53,11 @@ namespace CapMachine.Wpf.ViewModels Mapper = mapper; this.MachineRtDataService = machineRtDataService; - //MachineDataService = machineDataService; + //MachineDataService = machineDataService; DialogService = dialogService; + EventAggregator.GetEvent().Subscribe(LogicRuleChangeEventCall); + WriteNameCbxItems = new ObservableCollection() { new CbxItems(){ Key="转速",Text="转速"}, @@ -77,16 +79,8 @@ namespace CapMachine.Wpf.ViewModels InitLoadCanConfigPro(); - WriteRuleCbxItems = new ObservableCollection(); - //选择的读写规则 - foreach (var itemRule in LogicRuleService.LogicRuleDtos) - { - WriteRuleCbxItems.Add(new CbxItems() - { - Key = itemRule.Id.ToString(), - Text = itemRule.Name - }); - } + //初始化写规则下拉框 + InitWriteRuleCbx(); } @@ -110,6 +104,38 @@ namespace CapMachine.Wpf.ViewModels /// 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 @@ -150,7 +176,9 @@ namespace CapMachine.Wpf.ViewModels MsgName = item.MsgFrameName, SignalName = item.SignalName, SignalCmdValue = double.TryParse(item.DefautValue, out double result) == true ? result : 0, + LogicRuleDto = Mapper.Map(item.LogicRule), }); + //CanDriveService.CmdData.Add(new CanCmdData() //{ // ConfigName = item.Name, @@ -1124,7 +1152,11 @@ namespace CapMachine.Wpf.ViewModels System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); return; } - + if (CanDriveService.ToomossCanDrive.IsCycleSend) + { + System.Windows.MessageBox.Show("正在循环发送中,此时编辑可能会出现错误,请关闭循环发送后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } switch (Par) { @@ -1260,6 +1292,11 @@ namespace CapMachine.Wpf.ViewModels System.Windows.MessageBox.Show("选中CAN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); return; } + if (CanDriveService.ToomossCanDrive.IsCycleRevice) + { + System.Windows.MessageBox.Show("正在循环接受中,此时编辑可能会出现错误,请关闭循环发送后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } switch (Par) { diff --git a/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs b/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs index bb820ae..78b4f53 100644 --- a/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs +++ b/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs @@ -48,7 +48,7 @@ namespace CapMachine.Wpf.ViewModels set { _ListLogicRuleDto = value; RaisePropertyChanged(); } } - private LogicRuleDto _selectedRule; + private LogicRuleDto _selectedRule=new LogicRuleDto(); /// /// 当前选中的规则 /// @@ -58,6 +58,11 @@ namespace CapMachine.Wpf.ViewModels set { _selectedRule = value; RaisePropertyChanged(); } } + /// + /// 选中更改之前的LogicRuleDto + /// + public LogicRuleDto SelectedRuleOld { get; set; } + private DelegateCommand _GridSelectionChangedCmd; /// /// 选中行数据命令 @@ -82,6 +87,8 @@ namespace CapMachine.Wpf.ViewModels var selectedItem = par as LogicRuleDto; if (selectedItem != null) { + //防止需要未更改之前的数据 + SelectedRuleOld = selectedItem; //先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件 SelectedRule = selectedItem.DeepClone(); } @@ -90,6 +97,10 @@ namespace CapMachine.Wpf.ViewModels } + /// + /// 是否编辑 + /// + private bool IsRuleEdit { get; set; } = false; private DelegateCommand _RuleCmd; /// @@ -112,11 +123,8 @@ namespace CapMachine.Wpf.ViewModels } private void RuleCmdMethod(string par) { - if (SelectedRule==null) - { - MessageBox.Show("选中后再操作数据"); - return; - } + + IsRuleEdit = true; //先判断是否是正确的集合数据,防止DataGrid的数据源刷新导致的触发事件 switch (par) { @@ -125,9 +133,19 @@ namespace CapMachine.Wpf.ViewModels LogicRuleService.AddRule(Mapper.Map(SelectedRule)); break; case "Update": - LogicRuleService.UpdateRule(Mapper.Map(SelectedRule)); + if (SelectedRule == null) + { + MessageBox.Show("选中后再操作数据"); + return; + } + LogicRuleService.UpdateRule(Mapper.Map(SelectedRuleOld),Mapper.Map(SelectedRule)); break; case "Delete": + if (SelectedRule == null) + { + MessageBox.Show("选中后再操作数据"); + return; + } LogicRuleService.DeleteRule(SelectedRule.Name); break; default: @@ -181,7 +199,7 @@ namespace CapMachine.Wpf.ViewModels { DialogParameters pars = new DialogParameters { - { "NewData", "" } + { "IsRuleEdit", IsRuleEdit } }; RaiseRequestClose(new DialogResult(ButtonResult.OK, pars)); @@ -224,6 +242,7 @@ namespace CapMachine.Wpf.ViewModels public override void OnDialogOpened(IDialogParameters parameters) { Name = parameters.GetValue("Name"); + IsRuleEdit = false; } diff --git a/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs b/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs index ff64529..64b3558 100644 --- a/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs @@ -1079,7 +1079,11 @@ namespace CapMachine.Wpf.ViewModels System.Windows.MessageBox.Show("选中LIN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); return; } - + if (LinDriveService.ToomossLinDrive.IsCycleSend) + { + System.Windows.MessageBox.Show("正在循环发送中,此时编辑可能会出现错误,请关闭循环发送后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } switch (Par) { @@ -1214,6 +1218,11 @@ namespace CapMachine.Wpf.ViewModels System.Windows.MessageBox.Show("选中LIN配置名称后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); return; } + if (LinDriveService.ToomossLinDrive.IsCycleRevice) + { + System.Windows.MessageBox.Show("正在循环接受中,此时编辑可能会出现错误,请关闭循环发送后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); + return; + } switch (Par) { diff --git a/CapMachine.Wpf/Views/DialogLogicRuleView.xaml b/CapMachine.Wpf/Views/DialogLogicRuleView.xaml index 44c0ff9..86fced7 100644 --- a/CapMachine.Wpf/Views/DialogLogicRuleView.xaml +++ b/CapMachine.Wpf/Views/DialogLogicRuleView.xaml @@ -117,7 +117,7 @@ VerticalAlignment="Center" FontFamily="/Assets/Fonts/#iconfont" FontSize="18" - Text="" /> + Text="" /> + Text="" /> + Text="" /> --> @@ -244,7 +248,7 @@ FontFamily="/Assets/Fonts/#iconfont" FontSize="18" Foreground="White" - Text="" /> + Text="" /> + Text="" /> + Text="" /> -