using Admin.Core.Common; using Admin.Core.Common.Helper; using Admin.Core.IService; using Admin.Core.Model; using Admin.Core.Model.Model_New; using Admin.Core.Service; using Admin.Core.Socket; using Aucma.Core.HwPLc; using Aucma.Core.Palletiz.config; using Aucma.Core.Palletiz.Models; using Aucma.Core.Palletiz.ViewModels; using log4net; using Microsoft.Extensions.DependencyInjection; using NPOI.SS.Formula.UDF; using NPOI.SS.Util; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Interop; using TouchSocket.Sockets; namespace Aucma.Core.Palletiz.Business { internal class InStoreBusiness { private static readonly log4net.ILog _logger = LogManager.GetLogger(typeof(InStoreBusiness)); private readonly IProductOffLineServices _offlineService; private readonly IBaseSpaceInfoServices _spaceinfoService; private readonly AppConfig _appConfig; private AppConfig appConfig = new AppConfig(); public string storeCode = Appsettings.app("StoreInfo", "PalletizStoreCodeA"); // 过点数据表,物料完成记录MaterialCompletion private readonly IMaterialCompletionServices? _iMaterialCompletionServices = App.ServiceProvider.GetService(); private readonly IPrintBarCodeServices? _printBarCodeServices = App.ServiceProvider.GetService(); private readonly ICodeBindingRecordServices? _codeBindingServices = App.ServiceProvider.GetService(); private readonly IRecordInStoreServices? _recordInstoreServices = App.ServiceProvider.GetService(); #region 委托事件 /// /// 扫码信息刷新 /// public delegate void RefreshProductInfo(string productCode, string productModel, string orderCode); public static event RefreshProductInfo? RefreshProductInfoEvent; /// /// 提示信息刷新 /// public delegate void RefreshMsg(string msg); public static event RefreshMsg? RefreshMsgEvent; /// ///入库时DataGrid添加一条DataGrid记录 /// public delegate void AddData(RecordInStore record); public static event AddData? AddDataEvent; #endregion // private const string BarcodeRef = "6933973114570;1621240AP0098E3D3497"; private PlcModel plcCon = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("InStoreAPlc")); public InStoreBusiness() { _appConfig = new AppConfig(); _spaceinfoService = App.ServiceProvider.GetService(); _offlineService = App.ServiceProvider.GetService(); HandPalletizViewModel.HandSendEvent += InStore; // string AA = ExtractNumber("FD01_012"); } public void Init() { TouchSocketService.ReceivedClientBufferEvent += ReceivedBuffer; } /// /// Buffer缓冲 /// /// 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.Info($"收到客户端:{client.Id};心跳指令:{asciiStr}"); continue; } if (asciiStr.Contains("NoRead")) { NoReadHandle(client.Id); continue; } // _logger.Info($"收到客户端:{client.Id}条码信息:{asciiStr}"); InStore(client.Id, asciiStr); } while (false); } catch (Exception e) { _logger.Error($"Buffer缓冲异常:{e.Message}"); } } /// /// 入库申请 /// /// 货道区域 /// 20位是正常扫码传输的条码,手动入库传的是人工选择的成品型号 private void InStore(string spaceArea, string asciiStr) { RecordInStore recordInstore = new RecordInStore(); String msg = string.Empty; try { if (string.IsNullOrEmpty(asciiStr)) { throw new ArgumentException($"入库申请处理异常:条码信息为空"); } if (string.IsNullOrEmpty(spaceArea)) { throw new ArgumentException($"入库申请处理异常:货道区域为空"); } _offlineService.GetProductInfosBySnCode(asciiStr, out ProductOffline prodInfo); if (prodInfo == null) { throw new ArgumentException($"入库申请处理异常:根据成品码获取成品信息为空"); } RefreshProductInfoEvent?.Invoke(asciiStr,prodInfo.ProductModel,prodInfo.ProductOrderNo); GetSpaceInfoByMaterialType(spaceArea, prodInfo, out BaseSpaceInfo laseSpaceinfo, out BaseSpaceInfo spaceinfo); bool result = false; SendInStoreTask(asciiStr,spaceinfo, ref result,Convert.ToInt32(prodInfo.ProductMasterModel),ref msg,out int range); #region 添加入库记录 recordInstore.StoreCode = storeCode; recordInstore.StoreArea = spaceArea; recordInstore.SpaceCode = spaceinfo.SpaceCode; recordInstore.MaterialType = spaceinfo.MaterialType; recordInstore.MaterialCode = spaceinfo.MaterialType; recordInstore.InStoreTime = DateTime.Now; recordInstore.BarCodeCode = asciiStr; recordInstore.MaterialName = prodInfo.ProductName; recordInstore.InStoreAmount = range ; recordInstore.IsFlag = 0; recordInstore.CreatedTime = DateTime.Now; if (asciiStr.Length < 20) { recordInstore.EntryPattern = 1; } else { recordInstore.EntryPattern = 0; } #endregion if (!result) { msg = msg + "放行失败"; RefreshMsgEvent?.Invoke(msg); throw new ArgumentException($"入库申请处理异常:入库任务下发至PLC失败"); } else { msg = msg + "放行成功"; RefreshMsgEvent?.Invoke(msg); List spaceinfos = new List(); if (laseSpaceinfo != null) { laseSpaceinfo.InStoreFlag = 1; spaceinfos.Add(laseSpaceinfo); } spaceinfo.InStoreFlag = 3; spaceinfos.Add(spaceinfo); _spaceinfoService.UpdateSpaceInfo(spaceinfos); //刷新页面 AddDataEvent?.Invoke(recordInstore); } _ = _recordInstoreServices.AddAsync(recordInstore).Result; } catch (Exception e) { msg =$"入库逻辑处理异常:{e.Message}"; RefreshMsgEvent?.Invoke(msg); } } /// /// 添加过点数据,暂不添加 /// /// public async Task AddCompleteData(string ProductSnCode) { CodeBindingRecord bindingRecord1 = _codeBindingServices.FirstAsync(x => x.ProductCode == ProductSnCode).Result; #region 更新过点数据 if (bindingRecord1 != null && bindingRecord1.BoxCode != "") { PrintBarCode print = _printBarCodeServices.FirstAsync(x => x.MaterialBarcode == bindingRecord1.BoxCode).Result; if (print != null) { MaterialCompletion completion = new MaterialCompletion(); completion.OrderCode = print.OrderCode; completion.MaterialBarcode = bindingRecord1.BoxCode; completion.MaterialCode = print.MaterialCode; completion.MaterialName = print.MaterialName; // completion.StationName = "1009"; completion.CompleteDate = DateTime.Now; completion.ProductLineCode = "CX_02"; completion.isDownLine = 1; completion.ProductionCode = ProductSnCode; _ = _iMaterialCompletionServices.AddAsync(completion).Result; } } #endregion } /// /// 通过物料型号获取货道信息 /// /// /// /// /// /// /// private void GetSpaceInfoByMaterialType(string spaceArea, ProductOffline prodInfo, out BaseSpaceInfo laseSpaceinfo, out BaseSpaceInfo spaceinfo, bool isBig = false) { List spaceinfos = null; if (isBig) { _spaceinfoService.GetSpaceInfosByExpression(out spaceinfos, x => x.StoreCode == _appConfig.storeCode && x.SpaceArea == spaceArea && x.MaterialType == prodInfo.ProductCode && x.SpaceType == 2); } else { _spaceinfoService.GetSpaceInfosByExpression(out spaceinfos, x => x.StoreCode == _appConfig.storeCode && x.SpaceArea == spaceArea && x.MaterialType == prodInfo.ProductCode); } if (spaceinfos == null || spaceinfos.Count==0) { throw new ArgumentException($"通过物料型号获取货道信息异常:根据成品信息获取货道信息为空"); } spaceinfos = spaceinfos.OrderBy(x => x.ObjId).ToList(); MatchSpaceInfoByPlc(ref spaceinfos); if (spaceinfos == null || spaceinfos.Count==0) { throw new ArgumentException($"通过物料型号获取货道信息异常:通过PLC匹配可用货道信息为空"); } FiltrateSpaceInfo(spaceinfos, out laseSpaceinfo, out spaceinfo); if (spaceinfo == null || spaceinfos.Count==0) { throw new ArgumentException($"通过物料型号获取货道信息异常:未获取到匹配的货道信息"); } } /// /// 通过PLC匹配获取,去除已满的货道 /// /// private void MatchSpaceInfoByPlc(ref List spaceinfos) { if (plcCon == null) { Task.Delay(1000 * 3).Wait(); plcCon = PlcHelper.melsecList.FirstOrDefault(d => d.EquipName.Equals("InStoreAPlc")); if(plcCon == null) { throw new ArgumentException($"通过PLC匹配获取货道信息异常:Plc连接为空"); } } var _plc = plcCon.plc; foreach (var item in spaceinfos) { item.SpaceCode = ExtractNumber(item.SpaceName); var plcAddress = _appConfig.plcAddr.Where(x => x.spaceCode.ToString() == item.SpaceCode && x.spaceArea == item.SpaceArea).First(); bool isFlag = _plc.ReadBool(plcAddress.address); if (isFlag) { item.SpaceStatus = 3; } } spaceinfos = spaceinfos.Where(x => x.SpaceStatus != 3).ToList(); } /// /// 筛选货道信息 /// /// /// /// private void FiltrateSpaceInfo(List spaceinfos, out BaseSpaceInfo laseSpaceinfo, out BaseSpaceInfo spaceinfo) { if (spaceinfos == null || spaceinfos.Count == 0) { 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(); } } /// /// 下发入库任务至PLC /// /// /// /// private void SendInStoreTask(string asciiStr, BaseSpaceInfo spaceinfo, ref bool result,int prodWeight,ref string msg,out int rangeResult) { int spinFlag = -1; rangeResult = 0; if (plcCon == null) { throw new ArgumentException($"下发入库任务至PLC逻辑异常:Plc连接为空"); } var _plc = plcCon.plc; bool isFlag = true; int spaceCode = StringChange.ParseToInt(spaceinfo.SpaceCode); spinFlag =JudgeRotation(spaceCode, prodWeight, out int ranges); rangeResult = ranges; if (spinFlag == -1) { msg = $"成品码:{asciiStr},仓库区域:{spaceinfo.SpaceArea},匹配货道:{spaceinfo.SpaceCode};旋转角度匹配失败,请先设置该型号旋转规则!"; RefreshMsgEvent?.Invoke(msg); return; } msg = $"成品码:{asciiStr},仓库区域:{spaceinfo.SpaceArea},匹配货道:{spaceinfo.SpaceCode};旋转:{(spinFlag == 3 ? "0°" : "180°")};下发plc放行信号"; RefreshMsgEvent?.Invoke(msg); DateTime startTime = DateTime.Now; while (isFlag) { if((DateTime.Now - startTime).TotalSeconds > 15) { result = false; return; } bool answerFlag = _plc.ReadBool("B1000"); if (answerFlag) { isFlag = false; } Task.Delay(500).Wait(); } if (spaceinfo.SpaceArea == "A") { if (!_plc.WriteInt16("D2", spinFlag.ToString())) { throw new ArgumentException($"旋转角度下发至PLC失败"); } if (!_plc.WriteInt16("D29", spaceCode.ToString())) { throw new ArgumentException($"货道号下发至PLC失败"); } _plc.WriteInt16("B1001", "1");//发送完成信号 result = true; } else if (spaceinfo.SpaceArea == "B") { result = false; } } /// /// 根据货物容积确定旋转规则 转180度发1,不转发3 /// /// /// public int JudgeRotation(int spaceCode,int prodWeight, out int ranges) { try { List list = appConfig.GetJumpRanges(); foreach (JumpRange range in list) { if (range.MinModel <= prodWeight && range.MaxModel > prodWeight) // 找到该型号规则 { if (spaceCode % 2 == 0) // 偶数货道 { ranges = range.EvenSpaceRange; return RangeToInt(range.EvenSpaceRange); } else { ranges = range.OddSpaceRange; return RangeToInt(range.OddSpaceRange); } } } } catch (Exception ex) { Console.WriteLine("JudgeRotation"+ex.Message); } ranges = 0; return -1; } public int RangeToInt(int range) { int result = -1; switch (range) { case 0: result = 3; break; case 90: result = 1; break; case 180: result = 4; break; case 270: result = 2; break; } return result; } /// /// 提取货道号 /// /// /// 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" } } /// /// 读取失败处理 /// /// private void NoReadHandle(string client) { _logger.Error($"客户端:{client};读取失败!!!!!!"); } /// /// 获取成品库指定区域的货道信息 /// /// /// public List GetBaseSpaceinfos(string spaceArea) { _spaceinfoService.GetSpaceInfosByExpression(out List spaceinfos, x => x.StoreCode == _appConfig.storeCode && x.SpaceArea == spaceArea); return spaceinfos; } /// /// 获取货道信息 /// /// /// public BaseSpaceInfo GetSpaceinfosById(int id) { BaseSpaceInfo spaceInfo = _spaceinfoService.FirstAsync(x=>x.ObjId==id).Result; return spaceInfo; } } }