|
|
|
@ -0,0 +1,332 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Linq.Expressions;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
using SlnMesnac.Common;
|
|
|
|
|
using SlnMesnac.Config;
|
|
|
|
|
using SlnMesnac.Model.domain;
|
|
|
|
|
using SlnMesnac.Plc;
|
|
|
|
|
using SlnMesnac.Repository.service;
|
|
|
|
|
using SlnMesnac.TouchSocket;
|
|
|
|
|
using TouchSocket.Sockets;
|
|
|
|
|
|
|
|
|
|
namespace SlnMesnac.Business.business
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 分垛库入库逻辑
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class InStoreBusiness
|
|
|
|
|
{
|
|
|
|
|
private readonly ILogger<InStoreBusiness> _logger;
|
|
|
|
|
|
|
|
|
|
private readonly TcpServer _tcpServer;
|
|
|
|
|
|
|
|
|
|
private readonly AppConfig _appConfig;
|
|
|
|
|
|
|
|
|
|
private readonly StringChange _stringChange;
|
|
|
|
|
|
|
|
|
|
private readonly IProductOfflineService _offlineService;
|
|
|
|
|
|
|
|
|
|
private readonly IBaseSpaceinfoService _spaceinfoService;
|
|
|
|
|
|
|
|
|
|
private readonly PlcPool _plcPool;
|
|
|
|
|
|
|
|
|
|
private const string BarcodeRef = "6933973114570;1621240AP0098E3D3497";
|
|
|
|
|
|
|
|
|
|
public InStoreBusiness(TcpServer tcpServer, ILogger<InStoreBusiness> logger, IProductOfflineService offlineService, IBaseSpaceinfoService spaceinfoService, AppConfig appConfig, PlcPool plcPool, StringChange stringChange)
|
|
|
|
|
{
|
|
|
|
|
_tcpServer = tcpServer;
|
|
|
|
|
_logger = logger;
|
|
|
|
|
_offlineService = offlineService;
|
|
|
|
|
_spaceinfoService = spaceinfoService;
|
|
|
|
|
_appConfig = appConfig;
|
|
|
|
|
_plcPool = plcPool;
|
|
|
|
|
_stringChange = stringChange;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Init()
|
|
|
|
|
{
|
|
|
|
|
_tcpServer.ReceivedClientBufferEvent += ReceivedBuffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Buffer缓冲
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="buffer"></param>
|
|
|
|
|
private void ReceivedBuffer(SocketClient client,byte[] buffer)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//_logger.LogInformation($"接收客户端:{client.Id};原始报文:{_stringChange.bytesToHexStr(buffer, buffer.Length)}");
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
string asciiStr = Encoding.ASCII.GetString(buffer);
|
|
|
|
|
|
|
|
|
|
if (asciiStr.Contains("heartbeat"))
|
|
|
|
|
{
|
|
|
|
|
_logger.LogInformation($"收到客户端:{client.Id};心跳指令:{asciiStr}");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (asciiStr.Contains("NoRead"))
|
|
|
|
|
{
|
|
|
|
|
NoReadHandle(client.Id);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_logger.LogInformation($"收到客户端:{client.Id}条码信息:{asciiStr}");
|
|
|
|
|
InStore(client.Id, asciiStr);
|
|
|
|
|
} while (false);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"Buffer缓冲异常:{e.Message}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 入库申请
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="spaceArea">货道区域</param>
|
|
|
|
|
/// <param name="asciiStr"></param>
|
|
|
|
|
private void InStore(string spaceArea, string asciiStr)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(asciiStr))
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"入库申请处理异常:条码信息为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(spaceArea))
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"入库申请处理异常:货道区域为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (asciiStr.Contains(";") && asciiStr.Length == BarcodeRef.Length)
|
|
|
|
|
{
|
|
|
|
|
string[] splitStr = asciiStr.Split(";");
|
|
|
|
|
if (splitStr.Length > 1)
|
|
|
|
|
{
|
|
|
|
|
asciiStr = splitStr[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_offlineService.GetProductInfosBySnCode(asciiStr,out ProductOffline prodInfo);
|
|
|
|
|
|
|
|
|
|
if (prodInfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"入库申请处理异常:根据成品码获取成品信息为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetSpaceInfoByMaterialType(spaceArea, prodInfo, out BaseSpaceinfo laseSpaceinfo,
|
|
|
|
|
out BaseSpaceinfo spaceinfo);
|
|
|
|
|
bool result = false;
|
|
|
|
|
SendInStoreTask(spaceinfo, ref result);
|
|
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"入库申请处理异常:入库任务下发至PLC失败");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
List<BaseSpaceinfo> spaceinfos = new List<BaseSpaceinfo>();
|
|
|
|
|
if (laseSpaceinfo != null)
|
|
|
|
|
{
|
|
|
|
|
laseSpaceinfo.InstoreFlag = 1;
|
|
|
|
|
spaceinfos.Add(laseSpaceinfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spaceinfo.InstoreFlag = 3;
|
|
|
|
|
spaceinfos.Add(spaceinfo);
|
|
|
|
|
_spaceinfoService.UpdateSpaceInfo(spaceinfos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine(e.Message);
|
|
|
|
|
//异常处理,手动入库
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过物料型号获取货道信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="spaceArea"></param>
|
|
|
|
|
/// <param name="prodInfo"></param>
|
|
|
|
|
/// <param name="laseSpaceinfo"></param>
|
|
|
|
|
/// <param name="spaceinfo"></param>
|
|
|
|
|
/// <param name="isBig"></param>
|
|
|
|
|
/// <exception cref="ArgumentException"></exception>
|
|
|
|
|
private void GetSpaceInfoByMaterialType(string spaceArea,ProductOffline prodInfo,out BaseSpaceinfo laseSpaceinfo,out BaseSpaceinfo spaceinfo,bool isBig = false)
|
|
|
|
|
{
|
|
|
|
|
List<BaseSpaceinfo> spaceinfos = null;
|
|
|
|
|
if (isBig)
|
|
|
|
|
{
|
|
|
|
|
_spaceinfoService.GetSpaceInfosByExpression(out spaceinfos,x=>x.StoreCode == _appConfig.storeCode && x.SpaceArea == spaceArea && x.MaterialType == prodInfo.ProductCode && x.SpaceType == 1);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_spaceinfoService.GetSpaceInfosByExpression(out spaceinfos,x=>x.StoreCode == _appConfig.storeCode && x.SpaceArea == spaceArea && x.MaterialType == prodInfo.ProductCode);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (spaceinfos == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"通过物料型号获取货道信息异常:根据成品信息获取货道信息为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spaceinfos = spaceinfos.OrderBy(x => x.ObjId).ToList();
|
|
|
|
|
|
|
|
|
|
MatchSpaceInfoByPlc(ref spaceinfos);
|
|
|
|
|
|
|
|
|
|
if (spaceinfos == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"通过物料型号获取货道信息异常:通过PLC匹配可用货道信息为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FiltrateSpaceInfo(spaceinfos, out laseSpaceinfo, out spaceinfo);
|
|
|
|
|
|
|
|
|
|
if (spaceinfo == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"通过物料型号获取货道信息异常:未获取到匹配的货道信息");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 通过PLC匹配获取,去除已满的货道
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="spaceinfos"></param>
|
|
|
|
|
private void MatchSpaceInfoByPlc(ref List<BaseSpaceinfo> spaceinfos)
|
|
|
|
|
{
|
|
|
|
|
var _plc = _plcPool.GetPlcByKey("cpk");
|
|
|
|
|
|
|
|
|
|
foreach (var item in spaceinfos)
|
|
|
|
|
{
|
|
|
|
|
item.SpaceCode = ExtractNumber(item.SpaceName);
|
|
|
|
|
var plcAddress = _appConfig.plcConfig.First().plcAddr.Where(x => x.spaceCode.ToString() == item.SpaceCode && x.spaceArea == item.SpaceArea).First();
|
|
|
|
|
int isFlag = _plc.readInt16ByAddress(plcAddress.address);
|
|
|
|
|
if (isFlag == 1)
|
|
|
|
|
{
|
|
|
|
|
item.SpaceStatus = 3;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spaceinfos = spaceinfos.Where(x => x.SpaceStatus != 3).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 筛选货道信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="spaceinfos"></param>
|
|
|
|
|
/// <param name="spaceinfo"></param>
|
|
|
|
|
/// <exception cref="ArgumentException"></exception>
|
|
|
|
|
private void FiltrateSpaceInfo(List<BaseSpaceinfo> spaceinfos, out BaseSpaceinfo laseSpaceinfo,out BaseSpaceinfo spaceinfo)
|
|
|
|
|
{
|
|
|
|
|
if (spaceinfos == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"筛选货道信息异常:传入货道信息参数为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int count = spaceinfos.Where(x => x.InstoreFlag == 3).ToList().Count;
|
|
|
|
|
if ( count > 0)
|
|
|
|
|
{
|
|
|
|
|
int index = spaceinfos.FindIndex(entity => entity.InstoreFlag == 3);
|
|
|
|
|
laseSpaceinfo = spaceinfos[index];
|
|
|
|
|
int nextIndex = (index + 1) % spaceinfos.Count;
|
|
|
|
|
spaceinfo = spaceinfos[nextIndex];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
laseSpaceinfo = null;
|
|
|
|
|
spaceinfo = spaceinfos.First();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 下发入库任务至PLC
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="spaceinfo"></param>
|
|
|
|
|
/// <param name="result"></param>
|
|
|
|
|
/// <exception cref="ArgumentException"></exception>
|
|
|
|
|
private void SendInStoreTask(BaseSpaceinfo spaceinfo,ref bool result)
|
|
|
|
|
{
|
|
|
|
|
var _plc = _plcPool.GetPlcByKey("cpk");
|
|
|
|
|
bool isFlag = true;
|
|
|
|
|
|
|
|
|
|
while (isFlag)
|
|
|
|
|
{
|
|
|
|
|
bool answerFlag = _plc.readBoolByAddress("X1000");
|
|
|
|
|
|
|
|
|
|
if (answerFlag)
|
|
|
|
|
{
|
|
|
|
|
isFlag = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Task.Delay(1000*2).Wait();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int spaceCode = _stringChange.ParseToInt(spaceinfo.SpaceCode);
|
|
|
|
|
int spinFlag = 0;
|
|
|
|
|
if (spaceCode % 2 == 0) //偶数 转180°
|
|
|
|
|
{
|
|
|
|
|
spinFlag = 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (spaceinfo.SpaceArea == "A")
|
|
|
|
|
{
|
|
|
|
|
if (!_plc.writeInt16ByAddress("D2", spinFlag))
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"旋转角度下发至PLC失败");
|
|
|
|
|
}
|
|
|
|
|
if (!_plc.writeInt16ByAddress("D29", spaceCode))
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentException($"货道号下发至PLC失败");
|
|
|
|
|
}
|
|
|
|
|
result = true;
|
|
|
|
|
}else if (spaceinfo.SpaceArea == "B")
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
result = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 提取货道号
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="input"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
private static string ExtractNumber(string input)
|
|
|
|
|
{
|
|
|
|
|
string pattern = @"\d+";
|
|
|
|
|
|
|
|
|
|
Match match = Regex.Match(input, pattern);
|
|
|
|
|
|
|
|
|
|
if (match.Success)
|
|
|
|
|
{
|
|
|
|
|
return match.Value.TrimStart('0');
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return null; // 或者返回默认值,如"0"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 读取失败处理
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="client"></param>
|
|
|
|
|
private void NoReadHandle(string client)
|
|
|
|
|
{
|
|
|
|
|
_logger.LogError($"客户端:{client};读取失败!!!!!!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|