diff --git a/.windsurfrules b/.windsurfrules
new file mode 100644
index 0000000..aca25b0
--- /dev/null
+++ b/.windsurfrules
@@ -0,0 +1,9 @@
+我是一个 CSharp 软件开发者,我在开发一个压缩机耐久性能台的软件系统,主要功能如下:
+# 读取PLC的数据,PLC是西门子的S200
+# 通过DBC配置CAN,通过Ldf配置LIN通信
+# 通过配置程序步骤,能逐步的下载步骤信息到PLC中逐步的执行程序,步骤程序中有SV(设置值),下载的速度数据是下载到压缩机中
+# 获取所有的数据,包括PLC的数据和压缩机的数据,然后能绘制曲线
+# 能对获取的数据进行数据记录,保存到文件中,记录的值是SV数据
+# 能记录日志信息
+# 用中文回复我
+# 请延续我的编码框架
\ No newline at end of file
diff --git a/CapMachine.Model/CANLIN/CanLinRWConfig.cs b/CapMachine.Model/CANLIN/CanLinRWConfig.cs
index ca6e539..39ed93c 100644
--- a/CapMachine.Model/CANLIN/CanLinRWConfig.cs
+++ b/CapMachine.Model/CANLIN/CanLinRWConfig.cs
@@ -10,7 +10,7 @@ namespace CapMachine.Model.CANLIN
///
/// CAN和LIN的配置数据内容
///
- [Table(Name = "CanLinConfigContent")]
+ [Table(Name = "CanLinRWConfig")]
public class CanLinRWConfig
{
///
@@ -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/CapMachine.Model.csproj b/CapMachine.Model/CapMachine.Model.csproj
index eeb5253..b05dcd5 100644
--- a/CapMachine.Model/CapMachine.Model.csproj
+++ b/CapMachine.Model/CapMachine.Model.csproj
@@ -6,7 +6,7 @@
enable
-
+
diff --git a/CapMachine.Model/LogicRule.cs b/CapMachine.Model/LogicRule.cs
new file mode 100644
index 0000000..b25c84c
--- /dev/null
+++ b/CapMachine.Model/LogicRule.cs
@@ -0,0 +1,58 @@
+using CapMachine.Model.CANLIN;
+using FreeSql.DataAnnotations;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+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 513ba26..f917868 100644
--- a/CapMachine.Wpf/App.xaml.cs
+++ b/CapMachine.Wpf/App.xaml.cs
@@ -1,4 +1,4 @@
-using AutoMapper;
+using AutoMapper;
using CapMachine.Core;
using CapMachine.Core.IService;
using CapMachine.Wpf.MapperProfile;
@@ -94,7 +94,7 @@ namespace CapMachine.Wpf
try
{
var MachineCode = SoftAuthorizeHelper.GetMachineCode();
- SoftAuthorizeHelper.WriteMachineCodeToFile(MachineCode,"");
+ SoftAuthorizeHelper.WriteMachineCodeToFile(MachineCode, "");
var PublicKey = SoftAuthorizeHelper.GetPublicKeyDataByFilePath("");
var Lience = SoftAuthorizeHelper.GetLienceDataByFilePath("");
var IsOK = SoftAuthorizeHelper.CheckLience(MachineCode, PublicKey, Lience);
@@ -129,6 +129,7 @@ namespace CapMachine.Wpf
//containerRegistry.RegisterSingleton();
+ containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
containerRegistry.RegisterSingleton();
////注册设备服务
@@ -143,6 +144,7 @@ namespace CapMachine.Wpf
containerRegistry.RegisterSingleton();
+
containerRegistry.RegisterSingleton();
string strsqllite = System.AppDomain.CurrentDomain.BaseDirectory + @"Db\CapMachine.db";
@@ -201,8 +203,10 @@ namespace CapMachine.Wpf
containerRegistry.RegisterDialog();
containerRegistry.RegisterDialog();
containerRegistry.RegisterDialog();
+ containerRegistry.RegisterDialog();
containerRegistry.RegisterDialog();
+
//注册AutoMapper
diff --git a/CapMachine.Wpf/CapMachine.Wpf.csproj b/CapMachine.Wpf/CapMachine.Wpf.csproj
index 9362185..c175f67 100644
--- a/CapMachine.Wpf/CapMachine.Wpf.csproj
+++ b/CapMachine.Wpf/CapMachine.Wpf.csproj
@@ -664,12 +664,13 @@
+
-
-
-
-
-
+
+
+
+
+
diff --git a/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs b/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs
index 034b598..cb8acac 100644
--- a/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs
+++ b/CapMachine.Wpf/Dtos/CanLinRWConfigDto.cs
@@ -1,4 +1,5 @@
-using CapMachine.Model.CANLIN;
+using CapMachine.Model;
+using CapMachine.Model.CANLIN;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
@@ -70,7 +71,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..1e324d6
--- /dev/null
+++ b/CapMachine.Wpf/Dtos/LogicRuleDto.cs
@@ -0,0 +1,75 @@
+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 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/CanLinRWConfigProfile.cs b/CapMachine.Wpf/MapperProfile/CanLinRWConfigProfile.cs
index cc52ea6..b7902c8 100644
--- a/CapMachine.Wpf/MapperProfile/CanLinRWConfigProfile.cs
+++ b/CapMachine.Wpf/MapperProfile/CanLinRWConfigProfile.cs
@@ -14,7 +14,9 @@ namespace CapMachine.Wpf.MapperProfile
{
public CanLinRWConfigProfile()
{
- CreateMap().ReverseMap();
+ CreateMap()
+ .ForMember(dest => dest.LogicRuleDto, opt => opt.MapFrom(src => src.LogicRule))
+ .ReverseMap();
}
}
}
diff --git a/CapMachine.Wpf/MapperProfile/LogicRuleProfile.cs b/CapMachine.Wpf/MapperProfile/LogicRuleProfile.cs
new file mode 100644
index 0000000..e6c7e39
--- /dev/null
+++ b/CapMachine.Wpf/MapperProfile/LogicRuleProfile.cs
@@ -0,0 +1,20 @@
+using AutoMapper;
+using CapMachine.Model;
+using CapMachine.Wpf.Dtos;
+using CapMachine.Wpf.Models;
+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/Services/CanDriveService.cs b/CapMachine.Wpf/Services/CanDriveService.cs
index 42fd28c..7f31f3a 100644
--- a/CapMachine.Wpf/Services/CanDriveService.cs
+++ b/CapMachine.Wpf/Services/CanDriveService.cs
@@ -1,4 +1,4 @@
-using CapMachine.Model.CANLIN;
+using CapMachine.Model.CANLIN;
using CapMachine.Wpf.CanDrive;
using ImTools;
using Prism.Ioc;
@@ -195,7 +195,7 @@ namespace CapMachine.Wpf.Services
{
if (ToomossCanDrive.OpenState)
{
- if (ToomossCanDrive.IsCycleSend == false)
+ if (ToomossCanDrive.IsCycleSend == false)//要防止多次启动导致的问题,来回转换
{
if (CmdData.Count > 0)
{
diff --git a/CapMachine.Wpf/Services/ComActionService.cs b/CapMachine.Wpf/Services/ComActionService.cs
index 21fb180..69e51b8 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
{
@@ -22,6 +23,7 @@ namespace CapMachine.Wpf.Services
public DataRecordService DataRecordService { get; }
public SysRunService SysRunServer { get; }
public PPCService PPCService { get; }
+ public ProRuntimeService ProRuntimeService { get; }
public CanDriveService CanDriveService { get; }
public LinDriveService LinDriveService { get; }
public MachineRtDataService MachineRtDataService { get; }
@@ -29,7 +31,7 @@ namespace CapMachine.Wpf.Services
public ComActionService(ConfigService configService, IEventAggregator eventAggregator,
- DataRecordService dataRecordService, SysRunService sysRunService, PPCService pPCService, CanDriveService canDriveService, LinDriveService linDriveService,
+ DataRecordService dataRecordService, SysRunService sysRunService, PPCService pPCService, ProRuntimeService proRuntimeService, CanDriveService canDriveService, LinDriveService linDriveService,
MachineRtDataService machineRtDataService, IDialogService dialogService)
{
ConfigService = configService;
@@ -38,6 +40,7 @@ namespace CapMachine.Wpf.Services
DataRecordService = dataRecordService;
SysRunServer = sysRunService;
PPCService = pPCService;
+ ProRuntimeService = proRuntimeService;
CanDriveService = canDriveService;
LinDriveService = linDriveService;
MachineRtDataService = machineRtDataService;
@@ -61,6 +64,14 @@ namespace CapMachine.Wpf.Services
case "过热度/过冷度配置":
ShowSuperHeatCool(msg.Par);
break;
+ case "规则转换":
+ if (ProRuntimeService.MachineRunState1.IsRunState)
+ {
+ MessageBox.Show("请不要在运行时编辑规则转换,此时更改可能导致运行出错,请停止后再编辑");
+ return;
+ }
+ ShowLogicRule(msg.Par);
+ break;
default:
break;
}
@@ -93,6 +104,29 @@ namespace CapMachine.Wpf.Services
}
+ ///
+ /// 过热度和过冷度配置弹窗
+ ///
+ private void ShowLogicRule(object par)
+ {
+ //弹窗
+ DialogService.ShowDialog("DialogLogicRuleView", new DialogParameters() { { "Name", par } }, (par) =>
+ {
+ if (par.Result == ButtonResult.OK)
+ {
+ //保存配置信息
+ //PPCService.SaveSuperHeatCoolConfig();
+
+
+ }
+ else if (par.Result == ButtonResult.Cancel)
+ {
+ //取消
+
+ }
+
+ });
+ }
diff --git a/CapMachine.Wpf/Services/LinDriveService.cs b/CapMachine.Wpf/Services/LinDriveService.cs
index 1763f4b..6363025 100644
--- a/CapMachine.Wpf/Services/LinDriveService.cs
+++ b/CapMachine.Wpf/Services/LinDriveService.cs
@@ -1,4 +1,4 @@
-using CapMachine.Model.CANLIN;
+using CapMachine.Model.CANLIN;
using CapMachine.Wpf.LinDrive;
using ImTools;
using Prism.Ioc;
diff --git a/CapMachine.Wpf/Services/LogicRuleService.cs b/CapMachine.Wpf/Services/LogicRuleService.cs
new file mode 100644
index 0000000..c46f952
--- /dev/null
+++ b/CapMachine.Wpf/Services/LogicRuleService.cs
@@ -0,0 +1,670 @@
+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();
+ //.Reference(typeof(Math)) // 引用Math类
+ // //.SetVariable("Math", typeof(Math))
+ //.SetVariable("value", 0.2);
+
+ 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 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.TryRemove(updatedDto.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;
+ }
+
+ ///
+ /// 应用逻辑转换 - 主要使用方法
+ ///
+ /// 输入值
+ /// 规则名称
+ /// 转换后的输出值
+ 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);
+ }
+
+ ///
+ /// 将规则表达式预编译并缓存到字典中
+ ///
+ /// 要缓存的规则
+ 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); // 只定义参数类型,不传值
+
+ // 存入缓存
+ _expressionCache[rule.Name] = lambda;
+ }
+ 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 ApplyExpressionNoCache(double value, LogicRuleDto rule)
+ {
+ try
+ {
+
+ 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;
+ }
+ catch (Exception ex)
+ {
+ LogService.Error($"直接执行表达式失败: {ex.Message}");
+ return value;
+ }
+ }
+
+ ///
+ /// 批量应用逻辑转换 (高性能版本)
+ ///
+ /// 原始值字典(键为参数名称,值为原始值)
+ /// 转换后的值字典
+ public Dictionary ApplyBatchLogic(Dictionary values)
+ {
+ // 为了性能,预分配容量
+ var result = new Dictionary(values.Count);
+
+ // 缓存参数类型到规则的映射,避免重复查询
+ var cachedRulesByType = new Dictionary();
+
+ foreach (var entry in values)
+ {
+ 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); // 出错时使用原始值
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// 从参数名称确定参数类型
+ ///
+ /// 参数名称
+ /// 参数类型
+ 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 88ab62a..f72b880 100644
--- a/CapMachine.Wpf/Services/MachineRtDataService.cs
+++ b/CapMachine.Wpf/Services/MachineRtDataService.cs
@@ -40,6 +40,7 @@ namespace CapMachine.Wpf.Services
private IEventAggregator _EventAggregator { get; set; }
public AlarmService AlarmService { get; }
public ConfigService ConfigService { get; }
+ public LogicRuleService LogicRuleService { get; }
public CanDriveService CanDriveService { get; }
public LinDriveService LinDriveService { get; }
public SysRunService SysRunService { get; }
@@ -133,7 +134,7 @@ namespace CapMachine.Wpf.Services
/// 实例化函数
///
///
- public MachineRtDataService(IEventAggregator eventAggregator, AlarmService alarmService, ConfigService configService,
+ public MachineRtDataService(IEventAggregator eventAggregator, AlarmService alarmService, ConfigService configService, LogicRuleService logicRuleService,
CanDriveService canDriveService, LinDriveService linDriveService, SysRunService sysRunService)//, AlarmService alarmService
{
//ConcurrentDictionary keyValuePairs = new ConcurrentDictionary();
@@ -145,12 +146,12 @@ namespace CapMachine.Wpf.Services
//stopwatch.Stop(); //停止Stopwatch
//Console.WriteLine("Add Elapsed output runTime:{0}", stopwatch.Elapsed.ToString());
- //MelsecMcNetDrive.
//事件服务
_EventAggregator = eventAggregator;
AlarmService = alarmService;
ConfigService = configService;
+ LogicRuleService = logicRuleService;
CanDriveService = canDriveService;
LinDriveService = linDriveService;
SysRunService = sysRunService;
@@ -2703,6 +2704,7 @@ namespace CapMachine.Wpf.Services
//程序步骤的写入
ProRunStepWrite();
+ Console.WriteLine($"结果:{LogicRuleService.ApplyExpression(random.NextDouble() * 100, LogicRuleService.LogicRuleDtos.FirstOrDefault())}");
//stopwatch.Stop(); //停止Stopwatch
//Console.WriteLine("Add Elapsed output runTime:{0}", stopwatch.Elapsed.TotalSeconds.ToString());
diff --git a/CapMachine.Wpf/Services/NavigationMenuService.cs b/CapMachine.Wpf/Services/NavigationMenuService.cs
index db0c4eb..f5a02bd 100644
--- a/CapMachine.Wpf/Services/NavigationMenuService.cs
+++ b/CapMachine.Wpf/Services/NavigationMenuService.cs
@@ -40,10 +40,10 @@ namespace CapMachine.Wpf.Services
new NavigationItem("SuperHeatCool","过热度/过冷度配置","DialogSuperHeatCoolConfigView"),
//new NavigationItem("Palette","过冷度",""),
}),
- //new NavigationItem("", "PID设置","",new ObservableCollection()
- //{
- // new NavigationItem("Circle","转速PID",""),
- //}),
+ new NavigationItem("", "规则设置","",new ObservableCollection()
+ {
+ new NavigationItem("Rule","规则转换","DialogLogicRuleView"),
+ }),
//new NavigationItem("", "通信配置","",new ObservableCollection()
//{
// new NavigationItem("Circle","CAN配置","CANConfigView"),
diff --git a/CapMachine.Wpf/Services/ProRuntimeService.cs b/CapMachine.Wpf/Services/ProRuntimeService.cs
index ff13549..af8a046 100644
--- a/CapMachine.Wpf/Services/ProRuntimeService.cs
+++ b/CapMachine.Wpf/Services/ProRuntimeService.cs
@@ -1,4 +1,4 @@
-using AutoMapper;
+using AutoMapper;
using CapMachine.Model;
using CapMachine.Shared.Controls;
using CapMachine.Wpf.ChannelModel;
diff --git a/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs b/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs
index 5b2c0dd..885486b 100644
--- a/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs
+++ b/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs
@@ -37,7 +37,7 @@ namespace CapMachine.Wpf.ViewModels
{
public CANConfigViewModel(IDialogService dialogService, IFreeSql freeSql,
IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService,
- ComActionService actionService,
+ ComActionService actionService, LogicRuleService logicRuleService,
ConfigService configService, CanDriveService canDriveService,
IMapper mapper, MachineRtDataService machineRtDataService)
{
@@ -47,6 +47,7 @@ namespace CapMachine.Wpf.ViewModels
RegionManager = regionManager;
SysRunService = sysRunService;
ComActionService = actionService;
+ LogicRuleService = logicRuleService;
ConfigService = configService;
CanDriveService = canDriveService;
Mapper = mapper;
@@ -63,6 +64,7 @@ namespace CapMachine.Wpf.ViewModels
new CbxItems(){ Key="Anti_Sleep",Text="Anti_Sleep"},
};
+
ReadNameCbxItems = new ObservableCollection()
{
new CbxItems(){ Key="通讯转速",Text="通讯转速"},
@@ -72,8 +74,20 @@ namespace CapMachine.Wpf.ViewModels
new CbxItems(){ Key="通讯功率",Text="通讯功率"},
new CbxItems(){ Key="通讯芯片温度",Text="通讯芯片温度"},
};
+
InitLoadCanConfigPro();
+ WriteRuleCbxItems = new ObservableCollection();
+ //选择的读写规则
+ foreach (var itemRule in LogicRuleService.LogicRuleDtos)
+ {
+ WriteRuleCbxItems.Add(new CbxItems()
+ {
+ Key = itemRule.Id.ToString(),
+ Text = itemRule.Name
+ });
+ }
+
}
@@ -85,6 +99,7 @@ namespace CapMachine.Wpf.ViewModels
public IRegionManager RegionManager { get; }
public SysRunService SysRunService { get; }
public ComActionService ComActionService { get; }
+ public LogicRuleService LogicRuleService { get; }
public ConfigService ConfigService { get; }
public CanDriveService CanDriveService { get; }
public IMapper Mapper { get; }
@@ -107,7 +122,7 @@ namespace CapMachine.Wpf.ViewModels
//CAN配置集合数据
canLinConfigPros = FreeSql.Select().Where(a => a.CANLINInfo == CANLIN.CAN)
.Include(a => a.CANConfigExd)
- .IncludeMany(a => a.CanLinConfigContents)
+ .IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule))//,then=> then.Include(b=>b.LogicRule)
.ToList();
ListCanLinConfigPro = new ObservableCollection(canLinConfigPros);
@@ -116,7 +131,7 @@ namespace CapMachine.Wpf.ViewModels
SelectCanLinConfigPro = canLinConfigPros.Where(a => a.Id == SelectCanLinConfigPro.Id).FirstOrDefault()!;
//无数据就返回
if (SelectCanLinConfigPro == null) return;
-
+
SelectedCANConfigExdDto = Mapper.Map(SelectCanLinConfigPro!.CANConfigExd);
//配置信息
@@ -695,7 +710,7 @@ namespace CapMachine.Wpf.ViewModels
}
//(par as SelectionChangedEventArgs)!.AddedItems[0] == null
- if ((par as SelectionChangedEventArgs)!.AddedItems.Count==0)
+ if ((par as SelectionChangedEventArgs)!.AddedItems.Count == 0)
{
return;
}
@@ -833,7 +848,7 @@ namespace CapMachine.Wpf.ViewModels
//系统使用了CAN
ConfigService.CanLinRunStateModel.CurSysSelectedCanLin = CanLinEnum.Can;
}
-
+
//CAN DBC配置 有DBC配置的话,则直接加载DBC信息
if (!string.IsNullOrEmpty(SelectCanLinConfigPro.CANConfigExd.DbcPath))
{
@@ -980,6 +995,16 @@ namespace CapMachine.Wpf.ViewModels
set { _WriteNameCbxItems = value; RaisePropertyChanged(); }
}
+ private ObservableCollection _WriteRuleCbxItems;
+ ///
+ /// 写入的规格集合
+ ///
+ public ObservableCollection WriteRuleCbxItems
+ {
+ get { return _WriteRuleCbxItems; }
+ set { _WriteRuleCbxItems = value; RaisePropertyChanged(); }
+ }
+
private ObservableCollection _ReadNameCbxItems;
///
@@ -991,6 +1016,15 @@ namespace CapMachine.Wpf.ViewModels
set { _ReadNameCbxItems = value; RaisePropertyChanged(); }
}
+ private ObservableCollection _ReadRuleCbxItems;
+ ///
+ /// 读取的规格集合
+ ///
+ public ObservableCollection ReadRuleCbxItems
+ {
+ get { return _ReadRuleCbxItems; }
+ set { _ReadRuleCbxItems = value; RaisePropertyChanged(); }
+ }
//private string _SelectedWriteName;
/////
@@ -1106,6 +1140,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..bb820ae
--- /dev/null
+++ b/CapMachine.Wpf/ViewModels/DialogLogicRuleViewModel.cs
@@ -0,0 +1,233 @@
+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;
+ ///
+ /// 当前选中的规则
+ ///
+ public LogicRuleDto SelectedRule
+ {
+ get { return _selectedRule; }
+ set { _selectedRule = value; RaisePropertyChanged(); }
+ }
+
+ private DelegateCommand