You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
476 lines
17 KiB
476 lines
17 KiB
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<InjectionMoldingRequestReader> _logger;
|
|
private readonly IOptions<InjectionMoldingTaskOptions> _options;
|
|
private readonly IHttpClientFactory _httpClientFactory;
|
|
|
|
public InjectionMoldingRequestReader(
|
|
IInjectionIssueRequestAppService injectionRequest
|
|
|
|
, ILogger<InjectionMoldingRequestReader> logger
|
|
, IOptions<InjectionMoldingTaskOptions> options
|
|
, IHttpClientFactory httpClientFactory
|
|
, IItemBasicAppService itemService
|
|
, ILocationAppService locService
|
|
|
|
)
|
|
{
|
|
_injectionRequest = injectionRequest;
|
|
|
|
_logger = logger;
|
|
_options = options;
|
|
_httpClientFactory = httpClientFactory;
|
|
_itemService = itemService;
|
|
_locService = locService;
|
|
|
|
}
|
|
/// <summary>
|
|
/// 读取注塑叫料任务
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
|
|
public virtual async Task<List<IncomingFromExternal>> 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<IncomingFromExternal>();
|
|
}
|
|
if (string.IsNullOrEmpty(_options.Value.AutoRemote.AreaIDs))
|
|
{
|
|
_logger.LogInformation($"没有设置指定区域AutoRemote->AreaIDs");
|
|
|
|
|
|
return new List<IncomingFromExternal>();
|
|
}
|
|
var ids = _options.Value.AutoRemote.AreaIDs.Split(",");
|
|
List<ResponCargoItem> camralist = new List<ResponCargoItem>();
|
|
List<ResponCargoItem1> camralist1 = new List<ResponCargoItem1>();
|
|
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<UnCompletedRequestDto> inputdetail = new List<UnCompletedRequestDto>();
|
|
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<InjectionRequest> cameraList = new List<InjectionRequest>();
|
|
InjectionIssueRequestEditInput input = new InjectionIssueRequestEditInput();
|
|
input.Worker = "Vision";
|
|
input.IssueRequestType = EnumIssueRequestType.Vision;
|
|
input.AutoSubmit = true;
|
|
input.ActiveDate = DateTime.Now;
|
|
input.UseOnTheWayLocation = false;
|
|
input.Remark = "视觉叫料";
|
|
List<InjectionIssueRequestDetailInput> injectionRequestDetails = new List<InjectionIssueRequestDetailInput>();
|
|
//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<IncomingFromExternal>();
|
|
}
|
|
// 创建新的注塑请求并将数据写入数据库
|
|
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<IncomingFromExternal>();
|
|
//}
|
|
|
|
//if (string.IsNullOrEmpty(_options.Value.AutoRemote.AreaIDs))
|
|
//{
|
|
// _logger.LogInformation($"没有设置指定区域AutoRemote->AreaIDs");
|
|
// return new List<IncomingFromExternal>();
|
|
//}
|
|
|
|
//var ids=_options.Value.AutoRemote.AreaIDs.Split(",");
|
|
//List<ResponCargoItem> camralist = new List<ResponCargoItem>();
|
|
//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<IncomingFromExternal>();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 绑定物品库位信息,如果对错误返回错误新列表
|
|
/// </summary>
|
|
/// <param name="p_list"></param>
|
|
/// <returns></returns>
|
|
private async Task<List<string>> BindAsync(List<InjectionIssueRequestDetailInput> p_list)
|
|
{
|
|
// 异步方法,将输入的请求绑定到对应的物品和库位信息,返回错误列表
|
|
List<string> errors = new List<string>();
|
|
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;
|
|
}
|
|
|
|
// /// <summary>
|
|
// /// 读取摄像头API
|
|
// /// </summary>
|
|
// /// <param name="p_type"></param>
|
|
// /// <returns></returns>
|
|
// public async Task<string> 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<InjectionRequest> Parse(string p_str)
|
|
// {
|
|
// List<InjectionRequest> requests = new List<InjectionRequest>();
|
|
|
|
// return System.Text.Json.JsonSerializer.Deserialize<List<InjectionRequest>>(p_str);
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class InjectionRequest
|
|
{
|
|
/// <summary>
|
|
/// 物品M
|
|
/// </summary>
|
|
public string ItemCode { get; set; }
|
|
/// <summary>
|
|
/// 物品名称
|
|
/// </summary>
|
|
public string ItemName { get; set; }
|
|
/// <summary>
|
|
/// 发运库位
|
|
/// </summary>
|
|
public string ToLocCode { get; set; }
|
|
/// <summary>
|
|
/// 来源库位
|
|
/// </summary>
|
|
public string FromLocCode { get; set; }
|
|
/// <summary>
|
|
/// 数量
|
|
/// </summary>
|
|
public decimal Qty { get; set; }
|
|
|
|
}
|
|
private string MakeGrid<T>(string header,List<T> 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<string> contents = new List<string>();
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
}
|
|
|