diff --git a/CapMachine.Model/CANLIN/CanLinRWConfig.cs b/CapMachine.Model/CANLIN/CanLinRWConfig.cs
index ca6e539..148c576 100644
--- a/CapMachine.Model/CANLIN/CanLinRWConfig.cs
+++ b/CapMachine.Model/CANLIN/CanLinRWConfig.cs
@@ -61,5 +61,13 @@ namespace CapMachine.Model.CANLIN
public long CanLinConfigProId { get; set; }
public CanLinConfigPro? CanLinConfigPro { get; set; }
+
+
+ public long LogicRuleId { get; set; }
+ ///
+ /// CanLinConfig的逻辑转换规则
+ /// 比如:速度下发的数据SV是4000,但是下发到CAN的值是40,可能是其他的逻辑转换规则,这里就是保存其中的逻辑规则
+ ///
+ public LogicRule? LogicRule { get; set; }
}
}
diff --git a/CapMachine.Model/LogicRule.cs b/CapMachine.Model/LogicRule.cs
new file mode 100644
index 0000000..18675e1
--- /dev/null
+++ b/CapMachine.Model/LogicRule.cs
@@ -0,0 +1,52 @@
+using CapMachine.Model.CANLIN;
+using FreeSql.DataAnnotations;
+
+namespace CapMachine.Model
+{
+ ///
+ /// 逻辑转换规则模型
+ ///
+ [Table(Name = "LogicRule")]
+ public class LogicRule
+ {
+ ///
+ /// 主键ID
+ ///
+ [Column(IsPrimary = true, IsIdentity = true)]
+ public long Id { get; set; }
+
+ ///
+ /// 规则名称
+ ///
+ [Column(Name = "Name", StringLength = 50)]
+ public string? Name { get; set; }
+
+ ///
+ /// 规则描述
+ ///
+ [Column(Name = "Description", StringLength = 200)]
+ public string? Description { get; set; }
+
+ ///
+ /// 规则表达式
+ ///
+ [Column(Name = "Expression", StringLength = 500)]
+ public string? Expression { get; set; }
+
+ ///
+ /// 适用的参数类型(如:转速、功率等)
+ ///
+ [Column(Name = "ParameterType", StringLength = 50)]
+ public string? ParameterType { get; set; }
+
+ [Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
+ public DateTime CreateTime { get; set; }
+
+ ///
+ /// ///////////////////////////////////////////导航属性///////////////////////////////////////////////////////
+ ///
+
+ public List? CanLinRWConfigs { get; set; }
+
+ }
+}
diff --git a/CapMachine.Wpf/App.xaml.cs b/CapMachine.Wpf/App.xaml.cs
index ffc484d..8c8127f 100644
--- a/CapMachine.Wpf/App.xaml.cs
+++ b/CapMachine.Wpf/App.xaml.cs
@@ -123,7 +123,7 @@ namespace CapMachine.Wpf
//containerRegistry.RegisterSingleton();
//containerRegistry.RegisterSingleton();
-
+ containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
////注册设备服务
@@ -199,6 +199,7 @@ namespace CapMachine.Wpf
containerRegistry.RegisterDialog();
containerRegistry.RegisterDialog();
containerRegistry.RegisterDialog();
+ containerRegistry.RegisterDialog();
containerRegistry.RegisterDialog();
diff --git a/CapMachine.Wpf/CanDrive/CanCmdData.cs b/CapMachine.Wpf/CanDrive/CanCmdData.cs
index 58baba8..c7a8b74 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/CapMachine.Wpf.csproj b/CapMachine.Wpf/CapMachine.Wpf.csproj
index 5f97789..38d28f8 100644
--- a/CapMachine.Wpf/CapMachine.Wpf.csproj
+++ b/CapMachine.Wpf/CapMachine.Wpf.csproj
@@ -664,6 +664,7 @@
+
diff --git a/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs b/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs
index 034b598..8be29e9 100644
--- a/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs
+++ b/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs
@@ -70,7 +70,12 @@ namespace CapMachine.Wpf.Dtos
set { _DefautValue = value; RaisePropertyChanged(); }
}
-
+ public long LogicRuleId { get; set; }
+ ///
+ /// CanLinConfig的逻辑转换规则
+ /// 比如:速度下发的数据SV是4000,但是下发到CAN的值是40,可能是其他的逻辑转换规则,这里就是保存其中的逻辑规则
+ ///
+ public LogicRuleDto? LogicRuleDto { get; set; }
}
}
diff --git a/CapMachine.Wpf/Dtos/LogicRuleDto.cs b/CapMachine.Wpf/Dtos/LogicRuleDto.cs
new file mode 100644
index 0000000..7392007
--- /dev/null
+++ b/CapMachine.Wpf/Dtos/LogicRuleDto.cs
@@ -0,0 +1,73 @@
+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 LogicRuleDto : BindableBase
+ {
+ ///
+ /// 主键ID
+ ///
+ public int Id { get; set; }
+
+
+ private string _name = string.Empty;
+ ///
+ /// 规则名称
+ ///
+ public string Name
+ {
+ get { return _name; }
+ set { SetProperty(ref _name, value); }
+ }
+
+
+ private string _description = string.Empty;
+ ///
+ /// 规则描述
+ ///
+ public string Description
+ {
+ get { return _description; }
+ set { SetProperty(ref _description, value); }
+ }
+
+ private string _expression = string.Empty;
+ ///
+ /// 规则表达式
+ ///
+ public string Expression
+ {
+ get { return _expression; }
+ set { _expression = value; RaisePropertyChanged(); }
+ }
+
+
+ private string _parameterType = string.Empty;
+ ///
+ /// 适用的参数类型(如:转速、功率等)
+ ///
+ public string ParameterType
+ {
+ get { return _parameterType; }
+ set { SetProperty(ref _parameterType, value); }
+ }
+
+ private DateTime _CreateTime;
+ ///
+ /// 适用的参数类型(如:转速、功率等)
+ ///
+ public DateTime CreateTime
+ {
+ get { return _CreateTime; }
+ set { _CreateTime = value; RaisePropertyChanged(); }
+ }
+ }
+}
diff --git a/CapMachine.Wpf/MapperProfile/LogicRuleProfile.cs b/CapMachine.Wpf/MapperProfile/LogicRuleProfile.cs
new file mode 100644
index 0000000..51e2843
--- /dev/null
+++ b/CapMachine.Wpf/MapperProfile/LogicRuleProfile.cs
@@ -0,0 +1,19 @@
+using AutoMapper;
+using CapMachine.Model;
+using CapMachine.Wpf.Dtos;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace CapMachine.Wpf.MapperProfile
+{
+ public class LogicRuleProfile : Profile
+ {
+ public LogicRuleProfile()
+ {
+ CreateMap().ReverseMap();
+ }
+ }
+}
diff --git a/CapMachine.Wpf/Models/Tag/Cell/MeterValueAttrCell.cs b/CapMachine.Wpf/Models/Tag/Cell/MeterValueAttrCell.cs
index 58aa633..2ebe303 100644
--- a/CapMachine.Wpf/Models/Tag/Cell/MeterValueAttrCell.cs
+++ b/CapMachine.Wpf/Models/Tag/Cell/MeterValueAttrCell.cs
@@ -99,7 +99,7 @@ namespace CapMachine.Wpf.Models.Tag.Cell
}
}
- private string? _EngValueStr;
+ private string? _EngValueStr="0";
///
/// 工程值的字符串 MV
///
diff --git a/CapMachine.Wpf/PrismEvent/LogicRuleChangeEvent.cs b/CapMachine.Wpf/PrismEvent/LogicRuleChangeEvent.cs
new file mode 100644
index 0000000..7721b9d
--- /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
+{
+ public class LogicRuleChangeEvent : PubSubEvent
+ {
+
+ }
+}
diff --git a/CapMachine.Wpf/Services/CanFdDriveService.cs b/CapMachine.Wpf/Services/CanFdDriveService.cs
index 34f497e..7d3844f 100644
--- a/CapMachine.Wpf/Services/CanFdDriveService.cs
+++ b/CapMachine.Wpf/Services/CanFdDriveService.cs
@@ -1,5 +1,7 @@
using CapMachine.Model.CANLIN;
using CapMachine.Wpf.CanDrive;
+using CapMachine.Wpf.Models;
+using CapMachine.Wpf.Models.ProModelPars;
using ImTools;
using Prism.Ioc;
using Prism.Mvvm;
@@ -18,15 +20,17 @@ namespace CapMachine.Wpf.Services
public class CanFdDriveService : BindableBase
{
public HighSpeedDataService HighSpeedDataService { get; }
+ public LogicRuleService LogicRuleService { get; }
///
/// 实例化函数
///
- public CanFdDriveService(HighSpeedDataService highSpeedDataService, IContainerProvider containerProvider)
+ public CanFdDriveService(HighSpeedDataService highSpeedDataService, IContainerProvider containerProvider, LogicRuleService logicRuleService)
{
ToomossCanFDDrive = new ToomossCanFD(containerProvider);
//高速数据服务
HighSpeedDataService = highSpeedDataService;
+ LogicRuleService = logicRuleService;
//ToomossCanFDDrive.StartCanDrive();
}
@@ -172,7 +176,14 @@ namespace CapMachine.Wpf.Services
{
if (SpeedCanCmdData != null)
{
- SpeedCanCmdData.SignalCmdValue = SpeedData;
+ if (SpeedCanCmdData.LogicRuleDto == null)
+ {
+ //没有启动逻辑规则处理
+ SpeedCanCmdData.SignalCmdValue = SpeedData;
+ return;
+ }
+
+ SpeedCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(SpeedData, SpeedCanCmdData.LogicRuleDto);
}
//if (EnableCanCmdData != null)
//{
@@ -201,7 +212,12 @@ namespace CapMachine.Wpf.Services
{
if (PwLimitCanCmdData != null)
{
- PwLimitCanCmdData.SignalCmdValue = PwLimit;
+ if (PwLimitCanCmdData.LogicRuleDto==null)
+ {
+ PwLimitCanCmdData.SignalCmdValue = PwLimit;
+ return;
+ }
+ PwLimitCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(PwLimit, PwLimitCanCmdData.LogicRuleDto!);
}
}
@@ -226,7 +242,12 @@ namespace CapMachine.Wpf.Services
{
if (PTCPwCanCmdData != null)
{
- PTCPwCanCmdData.SignalCmdValue = PTCPw;
+ if (PTCPwCanCmdData.LogicRuleDto == null)
+ {
+ PTCPwCanCmdData.SignalCmdValue = PTCPw;
+ return;
+ }
+ PTCPwCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(PTCPw, PTCPwCanCmdData.LogicRuleDto!);
}
}
@@ -238,7 +259,12 @@ namespace CapMachine.Wpf.Services
{
if (PTCFlowCanCmdData != null)
{
- PTCFlowCanCmdData.SignalCmdValue = Flow;
+ if (PTCFlowCanCmdData.LogicRuleDto == null)
+ {
+ PTCFlowCanCmdData.SignalCmdValue = Flow;
+ return;
+ }
+ PTCFlowCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(Flow, PTCFlowCanCmdData.LogicRuleDto!);
}
}
@@ -250,7 +276,12 @@ namespace CapMachine.Wpf.Services
{
if (PTCWaterTempCanCmdData != null)
{
- PTCWaterTempCanCmdData.SignalCmdValue = WaterTemp;
+ if (PTCWaterTempCanCmdData.LogicRuleDto == null)
+ {
+ PTCWaterTempCanCmdData.SignalCmdValue = WaterTemp;
+ return;
+ }
+ PTCWaterTempCanCmdData.SignalCmdValue = LogicRuleService.ApplyExpressionFast(WaterTemp, PTCWaterTempCanCmdData.LogicRuleDto!);
}
}
diff --git a/CapMachine.Wpf/Services/ComActionService.cs b/CapMachine.Wpf/Services/ComActionService.cs
index 21fb180..8d34e8b 100644
--- a/CapMachine.Wpf/Services/ComActionService.cs
+++ b/CapMachine.Wpf/Services/ComActionService.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using System.Windows;
namespace CapMachine.Wpf.Services
{
@@ -61,6 +62,14 @@ namespace CapMachine.Wpf.Services
case "过热度/过冷度配置":
ShowSuperHeatCool(msg.Par);
break;
+ case "规则转换":
+ if (SysRunServer.MachineRunState1.IsRunState)
+ {
+ MessageBox.Show("请不要在运行时编辑规则转换,此时更改可能导致运行出错,请停止后再编辑");
+ return;
+ }
+ ShowLogicRule(msg.Par);
+ break;
default:
break;
}
@@ -93,6 +102,40 @@ namespace CapMachine.Wpf.Services
}
+ ///
+ /// 过热度和过冷度配置弹窗
+ ///
+ private void ShowLogicRule(object par)
+ {
+ //弹窗
+ DialogService.ShowDialog("DialogLogicRuleView", new DialogParameters() { { "Name", par } }, (par) =>
+ {
+ if (par.Result == ButtonResult.OK)
+ {
+ //保存配置信息
+ //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
new file mode 100644
index 0000000..5adc573
--- /dev/null
+++ b/CapMachine.Wpf/Services/LogicRuleService.cs
@@ -0,0 +1,578 @@
+using AutoMapper;
+using CapMachine.Core;
+using CapMachine.Model;
+using CapMachine.Wpf.Dtos;
+using DynamicExpresso;
+using FreeSql;
+using FreeSql.DataAnnotations;
+using Prism.Mvvm;
+using Syncfusion.Windows.Shared;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace CapMachine.Wpf.Services
+{
+ ///
+ /// 逻辑服务 - 用于处理数据逻辑转换
+ ///
+ public class LogicRuleService : BindableBase
+ {
+ private readonly ILogService LogService;
+ private readonly IFreeSql FreeSql;
+
+ ///
+ /// 逻辑转换规则集合
+ ///
+ public ObservableCollection LogicRuleDtos { get; private set; }
+
+ ///
+ /// DynamicExpresso解释器
+ ///
+ private Interpreter CurInterpreter { get; set; }
+ public IMapper Mapper { get; }
+
+ ///
+ /// 规则表达式缓存(高性能访问)
+ /// Key: 规则名称, Value: 已编译的Lambda表达式
+ ///private readonly ConcurrentDictionary> _expressionCache;
+ ///
+ private readonly ConcurrentDictionary> _expressionCache;
+
+ /////
+ ///// 创建包含指定值的参数数组
+ /////
+ //private Parameter[] CreateParameters(double value)
+ //{
+ // return new Parameter[]
+ // {
+ // new Parameter("value", typeof(double), value)
+ // };
+ //}
+
+ ///
+ /// 创建包含指定值的参数
+ ///
+ private Parameter CreateParameters(double value)
+ {
+ return new Parameter("value", typeof(double), value);
+
+ }
+
+ ///
+ /// 实例化函数
+ ///
+ public LogicRuleService(ILogService logService, IFreeSql freeSql, IMapper mapper)
+ {
+ LogService = logService;
+ FreeSql = freeSql;
+ Mapper = mapper;
+
+ // 初始化集合
+ LogicRuleDtos = new ObservableCollection();
+
+ _expressionCache = new ConcurrentDictionary>();
+
+ // 初始化DynamicExpresso解释器
+ CurInterpreter = new Interpreter();
+
+ try
+ {
+ // 从数据库加载规则
+ LoadRulesFromDatabase();
+
+ }
+ catch (Exception ex)
+ {
+ LogService.Error($"初始化逻辑服务失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 从数据库加载规则
+ ///
+ private void LoadRulesFromDatabase()
+ {
+ try
+ {
+ // 从数据库加载规则
+ var dbRules = FreeSql.Select().OrderBy(a => a.Id).ToList();
+ if (dbRules != null && dbRules.Count > 0)
+ {
+ LogicRuleDtos.Clear();
+ _expressionCache.Clear(); // 清空表达式缓存
+
+ foreach (var rule in dbRules)
+ {
+ LogicRuleDtos.Add(Mapper.Map(rule));
+ }
+
+ // 预编译所有表达式
+ WarmUpExpressionCache();
+
+ //LogService.Info($"已从数据库加载并预编译 {dbRules.Count} 条逻辑规则");
+ }
+ else
+ {
+ LogService.Warn("数据库中没有逻辑规则");
+ }
+ }
+ catch (Exception ex)
+ {
+ LogService.Error($"从数据库加载逻辑规则失败: {ex.Message}");
+ throw; // 重新抛出异常以便调用者处理
+ }
+ }
+
+
+ #region 增删改查LogicRule
+
+
+ ///
+ /// 添加新规则
+ ///
+ /// 规则对象
+ public void AddRule(LogicRule rule)
+ {
+ if (string.IsNullOrWhiteSpace(rule.Name))
+ {
+ MessageBox.Show("规则名称不能为空");
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(rule.Expression))
+ {
+ MessageBox.Show("规则表达式不能为空");
+ return;
+ }
+
+ if (LogicRuleDtos.Where(a => a.Name == rule.Name).Any())
+ {
+ MessageBox.Show("已经有另一个相同名称的规则了");
+ return;
+ }
+
+ // 验证表达式是否有效
+ if (!ValidateExpression(rule.Expression))
+ {
+ MessageBox.Show("规则表达式验证失败");
+ return;
+ }
+
+ if (InsertRuleToDb(rule, out LogicRule resultInsert))
+ {
+ //此时的resultInsert有新增的ID
+ // 添加规则
+ LogicRuleDtos.Add(Mapper.Map(resultInsert));
+
+ // 预编译并缓存表达式
+ CacheExpression(Mapper.Map(resultInsert));
+ }
+ else
+ {
+ MessageBox.Show("增加数据失败!");
+ return;
+ }
+ //LogService.Info($"添加新规则: {rule.Name}");
+ }
+
+ ///
+ /// 保存规格到数据库中
+ ///
+ ///
+ public bool InsertRuleToDb(LogicRule rule, out LogicRule ResultInsert)
+ {
+ try
+ {
+ // 插入规则到数据库
+ var result = FreeSql.Insert(rule).ExecuteInserted();
+
+ // 检查影响的行数
+ bool success = result.Count > 0;
+
+ if (success)
+ {
+ ResultInsert = result.FirstOrDefault()!;
+ return success;
+ //LogService.Info($"成功插入规则: {rule.Name}");
+
+ // 刷新内存中的规则集合
+ //LoadRulesFromDatabase();
+ }
+ else
+ {
+ LogService.Warn($"插入规则失败: {rule.Name},没有行受影响");
+ ResultInsert = null;
+ return success;
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ LogService.Error($"插入规则到数据库时发生异常: {ex.Message}");
+ ResultInsert = null;
+ return false;
+ }
+ }
+
+ ///
+ /// 更新规则
+ ///
+ /// 规则对象
+ public void UpdateRule(LogicRule ruleOld, LogicRule rule)
+ {
+ if (string.IsNullOrWhiteSpace(rule.Name))
+ {
+ MessageBox.Show("规则名称不能为空");
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(rule.Expression))
+ {
+ MessageBox.Show("规则表达式不能为空");
+ return;
+ }
+
+
+ // 验证表达式是否有效
+ if (!ValidateExpression(rule.Expression))
+ {
+ MessageBox.Show("规则表达式验证失败");
+ return;
+ }
+
+ if (UpdateRuleToDb(rule))
+ {
+ // 更新缓存
+ var updatedDto = LogicRuleDtos.FirstOrDefault(r => r.Id == rule.Id);
+ var insertIndex = LogicRuleDtos.ToList().FindIndex(x => x.Id > rule.Id);
+ if (updatedDto != null)
+ {
+ //移除数据
+ LogicRuleDtos.Remove(updatedDto);
+ if (insertIndex == -1)
+ {
+ LogicRuleDtos.Add(Mapper.Map(rule));
+ }
+ else
+ {
+ // 在找到的位置插入
+ LogicRuleDtos.Insert(insertIndex - 1, Mapper.Map(rule));
+ }
+
+ //有可能更改的是名称,那么新名称的话在_expressionCache中肯定是找不到的,可以用之前的ruleOld
+ _expressionCache.TryRemove(ruleOld.Name!, out _);
+ CacheExpression(updatedDto);
+ }
+ }
+
+ //LogService.Info($"更新规则: {rule.Name}");
+ }
+
+ ///
+ /// 更新规格到数据库中
+ ///
+ ///
+ public bool UpdateRuleToDb(LogicRule rule)
+ {
+ try
+ {
+ // 更新规则到数据库
+ var result = FreeSql.Update()
+ .Set(a => a.Name, rule.Name)
+ .Set(a => a.Description, rule.Description)
+ .Set(a => a.Expression, rule.Expression)
+ .Set(a => a.ParameterType, rule.ParameterType)
+ .Where(r => r.Id == rule.Id)
+ .ExecuteUpdated();
+
+ // 检查影响的行数
+ bool success = result.Count() > 0;
+
+ if (success)
+ {
+ //LogService.Info($"成功更新规则: {rule.Name}");
+
+ }
+ else
+ {
+ //LogService.Warn($"更新规则失败: {rule.Name},没有行受影响");
+ }
+
+ return success;
+ }
+ catch (Exception ex)
+ {
+ //LogService.Error($"更新规则到数据库时发生异常: {ex.Message}");
+ return false;
+ }
+ }
+
+ ///
+ /// 删除规则
+ ///
+ /// 规则名称
+ public void DeleteRule(string ruleName)
+ {
+ var rule = LogicRuleDtos.FirstOrDefault(r => r.Name == ruleName);
+ if (rule == null)
+ {
+ MessageBox.Show("找不到删除的数据");
+ return;
+ }
+
+ var Count = FreeSql.Delete().Where(r => r.Id == rule.Id).ExecuteAffrows();
+ if (Count > 0)
+ {
+ // 删除规则
+ LogicRuleDtos.Remove(rule);
+ // 从缓存中移除表达式
+ _expressionCache.TryRemove(ruleName, out _);
+ }
+
+ //LogService.Info($"删除规则: {ruleName}");
+ }
+
+ ///
+ /// 验证表达式是否有效
+ ///
+ /// 表达式字符串
+ /// 表达式是否有效
+ private bool ValidateExpression(string expression)
+ {
+ try
+ {
+ // 创建测试解释器并直接设置变量
+ var interpreter = new Interpreter()
+ .Reference(typeof(Math)) // 引用Math类
+ .SetVariable("Math", typeof(Math))
+ .SetVariable("value", 100); // 直接设置值变量
+
+ // 尝试编译表达式
+ var lambda = interpreter.Parse(expression);
+
+ // 尝试执行表达式
+ var result = lambda.Invoke();
+
+ // 检查结果是否为数值类型
+ if (result is double doubleResult)
+ {
+ // 验证结果不是NaN或Infinity
+ if (double.IsNaN(doubleResult) || double.IsInfinity(doubleResult))
+ {
+ //LogService.Warn($"表达式执行结果无效 (NaN或Infinity): {expression}");
+ return false;
+ }
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogService.Warn($"验证表达式失败: {expression}, 错误: {ex.Message}");
+ return false;
+ }
+ }
+
+
+ #endregion
+
+
+ ///
+ /// 根据参数类型获取适用的规则
+ ///
+ /// 参数类型
+ /// 适用的规则列表
+ public IEnumerable GetRulesByParameterType(string parameterType)
+ {
+ return LogicRuleDtos.Where(r => r.ParameterType == parameterType);
+ }
+
+ ///
+ /// 获取指定名称的规则
+ ///
+ /// 规则名称
+ /// 规则对象
+ public LogicRuleDto GetRuleByName(string ruleName)
+ {
+ var rule = LogicRuleDtos.FirstOrDefault(r => r.Name == ruleName);
+ if (rule == null)
+ {
+ throw new KeyNotFoundException($"找不到名为 {ruleName} 的规则");
+ }
+ return rule;
+ }
+
+
+ ///
+ /// 将规则表达式预编译并缓存到字典中
+ ///
+ /// 要缓存的规则
+ private void CacheExpression(LogicRuleDto rule)
+ {
+ if (string.IsNullOrEmpty(rule.Name) || string.IsNullOrEmpty(rule.Expression))
+ {
+ return; // 防止空名称或空表达式
+ }
+
+ try
+ {
+ // ****如下步骤很重要,尝试了很多次才正常运行****
+
+ // 使用已有的CreateParameters方法创建参数声明
+ var parameter = CreateParameters(0); // 值不重要,只是为了获取参数声明
+ // 只解析一次,得到 Lambda 对象
+ var lambda = CurInterpreter.Parse(rule.Expression, parameter); // 只定义参数类型,不传值
+ // 编译为强类型委托
+ var compiledFunc = lambda.Compile>();
+
+ // 存入缓存
+ _expressionCache[rule.Name] = compiledFunc;
+ }
+ catch (Exception ex)
+ {
+ LogService.Error($"缓存规则 {rule.Name} 表达式失败: {ex.Message}");
+ }
+ }
+
+ ///
+ /// 预热表达式缓存 - 预编译所有规则
+ ///
+ private void WarmUpExpressionCache()
+ {
+ foreach (var rule in LogicRuleDtos)
+ {
+ if (!_expressionCache.ContainsKey(rule.Name))
+ {
+ CacheExpression(rule);
+ }
+ }
+ LogService.Info($"已预编译 {_expressionCache.Count} 条规则表达式");
+ }
+
+ ///
+ /// 根据规则应用表达式(高性能版本)
+ ///
+ /// 输入值
+ /// 规则对象
+ /// 转换后的输出值
+ public double ApplyExpression(double value, LogicRuleDto rule)
+ {
+ try
+ {
+ // 尝试从缓存获取预编译的表达式
+ if (!_expressionCache.TryGetValue(rule.Name, out var compiledExpression))
+ {
+ // 如果缓存中没有,则编译并添加到缓存
+ CacheExpression(rule);
+
+ // 再次尝试获取
+ if (!_expressionCache.TryGetValue(rule.Name, out compiledExpression))
+ {
+ // 初始解析表达式(只需执行一次)
+ string expressionText = rule.Expression;
+
+ // 强类型函数
+ Func compiledFunc = (v) =>
+ {
+ // 高性能版本:直接根据公式计算
+ try
+ {
+ if (expressionText.Contains("value"))
+ {
+ var parameters = CreateParameters(v);
+ var lambda = CurInterpreter.Parse(expressionText, parameters);
+ return (double)lambda.Invoke();
+ }
+ else
+ {
+ // 简单表达式使用直接求值
+ return v / 100.0; // 默认处理
+ }
+ }
+ catch
+ {
+ // 出错时返回原值
+ return v;
+ }
+ };
+ // 再次尝试缓存
+ CacheExpression(rule);
+
+ return compiledFunc(value);
+ }
+ }
+
+ // 创建包含实际值的参数
+ var parameter = new Parameter("value", typeof(double), value);
+ // 使用预编译的表达式执行计算(高性能)
+ var convertedValue = (double)compiledExpression.Invoke(value);
+
+ return convertedValue;
+ }
+ catch (Exception ex)
+ {
+ //LogService.Error($"应用规则 {rule.Name} 失败: {ex.Message}");
+ return value; // 出错时返回原始值
+ }
+ }
+
+
+ ///
+ /// 快速的执行数据
+ ///
+ ///
+ ///
+ ///
+ 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;
+ }
+
+ // 直接调用委托,无反射开销
+ return CurActiveFunc(value);
+ }
+ catch
+ {
+ return value;
+ }
+ }
+
+
+ ///
+ /// 如果需要对多个数据应用相同规则,考虑实现批处理版本:
+ ///
+ ///
+ ///
+ ///
+ public IEnumerable ApplyExpressionBatch(IEnumerable values, LogicRuleDto rule)
+ {
+ if (!_expressionCache.TryGetValue(rule.Name, out var func))
+ {
+ CacheExpression(rule);
+ if (!_expressionCache.TryGetValue(rule.Name, out func))
+ return values;
+ }
+
+ // 使用并行处理大量数据
+ return values.AsParallel().Select(v =>
+ {
+ try { return func(v); }
+ catch { return v; }
+ });
+ }
+
+ }
+}
diff --git a/CapMachine.Wpf/Services/NavigationMenuService.cs b/CapMachine.Wpf/Services/NavigationMenuService.cs
index d96ed1e..ab57060 100644
--- a/CapMachine.Wpf/Services/NavigationMenuService.cs
+++ b/CapMachine.Wpf/Services/NavigationMenuService.cs
@@ -40,6 +40,10 @@ namespace CapMachine.Wpf.Services
new NavigationItem("SuperHeatCool","过热度/过冷度配置","DialogSuperHeatCoolConfigView"),
//new NavigationItem("Palette","过冷度",""),
}),
+ new NavigationItem("", "规则设置","",new ObservableCollection()
+ {
+ new NavigationItem("Rule","规则转换","DialogLogicRuleView"),
+ }),
//new NavigationItem("", "PID设置","",new ObservableCollection()
//{
// new NavigationItem("Circle","转速PID",""),
diff --git a/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs b/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs
index f20664c..86d2cf8 100644
--- a/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs
+++ b/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs
@@ -34,7 +34,7 @@ namespace CapMachine.Wpf.ViewModels
{
public CANFDConfigViewModel(IDialogService dialogService, IFreeSql freeSql,
IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService,
- ComActionService actionService,ILogService logService,
+ ComActionService actionService, ILogService logService, LogicRuleService logicRuleService,
ConfigService configService, CanFdDriveService canFdDriveService,
IMapper mapper, MachineRtDataService machineRtDataService)
{
@@ -44,6 +44,7 @@ namespace CapMachine.Wpf.ViewModels
RegionManager = regionManager;
SysRunService = sysRunService;
ComActionService = actionService;
+ LogicRuleService = logicRuleService;
LogService = logService;
ConfigService = configService;
CanFdDriveService = canFdDriveService;
@@ -127,8 +128,10 @@ namespace CapMachine.Wpf.ViewModels
new CbxItems(){ Key="通讯PTC膜温",Text="通讯PTC膜温"},
new CbxItems(){ Key="通讯PTC模块温度",Text="通讯PTC模块温度"},
};
- InitLoadCanConfigPro();
+ InitLoadCanConfigPro();
+ //初始化写规则下拉框
+ InitWriteRuleCbx();
}
@@ -140,6 +143,7 @@ namespace CapMachine.Wpf.ViewModels
public IRegionManager RegionManager { get; }
public SysRunService SysRunService { get; }
public ComActionService ComActionService { get; }
+ public LogicRuleService LogicRuleService { get; }
public ILogService LogService { get; }
public ConfigService ConfigService { get; }
public CanFdDriveService CanFdDriveService { get; }
@@ -151,8 +155,40 @@ 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
///
@@ -163,7 +199,8 @@ namespace CapMachine.Wpf.ViewModels
//CAN配置集合数据
canLinConfigPros = FreeSql.Select().Where(a => a.CANLINInfo == CANLIN.CANFD)
.Include(a => a.CANFdConfigExd)
- .IncludeMany(a => a.CanLinConfigContents)
+ .IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))//,then=> then.Include(b=>b.LogicRule)
+ //.IncludeMany(a => a.CanLinConfigContents)
.ToList();
ListCanLinConfigPro = new ObservableCollection(canLinConfigPros);
@@ -197,6 +234,7 @@ 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),
});
//CanFdDriveService.CmdData.Add(new CanCmdData()
//{
@@ -535,7 +573,7 @@ namespace CapMachine.Wpf.ViewModels
//CANConfigExdDto 数据
SelectedCANConfigExdDto = Mapper.Map(SelectCanLinConfigPro!.CANFdConfigExd);
- if (SelectedCANConfigExdDto!=null)
+ if (SelectedCANConfigExdDto != null)
{
//更新波特率等配置信息
CanFdDriveService.ToomossCanFDDrive.UpdateConfig((uint)SelectedCANConfigExdDto.ArbBaudRate,
@@ -557,6 +595,7 @@ 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),
});
//CanFdDriveService.CmdData.Add(new CanCmdData()
@@ -1084,6 +1123,15 @@ namespace CapMachine.Wpf.ViewModels
set { _ReadNameCbxItems = value; RaisePropertyChanged(); }
}
+ private ObservableCollection _WriteRuleCbxItems;
+ ///
+ /// 写入的规格集合
+ ///
+ public ObservableCollection WriteRuleCbxItems
+ {
+ get { return _WriteRuleCbxItems; }
+ set { _WriteRuleCbxItems = value; RaisePropertyChanged(); }
+ }
//private string _SelectedWriteName;
/////
@@ -1199,6 +1247,7 @@ namespace CapMachine.Wpf.ViewModels
//直接修改
FreeSql.Update(item.Id)
.Set(a => a.Name, item.Name)
+ .Set(a => a.LogicRuleId, item.LogicRuleId)
.Set(a => a.DefautValue, item.DefautValue)
.ExecuteAffrows();
//ListWriteCanLinRWConfigDto.Remove(SelectedWriteCanLinRWConfigDto);
diff --git a/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs b/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs
new file mode 100644
index 0000000..52add83
--- /dev/null
+++ b/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs
@@ -0,0 +1,252 @@
+using AutoMapper;
+using CapMachine.Core;
+using CapMachine.Model;
+using CapMachine.Wpf.Dtos;
+using CapMachine.Wpf.Services;
+using Masuit.Tools;
+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 DialogLogicRuleViewModel : DialogViewModel
+ {
+ public DialogLogicRuleViewModel(IFreeSql freeSql, IMapper mapper, LogicRuleService logicRuleService)
+ {
+ Title = "逻辑规则创建";
+
+ FreeSql = freeSql;
+ Mapper = mapper;
+ LogicRuleService = logicRuleService;
+
+ //var Data = Mapper.Map>(LogicRuleService.LogicRuleDtos);
+
+ ListLogicRuleDto = LogicRuleService.LogicRuleDtos;
+
+ }
+ public IFreeSql FreeSql { get; }
+ public IMapper Mapper { get; }
+ public LogicRuleService LogicRuleService { get; }
+
+ private ObservableCollection _ListLogicRuleDto;
+ ///
+ /// 数据集合
+ ///
+ public ObservableCollection ListLogicRuleDto
+ {
+ get { return _ListLogicRuleDto; }
+ set { _ListLogicRuleDto = value; RaisePropertyChanged(); }
+ }
+
+ private LogicRuleDto _selectedRule = new LogicRuleDto();
+ ///
+ /// 当前选中的规则
+ ///
+ public LogicRuleDto SelectedRule
+ {
+ get { return _selectedRule; }
+ set { _selectedRule = value; RaisePropertyChanged(); }
+ }
+
+ ///
+ /// 选中更改之前的LogicRuleDto
+ ///
+ public LogicRuleDto SelectedRuleOld { get; set; }
+
+ private DelegateCommand