逻辑规则和CAN结合的更改

This commit is contained in:
2025-04-23 20:57:54 +08:00
parent a7fc676b82
commit 0aee140e3f
10 changed files with 194 additions and 166 deletions

View File

@@ -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
/// 没有的话,则给默认值
/// </summary>
public double SignalCmdValue { get; set; }
///// <summary>
///// 逻辑规则Id
///// </summary>
//public long LogicRuleId { get; set; }
/// <summary>
/// CanLinConfig的逻辑转换规则
/// 比如速度下发的数据SV是4000但是下发到CAN的值是40可能是其他的逻辑转换规则这里就是保存其中的逻辑规则
/// </summary>
public LogicRuleDto? LogicRuleDto { get; set; }
}
}

View File

@@ -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<string>
{
}
}

View File

@@ -20,15 +20,17 @@ namespace CapMachine.Wpf.Services
{
public HighSpeedDataService HighSpeedDataService { get; }
public LogicRuleService LogicRuleService { get; }
/// <summary>
/// 实例化函数
/// </summary>
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);
}
/// <summary>
/// 更新速度信息
/// 默认是启动
@@ -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)
//{

View File

@@ -117,6 +117,15 @@ namespace CapMachine.Wpf.Services
//保存配置信息
//PPCService.SaveSuperHeatCoolConfig();
//是否改变规格
var ReturnValue = par.Parameters.GetValue<bool>("IsRuleEdit");
if (ReturnValue)
{
MessageBox.Show("检测到你已经改变了规则CAN或者LIN配置中如果已经加载规则或者连接的话则会出现错误那么你需要重启软件");
//逻辑可能更改了
EventAggregator.GetEvent<LogicRuleChangeEvent>().Publish("");
}
}
else if (par.Result == ButtonResult.Cancel)

View File

@@ -42,7 +42,7 @@ namespace CapMachine.Wpf.Services
/// Key: 规则名称, Value: 已编译的Lambda表达式
///private readonly ConcurrentDictionary<string, Func<double, double>> _expressionCache;
/// </summary>
private readonly ConcurrentDictionary<string, Lambda> _expressionCache;
private readonly ConcurrentDictionary<string, Func<double, double>> _expressionCache;
///// <summary>
///// 创建包含指定值的参数数组
@@ -60,7 +60,7 @@ namespace CapMachine.Wpf.Services
/// </summary>
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<LogicRuleDto>();
_expressionCache = new ConcurrentDictionary<string, Lambda>();
_expressionCache = new ConcurrentDictionary<string, Func<double, double>>();
// 初始化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
/// 更新规则
/// </summary>
/// <param name="rule">规则对象</param>
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<LogicRuleDto>(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;
}
/// <summary>
/// 应用逻辑转换 - 主要使用方法
/// </summary>
/// <param name="value">输入值</param>
/// <param name="ruleName">规则名称</param>
/// <returns>转换后的输出值</returns>
public double ApplyLogic(double value, string ruleName)
{
var rule = GetRuleByName(ruleName);
return ApplyExpression(value, rule);
}
/// <summary>
/// 应用逻辑转换(基于参数类型自动选择规则)
/// </summary>
/// <param name="value">输入值</param>
/// <param name="parameterType">参数类型</param>
/// <returns>转换后的输出值</returns>
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);
}
/// <summary>
/// 将规则表达式预编译并缓存到字典中
@@ -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<Func<double, double>>();
// 存入缓存
_expressionCache[rule.Name] = lambda;
_expressionCache[rule.Name] = compiledFunc;
}
catch (Exception ex)
{
@@ -557,114 +525,54 @@ namespace CapMachine.Wpf.Services
/// <summary>
/// 临时测试用
/// 快速的执行数据
/// </summary>
/// <param name="value"></param>
/// <param name="rule"></param>
/// <returns></returns>
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<double>(rule.Expression);
//Console.WriteLine($"直接执行: 输入={value}, 表达式={rule.Expression}, 结果={result}");
//return result;
// 直接调用委托,无反射开销
return CurActiveFunc(value);
}
catch (Exception ex)
catch
{
LogService.Error($"直接执行表达式失败: {ex.Message}");
return value;
}
}
/// <summary>
/// 批量应用逻辑转换 (高性能版本)
/// 如果需要对多个数据应用相同规则,考虑实现批处理版本
/// </summary>
/// <param name="values">原始值字典(键为参数名称,值为原始值)</param>
/// <returns>转换后的值字典</returns>
public Dictionary<string, double> ApplyBatchLogic(Dictionary<string, double> values)
/// <param name="values"></param>
/// <param name="rule"></param>
/// <returns></returns>
public IEnumerable<double> ApplyExpressionBatch(IEnumerable<double> values, LogicRuleDto rule)
{
// 为了性能,预分配容量
var result = new Dictionary<string, double>(values.Count);
// 缓存参数类型到规则的映射,避免重复查询
var cachedRulesByType = new Dictionary<string, LogicRuleDto>();
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; }
});
}
/// <summary>
/// 从参数名称确定参数类型
/// </summary>
/// <param name="paramName">参数名称</param>
/// <returns>参数类型</returns>
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 "通用";
}
}
}

View File

@@ -2537,6 +2537,8 @@ namespace CapMachine.Wpf.Services
/// </summary>
private OperateResult<byte[]> OperateResultBlockMVRead { get; set; }
private double TestValue = 0.2;
/// <summary>
/// PLC扫描线程
/// </summary>
@@ -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());

View File

@@ -53,9 +53,11 @@ namespace CapMachine.Wpf.ViewModels
Mapper = mapper;
this.MachineRtDataService = machineRtDataService;
//MachineDataService = machineDataService;
//MachineDataService = machineDataService;
DialogService = dialogService;
EventAggregator.GetEvent<LogicRuleChangeEvent>().Subscribe(LogicRuleChangeEventCall);
WriteNameCbxItems = new ObservableCollection<CbxItems>()
{
new CbxItems(){ Key="转速",Text="转速"},
@@ -77,16 +79,8 @@ namespace CapMachine.Wpf.ViewModels
InitLoadCanConfigPro();
WriteRuleCbxItems = new ObservableCollection<CbxItems>();
//选择的读写规则
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
/// </summary>
public IDialogService DialogService { get; }
#region
/// <summary>
/// 逻辑更改事件
/// </summary>
/// <param name="msg"></param>
/// <exception cref="NotImplementedException"></exception>
private void LogicRuleChangeEventCall(string msg)
{
//InitWriteRuleCbx();
}
/// <summary>
/// 初始化写规则下拉框
/// </summary>
private void InitWriteRuleCbx()
{
WriteRuleCbxItems = new ObservableCollection<CbxItems>();
//选择的读写规则
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<LogicRuleDto>(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)
{

View File

@@ -48,7 +48,7 @@ namespace CapMachine.Wpf.ViewModels
set { _ListLogicRuleDto = value; RaisePropertyChanged(); }
}
private LogicRuleDto _selectedRule;
private LogicRuleDto _selectedRule=new LogicRuleDto();
/// <summary>
/// 当前选中的规则
/// </summary>
@@ -58,6 +58,11 @@ namespace CapMachine.Wpf.ViewModels
set { _selectedRule = value; RaisePropertyChanged(); }
}
/// <summary>
/// 选中更改之前的LogicRuleDto
/// </summary>
public LogicRuleDto SelectedRuleOld { get; set; }
private DelegateCommand<object> _GridSelectionChangedCmd;
/// <summary>
/// 选中行数据命令
@@ -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
}
/// <summary>
/// 是否编辑
/// </summary>
private bool IsRuleEdit { get; set; } = false;
private DelegateCommand<string> _RuleCmd;
/// <summary>
@@ -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<LogicRule>(SelectedRule));
break;
case "Update":
LogicRuleService.UpdateRule(Mapper.Map<LogicRule>(SelectedRule));
if (SelectedRule == null)
{
MessageBox.Show("选中后再操作数据");
return;
}
LogicRuleService.UpdateRule(Mapper.Map<LogicRule>(SelectedRuleOld),Mapper.Map<LogicRule>(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<string>("Name");
IsRuleEdit = false;
}

View File

@@ -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)
{

View File

@@ -117,7 +117,7 @@
VerticalAlignment="Center"
FontFamily="/Assets/Fonts/#iconfont"
FontSize="18"
Text="&#xe63c;" />
Text="&#xe6f0;" />
<TextBlock Style="{StaticResource EditLabelStyle}" Text="规则名称" />
<TextBox
Width="250"
@@ -135,7 +135,7 @@
VerticalAlignment="Center"
FontFamily="/Assets/Fonts/#iconfont"
FontSize="18"
Text="&#xe67c;" />
Text="&#xe7e4;" />
<TextBlock Style="{StaticResource EditLabelStyle}" Text="规则描述" />
<TextBox
Width="250"
@@ -153,7 +153,7 @@
VerticalAlignment="Center"
FontFamily="/Assets/Fonts/#iconfont"
FontSize="18"
Text="&#xe679;" />
Text="&#xe9c1;" />
<TextBlock Style="{StaticResource EditLabelStyle}" Text="参数类型" />
<TextBox
Width="250"
@@ -211,10 +211,14 @@
</RichTextBox>-->
<TextBox
Height="100"
Margin="10,5"
Height="360"
Margin="0"
Padding="5"
AcceptsReturn="True"
Background="#404040"
FontSize="16"
FontWeight="Bold"
Foreground="WhiteSmoke"
Text="{Binding SelectedRule.Expression, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
@@ -244,7 +248,7 @@
FontFamily="/Assets/Fonts/#iconfont"
FontSize="18"
Foreground="White"
Text="&#xe62f;" />
Text="&#xe8c0;" />
<TextBlock
VerticalAlignment="Center"
FontSize="14"
@@ -265,7 +269,7 @@
FontFamily="/Assets/Fonts/#iconfont"
FontSize="18"
Foreground="White"
Text="&#xe63a;" />
Text="&#xe625;" />
<TextBlock
VerticalAlignment="Center"
FontSize="14"
@@ -286,7 +290,7 @@
FontFamily="/Assets/Fonts/#iconfont"
FontSize="18"
Foreground="White"
Text="&#xe646;" />
Text="&#xe933;" />
<TextBlock
VerticalAlignment="Center"
FontSize="14"
@@ -313,11 +317,11 @@
Command="{Binding SaveCmd}"
Content="确定"
Foreground="White" />
<Button
<!--<Button
Margin="10,0"
Command="{Binding CancelCmd}"
Content="取消"
Foreground="White" />
Foreground="White" />-->
</StackPanel>
</Grid>
</UserControl>