using Newtonsoft.Json; using System; using System.Configuration; using System.Data; using System.IO; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Windows; using HandyControl.Tools.Extension; using log4net; using SparkClient.Model.Common; using SparkClient.Model.Entity.ApiEntity; using SparkClient.Model.Helper; namespace SparkClient.Model.Services { /// /// SOC 客户端服务类,用于与远程服务器进行交互,包括启动图片收集任务、获取图片、获取采集状态等操作。 /// public class SOCClientService { // Log地址 private const string LogFilePath = @"..\..\..\Resource\Document\log.txt"; private static readonly ILog Logger = LogManager.GetLogger(typeof(SOCClientService)); /// /// 基础URL,用于构建完整的API请求地址。 /// private readonly string? _baseUrl; /// /// 认证令牌,用于HTTP请求的认证。 /// private readonly string _authToken; /// /// 构造函数,初始化基础URL和认证令牌。 /// public SOCClientService() { //_baseUrl = "http://192.168.3.100:8080"; _baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; _authToken = "your_basic_auth_token"; } /// /// 发送GET请求的通用方法。 /// /// 请求的完整URL /// HTTP响应 private async Task SendGetRequestAsync(string url) { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("Authorization", "Basic " + _authToken); return await client.GetAsync(url); } } /// /// 启动图片收集任务。 /// /// 任务状态 public async Task CollectImagesAsync() { 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 new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List()}; } var jsonResponse = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject(jsonResponse); if (result == null) { return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List()}; } return new SocResultEntity { Status = result.Status, Images = new List() , DeviceId = result.device_id}; } catch (Exception ex) { // 记录日志或进行其他处理 Console.WriteLine($"Error in DoSoc: {ex.Message}"); Logger.Warn($"Error in DoSoc: {ex.Message}"); // 或者使用日志框架记录日志 // logger.LogError(ex, "Error in DoSoc method."); return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() , DeviceId = ""}; } } /// /// 获取指定索引的图片。 /// /// 保存图片路径 /// 图片的字节数组 public async Task> RetrieveImageAsync(string? savePath) { List imageNames = new List(); // 读取图片接口 int imageIndex = 0; while (true) { string url = $"{_baseUrl}/retrieve_image/{imageIndex}"; try { var response = await SendGetRequestAsync(url); int status = (int)response.StatusCode; switch (status) { case 200: byte[] imageBytes = await response.Content.ReadAsByteArrayAsync(); // 获取 Content-Type 头以确定图片格式 string contentType = response.Content.Headers.ContentType.MediaType; string fileExtension = GetFileExtension(contentType); string fileName = Path.Combine(savePath, $"image_{imageIndex}{fileExtension}"); // 图片名称List imageNames.Add(Path.GetFileName(fileName)); // 保存图片 await File.WriteAllBytesAsync(fileName, imageBytes); imageIndex++; break; case 425: // 请求被锁定,等待一段时间后重试 await Task.Delay(1000); break; case 410: // 资源已被永久删除,跳过当前索引 imageIndex++; break; case 404: // 资源未找到,结束循环 return imageNames; default: // 其他状态码,记录警告并继续 Logger.Warn($"Unexpected status code: {status} for URL: {url}"); imageIndex++; break; } } catch (HttpRequestException ex) { // 捕获HTTP请求异常并记录错误信息 Logger.Error($"HTTP request failed for URL: {url}, Exception: {ex.Message}"); return imageNames; } catch (Exception ex) { // 捕获其他异常并记录错误信息,结束循环 Logger.Error($"An unexpected error occurred for URL: {url}, Exception: {ex.Message}"); return imageNames; } } } /// /// 获取图片采集状态。 /// /// 采集状态 public async Task CollectStatusAsync() { string url = $"{_baseUrl}/collect_status"; try { var response = await SendGetRequestAsync(url); if (response.IsSuccessStatusCode) { var jsonResponse = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject(jsonResponse); return result.Status; } return StatusCodes.DeviceNotFound; } catch (HttpRequestException ex) { return StatusCodes.DeviceNotFound; } catch (JsonException ex) { return StatusCodes.DeviceNotFound; } catch (Exception ex) { return StatusCodes.DeviceNotFound; } } /// /// 处理图片收集、保存和状态检查。 /// /// 操作结果 public async Task ProcessImageCollectionAsync() { try { // SOC接口 string? savePath = ConfigurationManager.AppSettings["ImageFileBasePath"]; // 清理 savePath 文件夹 if (Directory.Exists(savePath)) { Directory.Delete(savePath, true); } Directory.CreateDirectory(savePath); // 启动任务接口 SocResultEntity entity = await CollectImagesAsync(); // 成功 if (entity.Status != StatusCodes.Success) { // 启动任务失败 return new SocResultEntity { Status = entity.Status, Images = new List() }; } // 读取图片接口 List imageNames = await RetrieveImageAsync(savePath); if (imageNames.Count == 0) { // 采集状态失败 return new SocResultEntity { Status = StatusCodes.ImageFileReadFailure, Images = new List() }; } // 采集状态接口 string acquisitionStatus = await CollectStatusAsync(); // 成功 if (acquisitionStatus != StatusCodes.Success) { // 采集状态失败 return new SocResultEntity { Status = acquisitionStatus, Images = new List() }; } return new SocResultEntity { Status = acquisitionStatus, Images = imageNames, DeviceId = entity.DeviceId}; } catch (Exception e) { // 日志记录 // logger.Error(e, "发生异常"); string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] 发生异常: {e.Message}{Environment.NewLine}"; Logger.Error(logMessage); return new SocResultEntity { Status = StatusCodes.DeviceNotFound, Images = new List() }; } } /// /// 根据给定的 MIME 类型获取对应的文件扩展名。 /// /// HTTP 响应中的 Content-Type 头字段,表示内容的 MIME 类型。 /// 与 MIME 类型对应的文件扩展名。 /// 当传入的 MIME 类型不受支持时抛出此异常。 private string GetFileExtension(string contentType) { switch (contentType.ToLower()) { case "image/bmp": return ".bmp"; case "image/jpg": return ".jpg"; case "image/png": return ".png"; default: throw new InvalidOperationException($"Unsupported content type: {contentType}"); } } } /// /// 响应状态类,用于解析服务器返回的状态信息。 /// public class ResponseStatus { /// /// 状态码 /// public string Status { get; set; } /// /// 状态消息 /// public string Message { get; set; } /// /// 机器号 /// public string device_id { get; set; } } }