diff --git a/Language/en_US.xaml b/Language/en_US.xaml index 78eee89..31166bb 100644 --- a/Language/en_US.xaml +++ b/Language/en_US.xaml @@ -36,4 +36,16 @@ Button + + + Drawing is in progress + Cached images are cleared + Unable to send instructions tNo the SOC + Microcontroller access timeout + The microcontroller returns an error code + Camera not connected + Cutter not found + Algorithm call failed + Failed to read the image file + JSON parsing failed \ No newline at end of file diff --git a/Language/zh_CN.xaml b/Language/zh_CN.xaml index adf2446..1df8ea7 100644 --- a/Language/zh_CN.xaml +++ b/Language/zh_CN.xaml @@ -177,5 +177,16 @@ SYM等级 面1 + + 采图正在进行中 + 缓存图片被清理 + 无法向单片机发送指令 + 单片机访问超时 + 单片机返回错误码 + 摄像头未连接 + 未找到切工仪 + 算法调用失败 + 图片文件读取失败 + JSON解析失败 \ No newline at end of file diff --git a/Model/Entity/ApiEntity/AlgorithmResultEntity.cs b/Model/Entity/ApiEntity/AlgorithmResultEntity.cs index f399017..c850ac8 100644 --- a/Model/Entity/ApiEntity/AlgorithmResultEntity.cs +++ b/Model/Entity/ApiEntity/AlgorithmResultEntity.cs @@ -86,5 +86,10 @@ namespace SparkClient.Model.Entity.ApiEntity public string DiamondCode { get; set; } public string error_msg { get; set; } public string status { get; set; } + + /// + /// 机器号 + /// + public string DeviceId { get; set; } } } diff --git a/Model/Entity/ApiEntity/SocResultEntity.cs b/Model/Entity/ApiEntity/SocResultEntity.cs index 6e27429..0bc2ec0 100644 --- a/Model/Entity/ApiEntity/SocResultEntity.cs +++ b/Model/Entity/ApiEntity/SocResultEntity.cs @@ -12,4 +12,10 @@ public class SocResultEntity /// 图片名称列表 /// public List Images { get; set; } + + /// + /// 机器号 + /// + public string DeviceId { get; set; } + } \ No newline at end of file diff --git a/Model/Entity/ApiEntity/StatusCodes.cs b/Model/Entity/ApiEntity/StatusCodes.cs index 81abb75..56ae994 100644 --- a/Model/Entity/ApiEntity/StatusCodes.cs +++ b/Model/Entity/ApiEntity/StatusCodes.cs @@ -23,10 +23,19 @@ // 单片机返回错误码 public const string MicrocontrollerError = "S005"; + // 摄像头未连接 + public const string CameraNotConnected = "S006"; + // 未找到切工仪 public const string DeviceNotFound = "P001"; // 算法调用失败 public const string AlgorithmFailed = "P002"; + + // 图片文件读取失败 + public const string ImageFileReadFailure = "P003"; + + // JSON解析失败 + public const string JsonParseFailure = "P004"; } } \ No newline at end of file diff --git a/Model/Services/AlgorithmServer.cs b/Model/Services/AlgorithmServer.cs index db14aa3..295a382 100644 --- a/Model/Services/AlgorithmServer.cs +++ b/Model/Services/AlgorithmServer.cs @@ -1,8 +1,10 @@ -using System.Runtime.InteropServices; +using System.Data; +using System.Runtime.InteropServices; using System.Windows.Forms; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SparkClient.Model.Entity.ApiEntity; +using SparkClient.Model.Helper; namespace SparkClient.Model.Services { @@ -17,10 +19,26 @@ namespace SparkClient.Model.Services private static extern void FreeString(IntPtr ptr); // 添加公共方法 - public AlgorithmResultEntity CallParseJsonAndReturnActions(string shape, string shape_mode, string image_file_base_path, string image_files, string algo_config, Boolean half_circle) + public AlgorithmResultEntity CallParseJsonAndReturnActions(string shape, string shape_mode, string image_files) { try { + //半圆 + string circleSql = $"SELECT VALUE FROM CUTTER_CONFIG WHERE KEY = 'half_circle'"; + DataTable circleTable = DataBaseHelper.ExecuteQuery(circleSql); + 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); + object lightLevelValue = table.Rows[0][0]; + string algo_config = lightLevelValue.ToString() ?? throw new InvalidOperationException(); + + //图片根目录 + string image_file_base_path = "D:\\diamond_images"; + // 将所有变量拼接成一个 JSON 对象 JObject jsonData = new JObject( new JProperty("shape", shape), diff --git a/Model/Services/SOCClientService.cs b/Model/Services/SOCClientService.cs index 99eb449..28f193d 100644 --- a/Model/Services/SOCClientService.cs +++ b/Model/Services/SOCClientService.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System; +using System.Data; using System.IO; using System.Net.Http; using System.Text; @@ -8,6 +9,7 @@ using System.Windows; using HandyControl.Tools.Extension; using SparkClient.Model.Common; using SparkClient.Model.Entity.ApiEntity; +using SparkClient.Model.Helper; namespace SparkClient.Model.Services { @@ -60,17 +62,43 @@ namespace SparkClient.Model.Services /// /// 光照级别 /// 任务状态 - public async Task CollectImagesAsync(int lightLevel) + public async Task CollectImagesAsync() { - string url = $"{_baseUrl}/collect_images?light_level={lightLevel}"; - try { + // 光照度和半圆 + int lightLevel = 0; + string halfCircle = string.Empty; + // 查询光照度和半圆配置 + string sql = $"SELECT KEY, VALUE FROM CUTTER_CONFIG WHERE KEY IN ('light_level', 'half_circle')"; + DataTable table = DataBaseHelper.ExecuteQuery(sql); + + if (table == null || table.Rows.Count == 0) + { + throw new Exception("No data found for the specified keys."); + } + foreach (DataRow row in table.Rows) + { + string key = row["Key"].ToString() ?? string.Empty; + string value = row["Value"].ToString() ?? string.Empty; + + if (key == "light_level" && int.TryParse(value, out int parsedLightLevel)) + { + lightLevel = parsedLightLevel; // 光照度 + } + else if (key == "half_circle") + { + halfCircle = value; // 半圆 + } + } + + string url = $"{_baseUrl}/collect_images?light_level={lightLevel}&half_circle={halfCircle}"; + var response = await SendGetRequestAsync(url); if (!response.IsSuccessStatusCode) { - return "P001"; + return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() , DeviceId = ""}; } var jsonResponse = await response.Content.ReadAsStringAsync(); @@ -78,16 +106,18 @@ namespace SparkClient.Model.Services if (result == null) { - return "P001"; + return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() , DeviceId = ""}; } - - return result.Status; + return new SocResultEntity { Status = result.Status, Images = new List() , DeviceId = result.device_id}; + } catch (Exception ex) { - // 记录异常信息 - Console.WriteLine($"An error occurred while collecting images: {ex.Message}"); - return "P001"; + // 记录日志或进行其他处理 + Console.WriteLine($"Error in DoSoc: {ex.Message}"); + // 或者使用日志框架记录日志 + // logger.LogError(ex, "Error in DoSoc method."); + return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() , DeviceId = ""}; } } @@ -186,15 +216,15 @@ namespace SparkClient.Model.Services } catch (HttpRequestException ex) { - return "P001"; + return StatusCodes.DeviceNotFound; } catch (JsonException ex) { - return "P001"; + return StatusCodes.DeviceNotFound; } catch (Exception ex) { - return "P001"; + return StatusCodes.DeviceNotFound; } } @@ -202,26 +232,28 @@ namespace SparkClient.Model.Services /// 处理图片收集、保存和状态检查。 /// /// 光照级别 + /// 是否半圆 /// 图片保存路径 /// 操作结果 - public async Task ProcessImageCollectionAsync(int lightLevel, string savePath) + public async Task ProcessImageCollectionAsync() { try { + // SOC接口 + string savePath = @"d:\diamond_images"; // 清理 savePath 文件夹 if (Directory.Exists(savePath)) { Directory.Delete(savePath, true); } Directory.CreateDirectory(savePath); - // 启动任务接口 - string startStatus = await CollectImagesAsync(lightLevel); + SocResultEntity entity = await CollectImagesAsync(); // 成功 - if (startStatus != StatusCodes.Success) + if (entity.Status != StatusCodes.Success) { // 启动任务失败 - return new SocResultEntity { Status = startStatus, Images = new List() }; + return new SocResultEntity { Status = entity.Status, Images = new List() }; } // 读取图片接口 @@ -238,7 +270,7 @@ namespace SparkClient.Model.Services } } // 按下载时间排序图片名称 - return new SocResultEntity { Status = StatusCodes.Success, Images = imageNames }; + return new SocResultEntity { Status = StatusCodes.Success, Images = imageNames, DeviceId = entity.DeviceId}; } catch (Exception e) { @@ -288,5 +320,10 @@ namespace SparkClient.Model.Services /// 状态消息 /// public string Message { get; set; } + + /// + /// 机器号 + /// + public string device_id { get; set; } } } diff --git a/SparkClient.sln.DotSettings.user b/SparkClient.sln.DotSettings.user index 2523794..194dd5b 100644 --- a/SparkClient.sln.DotSettings.user +++ b/SparkClient.sln.DotSettings.user @@ -16,6 +16,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -23,6 +24,8 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -32,6 +35,7 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded diff --git a/SparkDB.db b/SparkDB.db index 808fa29..2165e78 100644 Binary files a/SparkDB.db and b/SparkDB.db differ diff --git a/ViewModel/Grading/DiamondSelectVM.cs b/ViewModel/Grading/DiamondSelectVM.cs index db2e259..3a6d297 100644 --- a/ViewModel/Grading/DiamondSelectVM.cs +++ b/ViewModel/Grading/DiamondSelectVM.cs @@ -16,6 +16,7 @@ using MessageBox = System.Windows.MessageBox; using System.Text; using System.IO; using System.Windows.Media; +using SparkClient.Model.Common; using Color = System.Windows.Media.Color; namespace SparkClient.ViewModel.Grading; @@ -113,9 +114,7 @@ public class DiamondSelectVM : BaseViewModel /// public async void StartGrading(object param) { - #if DEBUG - DoStartGrading(param); - #else + LoadingDialog loading = new LoadingDialog(); try { @@ -137,7 +136,7 @@ public class DiamondSelectVM : BaseViewModel } // 模拟耗时操作 //System.Threading.Thread.Sleep(50); // 休眠50毫秒 - await Task.Delay(400); + await Task.Delay(710); loading.setValue(i); progress = i; } @@ -154,38 +153,53 @@ public class DiamondSelectVM : BaseViewModel parameter.PavType = value.Split(" ")[2]; } + // 初始化SOC客户端服务,传入SOC端的地址和认证Token + _socClientService = new SOCClientService(); // 启动soc - // socResolt = await DoSoc(); - // if (socResolt.Status == "P001" || socResolt.Images.Count == 0) - // { - // // /*// 使用 Dispatcher 将 UI 操作调度到主线程 - // // Application.Current.Dispatcher.Invoke(() => - // // { - // // MsgDialog msgDialog = new MsgDialog(); - // // msgDialog.ShowDialog(); - // // }); - // // loading.Dispatcher.Invoke(() => loading.Close()); - // // return;*/ - // MessageBox.Show("未找到切工仪", "错误", MessageBoxButton.OK, MessageBoxImage.Error); - // loading.Dispatcher.Invoke(() => loading.Close()); - // return; - // } + socResolt = await _socClientService.ProcessImageCollectionAsync(); + switch (socResolt.Status) + { + case StatusCodes.DeviceNotFound: + ShowErrorMessage(MultilingualHelper.getString("DeviceNotFound"), loading); + return; + case StatusCodes.InProgress: + ShowErrorMessage(MultilingualHelper.getString("InProgress"), loading); + return; + case StatusCodes.CacheCleared: + ShowErrorMessage(MultilingualHelper.getString("CacheCleared"), loading); + return; + case StatusCodes.CannotSendCommand: + ShowErrorMessage(MultilingualHelper.getString("CannotSendCommand"), loading); + return; + case StatusCodes.MicrocontrollerTimeout: + ShowErrorMessage(MultilingualHelper.getString("MicrocontrollerTimeout"), loading); + return; + case StatusCodes.MicrocontrollerError: + ShowErrorMessage(MultilingualHelper.getString("MicrocontrollerError"), loading); + return; + case StatusCodes.CameraNotConnected: + ShowErrorMessage(MultilingualHelper.getString("CameraNotConnected"), loading); + return; + } + _algorithmServer = new AlgorithmServer(); + //图片集合 + 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\" ]" ; + // 启动算法 - parameter = await DoAlgorithm(socResolt, parameter.Shape, parameter.CrownType); - MessageBox.Show(parameter.error_msg); + parameter = _algorithmServer.CallParseJsonAndReturnActions(parameter.Shape, parameter.CrownType, image_files); + //机器号 + parameter.DeviceId = socResolt.DeviceId; switch (parameter.status) { - case "P002": - MessageBox.Show("P002:调用算法失败", "错误", MessageBoxButton.OK, MessageBoxImage.Error); - loading.Dispatcher.Invoke(() => loading.Close()); + case StatusCodes.AlgorithmFailed: + ShowErrorMessage(MultilingualHelper.getString("AlgorithmFailed"), loading); return; - case "P003": - MessageBox.Show("P003:图片文件读取失败", "错误", MessageBoxButton.OK, MessageBoxImage.Error); - loading.Dispatcher.Invoke(() => loading.Close()); + case StatusCodes.ImageFileReadFailure: + ShowErrorMessage(MultilingualHelper.getString("ImageFileReadFailure"), loading); return; - case "P004": - MessageBox.Show("P004:JSON解析失败", "错误", MessageBoxButton.OK, MessageBoxImage.Error); - loading.Dispatcher.Invoke(() => loading.Close()); + case StatusCodes.JsonParseFailure: + ShowErrorMessage(MultilingualHelper.getString("JsonParseFailure"), loading); return; } parameter.Standard = "IGI 2024"; @@ -222,9 +236,21 @@ public class DiamondSelectVM : BaseViewModel finally { } - #endif } + + // 将 UI 操作调度到主线程并显示错误信息 + void ShowErrorMessage(string errorMessage, LoadingDialog loading) + { + Application.Current.Dispatcher.Invoke(() => + { + MsgDialog msgDialog = new MsgDialog(); + msgDialog.ErrorMessage = errorMessage; + msgDialog.ShowDialog(); + }); + loading.Dispatcher.Invoke(() => loading.Close()); + } + /// /// 开始检测(对soc和算法开始通讯) /// @@ -310,67 +336,6 @@ public class DiamondSelectVM : BaseViewModel WindowManager.openContent.Add(vm); } - - /// - /// 启动切工仪接口。 - /// - /// 图片的字节数组 - private async Task DoSoc() - { - // 光照度 - string sql = new CutterConfigEntity - { - ItemName = null, - Key = null, - Value = null - }.GenerateSelectSQL(new List { "Value" }, new Dictionary { { "Key", "light_level" } }); - SqliteParameter[] sqliteParameters = [new("@Key", "light_level")]; - DataTable table = DataBaseHelper.ExecuteQuery(sql,sqliteParameters); - object lightLevelValue = table.Rows[0][0]; - if (!int.TryParse(lightLevelValue.ToString(), out int lightLevel)) - { - throw new InvalidOperationException("Light level value is not a valid integer."); - } - // 初始化SOC客户端服务,传入SOC端的地址和认证Token - _socClientService = new SOCClientService(); - // SOC接口 - string savePath = @"d:\\diamond_images"; - SocResultEntity resultEntity = await _socClientService.ProcessImageCollectionAsync(lightLevel, savePath); - return resultEntity; - } - - /// - /// 启动算法接口。 - /// - /// 切工仪接口返回值 - /// - /// - /// 定级参数,3D模型参数 - private Task DoAlgorithm(SocResultEntity socResolt, String shape, String crownType) - { - _algorithmServer = new AlgorithmServer(); - //钻石形状:shape - //钻石子形状 - string shape_mode = crownType; - //图片根目录 - string image_file_base_path = "D:\\diamond_images"; - //图片集合 - //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\" ]" ; - //半圆 - Boolean half_circle = false; - - //算法配置参数 - string sql = $"SELECT JSON FROM ALGORITHM_CONFIG ORDER BY JSON_ORDER ASC"; - DataTable table = DataBaseHelper.ExecuteQuery(sql); - object lightLevelValue = table.Rows[0][0]; - string algo_config = lightLevelValue.ToString() ?? throw new InvalidOperationException(); - - AlgorithmResultEntity algoResult = _algorithmServer.CallParseJsonAndReturnActions(shape, shape_mode, image_file_base_path, image_files, algo_config,half_circle); - - return Task.FromResult(algoResult); - } - } public class ButtonInfo { diff --git a/Views/Dialog/MsgDialog.xaml b/Views/Dialog/MsgDialog.xaml index b49866a..5d6883b 100644 --- a/Views/Dialog/MsgDialog.xaml +++ b/Views/Dialog/MsgDialog.xaml @@ -21,7 +21,7 @@ - @@ -33,13 +33,13 @@ BorderBrush="Transparent" Click="Skip_Click" /> + Fill="Azure" + Stroke="Black" + StrokeThickness="1" + HorizontalAlignment="Left" + VerticalAlignment="Top" + Margin="335,7,0,0" + Width="30" /> - + \ No newline at end of file diff --git a/Views/Dialog/MsgDialog.xaml.cs b/Views/Dialog/MsgDialog.xaml.cs index a46d98b..d3d117a 100644 --- a/Views/Dialog/MsgDialog.xaml.cs +++ b/Views/Dialog/MsgDialog.xaml.cs @@ -1,4 +1,5 @@ -using System.Windows; +using System.ComponentModel; +using System.Windows; using System.Windows.Input; using System.Windows.Media; @@ -7,13 +8,29 @@ namespace SparkClient.Views.Dialog /// /// MsgDialog.xaml 的交互逻辑 /// - public partial class MsgDialog : Window + public partial class MsgDialog : Window, INotifyPropertyChanged { + private string _errorMessage; + + public string ErrorMessage + { + get { return _errorMessage; } + set + { + if (_errorMessage != value) + { + _errorMessage = value; + OnPropertyChanged(nameof(ErrorMessage)); + } + } + } + public MsgDialog() { InitializeComponent(); this.Loaded += (s, e) => ApplyCornerRadiusClip(); this.SizeChanged += (s, e) => ApplyCornerRadiusClip(); + this.DataContext = this; // 设置 DataContext 以便绑定 } /// @@ -58,5 +75,12 @@ namespace SparkClient.Views.Dialog this.DragMove(); } } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } -} \ No newline at end of file +}