using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Volo.Abp.Application.Services; using Win_in.Sfs.Basedata.Application.Contracts; using Win_in.Sfs.Shared.Domain; using Win_in.Sfs.Shared.Domain.Shared; using Win_in.Sfs.Wms.DataExchange.Domain; using Win_in.Sfs.Wms.DataExchange.Domain.Shared; using Win_in.Sfs.Wms.DataExchange.WMS.PCK; using Win_in.Sfs.Wms.Store.Application.Contracts; using System.Text.Json.Serialization; using System.IdentityModel.Tokens.Jwt; using Volo.Abp; using System.Net.NetworkInformation; using Win_in.Sfs.Shared.Domain.Shared.Enums.Store; using System.Threading; using System.Diagnostics; using System.Reflection; using Microsoft.Extensions.Primitives; using Win_in.Sfs.Shared.Application; namespace Win_in.Sfs.Wms.DataExchange.Fawtyg.InjectionMoldingTaskAgent.Incoming; public class InjectionMoldingRequestReader : IReader { private readonly IInjectionIssueRequestAppService _injectionRequest; private readonly IItemBasicAppService _itemService; private readonly ILocationAppService _locService; private readonly ILogger _logger; private readonly IOptions _options; private readonly IHttpClientFactory _httpClientFactory; public InjectionMoldingRequestReader( IInjectionIssueRequestAppService injectionRequest , ILogger logger , IOptions options , IHttpClientFactory httpClientFactory , IItemBasicAppService itemService , ILocationAppService locService ) { _injectionRequest = injectionRequest; _logger = logger; _options = options; _httpClientFactory = httpClientFactory; _itemService = itemService; _locService = locService; } /// /// 读取注塑叫料任务 /// /// public virtual async Task> ReadAsync() { try { #if DEBUG _options.Value.AutoRemote.TimeCycle = 1; _options.Value.AutoRemote.Interval = 2; #endif // var sleepTime = (_options.Value.AutoRemote.TimeCycle*60/ _options.Value.AutoRemote.Interval)-10; var invterval = _options.Value.AutoRemote.Interval; var guid = DateTime.Now.ToString("yyyyMMddHHmmssfff"); Stopwatch sw = Stopwatch.StartNew(); Client client = new Client(_options.Value.AutoRemote.IpAddress, _httpClientFactory.CreateClient());//调用客户记录 var flag = await client.GetMacStaticAsync().ConfigureAwait(false); if (flag != 1) { // 记录错误日志并返回空列表 _logger.LogInformation($"读取到摄像头信息为不可用{DateTime.Now},请检查摄像头"); return new List(); } if (string.IsNullOrEmpty(_options.Value.AutoRemote.AreaIDs)) { _logger.LogInformation($"没有设置指定区域AutoRemote->AreaIDs"); return new List(); } var ids = _options.Value.AutoRemote.AreaIDs.Split(","); List camralist = new List(); List camralist1 = new List(); for (int i = 1; i <= invterval; i++) { foreach (var itm in ids)//遍历区域查找所有货物 { var idsList = await client.GetCargoStaticAsync(itm).ConfigureAwait(false); Thread.Sleep(1000);//设备读取50ms延时,设置延时时间为1000ms保证读取更新到信息 //flag 1-有货 0-空闲 foreach (var respon in idsList.Where(r => r.Flag == 0)) { var response = new ResponCargoItem1(); response.FromObject(respon); response.Number = $"第{i.ToString()}次读取"; camralist1.Add(response); } camralist.AddRange(idsList.Where(r => r.Flag == 0)); } _logger.LogInformation($"读取标识{guid}读取成功次数{i},耗时 {sw.ElapsedMilliseconds}毫秒"); } _logger.LogInformation($"标识{guid}读取{invterval}次接口表:{System.Text.Json.JsonSerializer.Serialize(camralist1)}"); _logger.LogInformation(MakeGrid($"标识{guid}读取{invterval}次接口表",camralist1)); sw.Stop(); //按区域、货位号、物品、标志 var group= camralist.GroupBy(r => new { r.AreaID, r.CargoID, r.PartCode, r.Flag }); //获取和次数相等的空闲数据 var list = group.Where(r => r.Count() == invterval).ToList(); var errorlist= group.Where(r => r.Count() != invterval).ToList(); if (errorlist.Count > 0) { _logger.LogInformation($"标识{guid}不能同步内容JSON:{System.Text.Json.JsonSerializer.Serialize(errorlist.Select(r => r.Key).ToList())}"); _logger.LogInformation(MakeGrid($"标识{guid}不能同步内容", errorlist)); } //如果有货位空闲 if (list.Count>0) { sw = Stopwatch.StartNew(); _logger.LogInformation($"开始标识{guid}同步WMS开始"); List inputdetail = new List(); foreach (var item in list.Select(r=>r.Key).ToList()) { UnCompletedRequestDto jobrequestinput = new UnCompletedRequestDto(); jobrequestinput.ItemCode = item.PartCode; jobrequestinput.LocCode = item.AreaID.ToString(); jobrequestinput.PositionCode = item.CargoID.ToString(); inputdetail.Add(jobrequestinput); } var uncompletelist = await _injectionRequest.Getlist(inputdetail).ConfigureAwait(false);//将所有库位物品信息查找未完成记录 var query = from itm in list.Select(r => r.Key).ToList() join itm1 in uncompletelist on new { locCode = itm.AreaID.ToString(), itmCode = itm.PartCode, PositionCode = itm.CargoID.ToString() } equals new { locCode = itm1.LocCode, itmCode = itm1.ItemCode, PositionCode = itm1.PositionCode } into temp from tm in temp.DefaultIfEmpty() where tm == null select itm; var injectionList = query.ToList();//已经完成的记录 _logger.LogInformation($"标识{guid}同步WMS内容:{System.Text.Json.JsonSerializer.Serialize(injectionList)}"); _logger.LogInformation(MakeGrid($"{guid}同步WMS内容", injectionList)); foreach (var inject in injectionList) { List cameraList = new List(); InjectionIssueRequestEditInput input = new InjectionIssueRequestEditInput(); input.Worker = "Vision"; input.IssueRequestType = EnumIssueRequestType.Vision; input.AutoSubmit = true; input.ActiveDate = DateTime.Now; input.UseOnTheWayLocation = false; input.Remark = "视觉叫料"; List injectionRequestDetails = new List(); //foreach (var job in cameraList) //{ var detailInput = new InjectionIssueRequestDetailInput() { ItemCode = inject.PartCode, ToLocationCode = inject.AreaID.ToString(), PositionCode = inject.CargoID, Qty = 1, RecommendType = EnumRecommendType.RAW, IssuedQty = 0, ReceivedQty = 0, Status = EnumStatus.Open, RequestStatus = EnumRequestStatus.New, BoxQty = 1 }; // 添加注塑叫料明细任务数据 injectionRequestDetails.Add(detailInput); //} input.Details.AddRange(injectionRequestDetails); // 通过 BindAsync 方法对物品仓库进行赋值 var errors = await BindAsync(input.Details).ConfigureAwait(false); if (errors.Count > 0) { // 记录错误日志并返回空列表 foreach (var error in errors) { _logger.LogInformation(error); } return new List(); } // 创建新的注塑请求并将数据写入数据库 await _injectionRequest.CreateAsync(input).ConfigureAwait(false); } _logger.LogInformation($"标识{guid}同步WMS结束,耗时{sw.ElapsedMilliseconds}毫秒"); } else { Thread.Sleep(1000); } //Client client = new Client(_options.Value.AutoRemote.IpAddress, _httpClientFactory.CreateClient());//调用客户记录 //var flag= await client.GetMacStaticAsync().ConfigureAwait(false); //if (flag!=1) //{ // // 记录错误日志并返回空列表 // _logger.LogInformation($"读取到摄像头信息为不可用{DateTime.Now},请检查摄像头"); // return new List(); //} //if (string.IsNullOrEmpty(_options.Value.AutoRemote.AreaIDs)) //{ // _logger.LogInformation($"没有设置指定区域AutoRemote->AreaIDs"); // return new List(); //} //var ids=_options.Value.AutoRemote.AreaIDs.Split(","); //List camralist = new List(); //foreach (var itm in ids)//遍历区域查找所有货物 //{ // var idsList= await client.GetCargoStaticAsync(itm).ConfigureAwait(false); // camralist.AddRange(idsList); //} //camralist = camralist.Where(p=>p.Flag==0).ToList(); //} } // 捕获特定异常并记录日志 catch (Exception ex) { _logger.LogInformation(ex.Message); } // 返回空列表 return new List(); } /// /// 绑定物品库位信息,如果对错误返回错误新列表 /// /// /// private async Task> BindAsync(List p_list) { // 异步方法,将输入的请求绑定到对应的物品和库位信息,返回错误列表 List errors = new List(); foreach (var request in p_list) { // 获取对应物品信息 var itm = await _itemService.GetByCodeAsync(request.ItemCode).ConfigureAwait(false); if (itm == null) { errors.Add($"编号:{request.ItemCode}物品表中没找到,请维护物品表!"); } else { // 更新请求中的物品描述和名称 request.ItemDesc1 = itm.Desc1; request.ItemDesc2 = itm.Desc2; request.ItemName = itm.Name; request.Uom = itm.BasicUom; } // 获取对应库位信息 var loc = await _locService.GetByCodeAsync(request.ToLocationCode).ConfigureAwait(false); if (loc == null) { errors.Add($"编号:{request.ToLocationCode}库位表中没找到,请维护库位表!"); } else { // 更新请求中的库位相关信息 request.ToLocationCode = loc.Code; request.ToLocationGroup = loc.LocationGroupCode; request.ToLocationErpCode = loc.ErpLocationCode; request.ToWarehouseCode = loc.WarehouseCode; request.ToLocationArea = loc.AreaCode; } } // 返回错误列表 return errors; } // /// // /// 读取摄像头API // /// // /// // /// // public async Task ReaderCameraApi() // { // try // { // // 从配置中获取远程摄像头的地址、用户名、密码和令牌 // var address = _options.Value.AutoRemote.IpAddress; // var username = _options.Value.AutoRemote.UserName; // var password = _options.Value.AutoRemote.Password; // var token = _options.Value.AutoRemote.Token; // // 创建一个HttpClient实例 // var client = _httpClientFactory.CreateClient(); // // 将用户名和密码转换为Base64编码的凭据,并设置请求的身份验证信息 // var credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}")); // client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentials); // // 发送GET请求到远程摄像头地址并等待响应 // var response = await client.PostAsync(address, new StringContent(token, Encoding.UTF8, "application/json")).ConfigureAwait(false); // // 如果请求成功,则返回响应内容,否则返回错误信息 // if (response.IsSuccessStatusCode) // { // return await response.Content.ReadAsStringAsync().ConfigureAwait(false); // } // } // catch (HttpRequestException ex) // { // _logger.LogInformation("远程摄像头连接失败:" + ex.Message); // } // return "Error occurred"; // } // private List Parse(string p_str) // { // List requests = new List(); // return System.Text.Json.JsonSerializer.Deserialize>(p_str); // } public class InjectionRequest { /// /// 物品M /// public string ItemCode { get; set; } /// /// 物品名称 /// public string ItemName { get; set; } /// /// 发运库位 /// public string ToLocCode { get; set; } /// /// 来源库位 /// public string FromLocCode { get; set; } /// /// 数量 /// public decimal Qty { get; set; } } private string MakeGrid(string header,List p_list) where T : class { StringBuilder sb = new StringBuilder(); sb.AppendLine(header); int rows = p_list.Count; var first = p_list.First(); var properties = first.GetType().GetProperties(); int columns = properties.Length; var columNames = first.GetType().GetProperties().ToList().Select(p => p.Name).ToList(); int cellWidth = 20; // 每个单元格的宽度 List contents = new List(); for (int i = 0; i < rows; i++) { var row = p_list[i]; foreach (PropertyInfo property in properties) { // 使用反射获取属性值 contents.Add(property.GetValue(row).ToString()); } } // 输出列头 for (int j = 0; j < columns; j++) { sb.Append("|"); sb.Append(FormatCell(columNames[j], cellWidth)); } sb.Append("|"); sb.AppendLine(); // 输出列头分隔线 for (int k = 0; k < columns * (cellWidth + 1) + 1; k++) { sb.Append("-"); } sb.AppendLine(); // 输出网格内容 for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { sb.Append("|"); sb.Append(FormatCell(contents[i * columns + j], cellWidth)); } sb.Append("|"); sb.AppendLine(); } return sb.ToString(); } private string FormatCell(object value, int width) { return value.ToString().PadLeft(width); } }