diff --git a/Language/en_US.xaml b/Language/en_US.xaml index b301fc8..3a52c5c 100644 --- a/Language/en_US.xaml +++ b/Language/en_US.xaml @@ -50,7 +50,7 @@ P004:JSON parsing failed P021:Diamonds need to be cleaned if detected P011:No diamond was detected - Check whether the cutting machine hatch is closed + S007:Check whether the cutting machine hatch is closed MSVC Runtime is not installed and errors may occur during program execution \ No newline at end of file diff --git a/Language/zh_CN.xaml b/Language/zh_CN.xaml index f0df0bc..48a2bf1 100644 --- a/Language/zh_CN.xaml +++ b/Language/zh_CN.xaml @@ -191,7 +191,7 @@ P004:JSON解析失败 P021:检测到钻石需进行清洁 P011:未检测到钻石 - 请检查切工仪设备舱门是否关闭 + S007:请检查切工仪设备舱门是否关闭 应用程序出现错误: diff --git a/Model/Entity/ApiEntity/StatusCodes.cs b/Model/Entity/ApiEntity/StatusCodes.cs index 411f8d8..24f3c97 100644 --- a/Model/Entity/ApiEntity/StatusCodes.cs +++ b/Model/Entity/ApiEntity/StatusCodes.cs @@ -5,6 +5,8 @@ /// public static class StatusCodes { + // 成功 + public const string Ok = "ok"; // 成功 public const string Success = "S000"; diff --git a/Model/Services/AlgorithmServer.cs b/Model/Services/AlgorithmServer.cs index 90d46a7..8d2569c 100644 --- a/Model/Services/AlgorithmServer.cs +++ b/Model/Services/AlgorithmServer.cs @@ -33,7 +33,7 @@ namespace SparkClient.Model.Services object halfCircleValue = circleTable.Rows[0][0]; bool.TryParse(halfCircleValue.ToString(), out bool boolResult); bool half_circle = boolResult; - + //算法配置参数 string sql = $"SELECT JSON FROM ALGORITHM_CONFIG ORDER BY JSON_ORDER ASC"; DataTable table = DataBaseHelper.ExecuteQuery(sql); @@ -43,6 +43,11 @@ namespace SparkClient.Model.Services //图片根目录 string? image_file_base_path = ConfigurationManager.AppSettings["ImageFileBasePath"]; + // 获取 log4net 日志文件所在的目录 + string? log4NetLogDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + // 构建C++ DLL 日志文件路径 + string algorithm_log_path = Path.Combine(log4NetLogDirectory, "logs"); + // 将所有变量拼接成一个 JSON 对象 JObject jsonData = new JObject( new JProperty("shape", shape), @@ -50,13 +55,12 @@ namespace SparkClient.Model.Services new JProperty("image_file_base_path", image_file_base_path), new JProperty("image_files", JToken.Parse(image_files)), new JProperty("half_circle", half_circle), + new JProperty("algorithm_log_path", algorithm_log_path), new JProperty("algo_config", JObject.Parse(algo_config)) ); - string jsonDataString = jsonData.ToString(); // 调用 C++ DLL 函数解析 JSON IntPtr resultPtr = DetectDiamond(jsonDataString); - string resultJson = Marshal.PtrToStringAnsi(resultPtr); // 释放 DLL 分配的内存 FreeString(resultPtr); @@ -71,7 +75,6 @@ namespace SparkClient.Model.Services measurements = new Measurements() }; } - // 反序列化 JSON 字符串为 AlgorithmResultEntity 对象 var result = JsonConvert.DeserializeObject(resultJson); @@ -85,73 +88,17 @@ namespace SparkClient.Model.Services measurements = new Measurements() }; } - + // 记录算法失败的状态 + Logger.Error($"Algorithm failed with status: {result.status}"); + // 记录算法失败的错误信息 + Logger.Error($"Algorithm failed with errorMsg: {result.error_msg}"); + // 处理 C++ DLL 日志文件 + //ProcessDllLog(); // 算法调用失败时,保存图片到历史记录文件夹 - if (result.status == StatusCodes.AlgorithmFailed) - { - // 从配置文件中读取 imageHistoryPath - // 定义历史记录文件夹路径 - string? imageHistoryPath = ConfigurationManager.AppSettings["ImageHistoryPath"]; - // 生成时间戳,格式为 yyyyMMddHHmmss - string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); - // 组合新的文件夹路径 - string newFolderPath = Path.Combine(imageHistoryPath, $"image-{timestamp}"); - - // 检查 D 盘内存空间 - DriveInfo dDrive = new DriveInfo("D"); - long requiredSpace = 10L * 1024 * 1024 * 1024; // 10GB - if (dDrive.TotalFreeSpace < requiredSpace) - { - // 如果 D 盘空间不足 10GB,删除最早创建的10个文件夹 - DirectoryInfo historyDir = new DirectoryInfo(imageHistoryPath);//获取历史记录文件夹的信息 - DirectoryInfo[] subDirs = historyDir.GetDirectories();//获取历史记录文件夹中的所有子文件夹 - if (subDirs.Length > 0) - { - // 按创建时间排序子文件夹 - var orderedSubDirs = subDirs.OrderBy(d => d.CreationTime).ToList(); - int foldersToDelete = Math.Min(10, orderedSubDirs.Count); - - // 删除最早的 10 个文件夹,如果不够 10 个则全删掉 - for (int i = 0; i < foldersToDelete; i++) - { - orderedSubDirs[i].Delete(true); - } - } - } - - // 创建新文件夹 - Directory.CreateDirectory(newFolderPath); - - // 保存图片到新文件夹 - try - { - // 解析 image_files JSON 数组 - JArray imageFilesArray = JArray.Parse(image_files); - string[] imageFiles = imageFilesArray.Select(token => token.ToString()).ToArray(); - - string? imageBasePath = ConfigurationManager.AppSettings["ImageFileBasePath"];// 图片根目录 - - foreach (string imageFile in imageFiles) - { - // 获取文件名 - string fileName = Path.GetFileName(imageFile); - // 构建完整的源文件路径 - string sourcePath = Path.Combine(imageBasePath, imageFile); - // 组合目标路径 - string destinationPath = Path.Combine(newFolderPath, fileName); - // 复制文件到目标路径,如果目标文件已存在则覆盖 - File.Copy(sourcePath, destinationPath, true); - } - } - catch (JsonException ex) - { - // 记录日志或处理异常 - Logger.Error($"Error parsing image_files JSON: {ex.Message}"); - Logger.Error($"Stack Trace: {ex.StackTrace}"); - } - } - - + // if (result.status == StatusCodes.AlgorithmFailed) + // { + // HandleAlgorithmFailure(image_files); + // } return result; } catch (Exception ex) @@ -173,6 +120,154 @@ namespace SparkClient.Model.Services }; } } + + /// + /// 处理算法调用失败时的逻辑,包括保存图片到历史记录文件夹 + /// + /// 图片文件路径的 JSON 字符串 + private void HandleAlgorithmFailure(string image_files) + { + + // 从配置文件中读取 imageHistoryPath + // 定义历史记录文件夹路径 + string? imageHistoryPath = ConfigurationManager.AppSettings["ImageHistoryPath"]; + if (string.IsNullOrEmpty(imageHistoryPath)) + { + Logger.Error("ImageHistoryPath is not configured in AppSettings."); + return; + } + + // 生成时间戳,格式为 yyyyMMddHHmmss + string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); + // 组合新的文件夹路径 + string newFolderPath = Path.Combine(imageHistoryPath, $"image-{timestamp}"); + + // 检查 D 盘内存空间 + DriveInfo dDrive = new DriveInfo("D"); + long requiredSpace = 1000L * 1024 * 1024 * 1024; // 10GB + if (dDrive.TotalFreeSpace < requiredSpace) + { + // 如果 D 盘空间不足 10GB,删除最早创建的10个文件夹 + DirectoryInfo historyDir = new DirectoryInfo(imageHistoryPath); // 获取历史记录文件夹的信息 + DirectoryInfo[] subDirs = historyDir.GetDirectories(); // 获取历史记录文件夹中的所有子文件夹 + if (subDirs.Length > 0) + { + // 按创建时间排序子文件夹 + var orderedSubDirs = subDirs.OrderBy(d => d.CreationTime).ToList(); + int foldersToDelete = Math.Min(10, orderedSubDirs.Count); + + // 删除最早的 10 个文件夹,如果不够 10 个则全删掉 + for (int i = 0; i < foldersToDelete; i++) + { + orderedSubDirs[i].Delete(true); + } + } + } + + // 创建新文件夹 + Directory.CreateDirectory(newFolderPath); + + // 保存图片到新文件夹 + try + { + // 解析 image_files JSON 数组 + JArray imageFilesArray = JArray.Parse(image_files); + string[] imageFiles = imageFilesArray.Select(token => token.ToString()).ToArray(); + + string? imageBasePath = ConfigurationManager.AppSettings["ImageFileBasePath"]; // 图片根目录 + if (string.IsNullOrEmpty(imageBasePath)) + { + Logger.Error("ImageFileBasePath is not configured in AppSettings."); + return; + } + + foreach (string imageFile in imageFiles) + { + // 获取文件名 + string fileName = Path.GetFileName(imageFile); + // 构建完整的源文件路径 + string sourcePath = Path.Combine(imageBasePath, imageFile); + // 组合目标路径 + string destinationPath = Path.Combine(newFolderPath, fileName); + // 复制文件到目标路径,如果目标文件已存在则覆盖 + File.Copy(sourcePath, destinationPath, true); + } + } + catch (JsonException ex) + { + // 记录日志或处理异常 + Logger.Error($"Error parsing image_files JSON: {ex.Message}"); + Logger.Error($"Stack Trace: {ex.StackTrace}"); + } + catch (Exception ex) + { + // 记录其他异常 + Logger.Error($"Error saving images: {ex.Message}"); + Logger.Error($"Stack Trace: {ex.StackTrace}"); + } + } + + /// + /// 处理 C++ DLL 的日志文件,将其复制到 log4net 日志目录下的 logs 文件夹,并记录其内容到日志中 + /// + private void ProcessDllLog() + { + try + { + // 获取系统临时目录路径(TMP 或 TEMP 环境变量) + string? tempDirectory = Environment.GetEnvironmentVariable("TMP") ?? Environment.GetEnvironmentVariable("TEMP"); + if (tempDirectory != null) + { + // 构建搜索模式 + string searchPattern = "*diamond_cut_inspector*"; + // 获取所有匹配的文件 + string[] logFiles = Directory.GetFiles(tempDirectory, searchPattern, SearchOption.TopDirectoryOnly); + if (logFiles.Length > 0) + { + // 找到最新的日志文件 + string latestLogFile = logFiles.OrderByDescending(file => new FileInfo(file).LastWriteTime).First(); + // 获取 log4net 日志文件所在的目录 + string log4netLogDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); + if (log4netLogDirectory != null) + { + // 构建 logs 目录路径 + string logsDirectory = Path.Combine(log4netLogDirectory, "logs"); + // 确保 logs 目录存在 + Directory.CreateDirectory(logsDirectory); + // 构建目标文件路径 + string targetFilePath = Path.Combine(logsDirectory, Path.GetFileName(latestLogFile)); + // 复制最新日志文件到 logs 目录 + File.Copy(latestLogFile, targetFilePath, true); + // 读取复制后的日志文件的内容 + string dllLogContent = File.ReadAllText(targetFilePath); + // 记录 C++ DLL 日志文件的内容到日志中 + Logger.Error("C++ DLL Log Content:"); + Logger.Error(dllLogContent); + } + else + { + Logger.Error("Unable to determine the log4net log directory."); + } + } + else + { + // 如果没有找到匹配的日志文件,记录错误信息 + Logger.Error("No C++ DLL log files found matching the pattern '*diamond_cut_inspector*.log'."); + } + } + else + { + // 如果无法获取临时目录路径,记录错误信息 + Logger.Error("Unable to determine the temporary directory path."); + } + } + catch (Exception ex) + { + // 记录读取或复制日志文件时的异常 + Logger.Error($"Error processing C++ DLL log file: {ex.Message}"); + Logger.Error($"Stack Trace: {ex.StackTrace}"); + } + } } } diff --git a/SparkClient.sln.DotSettings.user b/SparkClient.sln.DotSettings.user index 5990b75..ebbda40 100644 --- a/SparkClient.sln.DotSettings.user +++ b/SparkClient.sln.DotSettings.user @@ -57,6 +57,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded diff --git a/SparkDB.db b/SparkDB.db index 6b845ec..f7c0790 100644 Binary files a/SparkDB.db and b/SparkDB.db differ diff --git a/ViewModel/Grading/DiamondSelectVM.cs b/ViewModel/Grading/DiamondSelectVM.cs index f6a2906..9403e35 100644 --- a/ViewModel/Grading/DiamondSelectVM.cs +++ b/ViewModel/Grading/DiamondSelectVM.cs @@ -1,3 +1,4 @@ +using System.Configuration; using Newtonsoft.Json; using SparkClient.Model.Entity.ApiEntity; using SparkClient.Model.Helper; @@ -15,6 +16,8 @@ using SparkClient.Model.Services; using System.Text; using System.IO; using System.Windows.Media; +using log4net; +using Newtonsoft.Json.Linq; using SparkClient.Model.Common; using Color = System.Windows.Media.Color; using MessageBox = SparkClient.Views.Dialog.MessageBox; @@ -170,7 +173,6 @@ public class DiamondSelectVM : BaseViewModel parameter.CrownType = value.Split(" ")[1]; parameter.PavType = value.Split(" ")[2]; } - // 初始化SOC客户端服务,传入SOC端的地址和认证Token _socClientService = new SOCClientService(); // 启动soc @@ -207,6 +209,10 @@ public class DiamondSelectVM : BaseViewModel string image_files = JsonConvert.SerializeObject(socResolt.Images, Formatting.Indented); //string image_files =$"[ \"image_0.bmp\", \"image_1.bmp\", \"image_2.bmp\", \"image_3.bmp\", \"image_4.bmp\", \"image_5.bmp\", \"image_6.bmp\", \"image_7.bmp\", \"image_8.bmp\", \"image_9.bmp\", \"image_10.bmp\", \"image_11.bmp\", \"image_12.bmp\", \"image_13.bmp\", \"image_14.bmp\", \"image_15.bmp\", \"image_16.bmp\", \"image_17.bmp\", \"image_18.bmp\", \"image_19.bmp\", \"image_20.bmp\", \"image_21.bmp\", \"image_22.bmp\", \"image_23.bmp\", \"image_24.bmp\", \"image_25.bmp\", \"image_26.bmp\", \"image_27.bmp\", \"image_28.bmp\", \"image_29.bmp\", \"image_30.bmp\", \"image_31.bmp\", \"image_32.bmp\", \"image_33.bmp\", \"image_34.bmp\", \"image_35.bmp\", \"image_36.bmp\", \"image_37.bmp\", \"image_38.bmp\", \"image_39.bmp\", \"image_40.bmp\", \"image_41.bmp\", \"image_42.bmp\", \"image_43.bmp\", \"image_44.bmp\", \"image_45.bmp\", \"image_46.bmp\", \"image_47.bmp\", \"image_48.bmp\", \"image_49.bmp\", \"image_50.bmp\", \"image_51.bmp\", \"image_52.bmp\", \"image_53.bmp\", \"image_54.bmp\", \"image_55.bmp\", \"image_56.bmp\", \"image_57.bmp\", \"image_58.bmp\", \"image_59.bmp\", \"image_60.bmp\", \"image_61.bmp\", \"image_62.bmp\", \"image_63.bmp\", \"image_64.bmp\", \"image_65.bmp\", \"image_66.bmp\", \"image_67.bmp\", \"image_68.bmp\", \"image_69.bmp\", \"image_70.bmp\", \"image_71.bmp\", \"image_72.bmp\", \"image_73.bmp\", \"image_74.bmp\", \"image_75.bmp\", \"image_76.bmp\", \"image_77.bmp\", \"image_78.bmp\", \"image_79.bmp\", \"image_80.bmp\", \"image_81.bmp\", \"image_82.bmp\", \"image_83.bmp\", \"image_84.bmp\", \"image_85.bmp\", \"image_86.bmp\", \"image_87.bmp\", \"image_88.bmp\", \"image_89.bmp\", \"image_90.bmp\", \"image_91.bmp\", \"image_92.bmp\", \"image_93.bmp\", \"image_94.bmp\", \"image_95.bmp\", \"image_96.bmp\", \"image_97.bmp\", \"image_98.bmp\", \"image_99.bmp\"]" ; + // 保存图片到历史记录文件夹 + HandleAlgorithmFailure(image_files); + + // 启动算法 parameter = _algorithmServer.CallParseJsonAndReturnActions(parameter.Shape, parameter.CrownType, image_files); //机器号 @@ -365,7 +371,95 @@ public class DiamondSelectVM : BaseViewModel await Task.Delay(5); loading.Close(); } + } + /// + /// 处理算法调用失败时的逻辑,包括保存图片到历史记录文件夹 + /// + /// 图片文件路径的 JSON 字符串 + /// + private static readonly ILog Logger = LogManager.GetLogger(typeof(AlgorithmServer)); + private void HandleAlgorithmFailure(string image_files) + { + + // 从配置文件中读取 imageHistoryPath + // 定义历史记录文件夹路径 + string? imageHistoryPath = ConfigurationManager.AppSettings["ImageHistoryPath"]; + if (string.IsNullOrEmpty(imageHistoryPath)) + { + Logger.Error("ImageHistoryPath is not configured in AppSettings."); + return; + } + + // 生成时间戳,格式为 yyyyMMddHHmmss + string timestamp = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"); + // 组合新的文件夹路径 + string newFolderPath = Path.Combine(imageHistoryPath, $"image-{timestamp}"); + + // 检查 D 盘内存空间 + DriveInfo dDrive = new DriveInfo("D"); + long requiredSpace = 10L * 1024 * 1024 * 1024; // 10GB + if (dDrive.TotalFreeSpace < requiredSpace) + { + // 如果 D 盘空间不足 10GB,删除最早创建的10个文件夹 + DirectoryInfo historyDir = new DirectoryInfo(imageHistoryPath); // 获取历史记录文件夹的信息 + DirectoryInfo[] subDirs = historyDir.GetDirectories(); // 获取历史记录文件夹中的所有子文件夹 + if (subDirs.Length > 0) + { + // 按创建时间排序子文件夹 + var orderedSubDirs = subDirs.OrderBy(d => d.CreationTime).ToList(); + int foldersToDelete = Math.Min(10, orderedSubDirs.Count); + + // 删除最早的 10 个文件夹,如果不够 10 个则全删掉 + for (int i = 0; i < foldersToDelete; i++) + { + orderedSubDirs[i].Delete(true); + } + } + } + + // 创建新文件夹 + Directory.CreateDirectory(newFolderPath); + + // 保存图片到新文件夹 + try + { + // 解析 image_files JSON 数组 + JArray imageFilesArray = JArray.Parse(image_files); + string[] imageFiles = imageFilesArray.Select(token => token.ToString()).ToArray(); + + string? imageBasePath = ConfigurationManager.AppSettings["ImageFileBasePath"]; // 图片根目录 + if (string.IsNullOrEmpty(imageBasePath)) + { + Logger.Error("ImageFileBasePath is not configured in AppSettings."); + return; + } + + foreach (string imageFile in imageFiles) + { + // 获取文件名 + string fileName = Path.GetFileName(imageFile); + // 构建完整的源文件路径 + string sourcePath = Path.Combine(imageBasePath, imageFile); + // 组合目标路径 + string destinationPath = Path.Combine(newFolderPath, fileName); + // 复制文件到目标路径,如果目标文件已存在则覆盖 + File.Copy(sourcePath, destinationPath, true); + } + } + catch (JsonException ex) + { + // 记录日志或处理异常 + Logger.Error($"Error parsing image_files JSON: {ex.Message}"); + Logger.Error($"Stack Trace: {ex.StackTrace}"); + } + catch (Exception ex) + { + // 记录其他异常 + Logger.Error($"Error saving images: {ex.Message}"); + Logger.Error($"Stack Trace: {ex.StackTrace}"); + } + } /// /// 跳转至检测结果 ///