using System; using System.Data; using System.Diagnostics; using System.DirectoryServices.ActiveDirectory; using System.Dynamic; using System.Security.Cryptography.X509Certificates; using System.Security.Policy; using System.Text; using System.Text.RegularExpressions; using System.Threading; using Aop.Api.Domain; using Aspose.Cells.Charts; using JNPF; using JNPF.Common.Cache; using JNPF.Common.Core.Manager; using JNPF.Common.Dtos.VisualDev; using JNPF.Common.Extension; using JNPF.Common.Security; using JNPF.FriendlyException; using JNPF.Logging; using JNPF.Systems.Interfaces.System; using JNPF.TaskScheduler; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NetTaste; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Npgsql; using NPOI.OpenXmlFormats; using Org.BouncyCastle.Asn1.X509; using Org.BouncyCastle.Asn1.X509.Qualified; using Qiniu.Util; using Senparc.CO2NET.Helpers.Serializers; using SqlSugar; //using Swashbuckle.AspNetCore.SwaggerGen; using Tnb.BasicData.Entities; using Tnb.Common.Extension; using Tnb.Common.Redis; using Tnb.Common.Utils; using Tnb.EquipMgr.Entities; using Tnb.ProductionMgr.Entities; using Tnb.ProductionMgr.Entities.Dto; using Tnb.ProductionMgr.Entities.Enums; using Tnb.ProductionMgr.Interfaces; using Tnb.WarehouseMgr; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Configs; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Tnb.WarehouseMgr.Entities.Dto.Queries; using Tnb.WarehouseMgr.Entities.Entity; using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.ProductionMgr { //redis定时获取数采数据 public class RedisBackGround : IHostedService, IDisposable { #region 全局变量 private static Timer? GenTaskExecutetimer; private static Timer? Readtimer; private static Timer? CheckGettimer; private static Timer? Scantimer; private static Timer? SSXcodetimer; // 八工位缓存区补充空托盘 private static Timer? BGWCarrySupplementtimer; // 供料叠盘机空托盘自动入库 private static Timer? YCLGLDPJInstocktimer; // 外协叠盘机空托盘自动入库 private static Timer? YCLWXDPJInstocktimer; // 二楼上升降机 private static Timer? Floor2UpMachinecodetimer; // 二楼料架配送 private static Timer? Floor2timer送空托到上升降区; private static Timer? Floor2timer送满托到下升降区; private static Timer? Floor2timer移走上升降区未生成预任务且满托的料架; private static Timer? Floor2timer移走下升降区未生成预任务且空托的料架; // 四楼包材自动到二楼包材库 private static Timer? PackOutstockServicetimer; // 检查到电梯任务异常断开后处理 private Thread? ElevatorTaskExceptionHandleThread; public SemaphoreSlim s_taskCheckGet = new(1); public SemaphoreSlim s_taskScan = new(1); public SemaphoreSlim s_taskSSXcode = new(1); public SemaphoreSlim s_taskBGWCarrySupplement = new(1); public SemaphoreSlim s_taskYCLGLDPJInstock = new(1); public SemaphoreSlim s_taskYCLWXDPJInstock = new(1); public SemaphoreSlim s_taskExecuteFloor2UpMachinecodetimer = new(1); public SemaphoreSlim s_task送空托到上升降区 = new(1); public SemaphoreSlim s_task送满托到下升降区 = new(1); public SemaphoreSlim s_task移走上升降区未生成预任务且满托的料架 = new(1); public SemaphoreSlim s_task移走下升降区未生成预任务且空托的料架 = new(1); public SemaphoreSlim s_taskPackOutstockService = new(1); private StackExRedisHelper _redisData; private readonly IPrdInstockService _prdInstockService; private readonly ISqlSugarRepository _repository; private ISqlSugarClient db_Scantimer; private ISqlSugarClient db_CheckGettimer; private ISqlSugarClient db_SSXcodetimer; private ISqlSugarClient db_BGWCarrySupplementtimer; private ISqlSugarClient db_YCLGLDPJInstocktimer; private ISqlSugarClient db_YCLWXDPJInstocktimer; private ISqlSugarClient db_Floor2UpMachinecodetimer; private ISqlSugarClient db_Floor2timer送空托到上升降区; private ISqlSugarClient db_Floor2timer送满托到下升降区; private ISqlSugarClient db_Floor2timer移走上升降区未生成预任务且满托的料架; private ISqlSugarClient db_Floor2timer移走下升降区未生成预任务且空托的料架; private ISqlSugarClient db_PackOutstockService; private readonly IWmsPDAScanInStockService _wmsPDAScanInStock; private readonly IUserManager _userManager; private readonly IBillRullService _billRullService; private readonly IWareHouseService _wareHouseService; private readonly IWmsCarryBindService _wmsCarryBindService; private readonly IWmsCarryUnbindService _wmsCarryUnbindService; private readonly IWmsEmptyOutstockService _wmsEmptyOutstockService; private readonly IWmsPackOutstockService _wmsPackOutstockService; private readonly ElevatorControlConfiguration _eleCtlCfg = App.Configuration.Build(); static ConnectionStringsOptions connectionOpts = App.GetConfig("ConnectionStrings", true); static ConnectionConfig cfg = new() { ConfigId = connectionOpts.ConfigId, ConnectionString = connectionOpts.ConnectString, DbType = SqlSugar.DbType.PostgreSQL, IsAutoCloseConnection = true, }; #endregion #region 构造函数 public RedisBackGround(StackExRedisHelper redisData, IPrdInstockService prdInstockService, ISqlSugarRepository repository, IWmsPDAScanInStockService wmsPDAScanInStock , IUserManager userManager, IBillRullService billRullService, IWareHouseService wareHouseService, IWmsCarryBindService wmsCarryBindService, IWmsCarryUnbindService wmsCarryUnbindService, IWmsEmptyOutstockService wmsEmptyOutstockService, IWmsPackOutstockService wmsPackOutstockService) { _redisData = redisData; _prdInstockService = prdInstockService; _repository = repository; _wmsPDAScanInStock = wmsPDAScanInStock; _userManager = userManager; _billRullService = billRullService; _wareHouseService = wareHouseService; _wmsCarryBindService = wmsCarryBindService; _wmsEmptyOutstockService = wmsEmptyOutstockService; _wmsCarryUnbindService = wmsCarryUnbindService; _wmsPackOutstockService = wmsPackOutstockService; db_CheckGettimer = repository.CopyNew(); db_Scantimer = repository.CopyNew(); db_SSXcodetimer = repository.CopyNew(); db_BGWCarrySupplementtimer = repository.CopyNew(); db_YCLGLDPJInstocktimer = repository.CopyNew(); db_YCLWXDPJInstocktimer = repository.CopyNew(); db_Floor2UpMachinecodetimer = repository.CopyNew(); db_Floor2timer送空托到上升降区 = repository.CopyNew(); db_Floor2timer送满托到下升降区 = repository.CopyNew(); db_Floor2timer移走上升降区未生成预任务且满托的料架 = repository.CopyNew(); db_Floor2timer移走下升降区未生成预任务且空托的料架 = repository.CopyNew(); db_PackOutstockService = repository.CopyNew(); } #endregion #region ctu取货 //ctu取货 private async void CheckGet(object? state) { if (s_taskCheckGet.CurrentCount == 0) return; await s_taskCheckGet.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行CheckGet"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行CheckGet"); Dictionary getdic = new Dictionary(); getdic.Add("SSX-021-005", new string[] { "YTCS", "AllowFullOut_CS05", "LiftCode" }); getdic.Add("SSX-011-002", new string[] { "YTCS", "AllowAgvFullIn_CS02", "Code_CS02" }); getdic.Add("SSX-011-004", new string[] { "YTCS", "AllowCtuFullOut_CS04", "Code_CS04" }); getdic.Add("SSX-011-008", new string[] { "东面提升机输送线", "入库输送线8允许出箱", "入库输送线8条码" }); getdic.Add("SSX-111-011", new string[] { "东面提升机输送线", "下升降机11允许出箱", "下升降机11条码" }); getdic.Add("SSX-111-012", new string[] { "东面提升机输送线", "下升降机12允许出箱", "下升降机12条码" }); getdic.Add("ZSSSXCTU02", new string[] { "YTCS", "AllowAgvEmptyOut_CS03", "" }); getdic.Add("ZSSSXCTU01", new string[] { "YTCS", "AllowAgvEmptyOut_CS01", "" }); // s_taskCheckGet foreach (var key in getdic.Keys) { var strs = getdic.Where(p => p.Key == key).First().Value; bool result = await GetBoolTag(strs[0], strs[1]); if (result) { if (!string.IsNullOrEmpty(strs[2])) { string coderesult = await GetStringTag(strs[0], strs[2]); coderesult = coderesult.Replace("\r", "").Replace("\\r", "").Replace(" ", ""); if (string.IsNullOrEmpty(coderesult)) { continue; } LoggerSSX.LogInformation($@"【定时任务CheckGet】 成功取到{strs[2]}值:{coderesult}"); //using (var _db = _repository.AsSugarClient().CopyNew()) //{ var DistaskH = db_CheckGettimer.Queryable().Where(p => p.carry_code == coderesult && p.status == WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID && string.IsNullOrEmpty(p.extras)).First(); if (DistaskH != null) { LoggerSSX.LogInformation($@"【定时任务CheckGet】 成功找到载具:{coderesult} 对应的任务执行单{DistaskH.bill_code}"); dynamic reqBody = new ExpandoObject(); reqBody.taskCode = DistaskH.bill_code; reqBody.slotCode = key; reqBody.containerCode = coderesult; CancellationTokenSource Ctu = new(); LoggerSSX.LogInformation($"【定时任务CheckGet】 开始发送请求到 http://192.168.11.104:1880/wcs/notify/cargo 载具:{coderesult}"); dynamic respBody = HttpClientHelper.PostStreamAsync("http://192.168.11.104:1880/wcs/notify/cargo", reqBody, Ctu.Token).Result; LoggerSSX.LogInformation($"【定时任务CheckGet】 接收请求 http://192.168.11.104:1880/wcs/notify/cargo 结果 {respBody} "); DistaskH.extras = respBody; db_CheckGettimer.Updateable(DistaskH).ExecuteCommand(); Ctu.Dispose(); } else { LoggerSSX.LogInformation($@"【定时任务CheckGet】 {key}->{strs[0]} {strs[2]} 采集结果:{$@"任务执行(wms_distask_h)中找不到匹配的记录 任务执行需要存在载具编号(carry_code)为{coderesult} 且单据状态(status)为已下达(26126853976101) 且扩展字段(extras)为空的记录 (可能是WCS系统中存在载具{coderesult}的历史任务未清空) select extras,* from wms_distask_h where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STATUS_YXD_ID}' "}"); } //} } } } } catch(NpgsqlException ex) { Console.WriteLine("【CheckGet】" + ex.Message); LoggerSSX.LogError(ex.ToString()); //db_CheckGettimer = new SqlSugarClient(cfg); } catch (Exception ex) { Console.WriteLine("【CheckGet】" + ex.Message); LoggerSSX.LogError(ex.ToString()); } finally { s_taskCheckGet.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行CheckGet {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行CheckGet {stopwatch.ElapsedMilliseconds} ms"); } } #endregion #region 弃用 //获取redis数据 private async void GetRedisData(object? state) { var _redisReadConfigs = _repository.AsQueryable().Where(p => p.enabled == 1).ToList(); foreach (var config in _redisReadConfigs) { try { var json = await _redisData.GetHash(config.dev_name!, config.tag_name!); if (json == null) { continue; } JObject? res = JsonConvert.DeserializeObject(json); if (config.data_type == (int)DataType.INT) { if (config.check_type == (int)CheckType.相等) { if (res.Value("Value") == int.Parse(config.data!)) { InstockInput instockInput = new() { equip_code = res["DevName"]!.ToString(), label_code = res["TagName"]!.ToString() }; TriggerEvent((EventType)config.event_type, instockInput); } } else if (config.check_type == (int)CheckType.包含) { int[] ints = Array.ConvertAll(config.data!.Replace("[", "").Replace("]", "").Split(",", StringSplitOptions.RemoveEmptyEntries), int.Parse); if (ints.Contains(res.Value("Value"))) { InstockInput instockInput = new() { equip_code = res["DevName"]!.ToString(), label_code = res["TagName"]!.ToString() }; TriggerEvent((EventType)config.event_type, instockInput); } } } else if (config.data_type == (int)DataType.BOOL) { if (config.check_type == (int)CheckType.相等) { if (res.Value("Value") == bool.Parse(config.data!)) { InstockInput instockInput = new() { equip_code = res["DevName"]!.ToString(), label_code = res["TagName"]!.ToString() }; TriggerEvent((EventType)config.event_type, instockInput); } } } } catch (Exception) { } } } private void TriggerEvent(EventType eventType, InstockInput instockInput) { switch (eventType) { case EventType.注塑空满箱请求: _prdInstockService.InstockTypeOne(instockInput); break; case EventType.挤出空满箱请求: _prdInstockService.InstockTubeOne(instockInput); break; case EventType.限位请求: _prdInstockService.InstockOutPack(instockInput); break; default: break; } } #endregion #region 八工位 //扫码入库 private async void ScanInStock(object? state) { if (s_taskScan.CurrentCount == 0) return; await s_taskScan.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行ScanInStock"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行ScanInStock"); Dictionary getdic = new Dictionary(); getdic.Add("BGWRKYCL02", new string[] { "CP8", "AllowGetFullBox1", "code1", "PutDoneEmptyBox", "false" }); getdic.Add("BGWRKYCL01", new string[] { "CP8", "AllowGetFullBox2", "code2", "PutDoneEmptyBox", "false" }); foreach (var key in getdic.Keys) { var strs = getdic.Where(p => p.Key == key).First().Value; bool result = await GetBoolTag(strs[0], strs[1]); if (result) { LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} {strs[1]}采集到 {result}"); Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = strs[0], ["token"] = _eleCtlCfg.token, ["TagName"] = strs[3], ["Value"] = strs[4], }; LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} 发送PutDoneEmptyBox指令 {_eleCtlCfg.WriteTagUrl} {JsonConvert.SerializeObject(dicCommand)}"); HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand).Wait(); string coderesult = await GetStringTag(strs[0], strs[2]); LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} 获取到扫码信息: {coderesult}"); //using (var _db = _repository.AsSugarClient().CopyNew()) { WmsCarryH? carry = db_Scantimer.Queryable().Single(it => it.carry_code == coderesult); LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} 查找{coderesult}绑定的托盘: {JsonConvert.SerializeObject(carry)}"); if (carry != null) { if (db_Scantimer.Queryable().Where(p => p.carry_id == carry.id && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID && p.status != WmsWareHouseConst.TASK_BILL_STATUS_CANCEL_ID).Any()) { LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} 托盘 {carry.carry_code} 找到了执行任务状态(status)既不是26126860808229(已完成)或26126863175461(已取消)的历史任务,此时不能执行入库"); continue; } var WmsCarryCode = db_Scantimer.Queryable().Where(it => it.carry_id == carry.id).OrderByDescending(it => it.id).First(); // 用适当的字段替换 YourTimestampField if (WmsCarryCode != null) { LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} 查找到托盘{carry.carry_code}在WmsCarryCode中存在"); VisualDevModelDataCrInput input = new VisualDevModelDataCrInput(); input.data = new Dictionary(); input.data.Add("barcode", coderesult); input.data.Add("codeqty", WmsCarryCode.codeqty);//条码数量 input.data.Add("material_code", WmsCarryCode.material_code); input.data.Add("extras", key);//location_code input.data.Add("warehouse_id", "1");//TEST input.data.Add("bill_code", "");//采购收货单号 input.data.Add("code_batch", WmsCarryCode.code_batch!);//批次 input.data.Add("material_specification", WmsCarryCode.material_specification!);//规格型号 input.data.Add("container_no", WmsCarryCode.container_no!);//箱号 input.data.Add("material_id", WmsCarryCode.material_id); input.data.Add("id", null); _wmsPDAScanInStock.ScanInStockByRedis(input).Wait(); } else { LoggerBGWCarrySupplement.LogInformation($"【ScanInStock】 八工位 {key} 托盘 {carry.carry_code} 未绑定物料条码!"); } } } } } } catch (Exception ex) { Console.WriteLine("【ScanInStock】" + ex.Message); LoggerBGWCarrySupplement.LogError($"【ScanInStock】 八工位扫到码发送入库请求发生异常:{ex}"); } finally { s_taskScan.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行ScanInStock {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行ScanInStock {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 八工位空托盘补充 /// private async void BGWCarrySupplement(object? state) { if (s_taskBGWCarrySupplement.CurrentCount == 0) return; await s_taskBGWCarrySupplement.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行BGWCarrySupplement"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行BGWCarrySupplement"); Dictionary getdic = new Dictionary(); getdic.Add("YCLCKBGW", new string[] { "CP8", "AllowPutEmptyBox1" }); await db_BGWCarrySupplementtimer.Ado.BeginTranAsync(); foreach (var key in getdic.Keys) { var strs = getdic.Where(p => p.Key == key).First().Value; bool result = await GetBoolTag(strs[0], strs[1]); if (result) { LoggerBGWCarrySupplement.LogInformation($"【BGWCarrySupplementtimer】读取到信号{strs[1]} 值为{result} "); //using (var _db = _repository.AsSugarClient().CopyNew()) { BasLocation endLocation = db_BGWCarrySupplementtimer.Queryable().Where(r => r.location_code == key).First(); if (endLocation == null) { LoggerBGWCarrySupplement.LogWarning($"【BGWCarrySupplementtimer】 {key}未维护库位信息"); continue; } if (endLocation.is_lock == 1) { LoggerBGWCarrySupplement.LogInformation($"【BGWCarrySupplementtimer】 八工位 {key} 已锁定"); continue; } // 未锁定且已占用且库位中没有记录托盘 此时认为是叠盘机送过来的 var wmsLoc = db_BGWCarrySupplementtimer.Queryable() .LeftJoin((a, b) => a.id == b.location_id) .Where((a, b) => a.is_lock == 0 && a.is_use == "1" && a.wh_id == WmsWareHouseConst.WAREHOUSE_YCL_ID && a.location_code.Contains("YCL-") && a.is_type == "0") .OrderBy((a, b) => a.location_code) // 当前是按库位排序出库 .Select((a, b) => new { BasLocation = a, WmsCarryH = b }).ToList().GroupBy(p => p.BasLocation) .Where(group => { // 是否存在托盘 bool isExistsCarry = false; foreach (var item in group) { if (!string.IsNullOrEmpty(item.WmsCarryH.carry_code)) { isExistsCarry = true; break; } } if (isExistsCarry) return false; else return true; }).Select(r => r.Key); if (wmsLoc.Count() == 0) { LoggerBGWCarrySupplement.LogInformation($"【BGWCarrySupplementtimer】 没有未锁定且已占用且库位中没有记录托盘的数据"); continue; } BasLocation startLocation = wmsLoc.First(); //锁定起点库位 await db_BGWCarrySupplementtimer.Updateable().SetColumns(r => r.is_lock == 1).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); ////锁定终点库位 更新为空闲 //await _db.Updateable().SetColumns(r => new BasLocation { is_lock = 1, is_use = "0" }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); LoggerBGWCarrySupplement.LogInformation($"【BGWCarrySupplementtimer】锁定起点库位 开始生成 {startLocation.location_code} 到 {endLocation.location_code} 预任务 "); bool result_createPretask = await createPretask(startLocation.id, endLocation.id, "", "", LoggerBGWCarrySupplement, db_BGWCarrySupplementtimer); if (!result_createPretask) { LoggerBGWCarrySupplement.LogWarning($"【BGWCarrySupplementtimer】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成失败 "); throw new Exception($"【BGWCarrySupplementtimer】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成失败"); } LoggerBGWCarrySupplement.LogInformation($"【BGWCarrySupplementtimer】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成成功"); } _ = _wareHouseService.GenTaskExecute(); } } await db_BGWCarrySupplementtimer.Ado.CommitTranAsync(); } catch (ObjectDisposedException ex) { LoggerBGWCarrySupplement.LogError($"【BGWCarrySupplementtimer】 数据库连接异常:{ex.Message}"); LoggerBGWCarrySupplement.LogError($"【BGWCarrySupplementtimer】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_BGWCarrySupplementtimer = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【BGWCarrySupplement】" + ex.Message); LoggerBGWCarrySupplement.LogError($"【BGWCarrySupplementtimer】 数据库连接异常:{ex}"); // 数据库连接断开时会报错 try { await db_BGWCarrySupplementtimer.Ado.RollbackTranAsync(); } catch { }; } finally { s_taskBGWCarrySupplement.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行BGWCarrySupplement {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行BGWCarrySupplement {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 供料叠盘机空托盘自动入库 /// private async void YCLGLDPJInstock(object? state) { if (s_taskYCLGLDPJInstock.CurrentCount == 0) return; await s_taskYCLGLDPJInstock.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行YCLGLDPJInstock"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行YCLGLDPJInstock"); Dictionary getdic = new Dictionary(); getdic.Add("SGW-YCL", new string[] { "CP3-5", "AllowGetFullBox" }); await db_YCLGLDPJInstocktimer.Ado.BeginTranAsync(); foreach (var key in getdic.Keys) { var strs = getdic.Where(p => p.Key == key).First().Value; bool result = await GetBoolTag(strs[0], strs[1]); if (result) { LoggerYCLGLDPJInstock.LogInformation($"【YCLGLDPJInstock】 三工位叠盘机 {key} {strs[1]}采集到 {result}"); //using (var db = _repository.AsSugarClient().CopyNew()) { BasLocation startLocation = db_YCLGLDPJInstocktimer.Queryable().Where(r => r.location_code == key).First(); if (startLocation == null) { LoggerYCLGLDPJInstock.LogWarning($"【YCLGLDPJInstock】 {key}未维护库位信息"); continue; } if (startLocation.is_lock == 1) { LoggerYCLGLDPJInstock.LogInformation($"【YCLGLDPJInstock】 三工位叠盘机 {key} 已锁定"); continue; } // 找到未锁定且未占用的库位 var endLocations = db_YCLGLDPJInstocktimer.Queryable() .Where(a => a.is_lock == 0 && a.is_use == "0" && a.wh_id == WmsWareHouseConst.WAREHOUSE_YCL_ID && a.location_code.Contains("YCL-") && a.is_type == "0"); LoggerYCLGLDPJInstock.LogInformation($"【YCLGLDPJInstock】 sql {endLocations.ToSqlString()}"); if (endLocations.Count() == 0) { LoggerYCLGLDPJInstock.LogWarning($"【YCLGLDPJInstock】 当前没有空库位可以入库"); continue; } BasLocation endLocation = endLocations.First(); //锁定起点库位 更新为空闲 await db_YCLGLDPJInstocktimer.Updateable().SetColumns(r => new BasLocation { is_lock = 1, is_use = "0" }).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); //锁定终点库位 await db_YCLGLDPJInstocktimer.Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); bool result_createPretask = await createPretask(startLocation.id, endLocation.id, "", "", LoggerYCLGLDPJInstock, db_YCLGLDPJInstocktimer); if (!result_createPretask) { LoggerYCLGLDPJInstock.LogWarning($"【YCLGLDPJInstock】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成失败"); throw new Exception($"【YCLGLDPJInstock】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成失败"); } LoggerYCLGLDPJInstock.LogWarning($"【YCLGLDPJInstock】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成成功"); } _ = _wareHouseService.GenTaskExecute(); } } await db_YCLGLDPJInstocktimer.Ado.CommitTranAsync(); } catch (ObjectDisposedException ex) { LoggerYCLGLDPJInstock.LogError($"【YCLGLDPJInstock】 数据库连接异常:{ex.Message}"); LoggerYCLGLDPJInstock.LogError($"【YCLGLDPJInstock】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_YCLGLDPJInstocktimer = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【YCLGLDPJInstock】" + ex.Message); LoggerYCLGLDPJInstock.LogError($"【YCLGLDPJInstock】 数据库连接异常:{ex}"); // 数据库连接断开时会报错 try { await db_YCLGLDPJInstocktimer.Ado.RollbackTranAsync(); } catch { }; } finally { s_taskYCLGLDPJInstock.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行YCLGLDPJInstock {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行YCLGLDPJInstock {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 外协叠盘机空托盘自动入库 /// private async void YCLWXDPJInstock(object? state) { if (s_taskYCLWXDPJInstock.CurrentCount == 0) return; await s_taskYCLWXDPJInstock.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行YCLWXDPJInstock"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行YCLWXDPJInstock"); Dictionary getdic = new Dictionary(); getdic.Add("未定", new string[] { "CP3-3", "AllowGetFullBox" }); await db_YCLWXDPJInstocktimer.Ado.BeginTranAsync(); foreach (var key in getdic.Keys) { var strs = getdic.Where(p => p.Key == key).First().Value; bool result = await GetBoolTag(strs[0], strs[1]); if (result) { LoggerYCLGLDPJInstock.LogInformation($"【YCLWXDPJInstock】 外协叠盘机 {key} {strs[1]}采集到 {result}"); BasLocation startLocation = db_YCLWXDPJInstocktimer.Queryable().Where(r => r.location_code == key).First(); if (startLocation == null) { LoggerYCLGLDPJInstock.LogWarning($"【YCLWXDPJInstock】 {key}未维护库位信息"); continue; } if (startLocation.is_lock == 1) { LoggerYCLGLDPJInstock.LogInformation($"【YCLWXDPJInstock】 外协叠盘机 {key} 已锁定"); continue; } // 找到未锁定且未占用的库位 var endLocations = db_YCLWXDPJInstocktimer.Queryable() .Where(a => a.is_lock == 0 && a.is_use == "0" && a.wh_id == WmsWareHouseConst.WAREHOUSE_YCL_ID && a.location_code.Contains("YCL-") && a.is_type == "0"); LoggerYCLGLDPJInstock.LogInformation($"【YCLWXDPJInstock】 sql {endLocations.ToSqlString()}"); if (endLocations.Count() == 0) { LoggerYCLGLDPJInstock.LogWarning($"【YCLWXDPJInstock】 当前没有空库位可以入库"); continue; } BasLocation endLocation = endLocations.First(); //锁定起点库位 更新为空闲 await db_YCLWXDPJInstocktimer.Updateable().SetColumns(r => new BasLocation { is_lock = 1, is_use = "0" }).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); //锁定终点库位 await db_YCLWXDPJInstocktimer.Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); bool result_createPretask = await createPretask(startLocation.id, endLocation.id, "", "", LoggerYCLGLDPJInstock, db_YCLWXDPJInstocktimer); if (!result_createPretask) { LoggerYCLGLDPJInstock.LogWarning($"【YCLWXDPJInstock】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成失败"); throw new Exception($"【YCLWXDPJInstock】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成失败"); } LoggerYCLGLDPJInstock.LogWarning($"【YCLWXDPJInstock】 {startLocation.location_code} 到 {endLocation.location_code} 预任务生成成功"); _ = _wareHouseService.GenTaskExecute(); } } await db_YCLWXDPJInstocktimer.Ado.CommitTranAsync(); } catch (ObjectDisposedException ex) { LoggerYCLGLDPJInstock.LogError($"【YCLWXDPJInstock】 数据库连接异常:{ex.Message}"); LoggerYCLGLDPJInstock.LogError($"【YCLWXDPJInstock】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_YCLWXDPJInstocktimer = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【YCLGLDPJInstock】" + ex.Message); LoggerYCLGLDPJInstock.LogError($"【YCLWXDPJInstock】 数据库连接异常:{ex}"); // 数据库连接断开时会报错 try { await db_YCLWXDPJInstocktimer.Ado.RollbackTranAsync(); } catch { }; } finally { s_taskYCLWXDPJInstock.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行YCLWXDPJInstock {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行YCLWXDPJInstock {stopwatch.ElapsedMilliseconds} ms"); } } #endregion #region 中储仓 private async void SSXcode(object? state) { if (s_taskSSXcode.CurrentCount == 0) return; await s_taskSSXcode.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行SSXcode"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行SSXcode"); Dictionary dic = new Dictionary(); dic.Add("东面提升机输送线", new string[] { "下升降机判断请求", "下升降机判断条码", "下升降机判断完毕", "下升降机判断结果" }); Dictionary putdic = new Dictionary(); putdic.Add("SSX-111-011", 11); putdic.Add("SSX-111-012", 12); foreach (var key in dic.Keys) { var strs = dic.Where(p => p.Key == key).First().Value; bool re = await GetBoolTag(key, strs[0]); if (!re) continue; string? result = await GetStringTag(key, strs[1]); if (!string.IsNullOrEmpty(result)) { if (result.Length < 5) { result = "LX" + result.Replace("\r", ""); } var DistaskH = db_SSXcodetimer.Queryable().Where(p => p.carry_code == result && p.status != WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID).OrderByDescending(p => p.create_time).First(); if (DistaskH != null) { LoggerSSX.LogInformation($"【定时任务SSXcode】DistaskH != null putdic.Keys.Contains(DistaskH.startlocation_code):{putdic.Keys.Contains(DistaskH.startlocation_code)} {result}"); Dictionary dicCommand2 = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[3], ["Value"] = putdic.Keys.Contains(DistaskH.startlocation_code) ? putdic.Where(p => p.Key == DistaskH.startlocation_code).First().Value.ToString() : "13", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand2).Wait(); Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[2], ["Value"] = "true", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand).Wait(); } else { LoggerSSX.LogInformation($"【定时任务SSXcode】DistaskH == null "); Dictionary dicCommand2 = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[3], ["Value"] = "13", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand2).Wait(); Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = key, ["token"] = _eleCtlCfg.token, ["TagName"] = strs[2], ["Value"] = "true", }; HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand).Wait(); } } } } catch (Exception ex) { Console.WriteLine("【SSXcode】" + ex.Message); LoggerSSX.LogInformation($"【定时任务SSXcode】发生异常 {ex}"); } finally { s_taskSSXcode.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString($"yyyy-MM-dd HH:mm:ss")} 结束执行SSXcode {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString($"yyyy-MM-dd HH:mm:ss")} 结束执行SSXcode {stopwatch.ElapsedMilliseconds} ms"); } } #endregion #region 二楼上升降机机械臂 // 上升降机扫码 需要等待空料架区 此处需要轮询 private async void Floor2UpMachinecode(object? args) { if (s_taskExecuteFloor2UpMachinecodetimer.CurrentCount == 0) return; s_taskExecuteFloor2UpMachinecodetimer.Wait(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行Floor2UpMachinecode"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行Floor2UpMachinecode"); string barcode = await GetStringTag("东面提升机输送线", MechanicalArmConsts.上升降机条码); if (string.IsNullOrEmpty(barcode)) { LoggerFloor2UpDownMachine.LogError($@"【上升降机】未取到条码数据"); return; } //using (var db = _repository.AsSugarClient().CopyNew()) { // 读取上升降机的左右料架区配置 string[] configs = new string[2] { "二楼上升降机机械臂左", "二楼上升降机机械臂右" }; // 左右料架区配置 List WmsMechanicalArmHs = db_Floor2UpMachinecodetimer.Queryable() .Where(r => configs.Contains(r.name) && r.agvconfirm == 1).ToList(); // 是否可以放货 if (WmsMechanicalArmHs.Count == 0) { LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】目前没有可以放货的料架区(料架区一个料架都没有,如果实际有料架说明系统缓存表与实际不对应,需要重置缓存表信息)"); return; } // 如果条码已被绑定 if (WmsMechanicalArmHs.Where(r => !string.IsNullOrEmpty(r.barcodes) && r.barcodes.Contains(barcode)).Count() > 0) { LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】条码{barcode}已被绑定"); return; } LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】扫描到有效条码 {barcode}"); // 获取下到输送线9和10的未完成的转库单 List WmsMaterialTransfers = db_Floor2UpMachinecodetimer.Queryable() .InnerJoin((a, b) => a.id == b.bill_id) .Where((a, b) => a.warehouse_instock == "33780009364245" && a.warehouse_outstock == "2" && a.remainbindracknum > 0 && b.carry_code == barcode).ToList(); if (WmsMaterialTransfers.Count() == 0) { LoggerFloor2UpDownMachine.LogWarning($@"【上升降机】未找到条码{barcode}的输送线为9、10的转库单,可能是出入仓库选择有误或者此载具在中储仓发生了错乱"); return; } // 转库单 WmsMaterialTransfer WmsMaterialTransfer = WmsMaterialTransfers.OrderByDescending(r => r.create_time).First(); // 找到条码在的转库单 string ckdCode = WmsMaterialTransfer.bill_code; int ckdRemainBindRackNum = (int)(WmsMaterialTransfer.remainbindracknum != null ? WmsMaterialTransfer.remainbindracknum : 0); //扫描到的料箱 a.对应转库单的b.码垛计数未达到满托数量的料架区 IEnumerable targetConfigs = WmsMechanicalArmHs.Where(r => r.outbill == ckdCode && r.stackingcount < r.maxnum); WmsMechanicalArmH target; await db_Floor2UpMachinecodetimer.Ado.BeginTranAsync(); // 找不到对应的料架 if (targetConfigs.Count() == 0) { // 有空闲料架区且绑定了料架时 targetConfigs = WmsMechanicalArmHs.Where(r => string.IsNullOrEmpty(r.outbill)).OrderBy(r => r.id); if (targetConfigs.Count() > 0) { target = targetConfigs.First(); // 计算当前料架区的满托数量 int? maxnum = ckdRemainBindRackNum > target.maxracknum ? ckdRemainBindRackNum % target.maxracknum : ckdRemainBindRackNum; // 更新 转库单、满托数量 LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】为条码 {barcode} 所在的转库单 {ckdCode} 占用了一个空闲料架"); await db_Floor2UpMachinecodetimer.Updateable().SetColumns(r => new WmsMechanicalArmH { outbill = ckdCode, maxnum = maxnum }).Where(r => r.id == target.id).ExecuteCommandAsync(); bool result = await Floor2UpDownMachinecode_SetTag($"上升降机满托{target.stackingposition}数量", maxnum.ToString()); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】设定升降机满托{target.stackingposition}满托数量为 {maxnum} 结果为 {result}"); if (!result) { throw new Exception($@"【上升降机】设定升降机满托{target.stackingposition}满托数量为 {maxnum} 结果为 {result}"); } // 尝试写入空托送到信号 bool result上升降机空托送到 = await Floor2UpDownMachinecode_SetTag($"上升降机空托{target.stackingposition}送到", "true"); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写 上升降机空托{target.stackingposition}送到 结果为{result上升降机空托送到}"); if (!result上升降机空托送到) { return; } } else { LoggerFloor2UpDownMachine.LogError($@"【上升降机】条码{barcode}找不到绑定转库单{ckdCode}的料架区,且没有空闲的料架区可以用于绑定此转库单!"); await db_Floor2UpMachinecodetimer.Ado.RollbackTranAsync(); return; } } //如有多个料架绑定同个转库单则取第一个未满托的料架 target = targetConfigs.First(); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】当前条码目标料架区为 {JsonConvert.SerializeObject(target)}"); // 料架信息 WmsCarryH rack = db_Floor2UpMachinecodetimer.Queryable().Where(r => r.id == target.rackid).ToList()[0]; // 料箱信息 WmsCarryH LX = db_Floor2UpMachinecodetimer.Queryable().Where(r => r.carry_code == barcode).ToList()[0]; // 绑定料箱到料架 CarryBindInput carryBindInput = new(); carryBindInput.carry_id = target.rackid; carryBindInput.carry_code = target.rackcode; carryBindInput.membercarry_id = LX.id; carryBindInput.membercarry_code = LX.carry_code; carryBindInput.carrystd_id = rack.carrystd_id; carryBindInput.source_code = target.outbill; int row = await db_Floor2UpMachinecodetimer.Updateable().SetColumns(r => r.carry_status == ((int)(EnumCarryStatus.齐套)).ToString()).Where(r => r.id == target.rackid).ExecuteCommandAsync(); if (row == 0) { throw new Exception($"【上升降机】料架{target.rackcode}状态回写失败"); } WarehouseMgr.Entities.Dto.Outputs.Result bindResult = await _wmsCarryBindService.CarryBind(carryBindInput, db_Floor2UpMachinecodetimer); if (bindResult.code != JNPF.Common.Enums.HttpStatusCode.OK) { throw new Exception(bindResult.msg); } // 回写料箱条码、码垛计数 await db_Floor2UpMachinecodetimer.Updateable().SetColumns(r => new WmsMechanicalArmH { barcodes = $"{target.barcodes},{barcode}".Trim(','), stackingcount = r.stackingcount + 1, mechanicalconfirm = 1 }).Where(r => r.id == target.id).ExecuteCommandAsync(); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写料箱条码、码垛计数"); // 回写转库单的剩余可绑定料架数量 await db_Floor2UpMachinecodetimer.Updateable().SetColumns(r => new WmsMaterialTransfer { remainbindracknum = r.remainbindracknum - 1 }).Where(r => r.id == WmsMaterialTransfer.id).ExecuteCommandAsync(); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】回写转库单的剩余可绑定料架数量"); // 开始码垛 bool result_开始码垛 = await Floor2UpDownMachinecode_SetTag(MechanicalArmConsts.上升降机当前码垛位, target.stackingposition.ToString()); LoggerFloor2UpDownMachine.LogInformation($@"【上升降机】码垛位{target.stackingposition}码垛结果 {result_开始码垛}"); if (!result_开始码垛) { throw new Exception($@"【上升降机】码垛结果 {result_开始码垛}"); } await db_Floor2UpMachinecodetimer.Ado.CommitTranAsync(); } } catch (ObjectDisposedException ex) { LoggerFloor2UpDownMachine.LogError($"【上升降机】 数据库连接异常:{ex.Message}"); LoggerFloor2UpDownMachine.LogError($"【上升降机】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_Floor2UpMachinecodetimer = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【上升降机】" + ex.Message); LoggerFloor2UpDownMachine.LogError($"【上升降机】 数据库连接异常:{ex}"); // 数据库连接断开时会报错 try { await db_Floor2UpMachinecodetimer.Ado.RollbackTranAsync(); } catch { }; } finally { s_taskExecuteFloor2UpMachinecodetimer.Release(); if (!db_Floor2UpMachinecodetimer.Ado.Transaction.IsNull()) try { await db_Floor2UpMachinecodetimer.Ado.CommitTranAsync(); } catch { }; stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行Floor2UpMachinecode {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行Floor2UpMachinecode {stopwatch.ElapsedMilliseconds} ms"); } } // 二楼机械臂信号对应机械臂字典 Dictionary floor2mechanicalAtmDic = new Dictionary() { {"上升降机请求送空托1","二楼上升降机机械臂左"}, {"上升降机请求送空托2","二楼上升降机机械臂右"}, {"下升降机请求送满托1","二楼下升降机机械臂左"}, {"下升降机请求送满托2","二楼下升降机机械臂右"}, {"上升降机请求取满托1","二楼上升降机机械臂左"}, {"上升降机请求取满托2","二楼上升降机机械臂右"}, {"下升降机请求取空托1","二楼下升降机机械臂左"}, {"下升降机请求取空托2","二楼下升降机机械臂右"}, }; /// /// 送空托到上升降区 /// /// public async void 送空托到上升降区(object? args) { if (s_task送空托到上升降区.CurrentCount == 0) return; await s_task送空托到上升降区.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行送空托到上升降区"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行送空托到上升降区"); #region 检查信号 List configs_upMachine = new List(); if (await GetBoolTag("东面提升机输送线", $"上升降机请求送空托1")) { LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】上升降机请求送空托1 true"); configs_upMachine.Add(floor2mechanicalAtmDic["上升降机请求送空托1"]); } if (await GetBoolTag("东面提升机输送线", $"上升降机请求送空托2")) { LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】上升降机请求送空托2 true"); configs_upMachine.Add(floor2mechanicalAtmDic["上升降机请求送空托2"]); } // 没有有效信号 if (configs_upMachine.Count == 0) return; #endregion //using (var db = _repository.AsSugarClient().CopyNew()) { // 找到没有绑定料架的且库位未锁定的料架区 ISugarQueryable WmsMechanicalArmHsuagar = db_Floor2timer送空托到上升降区.Queryable() .InnerJoin((a, b) => a.location_id == b.id) .Where((a, b) => string.IsNullOrEmpty(a.rackcode) && b.is_lock == 0 && configs_upMachine.Contains(a.name)); List WmsMechanicalArmHs = WmsMechanicalArmHsuagar.ToList(); if (WmsMechanicalArmHs.Count() == 0) { LoggerFloor2RackDelivery.LogWarning($"【送空托到上升降区】 无需补充料架区 {WmsMechanicalArmHsuagar.ToSqlString()}"); return; } await db_Floor2timer送空托到上升降区.Ado.BeginTranAsync(); // 料架区 foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { // 找到占用且未锁定的库位上的空料架 ISugarQueryable rackStartLocations = db_Floor2timer送空托到上升降区.Queryable() .InnerJoin((a, b) => a.id == b.location_id) .LeftJoin((a, b, c) => b.id == c.carry_id) .Where((a, b, c) => a.wh_id == "33780009364245" && a.is_use == "1" && a.is_lock == 0 && a.is_type == "0" && string.IsNullOrEmpty(c.id) && b.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID).OrderBy(a => a.id).Take(1); if (rackStartLocations.Count() == 0) { LoggerFloor2RackDelivery.LogWarning($"【送空托到上升降区】 暂存仓中没有可用的空料架 {rackStartLocations.ToSqlString()}"); continue; } LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 即将补充料架区{wmsMechanicalArmH.name}"); BasLocation startLocation = rackStartLocations.First(); List wmsCarryHs = db_Floor2timer送空托到上升降区.Queryable().Where(r => r.location_id == startLocation.id).ToList(); if (wmsCarryHs.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起点{startLocation.id} {startLocation.location_code}上找不到料架"); continue; } if (wmsCarryHs.Count > 1) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 起点{startLocation.id} {startLocation.location_code}上存在多个料架"); continue; } // 空料架 WmsCarryH targetCarry = wmsCarryHs[0]; await db_Floor2timer送空托到上升降区.Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); await db_Floor2timer送空托到上升降区.Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == wmsMechanicalArmH.location_id).ExecuteCommandAsync(); LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 开始生成预任务 起点{startLocation.location_code} 终点{wmsMechanicalArmH.location_code} 料架 {targetCarry.carry_code}"); bool result = await createPretask(startLocation.id, wmsMechanicalArmH.location_id, targetCarry.id, targetCarry.carry_code, LoggerFloor2RackDelivery, db_Floor2timer送空托到上升降区); if (!result) { LoggerFloor2RackDelivery.LogInformation($"【送空托到上升降区】 未成功生成预任务 起点{startLocation.location_code} 终点{wmsMechanicalArmH.location_code} 料架 {targetCarry.carry_code}"); throw new Exception($"【送空托到上升降区】 未成功生成预任务 起点{startLocation.location_code} 终点{wmsMechanicalArmH.location_code} 料架 {wmsMechanicalArmH.rackcode}"); } } await db_Floor2timer送空托到上升降区.Ado.CommitTranAsync(); } } catch (ObjectDisposedException ex) { LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 数据库连接异常:{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_Floor2timer送空托到上升降区 = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【上升降机】" + ex.Message); LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 {ex.Message}"); LoggerFloor2RackDelivery.LogError($"【送空托到上升降区】 {ex.StackTrace}"); // 数据库连接断开时会报错 try { await db_Floor2timer送空托到上升降区.Ado.RollbackTranAsync(); } catch { }; } finally { s_task送空托到上升降区.Release(); if (!db_Floor2timer送空托到上升降区.Ado.Transaction.IsNull()) try { await db_Floor2timer送空托到上升降区.Ado.CommitTranAsync(); } catch { }; _wareHouseService.GenTaskExecute(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行送空托到上升降区 {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行送空托到上升降区 {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 送满托到下升降区 /// /// public async void 送满托到下升降区(object? args) { if (s_task送满托到下升降区.CurrentCount == 0) return; await s_task送满托到下升降区.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行送满托到下升降区"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行送满托到下升降区"); #region 检查信号 List configs_upMachine = new List(); if (await GetBoolTag("东面提升机输送线", $"下升降机请求送满托1")) { LoggerFloor2RackDelivery.LogInformation($"【送满托到下升降区】下升降机请求送满托1 true"); configs_upMachine.Add(floor2mechanicalAtmDic["下升降机请求送满托1"]); } if (await GetBoolTag("东面提升机输送线", $"下升降机请求送满托2")) { LoggerFloor2RackDelivery.LogInformation($"【送满托到下升降区】下升降机请求送满托2 true"); configs_upMachine.Add(floor2mechanicalAtmDic["下升降机请求送满托2"]); } // 没有有效信号 if (configs_upMachine.Count == 0) return; #endregion //using (var db = _repository.AsSugarClient().CopyNew()) { // 找到没有绑定料架的且库位未锁定的料架区 ISugarQueryable WmsMechanicalArmHsuagar = db_Floor2timer送满托到下升降区.Queryable() .InnerJoin((a, b) => a.location_id == b.id) .Where((a, b) => string.IsNullOrEmpty(a.rackcode) && b.is_lock == 0 && configs_upMachine.Contains(a.name)); List WmsMechanicalArmHs = WmsMechanicalArmHsuagar.ToList(); if (WmsMechanicalArmHs.Count() == 0) { LoggerFloor2RackDelivery.LogWarning($"【送满托到下升降区】 无需补充料架区 {WmsMechanicalArmHsuagar.ToSqlString()}"); return; } await db_Floor2timer送满托到下升降区.Ado.BeginTranAsync(); // 料架区 foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { // 找到占用且未锁定的库位上的满料架且料架中的料箱是空的 List rackStartLocations = db_Floor2timer送满托到下升降区.Queryable() .InnerJoin((a, b) => a.id == b.location_id) .LeftJoin((a, b, c) => b.id == c.carry_id) // 有料箱 .LeftJoin((a, b, c, d) => c.membercarry_id == d.carry_id) .Where((a, b, c, d) => a.wh_id == "33780009364245" && a.is_use == "1" && a.is_lock == 0 && a.is_type == "0" && !string.IsNullOrEmpty(c.id) && b.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID).OrderBy((a, b, c, d) => d.id).Select((a, b, c, d) => new // 关联载具物料明细表 { wmsCarryH = b, basLocation = a, WmsCarryCode_id = d.id }).ToList().GroupBy(r => r.basLocation.location_code).Select(r => { var item = r.FirstOrDefault(); // 空载具入库: 前面通过OrderBy(d => d.id)对WmsCarryCode_id进行了排序 那么如果第一行有数据则说明存在非空料箱 // 没有物料且没有退料标记的不满足出库条件 if (!string.IsNullOrEmpty(item.WmsCarryCode_id) && item.wmsCarryH.carry_status != ((int)(EnumCarryStatus.退料)).ToString()) { return new BasLocation(); } else { // 进这里说明库位下的料箱都为空 return item.basLocation; } }) // 筛选非空库位数据 .Where(r => !string.IsNullOrEmpty(r.location_code)).ToList(); if (rackStartLocations.Count() == 0) { //LoggerFloor2RackDelivery.LogWarning($"【送满托到下升降区】 暂存仓中没有可用的满料架 {db_Floor2timer送满托到下升降区.Queryable() //.InnerJoin((a, b) => a.id == b.location_id) //.LeftJoin((a, b, c) => b.id == c.carry_id) // 有料箱 //.LeftJoin((a, b, c, d) => c.membercarry_id == d.carry_id) //.Where((a, b, c, d) => a.wh_id == "33780009364245" && a.is_use == "1" && a.is_lock == 0 && a.is_type == "0" && !string.IsNullOrEmpty(c.id) //&& b.carrystd_id == WmsWareHouseConst.CARRY_LJSTD_ID).OrderBy((a, b, c, d) => d.id).Select((a, b, c, d) => new // 关联载具物料明细表 //{ // basLocation = a, // WmsCarryCode_id = d.id //}).ToSqlString()}"); continue; } LoggerFloor2RackDelivery.LogInformation($"【送满托到下升降区】 即将补充料架区{wmsMechanicalArmH.name}"); BasLocation startLocation = rackStartLocations.First(); List wmsCarryHs = db_Floor2timer送满托到下升降区.Queryable().Where(r => r.location_id == startLocation.id).ToList(); if (wmsCarryHs.Count == 0) { LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 起点{startLocation.id} {startLocation.location_code}上找不到料架"); continue; } if (wmsCarryHs.Count > 1) { LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 起点{startLocation.id} {startLocation.location_code}上存在多个料架"); continue; } // 满料架 WmsCarryH targetCarry = wmsCarryHs[0]; await db_Floor2timer送满托到下升降区.Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == startLocation.id).ExecuteCommandAsync(); await db_Floor2timer送满托到下升降区.Updateable().SetColumns(r => new BasLocation { is_lock = 1 }).Where(r => r.id == wmsMechanicalArmH.location_id).ExecuteCommandAsync(); LoggerFloor2RackDelivery.LogInformation($"【送满托到下升降区】 开始生成预任务 起点{startLocation.location_code} 终点{wmsMechanicalArmH.location_code} 料架 {targetCarry.carry_code}"); bool result = await createPretask(startLocation.id, wmsMechanicalArmH.location_id, targetCarry.id, targetCarry.carry_code, LoggerFloor2RackDelivery, db_Floor2timer送满托到下升降区); if (!result) { LoggerFloor2RackDelivery.LogInformation($"【送满托到下升降区】 未成功生成预任务 起点{startLocation.location_code} 终点{wmsMechanicalArmH.location_code} 料架 {targetCarry.carry_code}"); throw new Exception($"【送满托到下升降区】 未成功生成预任务 起点{startLocation.location_code} 终点{wmsMechanicalArmH.location_code} 料架 {targetCarry.carry_code}"); } } await db_Floor2timer送满托到下升降区.Ado.CommitTranAsync(); } } catch (ObjectDisposedException ex) { LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 数据库连接异常:{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_Floor2timer送满托到下升降区 = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【上升降机】" + ex.Message); LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 {ex.Message}"); LoggerFloor2RackDelivery.LogError($"【送满托到下升降区】 {ex.StackTrace}"); // 数据库连接断开时会报错 try { await db_Floor2timer送满托到下升降区.Ado.RollbackTranAsync(); } catch { }; } finally { s_task送满托到下升降区.Release(); if (!db_Floor2timer送满托到下升降区.Ado.Transaction.IsNull()) try { await db_Floor2timer送满托到下升降区.Ado.CommitTranAsync(); } catch { }; _wareHouseService.GenTaskExecute(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行送满托到下升降区 {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行送满托到下升降区 {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 移走上升降区未生成预任务且满托的料架 /// /// public async void 移走上升降区未生成预任务且满托的料架(object? args) { if (s_task移走上升降区未生成预任务且满托的料架.CurrentCount == 0) return; await s_task移走上升降区未生成预任务且满托的料架.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行移走上升降区未生成预任务且满托的料架"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行移走上升降区未生成预任务且满托的料架"); #region 检查信号 List configs_upMachine = new List(); if (await GetBoolTag("东面提升机输送线", $"上升降机请求取满托1")) { LoggerFloor2RackDelivery.LogInformation($"【移走上升降区未生成预任务且满托的料架】上升降机请求取满托1 true"); configs_upMachine.Add(floor2mechanicalAtmDic["上升降机请求取满托1"]); } if (await GetBoolTag("东面提升机输送线", $"上升降机请求取满托2")) { LoggerFloor2RackDelivery.LogInformation($"【移走上升降区未生成预任务且满托的料架】上升降机请求取满托2 true"); configs_upMachine.Add(floor2mechanicalAtmDic["上升降机请求取满托2"]); } // 没有有效信号 if (configs_upMachine.Count == 0) return; #endregion //using (var db = _repository.AsSugarClient().CopyNew()) { //await db.BeginTranAsync(); // 读取上升降机的左右料架区配置 await db_Floor2timer移走上升降区未生成预任务且满托的料架.Ado.BeginTranAsync(); List WmsMechanicalArmHs = db_Floor2timer移走上升降区未生成预任务且满托的料架.Queryable().Where(r => r.stackingcount == r.maxnum && r.maxnum != 0 && !string.IsNullOrEmpty(r.rackcode) && r.iscreatepretask == 0 && configs_upMachine.Contains(r.name) && r.mechanicalconfirm == 1).ToList(); foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { LoggerFloor2RackDelivery.LogInformation($"【移走上升降区满托的料架】 开始执行预任务生成 {wmsMechanicalArmH.location_code} {wmsMechanicalArmH.outbill} {wmsMechanicalArmH.barcodes}"); await db_Floor2timer移走上升降区未生成预任务且满托的料架.Updateable().SetColumns(r => new WmsMechanicalArmH { iscreatepretask = 1 }).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync(); // 找到未占用且未锁定的库位 ISugarQueryable rackEndLocations = db_Floor2timer移走上升降区未生成预任务且满托的料架.Queryable() .Where(r => r.wh_id == "33780009364245" && r.is_use == "0" && r.is_lock == 0 && r.is_type == "0").OrderBy(a => a.id).Take(1); if (rackEndLocations.Count() == 0) { LoggerFloor2RackDelivery.LogWarning($"【移走上升降区满托的料架】 暂存仓中没有可用的空库位 {rackEndLocations.ToSqlString()}"); continue; } BasLocation endLocation = rackEndLocations.First(); // 锁住终点库位 await db_Floor2timer移走上升降区未生成预任务且满托的料架.Updateable(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); LoggerFloor2RackDelivery.LogInformation($"【移走上升降区满托的料架】 开始执行预任务生成: 料架区为{wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 料架为{wmsMechanicalArmH.rackcode}"); WmsMaterialTransfer wmsMaterialTransfer = await db_Floor2timer移走上升降区未生成预任务且满托的料架.Queryable().Where(r => r.bill_code == wmsMechanicalArmH.outbill).FirstAsync(); string wmsMaterialTransferId = ""; if (wmsMaterialTransfer != null) { wmsMaterialTransferId = wmsMaterialTransfer.id; } else { LoggerFloor2RackDelivery.LogWarning($"【移走上升降区满托的料架】找不到转库单{wmsMechanicalArmH.outbill}"); } bool result = await createPretask(wmsMechanicalArmH.location_id, endLocation.id, wmsMechanicalArmH.rackid, wmsMechanicalArmH.rackcode, LoggerFloor2RackDelivery, db_Floor2timer移走上升降区未生成预任务且满托的料架, true, wmsMaterialTransferId); if (!result) { LoggerFloor2RackDelivery.LogError($"【移走上升降区满托的料架】 未成功生成预任务 起点{wmsMechanicalArmH.location_code} 终点{endLocation.location_code} 料架 {wmsMechanicalArmH.rackcode}"); throw new Exception($"【移走上升降区满托的料架】 未成功生成预任务 起点{wmsMechanicalArmH.location_code} 终点{endLocation.location_code} 料架 {wmsMechanicalArmH.rackcode}"); } LoggerFloor2RackDelivery.LogInformation($"【移走上升降区满托的料架】 成功生成预任务 {result}"); } await db_Floor2timer移走上升降区未生成预任务且满托的料架.Ado.CommitTranAsync(); } } catch (ObjectDisposedException ex) { LoggerFloor2RackDelivery.LogError($"【移走上升降区未生成预任务且满托的料架】 数据库连接异常:{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【移走上升降区未生成预任务且满托的料架】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_Floor2timer移走上升降区未生成预任务且满托的料架 = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【上升降机】" + ex.Message); LoggerFloor2RackDelivery.LogError($"【移走上升降区未生成预任务且满托的料架】{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【移走上升降区未生成预任务且满托的料架】{ex.StackTrace}"); // 数据库连接断开时会报错 try { await db_Floor2timer移走上升降区未生成预任务且满托的料架.Ado.RollbackTranAsync(); } catch { }; } finally { s_task移走上升降区未生成预任务且满托的料架.Release(); if (!db_Floor2timer移走上升降区未生成预任务且满托的料架.Ado.Transaction.IsNull()) // 数据库连接断开时会报错 try { await db_Floor2timer移走上升降区未生成预任务且满托的料架.Ado.CommitTranAsync(); } catch { }; _wareHouseService.GenTaskExecute(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行移走上升降区未生成预任务且满托的料架 {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行移走上升降区未生成预任务且满托的料架 {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 移走下升降区未生成预任务且空托的料架 /// /// public async void 移走下升降区未生成预任务且空托的料架(object? args) { if (s_task移走下升降区未生成预任务且空托的料架.CurrentCount == 0) return; await s_task移走下升降区未生成预任务且空托的料架.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行移走下升降区未生成预任务且空托的料架"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行移走下升降区未生成预任务且空托的料架"); #region 检查信号 List configs_upMachine = new List(); if (await GetBoolTag("东面提升机输送线", $"下升降机请求取空托1")) { LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】下升降机请求取空托1 true"); configs_upMachine.Add(floor2mechanicalAtmDic["下升降机请求取空托1"]); } if (await GetBoolTag("东面提升机输送线", $"下升降机请求取空托2")) { LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】下升降机请求取空托2 true"); configs_upMachine.Add(floor2mechanicalAtmDic["下升降机请求取空托2"]); } // 没有有效信号 if (configs_upMachine.Count == 0) return; #endregion //using (var db = _repository.AsSugarClient().CopyNew()) { //await db.BeginTranAsync(); // 读取下升降机的左右料架区配置 List WmsMechanicalArmHs = db_Floor2timer移走下升降区未生成预任务且空托的料架.Queryable().Where(r => !string.IsNullOrEmpty(r.rackcode) && r.iscreatepretask == 0 && configs_upMachine.Contains(r.name)).ToList(); foreach (WmsMechanicalArmH wmsMechanicalArmH in WmsMechanicalArmHs) { LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】 开始执行预任务生成 {wmsMechanicalArmH.location_code} {wmsMechanicalArmH.outbill} {wmsMechanicalArmH.barcodes}"); await db_Floor2timer移走下升降区未生成预任务且空托的料架.Ado.BeginTranAsync(); await db_Floor2timer移走下升降区未生成预任务且空托的料架.Updateable().SetColumns(r => new WmsMechanicalArmH { iscreatepretask = 1 }).Where(r => r.id == wmsMechanicalArmH.id).ExecuteCommandAsync(); // 找到未占用且未锁定的库位 ISugarQueryable rackEndLocations = db_Floor2timer移走下升降区未生成预任务且空托的料架.Queryable() .Where(r => r.wh_id == "33780009364245" && r.is_use == "0" && r.is_lock == 0 && r.is_type == "0").OrderBy(a => a.id).Take(1); if (rackEndLocations.Count() == 0) { //LoggerFloor2RackDelivery.LogWarning($"【移走下升降区空托的料架】 暂存仓中没有可用的空库位 {rackEndLocations.ToSqlString()}"); continue; } BasLocation endLocation = rackEndLocations.First(); int row = await db_Floor2timer移走下升降区未生成预任务且空托的料架.Updateable().SetColumns(r => r.carry_status == "0").Where(r => r.id == wmsMechanicalArmH.rackid).ExecuteCommandAsync(); if (row == 0) { throw new Exception($"【移走下升降区空托的料架】料架{wmsMechanicalArmH.rackcode}状态回写失败"); } // 解除绑定料箱到料架 CarryBindInput carryBindInput = new() { }; carryBindInput.carry_id = wmsMechanicalArmH.rackid; carryBindInput.carry_code = wmsMechanicalArmH.rackcode; carryBindInput.source_code = wmsMechanicalArmH.outbill; Tnb.WarehouseMgr.Entities.Dto.Outputs.Result unbindResult = await _wmsCarryUnbindService.CarryUnbind(carryBindInput, db_Floor2timer移走下升降区未生成预任务且空托的料架); if (unbindResult.code != JNPF.Common.Enums.HttpStatusCode.OK) { throw new Exception(unbindResult.msg); } // 锁住终点库位 await db_Floor2timer移走下升降区未生成预任务且空托的料架.Updateable(r => new BasLocation { is_lock = 1 }).Where(r => r.id == endLocation.id).ExecuteCommandAsync(); LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】 开始执行预任务生成: 料架区为{wmsMechanicalArmH.name}{wmsMechanicalArmH.stackingposition} 料架为{wmsMechanicalArmH.rackcode}"); bool result = await createPretask(wmsMechanicalArmH.location_id, endLocation.id, wmsMechanicalArmH.rackid, wmsMechanicalArmH.rackcode, LoggerFloor2RackDelivery, db_Floor2timer移走下升降区未生成预任务且空托的料架, true); if (!result) { LoggerFloor2RackDelivery.LogInformation($"【移走下升降区空托的料架】 未成功生成预任务 起点{wmsMechanicalArmH.location_code} 终点{endLocation.location_code} 料架 {wmsMechanicalArmH.rackcode}"); throw new Exception($"【移走下升降区空托的料架】 未成功生成预任务 起点{wmsMechanicalArmH.location_code} 终点{endLocation.location_code} 料架 {wmsMechanicalArmH.rackcode}"); } await db_Floor2timer移走下升降区未生成预任务且空托的料架.Ado.CommitTranAsync(); } } } catch (ObjectDisposedException ex) { LoggerFloor2RackDelivery.LogError($"【移走下升降区空托的料架】 数据库连接异常:{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【移走下升降区空托的料架】 数据库连接异常:{ex.StackTrace}"); if (ex.Source == "Npgsql") db_Floor2timer移走下升降区未生成预任务且空托的料架 = _repository.AsSugarClient().CopyNew(); } catch (Exception ex) { Console.WriteLine("【移走下升降区空托的料架】" + ex.Message); LoggerFloor2RackDelivery.LogError($"【移走下升降区空托的料架】{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【移走下升降区空托的料架】{ex.StackTrace}"); // 数据库连接断开时会报错 try { await db_Floor2timer移走下升降区未生成预任务且空托的料架.Ado.RollbackTranAsync(); } catch { }; } finally { s_task移走下升降区未生成预任务且空托的料架.Release(); if (!db_Floor2timer移走下升降区未生成预任务且空托的料架.Ado.Transaction.IsNull()) try { await db_Floor2timer移走下升降区未生成预任务且空托的料架.Ado.CommitTranAsync(); } catch { }; _wareHouseService.GenTaskExecute(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行移走下升降区未生成预任务且空托的料架 {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行移走下升降区未生成预任务且空托的料架 {stopwatch.ElapsedMilliseconds} ms"); } } /// /// 定时触发一次任务执行生成 /// /// public async void GenTaskExecute(object? args) { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 触发任务执行"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 触发任务执行"); _wareHouseService.GenTaskExecute(); } // 上下升降机生成预任务(补充料架、上升降机取货到料架、上升降机满托运走,下升降机拿货到输送线、下升降机空托运走) private async Task createPretask(string startlocation_id, string endlocation_id, string carry_id, string carry_code, ILogger logger, ISqlSugarClient dbConn, bool isSync2Erp = false, string source_id = "") { CommonCreatePretaskInput commonCreatePretaskInput = new CommonCreatePretaskInput(); commonCreatePretaskInput.startlocation_id = startlocation_id; commonCreatePretaskInput.endlocation_id = endlocation_id; commonCreatePretaskInput.carry_id = carry_id; commonCreatePretaskInput.carry_code = carry_code; commonCreatePretaskInput.task_type = WmsWareHouseConst.BIZTYPE_WMSTRANSFER_ID; commonCreatePretaskInput.biz_type = isSync2Erp ? "erp_qtrk" : ""; commonCreatePretaskInput.require_id = ""; commonCreatePretaskInput.source_id = source_id; commonCreatePretaskInput.isExcuteMission = false; logger.LogInformation($"开始执行 GenPreTask {JsonConvert.SerializeObject(commonCreatePretaskInput)}"); var res = await _wareHouseService.CommonCreatePretask(commonCreatePretaskInput, dbConn); if (res.code == JNPF.Common.Enums.HttpStatusCode.OK) { logger.LogInformation($"GenPreTask 结果 {JsonConvert.SerializeObject(res)}"); return true; } return false; } /// /// 四楼包材自动到二楼包材库 /// /// public async void PackOutstockService(object? args) { if (s_taskPackOutstockService.CurrentCount == 0) return; await s_taskPackOutstockService.WaitAsync(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); try { Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行四楼包材自动到二楼包材库"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 开始执行四楼包材自动到二楼包材库"); await _wmsPackOutstockService.Distribute(); } catch (Exception ex) { Console.WriteLine("【四楼包材自动到二楼包材库】" + ex.Message); LoggerFloor2RackDelivery.LogError($"【四楼包材自动到二楼包材库】{ex.Message}"); LoggerFloor2RackDelivery.LogError($"【四楼包材自动到二楼包材库】{ex.StackTrace}"); } finally { s_taskPackOutstockService.Release(); stopwatch.Stop(); Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束四楼包材自动到二楼包材库 {stopwatch.ElapsedMilliseconds} ms"); LoggerTimer.LogInformation($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 结束执行四楼包材自动到二楼包材库 {stopwatch.ElapsedMilliseconds} ms"); } } async void ElevatorTaskExceptionHandle(object args) { List wmsDistaskHs = _repository.AsSugarClient().Queryable() .Where(r => r.startlocation_code.Contains("DT") && r.endlocation_code.Contains("DT") && r.act_start_date != null && r.act_end_date == null).ToList(); LoggerElevatorTask.Information($"【ElevatorTaskExceptionHandle】检查到需要恢复的电梯任务{wmsDistaskHs.Count}条 {string.Join(',', wmsDistaskHs.Select(x => x.bill_code))}"); foreach (WmsDistaskH wmsDistaskH in wmsDistaskHs) { ElevagorInfoQuery q = new() { endlocation_id = wmsDistaskH.endlocation_id, taskCode = wmsDistaskH.bill_code }; LoggerElevatorTask.Information($"【ElevatorTaskExceptionHandle】执行电梯任务时 根据任务单号获取电梯参数 {JsonConvert.SerializeObject(q)}"); var e = await _wareHouseService.FindElevatorFromPars(q); LoggerElevatorTask.Information($"【ElevatorTaskExceptionHandle】执行电梯任务时 根据任务单号获取电梯结果 {JsonConvert.SerializeObject(e)}"); if (e == null) continue; wmsDistaskH.device_id = e.device_id; await _wareHouseService.ExecuteTargetFloorTask(wmsDistaskH); } } #region 内存测试 public async Task GetBoolTag(string DevName, string field) { try { string jsonString = await _redisData.GetHash(DevName, field); if (string.IsNullOrEmpty(jsonString)) return false; JObject jsonObject = JObject.Parse(jsonString); if (jsonObject.TryGetValue("Value", out JToken valueToken2)) { return bool.Parse(valueToken2.ToString()); } else { Console.WriteLine($"未找到匹配项 {DevName} {field}"); } } catch (Exception ex) { Console.WriteLine($"未找到匹配项{DevName} {field}"); } return false; } public async Task GetStringTag(string DevName, string field) { #region //try //{ // string jsonString = await _redisData.GetHash(DevName, field); // JObject jsonObject = JObject.Parse(jsonString); // if (jsonObject.TryGetValue("StatusCode", out JToken valueToken1)) // { // if (valueToken1.ToString() == "-1") // return ""; // } // if (jsonObject.TryGetValue("Value", out JToken valueToken2)) // { // return valueToken2.ToString(); // } // else // { // Console.WriteLine($"未找到匹配项 {DevName} {field}"); // } //} //catch (Exception ex) //{ // // 捕获并处理异常 // Console.WriteLine($"发生异常: {ex.Message}"); //} //return $"未找到匹配项 {DevName} {field}"; #endregion try { string jsonString = await _redisData.GetHash(DevName, field); if (string.IsNullOrEmpty(jsonString)) return ""; string pattern = "\"Value\":\"(.*?)\""; System.Text.RegularExpressions.Match match = Regex.Match(jsonString, pattern); if (match.Success) { return match.Groups[1].Value; } else { Console.WriteLine($"未找到匹配项{DevName} {field}"); } } catch (Exception ex) { Console.WriteLine($"未找到匹配项{DevName} {field}"); } return $"未找到匹配项 {DevName} {field}"; } private async Task Floor2UpDownMachinecode_SetTag(string tag, string value) { string DevName = "东面提升机输送线"; Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = DevName, ["token"] = _eleCtlCfg.token, ["TagName"] = tag, ["Value"] = value, }; string result = await HttpClientHelper.GetRequestAsync(_eleCtlCfg.WriteTagUrl, dicCommand); return result.Contains("Ok"); //测试 //string DevName = "东面提升机输送线"; //JObject valueJson = new JObject(); //valueJson["Value"] = value; //_redisData.SetHash(DevName, tag, valueJson.ToString()); //return true; } #endregion #endregion public Task StartAsync(CancellationToken cancellationToken) { //Readtimer = new Timer(GetRedisData, null, TimeSpan.Zero, TimeSpan.FromSeconds(300)); CheckGettimer = new Timer(CheckGet, null, TimeSpan.Zero, TimeSpan.FromSeconds(10)); Scantimer = new Timer(ScanInStock, null, TimeSpan.Zero, TimeSpan.FromSeconds(60)); SSXcodetimer = new Timer(SSXcode, null, TimeSpan.Zero, TimeSpan.FromSeconds(10)); // 八工位缓存区补充空托盘 BGWCarrySupplementtimer = new Timer(BGWCarrySupplement, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); // 供料叠盘机空托盘自动入库 YCLGLDPJInstocktimer = new Timer(YCLGLDPJInstock, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); // 外协叠盘机空托盘自动入库 //YCLWXDPJInstocktimer = new Timer(YCLWXDPJInstock, null, TimeSpan.Zero, TimeSpan.FromSeconds(100000)); // 二楼上升降机 Floor2UpMachinecodetimer = new Timer(Floor2UpMachinecode, null, TimeSpan.Zero, TimeSpan.FromSeconds(20)); // 二楼料架配送 Floor2timer送空托到上升降区 = new Timer(送空托到上升降区, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); Floor2timer送满托到下升降区 = new Timer(送满托到下升降区, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); Floor2timer移走上升降区未生成预任务且满托的料架 = new Timer(移走上升降区未生成预任务且满托的料架, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); Floor2timer移走下升降区未生成预任务且空托的料架 = new Timer(移走下升降区未生成预任务且空托的料架, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); GenTaskExecutetimer = new Timer(GenTaskExecute, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); //PackOutstockServicetimer = new Timer(PackOutstockService, null, TimeSpan.Zero, TimeSpan.FromSeconds(60)); ElevatorTaskExceptionHandleThread = new Thread(ElevatorTaskExceptionHandle); ElevatorTaskExceptionHandleThread.Start(); return Task.CompletedTask; } public Task StopAsync(CancellationToken cancellationToken) { return Task.CompletedTask; } public void Dispose() { Console.WriteLine("*****************Dispose*****************"); Log.Information("*****************Dispose*****************"); Readtimer?.Dispose(); CheckGettimer?.Dispose(); Scantimer?.Dispose(); SSXcodetimer?.Dispose(); Floor2UpMachinecodetimer?.Dispose(); Floor2timer送空托到上升降区?.Dispose(); Floor2timer送满托到下升降区?.Dispose(); Floor2timer移走上升降区未生成预任务且满托的料架?.Dispose(); Floor2timer移走下升降区未生成预任务且空托的料架?.Dispose(); BGWCarrySupplementtimer?.Dispose(); YCLGLDPJInstocktimer?.Dispose(); YCLWXDPJInstocktimer?.Dispose(); } #region 日志 private static readonly Dictionary s_logLevelMap = new() { [LogLevel.Debug] = "DBG", [LogLevel.Information] = "INF", [LogLevel.Warning] = "WRN", [LogLevel.Error] = "ERR", }; protected string _LoggerElevatorTaskFileName = ""; protected ILogger _LoggerElevatorTask; protected ILogger LoggerElevatorTask { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customElevatorTask{DateTime.Now:yyyyMMdd}.log"; if (_LoggerElevatorTaskFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerElevatorTask = loggerFactory.CreateLogger(this.GetType()); _LoggerElevatorTaskFileName = newFileName; } return _LoggerElevatorTask; } } protected string _LoggerBGWFileName = ""; protected ILogger _LoggerBGW; protected ILogger LoggerBGW { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customBGW{DateTime.Now:yyyyMMdd}.log"; if (_LoggerBGWFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerBGW = loggerFactory.CreateLogger(this.GetType()); _LoggerBGWFileName = newFileName; } return _LoggerBGW; } } protected string _LoggerSSXFileName = ""; protected ILogger _LoggerSSX; protected ILogger LoggerSSX { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customSSX{DateTime.Now:yyyyMMdd}.log"; if (_LoggerSSXFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerSSX = loggerFactory.CreateLogger(this.GetType()); _LoggerSSXFileName = newFileName; } return _LoggerSSX; } } // 二楼上下升降机日志 protected string _LoggerFloor2UpDownMachineFileName = ""; protected ILogger _LoggerFloor2UpDownMachine; protected ILogger LoggerFloor2UpDownMachine { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customFloor2UpDownMachine{DateTime.Now:yyyyMMdd}.log"; if (_LoggerFloor2UpDownMachineFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerFloor2UpDownMachine = loggerFactory.CreateLogger(this.GetType()); _LoggerFloor2UpDownMachineFileName = newFileName; } return _LoggerFloor2UpDownMachine; } } // 二楼料架补充 protected string _LoggerFloor2RackDeliveryFileName = ""; protected ILogger _LoggerFloor2RackDelivery; protected ILogger LoggerFloor2RackDelivery { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customFloor2RackDelivery{DateTime.Now:yyyyMMdd}.log"; if (_LoggerFloor2RackDeliveryFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerFloor2RackDelivery = loggerFactory.CreateLogger(this.GetType()); _LoggerFloor2RackDeliveryFileName = newFileName; } return _LoggerFloor2RackDelivery; } } protected string _LoggerBGWCarrySupplementFileName = ""; protected ILogger _LoggerBGWCarrySupplement; protected ILogger LoggerBGWCarrySupplement { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customBGWCarrySupplement{DateTime.Now:yyyyMMdd}.log"; if (_LoggerBGWCarrySupplementFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerBGWCarrySupplement = loggerFactory.CreateLogger(this.GetType()); _LoggerBGWCarrySupplementFileName = newFileName; } return _LoggerBGWCarrySupplement; } } protected string _LoggerYCLGLDPJInstockFileName = ""; protected ILogger _LoggerYCLGLDPJInstock; protected ILogger LoggerYCLGLDPJInstock { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customYCLGLDPJInstock{DateTime.Now:yyyyMMdd}.log"; if (_LoggerYCLGLDPJInstockFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerYCLGLDPJInstock = loggerFactory.CreateLogger(this.GetType()); _LoggerYCLGLDPJInstockFileName = newFileName; } return _LoggerYCLGLDPJInstock; } } protected string _LoggerTimerFileName = ""; protected ILogger _LoggerTimer; protected ILogger LoggerTimer { get { string newFileName = $"{AppContext.BaseDirectory}/logs/customTimer{DateTime.Now:yyyyMMdd}.log"; if (_LoggerTimerFileName != newFileName) { ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddFile(newFileName, cfgOpts => { //cfgOpts.DateFormat = "yyyy-MM-dd HH:mm:ss.fff"; cfgOpts.MessageFormat = (logMsg) => { var logLevel = s_logLevelMap[logMsg.LogLevel]; var sb = new StringBuilder(); _ = sb.Append($"[{logLevel}] "); _ = sb.Append($"{logMsg.LogName} "); _ = sb.Append($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} "); _ = sb.Append($"#{logMsg.EventId.Id} "); _ = sb.Append(logMsg.Message + " "); _ = sb.Append(logMsg.Exception?.ToString()); return sb.ToString(); }; })); _LoggerTimer = loggerFactory.CreateLogger(this.GetType()); _LoggerTimerFileName = newFileName; } return _LoggerTimer; } } #endregion } }