18 Commits

Author SHA1 Message Date
b217acd7e9 ClaudeCode 更改2 2026-05-14 22:04:31 +08:00
df3da9d9cb Cladude code 更改 2026-05-14 18:26:22 +08:00
268f4baf99 同步25001 can 2026-05-14 17:33:37 +08:00
2b2097d1ed 改动8 2026-05-14 17:21:47 +08:00
b67ba5bb27 改动7 2026-05-14 16:32:20 +08:00
0fb230079b 改动6 2026-05-14 15:23:03 +08:00
196df6b181 现场修改6 2026-05-14 15:08:34 +08:00
873f6ced0a 现场功能更改5 2026-05-14 14:57:28 +08:00
985ad12d63 现场更改4 2026-05-14 14:39:47 +08:00
53ca705ab0 现场更改3 2026-05-14 14:05:17 +08:00
4f5c6949f4 现场更改2 2026-05-14 11:36:56 +08:00
1dfcf5f77a 现场查找程序崩溃问题1 2026-05-14 11:07:57 +08:00
4cdda056b4 现场增加日志功能 2026-05-14 10:41:23 +08:00
e954988fb5 精确发送更改 2025-05-12 10:10:13 +08:00
c1df40ac4c StartPrecisionCycleSendMsg 更改 2025-05-12 10:07:51 +08:00
8b96c482f7 打补丁 2025-03-04 22:34:46 +08:00
d0aca2cbdb 时间字符串更改 2025-02-27 20:15:39 +08:00
f02e336f34 取消Cmd的console的实时消息和运行cmd窗口弹出 2025-02-26 16:16:35 +08:00
11 changed files with 1062 additions and 410 deletions

View File

@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"mcp__filesystem__directory_tree"
]
}
}

View File

@@ -261,7 +261,7 @@ namespace CapMachine.Wpf
//给当前的全局异常捕捉服务使用 //给当前的全局异常捕捉服务使用
LogService = ContainerLocator.Container.Resolve<ILogService>(); LogService = ContainerLocator.Container.Resolve<ILogService>();
LogService.Error("Start-->OnInitialized"); LogService.Info("程序启动");
base.OnInitialized(); base.OnInitialized();
//#endregion //#endregion
@@ -283,13 +283,31 @@ namespace CapMachine.Wpf
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
//非UI线程未捕获异常处理事件 (例如自己创建的一个子线程) //非UI线程未捕获异常处理事件 (例如自己创建的一个子线程)
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
//首次抛出(含被吞掉的)异常也落日志,便于排查闪退场景下原生互操作异常
AppDomain.CurrentDomain.FirstChanceException += (s, fce) =>
{
try
{
var ex = fce.Exception;
//只关心严重异常,避免日志被刷爆
if (ex is AccessViolationException
|| ex is System.Runtime.InteropServices.SEHException
|| ex is StackOverflowException
|| ex is OutOfMemoryException)
{
LogService?.Error($"[FirstChance-FATAL] {ex.GetType().Name}: {ex.Message}\r\n{ex.StackTrace}");
}
}
catch { /* 异常处理函数中绝不能再抛 */ }
};
} }
void App_Exit(object sender, ExitEventArgs e) void App_Exit(object sender, ExitEventArgs e)
{ {
//程序退出时需要处理的业务 //程序退出时需要处理的业务
LogService.Error("程序退出"); LogService.Info("App-程序退出");
} }
@@ -304,12 +322,14 @@ namespace CapMachine.Wpf
try try
{ {
HandleException(e.Exception); HandleException(e.Exception);
MessageBox.Show("UI线程异常:" + e.Exception.Message); //MessageBox.Show("UI线程异常:" + e.Exception.Message);
LogService.Error("UI线程异常:" + e.Exception.Message);
} }
catch (Exception ex) catch (Exception ex)
{ {
HandleException(ex); HandleException(ex);
MessageBox.Show("UI线程发生致命错误"); //MessageBox.Show("UI线程发生致命错误");
LogService.Error("UI线程发生致命错误");
} }
finally finally
{ {
@@ -346,8 +366,8 @@ namespace CapMachine.Wpf
{ {
sbEx.Append(e.ExceptionObject); sbEx.Append(e.ExceptionObject);
} }
MessageBox.Show(sbEx.ToString()); //MessageBox.Show(sbEx.ToString());
LogService.Error(sbEx.ToString());
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -374,7 +394,8 @@ namespace CapMachine.Wpf
{ {
HandleException(exception); HandleException(exception);
//task线程内未处理捕获 //task线程内未处理捕获
MessageBox.Show("Task线程异常" + e.Exception.Message); //MessageBox.Show("Task线程异常" + e.Exception.Message);
LogService.Error($"Task线程异常");
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -395,7 +416,7 @@ namespace CapMachine.Wpf
private void HandleException(Exception ex) private void HandleException(Exception ex)
{ {
//记录日志 //记录日志
LogService.Error(ex.ToString()); LogService.Error($"App捕捉HandleException-{ex.ToString()}");
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework> <TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
@@ -15,6 +15,7 @@
<None Remove="Assets\Images\favicon.ico" /> <None Remove="Assets\Images\favicon.ico" />
<None Remove="Assets\Images\Logo.png" /> <None Remove="Assets\Images\Logo.png" />
<None Remove="Assets\Images\参考工艺图.png" /> <None Remove="Assets\Images\参考工艺图.png" />
<None Remove="NLog.config" />
<None Remove="PPCalculation\REFPROP\FLUIDS\13BUTADIENE.FLD" /> <None Remove="PPCalculation\REFPROP\FLUIDS\13BUTADIENE.FLD" />
<None Remove="PPCalculation\REFPROP\FLUIDS\1BUTENE.FLD" /> <None Remove="PPCalculation\REFPROP\FLUIDS\1BUTENE.FLD" />
<None Remove="PPCalculation\REFPROP\FLUIDS\1BUTYNE.FLD" /> <None Remove="PPCalculation\REFPROP\FLUIDS\1BUTYNE.FLD" />
@@ -184,6 +185,9 @@
<Content Include="Assets\Images\Logo.png"> <Content Include="Assets\Images\Logo.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="PPCalculation\REFPROP\FLUIDS\13BUTADIENE.FLD"> <Content Include="PPCalculation\REFPROP\FLUIDS\13BUTADIENE.FLD">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>

View File

@@ -43,10 +43,22 @@ namespace CapMachine.Wpf.Converts
//int second = TotalSec % 60; //int second = TotalSec % 60;
//return string.Format("{0}:{1}:{2}", hour, minute, second); //return string.Format("{0}:{1}:{2}", hour, minute, second);
////Console.WriteLine(result); //////Console.WriteLine(result);
TimeSpan TimeInfo = TimeSpan.FromSeconds(TotalSec); //TimeSpan TimeInfo = TimeSpan.FromSeconds(TotalSec);
return TimeInfo.ToString(); //return TimeInfo.ToString();
return ConvertSecToTimeStr(TotalSec);
}
private string ConvertSecToTimeStr(int totalSeconds)
{
int hours = totalSeconds / 3600;
int remainingSeconds = totalSeconds % 3600;
int minutes = remainingSeconds / 60;
int seconds = remainingSeconds % 60;
return $"{hours}:{minutes:D2}:{seconds:D2}";
} }
/// <summary> /// <summary>
@@ -57,8 +69,9 @@ namespace CapMachine.Wpf.Converts
{ {
try try
{ {
TimeSpan TimeInfo = TimeSpan.Parse(timeString); //TimeSpan TimeInfo = TimeSpan.Parse(timeString);
return (int)TimeInfo.TotalSeconds; //return (int)TimeInfo.TotalSeconds;
return ConvertTimeStrToSecs(timeString);
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -68,5 +81,23 @@ namespace CapMachine.Wpf.Converts
} }
public int ConvertTimeStrToSecs(string timeString)
{
string[] parts = timeString.Split(':');
if (parts.Length != 3) return 0;
//throw new FormatException("Invalid time format. Use 'hh:mm:ss'");
if (!int.TryParse(parts[0], out int hours) || hours < 0) return 0;
//throw new ArgumentException("小時必須為非負整數");
if (!int.TryParse(parts[1], out int minutes) || minutes < 0 || minutes >= 60) return 0;
//throw new ArgumentException("分鐘必須為 0-59 的整數");
if (!int.TryParse(parts[2], out int seconds) || seconds < 0 || seconds >= 60) return 0;
//throw new ArgumentException("秒必須為 0-59 的整數");
return hours * 3600 + minutes * 60 + seconds;
}
} }
} }

View File

@@ -72,6 +72,8 @@ namespace CapMachine.Wpf.Models.Tag
get { return _OperateResultSource; } get { return _OperateResultSource; }
set set
{ {
if (value!.Content == null) return;
switch (ValueType) switch (ValueType)
{ {
case DataType.Short: case DataType.Short:

View File

@@ -102,6 +102,7 @@ namespace CapMachine.Wpf.Services
/// 在程序配置好后就确定要发送哪些数据 /// 在程序配置好后就确定要发送哪些数据
/// </summary> /// </summary>
public List<CanCmdData> CmdData { get; set; } = new List<CanCmdData>(); public List<CanCmdData> CmdData { get; set; } = new List<CanCmdData>();
private readonly object _cmdDataLock = new object();
/// <summary> /// <summary>
/// 增加发送的指令数据 /// 增加发送的指令数据
@@ -128,7 +129,10 @@ namespace CapMachine.Wpf.Services
break; break;
} }
//添加到发送数据集合 //添加到发送数据集合
CmdData.Add(SendCanCmdData); lock (_cmdDataLock)
{
CmdData.Add(SendCanCmdData);
}
} }
@@ -141,7 +145,10 @@ namespace CapMachine.Wpf.Services
{ {
if (SpeedCanCmdData != null) if (SpeedCanCmdData != null)
{ {
SpeedCanCmdData.SignalCmdValue = SpeedData; lock (_cmdDataLock)
{
SpeedCanCmdData.SignalCmdValue = SpeedData;
}
} }
//if (EnableCanCmdData != null) //if (EnableCanCmdData != null)
//{ //{
@@ -157,7 +164,10 @@ namespace CapMachine.Wpf.Services
{ {
if (EnableCanCmdData != null) if (EnableCanCmdData != null)
{ {
EnableCanCmdData.SignalCmdValue = IsEnable ? 1 : 0; lock (_cmdDataLock)
{
EnableCanCmdData.SignalCmdValue = IsEnable ? 1 : 0;
}
} }
} }
@@ -174,7 +184,18 @@ namespace CapMachine.Wpf.Services
//更新速度信息 //更新速度信息
UpdateSpeedCmdData(SpeedData); UpdateSpeedCmdData(SpeedData);
ToomossCanDrive.SendCanMsg(CmdData); List<CanCmdData> cmdDataSnapshot;
lock (_cmdDataLock)
{
cmdDataSnapshot = CmdData.Select(x => new CanCmdData
{
ConfigName = x.ConfigName,
MsgName = x.MsgName,
SignalName = x.SignalName,
SignalCmdValue = x.SignalCmdValue
}).ToList();
}
ToomossCanDrive.SendCanMsg(cmdDataSnapshot);
} }
else else
{ {
@@ -189,7 +210,7 @@ namespace CapMachine.Wpf.Services
/// <summary> /// <summary>
/// 循环发送数据到CAN /// 循环发送数据到CAN
/// </summary> /// </summary>
public void CycleSendMsg() public void CycleSendMsg()
{ {
@@ -201,7 +222,7 @@ namespace CapMachine.Wpf.Services
{ {
ToomossCanDrive.IsCycleSend = true; ToomossCanDrive.IsCycleSend = true;
ToomossCanDrive.CmdData = CmdData; ToomossCanDrive.CmdData = CmdData;
ToomossCanDrive.StartCycleSendMsg(); ToomossCanDrive.StartPrecisionCycleSendMsg();
} }
else else
{ {
@@ -210,7 +231,7 @@ namespace CapMachine.Wpf.Services
} }
else else
{ {
ToomossCanDrive.IsCycleSend = false; ToomossCanDrive.StopCycleSendMsg();
} }
} }
@@ -255,10 +276,10 @@ namespace CapMachine.Wpf.Services
{ {
if (!ToomossCanDrive.IsCycleRevice) return 0; if (!ToomossCanDrive.IsCycleRevice) return 0;
if (ListCanDbcModel.Any(a => a.Name == Name)) var dbcModel = ListCanDbcModel.FindFirst(a => a.Name == Name);
if (dbcModel != null && !string.IsNullOrWhiteSpace(dbcModel.SignalRtValue))
{ {
//double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue, out double Result1); return double.TryParse(dbcModel.SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
return double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
} }
return 0; return 0;
} }
@@ -274,10 +295,10 @@ namespace CapMachine.Wpf.Services
{ {
if (!ToomossCanDrive.IsCycleRevice) return 0; if (!ToomossCanDrive.IsCycleRevice) return 0;
if (ListCanDbcModel.Any(a => a.Name == Name)) var dbcModel = ListCanDbcModel.FindFirst(a => a.Name == Name);
if (dbcModel != null && !string.IsNullOrWhiteSpace(dbcModel.SignalRtValue))
{ {
//double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue, out double Result1); return double.TryParse(dbcModel.SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
return double.TryParse(ListCanDbcModel.FindFirst(a => a.Name == Name).SignalRtValue.Split(" ")[0], out double Result) == true ? Result : 0;
} }
return 0; return 0;
} }

View File

@@ -36,6 +36,7 @@ namespace CapMachine.Wpf.Services
public CanDriveService CanDriveService { get; } public CanDriveService CanDriveService { get; }
public LinDriveService LinDriveService { get; } public LinDriveService LinDriveService { get; }
public SysRunService SysRunService { get; } public SysRunService SysRunService { get; }
public ILogService LogService { get; }
/// <summary> /// <summary>
/// PLCScanTask扫描Task /// PLCScanTask扫描Task
@@ -112,7 +113,7 @@ namespace CapMachine.Wpf.Services
/// </summary> /// </summary>
/// <param name="eventAggregator"></param> /// <param name="eventAggregator"></param>
public MachineRtDataService(IEventAggregator eventAggregator, AlarmService alarmService, ConfigService configService, public MachineRtDataService(IEventAggregator eventAggregator, AlarmService alarmService, ConfigService configService,
CanDriveService canDriveService, LinDriveService linDriveService, SysRunService sysRunService)//, AlarmService alarmService CanDriveService canDriveService, LinDriveService linDriveService, SysRunService sysRunService, ILogService logService)//, AlarmService alarmService
{ {
//ConcurrentDictionary<DateTime, RecordInfo> keyValuePairs = new ConcurrentDictionary<DateTime, RecordInfo>(); //ConcurrentDictionary<DateTime, RecordInfo> keyValuePairs = new ConcurrentDictionary<DateTime, RecordInfo>();
@@ -130,6 +131,7 @@ namespace CapMachine.Wpf.Services
CanDriveService = canDriveService; CanDriveService = canDriveService;
LinDriveService = linDriveService; LinDriveService = linDriveService;
SysRunService = sysRunService; SysRunService = sysRunService;
LogService = logService;
//秒触发一次 //秒触发一次
CycleTimer = new System.Timers.Timer(500); CycleTimer = new System.Timers.Timer(500);
@@ -1108,14 +1110,20 @@ namespace CapMachine.Wpf.Services
/// </summary> /// </summary>
private void RtScanDeviceStart() private void RtScanDeviceStart()
{ {
LogService.Info("RtScanDeviceStart 开始启动 PLC 扫描线程");
PLCScanTask = Task.Run(async () => PLCScanTask = Task.Run(async () =>
{ {
Stopwatch stopwatch = new Stopwatch(); Stopwatch stopwatch = new Stopwatch();
int cycleCount = 0;
while (ThreadEnable) while (ThreadEnable)
{ {
//await Task.Delay(5); cycleCount++;
await Task.CompletedTask; if (cycleCount % 100 == 0)
{
LogService.Info($"RtScanDeviceStart 循环计数: {cycleCount}");
}
await Task.Delay(50);
DiagnosticsTime.Reset(); DiagnosticsTime.Reset();
DiagnosticsTime.Start(); DiagnosticsTime.Start();
@@ -1134,6 +1142,7 @@ namespace CapMachine.Wpf.Services
// IsShowCount = 0; // IsShowCount = 0;
// IsValueShow = true; // IsValueShow = true;
//} //}
foreach (var itemTag in TagManger.DicTags) foreach (var itemTag in TagManger.DicTags)
{ {
//TagManger.GetTagInfoValueByName<short>(itemTag.Value.Name)!.Value = (short)random.Next(0, 100); //TagManger.GetTagInfoValueByName<short>(itemTag.Value.Name)!.Value = (short)random.Next(0, 100);
@@ -1172,7 +1181,15 @@ namespace CapMachine.Wpf.Services
{ {
case CanLinEnum.Can: case CanLinEnum.Can:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC
SiemensDrive.Write(itemTag.Value.PVAddress, (short)CanDriveService.GetDbcSpeedValueBySpeedName("通讯转速")); try
{
var speedValue = CanDriveService.GetDbcSpeedValueBySpeedName("通讯转速");
SiemensDrive.Write(itemTag.Value.PVAddress, (short)speedValue);
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 读取CAN通讯转速失败: {ex.Message}");
}
//itemTag.Value.EngPvValue = 0; //itemTag.Value.EngPvValue = 0;
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1190,7 +1207,15 @@ namespace CapMachine.Wpf.Services
{ {
case CanLinEnum.Can: case CanLinEnum.Can:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(CanDriveService.GetDbcValueByName("通讯母线电压") * itemTag.Value.Precision)); try
{
var voltageValue = CanDriveService.GetDbcValueByName("通讯母线电压");
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(voltageValue * itemTag.Value.Precision));
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 读取CAN通讯母线电压失败: {ex.Message}");
}
//itemTag.Value.EngPvValue = 0; //itemTag.Value.EngPvValue = 0;
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1208,7 +1233,15 @@ namespace CapMachine.Wpf.Services
{ {
case CanLinEnum.Can: case CanLinEnum.Can:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(CanDriveService.GetDbcValueByName("通讯母线电流") * itemTag.Value.Precision)); try
{
var currentValue = CanDriveService.GetDbcValueByName("通讯母线电流");
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(currentValue * itemTag.Value.Precision));
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 读取CAN通讯母线电流失败: {ex.Message}");
}
//itemTag.Value.EngPvValue = 0; //itemTag.Value.EngPvValue = 0;
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1226,7 +1259,15 @@ namespace CapMachine.Wpf.Services
{ {
case CanLinEnum.Can: case CanLinEnum.Can:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(CanDriveService.GetDbcValueByName("通讯相电流") * itemTag.Value.Precision)); try
{
var phaseCurrentValue = CanDriveService.GetDbcValueByName("通讯相电流");
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(phaseCurrentValue * itemTag.Value.Precision));
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 读取CAN通讯相电流失败: {ex.Message}");
}
//itemTag.Value.EngPvValue = 0; //itemTag.Value.EngPvValue = 0;
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1244,7 +1285,15 @@ namespace CapMachine.Wpf.Services
{ {
case CanLinEnum.Can: case CanLinEnum.Can:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(CanDriveService.GetDbcValueByName("通讯功率") * itemTag.Value.Precision)); try
{
var powerValue = CanDriveService.GetDbcValueByName("通讯功率");
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(powerValue * itemTag.Value.Precision));
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 读取CAN通讯功率失败: {ex.Message}");
}
//itemTag.Value.EngPvValue = 0; //itemTag.Value.EngPvValue = 0;
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1262,7 +1311,15 @@ namespace CapMachine.Wpf.Services
{ {
case CanLinEnum.Can: case CanLinEnum.Can:
//通信转速 Dbc中间配置名称的转速数据读取出来 给PLC //通信转速 Dbc中间配置名称的转速数据读取出来 给PLC
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(CanDriveService.GetDbcValueByName("通讯芯片温度") * itemTag.Value.Precision)); try
{
var tempValue = CanDriveService.GetDbcValueByName("通讯芯片温度");
SiemensDrive.Write(itemTag.Value.PVAddress, (short)(tempValue * itemTag.Value.Precision));
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 读取CAN通讯芯片温度失败: {ex.Message}");
}
//itemTag.Value.EngPvValue = 0; //itemTag.Value.EngPvValue = 0;
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1296,7 +1353,15 @@ namespace CapMachine.Wpf.Services
if (itemTag.Value.Group == "CANLIN") if (itemTag.Value.Group == "CANLIN")
{ {
//回读CAN通信的DBC集合数据到集合中 //回读CAN通信的DBC集合数据到集合中
itemTag.Value.EngPvValue = CanDriveService.GetDbcValueByName(itemTag.Value.NameNoUnit); try
{
var dbcValue = CanDriveService.GetDbcValueByName(itemTag.Value.NameNoUnit);
itemTag.Value.EngPvValue = dbcValue;
}
catch (Exception ex)
{
LogService.Error($"RtScanDeviceStart 回读CAN数据 {itemTag.Value.NameNoUnit} 失败: {ex.Message}");
}
} }
break; break;
case CanLinEnum.Lin: case CanLinEnum.Lin:
@@ -1437,8 +1502,11 @@ namespace CapMachine.Wpf.Services
} }
catch (Exception ex) catch (Exception ex)
{ {
//LogService.Info($"时间:{DateTime.Now.ToString()}-【Meter】-{ex.Message}"); LogService.Error($"RtScanDeviceStart 扫描异常 (周期 {cycleCount}): {ex.Message}\r\n堆栈: {ex.StackTrace}");
}
finally
{
DiagnosticsTime.Stop();
} }
DiagnosticsTime.Stop(); DiagnosticsTime.Stop();

View File

@@ -39,9 +39,9 @@ namespace CapMachine.Wpf.ViewModels
IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService, IEventAggregator eventAggregator, IRegionManager regionManager, SysRunService sysRunService,
ComActionService actionService, ComActionService actionService,
ConfigService configService, CanDriveService canDriveService, ConfigService configService, CanDriveService canDriveService,
IMapper mapper, MachineRtDataService machineRtDataService) IMapper mapper, MachineRtDataService machineRtDataService, ILogService logService)
{ {
//LogService = logService; LogService = logService;
FreeSql = freeSql; FreeSql = freeSql;
EventAggregator = eventAggregator; EventAggregator = eventAggregator;
RegionManager = regionManager; RegionManager = regionManager;
@@ -52,7 +52,6 @@ namespace CapMachine.Wpf.ViewModels
Mapper = mapper; Mapper = mapper;
this.MachineRtDataService = machineRtDataService; this.MachineRtDataService = machineRtDataService;
//MachineDataService = machineDataService;
DialogService = dialogService; DialogService = dialogService;
WriteNameCbxItems = new ObservableCollection<CbxItems>() WriteNameCbxItems = new ObservableCollection<CbxItems>()
@@ -89,6 +88,7 @@ namespace CapMachine.Wpf.ViewModels
public CanDriveService CanDriveService { get; } public CanDriveService CanDriveService { get; }
public IMapper Mapper { get; } public IMapper Mapper { get; }
private MachineRtDataService MachineRtDataService { get; } private MachineRtDataService MachineRtDataService { get; }
public ILogService LogService { get; }
/// <summary> /// <summary>
/// 弹窗服务 /// 弹窗服务
@@ -104,55 +104,58 @@ namespace CapMachine.Wpf.ViewModels
/// </summary> /// </summary>
private void InitLoadCanConfigPro() private void InitLoadCanConfigPro()
{ {
//CAN配置集合数据 try
canLinConfigPros = FreeSql.Select<CanLinConfigPro>().Where(a => a.CANLINInfo == CANLIN.CAN)
.Include(a => a.CANConfigExd)
.IncludeMany(a => a.CanLinConfigContents)
.ToList();
ListCanLinConfigPro = new ObservableCollection<CanLinConfigPro>(canLinConfigPros);
if (SelectCanLinConfigPro != null)
{ {
SelectCanLinConfigPro = canLinConfigPros.Where(a => a.Id == SelectCanLinConfigPro.Id).FirstOrDefault()!; LogService.Info("开始加载CAN配置数据");
//无数据就返回 //CAN配置集合数据
if (SelectCanLinConfigPro == null) return; canLinConfigPros = FreeSql.Select<CanLinConfigPro>().Where(a => a.CANLINInfo == CANLIN.CAN)
.Include(a => a.CANConfigExd)
SelectedCANConfigExdDto = Mapper.Map<CANConfigExdDto>(SelectCanLinConfigPro!.CANConfigExd); .IncludeMany(a => a.CanLinConfigContents)
.ToList();
//配置信息 ListCanLinConfigPro = new ObservableCollection<CanLinConfigPro>(canLinConfigPros);
var WirteData = SelectCanLinConfigPro.CanLinConfigContents!.Where(a => a.RWInfo == RW.Write).ToList(); if (SelectCanLinConfigPro != null)
if (WirteData != null && WirteData.Count > 0)
{ {
ListWriteCanLinRWConfigDto = new ObservableCollection<CanLinRWConfigDto>(Mapper.Map<List<CanLinRWConfigDto>>(WirteData)); SelectCanLinConfigPro = canLinConfigPros.Where(a => a.Id == SelectCanLinConfigPro.Id).FirstOrDefault()!;
//无数据就返回
if (SelectCanLinConfigPro == null) return;
SelectedCANConfigExdDto = Mapper.Map<CANConfigExdDto>(SelectCanLinConfigPro!.CANConfigExd);
//加载把当前的配置信息给指令 //配置信息
CanDriveService.CmdData.Clear(); var WirteData = SelectCanLinConfigPro.CanLinConfigContents!.Where(a => a.RWInfo == RW.Write).ToList();
foreach (var item in WirteData) if (WirteData != null && WirteData.Count > 0)
{ {
CanDriveService.AddCmdData(new CanCmdData() ListWriteCanLinRWConfigDto = new ObservableCollection<CanLinRWConfigDto>(Mapper.Map<List<CanLinRWConfigDto>>(WirteData));
{
ConfigName = item.Name,
MsgName = item.MsgFrameName,
SignalName = item.SignalName,
SignalCmdValue = double.TryParse(item.DefautValue, out double result) == true ? result : 0,
});
//CanDriveService.CmdData.Add(new CanCmdData()
//{
// ConfigName = item.Name,
// MsgName = item.MsgFrameName,
// SignalName = item.SignalName,
// SignalCmdValue = double.TryParse(item.DefautValue, out double result) == true ? result : 0,
//});
}
}
var ReadData = SelectCanLinConfigPro.CanLinConfigContents!.Where(a => a.RWInfo == RW.Read).ToList();
if (ReadData != null && ReadData.Count > 0)
{
ListReadCanLinRWConfigDto = new ObservableCollection<CanLinRWConfigDto>(Mapper.Map<List<CanLinRWConfigDto>>(ReadData));
}
//匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListCanDbcModel //加载把当前的配置信息给指令
MatchSeletedAndCanDbcModel(); CanDriveService.CmdData.Clear();
foreach (var item in WirteData)
{
CanDriveService.AddCmdData(new CanCmdData()
{
ConfigName = item.Name,
MsgName = item.MsgFrameName,
SignalName = item.SignalName,
SignalCmdValue = double.TryParse(item.DefautValue, out double result) == true ? result : 0,
});
}
}
var ReadData = SelectCanLinConfigPro.CanLinConfigContents!.Where(a => a.RWInfo == RW.Read).ToList();
if (ReadData != null && ReadData.Count > 0)
{
ListReadCanLinRWConfigDto = new ObservableCollection<CanLinRWConfigDto>(Mapper.Map<List<CanLinRWConfigDto>>(ReadData));
}
//匹配选中的SelectCanLinConfigPro.CanLinConfigContents和ListCanDbcModel
MatchSeletedAndCanDbcModel();
}
LogService.Info("CAN配置数据加载成功");
}
catch (Exception ex)
{
LogService.Error($"加载CAN配置数据失败: {ex.Message}\r\n堆栈: {ex.StackTrace}");
System.Windows.MessageBox.Show($"加载CAN配置数据失败: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
} }
} }
@@ -373,41 +376,70 @@ namespace CapMachine.Wpf.ViewModels
} }
break; break;
case "Active": case "Active":
try
//激活到取消的状态的判断
if (IsCanConfigProActive == true)
{ {
//控件的激活 LogService.Info("开始执行CAN配置激活操作");
IsCanConfigProActive = !IsCanConfigProActive; //激活到取消的状态的判断
//控件的激活配置信息 if (IsCanConfigProActive == true)
IsCANConfigDatagridActive = !IsCanConfigProActive;
return;
}
if ((CanDriveService.ToomossCanDrive.OpenState == true && CanDriveService.ToomossCanDrive.DbcParserState == true))
{
if (SelectCanLinConfigPro != null)
{ {
LogService.Info("准备取消激活状态");
//控件的激活 //控件的激活
IsCanConfigProActive = !IsCanConfigProActive; IsCanConfigProActive = !IsCanConfigProActive;
LogService.Info("IsCanConfigProActive已更新");
//控件的激活配置信息 //控件的激活配置信息
IsCANConfigDatagridActive = !IsCanConfigProActive; IsCANConfigDatagridActive = !IsCanConfigProActive;
LogService.Info("IsCANConfigDatagridActive已更新");
//当前使用的CAN 配置信息 LogService.Info("CAN配置已取消激活");
CanDriveService.InitCanConfig(SelectCanLinConfigPro); return;
}
if ((CanDriveService.ToomossCanDrive.OpenState == true && CanDriveService.ToomossCanDrive.DbcParserState == true))
{
if (SelectCanLinConfigPro != null)
{
LogService.Info($"准备激活配置: {SelectCanLinConfigPro.ConfigName}");
//控件的激活
IsCanConfigProActive = !IsCanConfigProActive;
LogService.Info("IsCanConfigProActive已更新为true");
//控件的激活配置信息
IsCANConfigDatagridActive = !IsCanConfigProActive;
LogService.Info("IsCANConfigDatagridActive已更新");
//当前使用的CAN 配置信息
LogService.Info("开始调用InitCanConfig");
CanDriveService.InitCanConfig(SelectCanLinConfigPro);
LogService.Info("InitCanConfig完成");
LogService.Info("开始调用InitLoadCanConfigPro");
InitLoadCanConfigPro();
LogService.Info($"CAN配置激活成功: {SelectCanLinConfigPro.ConfigName}");
}
else
{
System.Windows.MessageBox.Show("选中后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
}
InitLoadCanConfigPro();
} }
else else
{ {
System.Windows.MessageBox.Show("选中后再操作", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); System.Windows.MessageBox.Show("请确保CAN连接打开和Dbc解析成功后再激活", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand);
} }
} }
else catch (Exception ex)
{ {
System.Windows.MessageBox.Show("请确保CAN连接打开和Dbc解析成功后再激活", "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Hand); LogService.Error($"CAN配置激活操作失败: {ex.Message}\r\n堆栈: {ex.StackTrace}");
System.Windows.MessageBox.Show($"CAN配置激活操作失败: {ex.Message}", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
//恢复状态
try
{
IsCanConfigProActive = false;
IsCANConfigDatagridActive = true;
}
catch (Exception restoreEx)
{
LogService.Error($"恢复状态失败: {restoreEx.Message}");
}
} }
break; break;
default: default:

View File

@@ -17,6 +17,7 @@ using System.Collections.ObjectModel;
using System.Data; using System.Data;
using System.Text; using System.Text;
using System.Windows; using System.Windows;
using System.Windows.Controls;
namespace CapMachine.Wpf.ViewModels namespace CapMachine.Wpf.ViewModels
{ {
@@ -1759,7 +1760,16 @@ namespace CapMachine.Wpf.ViewModels
// cr.EndEdit(); // cr.EndEdit();
//} //}
var dd = par; //if (par is DataGrid dataGrid && dataGrid.SelectedCells.Count > 0)
//{
// var selectedCell = dataGrid.SelectedCells[0];
// string columnHeader = selectedCell.Column.Header?.ToString();
// // 处理列头信息
//}
//var dd = par;
//var dd = new SelectedCellsCollection(); //var dd = new SelectedCellsCollection();
//if (par is SelectedCellCo selectedCells) //if (par is SelectedCellCo selectedCells)
//{ //{
@@ -15897,8 +15907,16 @@ namespace CapMachine.Wpf.ViewModels
{ {
try try
{ {
TimeSpan TimeInfo = TimeSpan.FromSeconds(TotalSec); //TimeSpan TimeInfo = TimeSpan.FromSeconds(TotalSec);
return TimeInfo.ToString(); //return TimeInfo.ToString();
int hours = TotalSec / 3600;
int remainingSeconds = TotalSec % 3600;
int minutes = remainingSeconds / 60;
int seconds = remainingSeconds % 60;
return $"{hours}:{minutes:D2}:{seconds:D2}";
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -15908,8 +15926,6 @@ namespace CapMachine.Wpf.ViewModels
} }
#region #region
/// <summary> /// <summary>

View File

@@ -833,9 +833,11 @@
<prism:InvokeCommandAction Command="{Binding GridSelectionChangedCmd}" CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" /> <prism:InvokeCommandAction Command="{Binding GridSelectionChangedCmd}" CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" />
</i:EventTrigger> </i:EventTrigger>
<i:EventTrigger EventName="SelectedCellsChanged"> <i:EventTrigger EventName="SelectedCellsChanged">
<prism:InvokeCommandAction Command="{Binding GridSelectedCellsChangedCmd}" CommandParameter="{Binding SelectedCells, ElementName=MainDatagrid}" /> <prism:InvokeCommandAction Command="{Binding GridSelectedCellsChangedCmd}" CommandParameter="{Binding ElementName=MainDatagrid}" />
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
<!-- CommandParameter="{Binding SelectedCells, ElementName=MainDatagrid}" /> -->
<!--<prism:InvokeCommandAction Command="{Binding GridSelectionChangedCmd}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}" />--> <!--<prism:InvokeCommandAction Command="{Binding GridSelectionChangedCmd}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}}" />-->
<!-- CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" --> <!-- CommandParameter="{Binding ElementName=MainDatagrid, Path=SelectedItem}" -->
<!--<DataGrid.RowStyle> <!--<DataGrid.RowStyle>
@@ -1474,7 +1476,7 @@
VerticalAlignment="Center" VerticalAlignment="Center"
FontSize="12" FontSize="12"
FontWeight="Bold" FontWeight="Bold"
Text="COND1温度&#10;(℃)" /> Text="冷凝器出口水温&#x0A;(℃)" />
</StackPanel> </StackPanel>
</TabItem.Header> </TabItem.Header>
<Controls:MeterConfig <Controls:MeterConfig
@@ -1488,7 +1490,7 @@
EditCommand="{Binding ProStepCond1TempEditCmd}" EditCommand="{Binding ProStepCond1TempEditCmd}"
IsTimeOk="{Binding MeterCond1TempExDto.IsTimeOk}" IsTimeOk="{Binding MeterCond1TempExDto.IsTimeOk}"
ListMeter="{Binding ListSlopMeterCond1TempItems}" ListMeter="{Binding ListSlopMeterCond1TempItems}"
MeterName="COND1温度" MeterName="冷凝器出口水温"
MeterSelectedChangedCmd="{Binding MeterCond1TempSlopSelectedChangedCmd}" MeterSelectedChangedCmd="{Binding MeterCond1TempSlopSelectedChangedCmd}"
ParConfigCommand="{Binding MeterCond1TempParConfigCmd}" ParConfigCommand="{Binding MeterCond1TempParConfigCmd}"
SelectedMeter="{Binding SelectedSlopCond1Temp, Mode=TwoWay}" SelectedMeter="{Binding SelectedSlopCond1Temp, Mode=TwoWay}"
@@ -1633,6 +1635,40 @@
</TabItem>--> </TabItem>-->
<TabItem>
<TabItem.Header>
<StackPanel
Width="90"
Margin="-20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="12"
FontWeight="Bold"
Text="吸气混合器温度&#x0A;(℃)" />
</StackPanel>
</TabItem.Header>
<Controls:MeterConfig
Margin="5,5,0,5"
AddCommand="{Binding ProStepOS2TempAddCmd}"
ConstSlopSelectedIndex="{Binding ProStepOS2TempSwitchConstSlopIndex, Mode=TwoWay}"
ConstantSaveCommand="{Binding ProStepOS2TempConstantSaveCmd}"
ConstantValue="{Binding SelectedConstOS2TempValue, Mode=TwoWay}"
Cycle="{Binding MeterOS2TempExDto.SlopCycle}"
DeleteCommand="{Binding ProStepOS2TempDeleteCmd}"
EditCommand="{Binding ProStepOS2TempEditCmd}"
IsTimeOk="{Binding MeterOS2TempExDto.IsTimeOk}"
ListMeter="{Binding ListSlopMeterOS2TempItems}"
MeterName="吸气混合器温度"
MeterSelectedChangedCmd="{Binding MeterOS2TempSlopSelectedChangedCmd}"
ParConfigCommand="{Binding MeterOS2TempParConfigCmd}"
SelectedMeter="{Binding SelectedSlopOS2Temp, Mode=TwoWay}"
SwitchConstSlopCommand="{Binding MeterOS2TempSwitchConstSlopCmd}"
TotalSlopTime="{Binding MeterOS2TempExDto.SlopTime}" />
</TabItem>
<TabItem> <TabItem>
<TabItem.Header> <TabItem.Header>
@@ -1668,7 +1704,6 @@
TotalSlopTime="{Binding MeterHVVolExDto.SlopTime}" /> TotalSlopTime="{Binding MeterHVVolExDto.SlopTime}" />
</TabItem> </TabItem>
<TabItem> <TabItem>
<TabItem.Header> <TabItem.Header>
<StackPanel <StackPanel
@@ -1771,39 +1806,7 @@
TotalSlopTime="{Binding MeterOS1TempExDto.SlopTime}" /> TotalSlopTime="{Binding MeterOS1TempExDto.SlopTime}" />
</TabItem>--> </TabItem>-->
<TabItem>
<TabItem.Header>
<StackPanel
Width="90"
Margin="-20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="12"
FontWeight="Bold"
Text="OS2温度&#10;(℃)" />
</StackPanel>
</TabItem.Header>
<Controls:MeterConfig
Margin="5,5,0,5"
AddCommand="{Binding ProStepOS2TempAddCmd}"
ConstSlopSelectedIndex="{Binding ProStepOS2TempSwitchConstSlopIndex, Mode=TwoWay}"
ConstantSaveCommand="{Binding ProStepOS2TempConstantSaveCmd}"
ConstantValue="{Binding SelectedConstOS2TempValue, Mode=TwoWay}"
Cycle="{Binding MeterOS2TempExDto.SlopCycle}"
DeleteCommand="{Binding ProStepOS2TempDeleteCmd}"
EditCommand="{Binding ProStepOS2TempEditCmd}"
IsTimeOk="{Binding MeterOS2TempExDto.IsTimeOk}"
ListMeter="{Binding ListSlopMeterOS2TempItems}"
MeterName="OS2温度"
MeterSelectedChangedCmd="{Binding MeterOS2TempSlopSelectedChangedCmd}"
ParConfigCommand="{Binding MeterOS2TempParConfigCmd}"
SelectedMeter="{Binding SelectedSlopOS2Temp, Mode=TwoWay}"
SwitchConstSlopCommand="{Binding MeterOS2TempSwitchConstSlopCmd}"
TotalSlopTime="{Binding MeterOS2TempExDto.SlopTime}" />
</TabItem>
<!--<TabItem> <!--<TabItem>
<TabItem.Header> <TabItem.Header>
@@ -1906,40 +1909,6 @@
TotalSlopTime="{Binding MeterPTCPwExDto.SlopTime}" /> TotalSlopTime="{Binding MeterPTCPwExDto.SlopTime}" />
</TabItem>--> </TabItem>-->
<TabItem>
<TabItem.Header>
<StackPanel
Width="90"
Margin="-20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="12"
FontWeight="Bold"
Text="压缩机环境湿度&#10;(%)" />
</StackPanel>
</TabItem.Header>
<Controls:MeterConfig
Margin="5,5,0,5"
AddCommand="{Binding ProStepEnvRHAddCmd}"
ConstSlopSelectedIndex="{Binding ProStepEnvRHSwitchConstSlopIndex, Mode=TwoWay}"
ConstantSaveCommand="{Binding ProStepEnvRHConstantSaveCmd}"
ConstantValue="{Binding SelectedConstEnvRHValue, Mode=TwoWay}"
Cycle="{Binding MeterEnvRHExDto.SlopCycle}"
DeleteCommand="{Binding ProStepEnvRHDeleteCmd}"
EditCommand="{Binding ProStepEnvRHEditCmd}"
IsTimeOk="{Binding MeterEnvRHExDto.IsTimeOk}"
ListMeter="{Binding ListSlopMeterEnvRHItems}"
MeterName="压缩机环境湿度"
MeterSelectedChangedCmd="{Binding MeterEnvRHSlopSelectedChangedCmd}"
ParConfigCommand="{Binding MeterEnvRHParConfigCmd}"
SelectedMeter="{Binding SelectedSlopEnvRH, Mode=TwoWay}"
SwitchConstSlopCommand="{Binding MeterEnvRHSwitchConstSlopCmd}"
TotalSlopTime="{Binding MeterEnvRHExDto.SlopTime}" />
</TabItem>
<TabItem> <TabItem>
<TabItem.Header> <TabItem.Header>
<StackPanel <StackPanel
@@ -1974,6 +1943,40 @@
TotalSlopTime="{Binding MeterEnvTempExDto.SlopTime}" /> TotalSlopTime="{Binding MeterEnvTempExDto.SlopTime}" />
</TabItem> </TabItem>
<TabItem>
<TabItem.Header>
<StackPanel
Width="90"
Margin="-20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="12"
FontWeight="Bold"
Text="压缩机环境湿度&#10;(%)" />
</StackPanel>
</TabItem.Header>
<Controls:MeterConfig
Margin="5,5,0,5"
AddCommand="{Binding ProStepEnvRHAddCmd}"
ConstSlopSelectedIndex="{Binding ProStepEnvRHSwitchConstSlopIndex, Mode=TwoWay}"
ConstantSaveCommand="{Binding ProStepEnvRHConstantSaveCmd}"
ConstantValue="{Binding SelectedConstEnvRHValue, Mode=TwoWay}"
Cycle="{Binding MeterEnvRHExDto.SlopCycle}"
DeleteCommand="{Binding ProStepEnvRHDeleteCmd}"
EditCommand="{Binding ProStepEnvRHEditCmd}"
IsTimeOk="{Binding MeterEnvRHExDto.IsTimeOk}"
ListMeter="{Binding ListSlopMeterEnvRHItems}"
MeterName="压缩机环境湿度"
MeterSelectedChangedCmd="{Binding MeterEnvRHSlopSelectedChangedCmd}"
ParConfigCommand="{Binding MeterEnvRHParConfigCmd}"
SelectedMeter="{Binding SelectedSlopEnvRH, Mode=TwoWay}"
SwitchConstSlopCommand="{Binding MeterEnvRHSwitchConstSlopCmd}"
TotalSlopTime="{Binding MeterEnvRHExDto.SlopTime}" />
</TabItem>
</TabControl> </TabControl>