diff --git a/ProductionMgr/Tnb.ProductionMgr/RedisBackGround.cs b/ProductionMgr/Tnb.ProductionMgr/RedisBackGround.cs index 0e379bf7..37e8ae14 100644 --- a/ProductionMgr/Tnb.ProductionMgr/RedisBackGround.cs +++ b/ProductionMgr/Tnb.ProductionMgr/RedisBackGround.cs @@ -49,6 +49,7 @@ 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; @@ -82,6 +83,10 @@ namespace Tnb.ProductionMgr // 四楼包材自动到二楼包材库 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); @@ -920,7 +925,7 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA 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 && a.status != WmsWareHouseConst.BILLSTATUS_COMPLETE_ID).ToList(); + && b.carry_code == barcode).ToList(); if (WmsMaterialTransfers.Count() == 0) { @@ -1458,7 +1463,16 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA WmsMaterialTransfer wmsMaterialTransfer = await db_Floor2timer移走上升降区未生成预任务且满托的料架.Queryable().Where(r => r.bill_code == wmsMechanicalArmH.outbill).FirstAsync(); - bool result = await createPretask(wmsMechanicalArmH.location_id, endLocation.id, wmsMechanicalArmH.rackid, wmsMechanicalArmH.rackcode, LoggerFloor2RackDelivery, db_Floor2timer移走上升降区未生成预任务且满托的料架, true, wmsMaterialTransfer.id); + 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}"); @@ -1697,7 +1711,29 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA 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 内存测试 @@ -1842,7 +1878,10 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA GenTaskExecutetimer = new Timer(GenTaskExecute, null, TimeSpan.Zero, TimeSpan.FromSeconds(30)); - PackOutstockServicetimer = new Timer(PackOutstockService, null, TimeSpan.Zero, TimeSpan.FromSeconds(60)); + //PackOutstockServicetimer = new Timer(PackOutstockService, null, TimeSpan.Zero, TimeSpan.FromSeconds(60)); + + ElevatorTaskExceptionHandleThread = new Thread(ElevatorTaskExceptionHandle); + ElevatorTaskExceptionHandleThread.Start(); return Task.CompletedTask; } @@ -1882,6 +1921,41 @@ where carry_code = '{coderesult}' and status = '{WmsWareHouseConst.TASK_BILL_STA [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 diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWareHouseService.cs b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWareHouseService.cs index daf50c8c..192323cb 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWareHouseService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IWareHouseService.cs @@ -6,6 +6,7 @@ using Tnb.BasicData.Entities; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Dto.Inputs; +using Tnb.WarehouseMgr.Entities.Dto.Queries; namespace Tnb.WarehouseMgr.Interfaces { @@ -143,11 +144,17 @@ namespace Tnb.WarehouseMgr.Interfaces Func AddUnExecuteTask { get; set; } Task Check(string code, string action); /// - /// // 二楼机械臂 + /// // 二楼机械臂(请求) /// /// Task Floor2MechanicalConfirm(WmsDistaskH disTask, string action); + /// + /// // 二楼机械臂(完成) + /// + /// + Task Floor2MechanicalComplete(WmsDistaskH disTask, string action); + /// /// 二楼kiva把料架送到下升降机后生成中储仓入库任务 /// @@ -163,5 +170,13 @@ namespace Tnb.WarehouseMgr.Interfaces [HttpPost, NonUnify, AllowAnonymous] Task CommonCreatePretask(CommonCreatePretaskInput input, ISqlSugarClient db = null); + /// + /// 执行到目标楼层电梯任务 + /// + /// + /// + Task ExecuteTargetFloorTask(WmsDistaskH disTask); + + Task FindElevatorFromPars(ElevagorInfoQuery input); } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs index abfccc2d..3a03f63c 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs @@ -653,6 +653,9 @@ namespace Tnb.WarehouseMgr Logger.Information($"taskCompleUpInput json parameter:{JsonConvert.SerializeObject(taskCompleUpInput)}"); await _wareHouseService.TaskComplate(taskCompleUpInput); await _wareHouseService.SsxControl(disTask, "UNLOAD"); + + await _wareHouseService.Floor2MechanicalComplete(disTask, "UNLOAD"); + Logger.Information($"【TaskCallback】 Agv放货完成,任务编号:{string.Join(",", disTasks.Select(x => x.bill_code))}"); } diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs index dd4f9bea..df6ad2ec 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs @@ -953,26 +953,10 @@ namespace Tnb.WarehouseMgr }).Where(r => r.id == target.id).ExecuteCommandAsync(); Logger.Information($"【二楼机械臂Floor2MechanicalComplete】{disTask.bill_code} AGV已到货 {disTask.endpoint_code} 更新缓存表{target.id}"); - // 下升降机写满托数量和送到信号 if (rackAreaPointsDown.Contains(disTask.endlocation_code)) { int LXCount = _db.Queryable().Where(a => a.carry_id == disTask.carry_id).Count(); - bool result = await Floor2UpDownMachinecode_SetTag($"下升降机满托{target.stackingposition}数量", LXCount.ToString()); - Logger.LogInformation($@"【送满托到下升降区】设定下升降机满托{target.stackingposition}满托数量为 {LXCount} 结果为 {result}"); - if (!result) - { - throw new Exception($"下升降机满托{target.stackingposition}数量 写入失败"); - } - - // 尝试写入满托送到信号 - bool result下升降机空托送到 = await Floor2UpDownMachinecode_SetTag($"下升降机满托{target.stackingposition}送到", "true"); - Logger.LogInformation($@"【送满托到下升降区】回写 下升降机满托{target.stackingposition}送到 结果为{result下升降机空托送到}"); - if (!result下升降机空托送到) - { - throw new Exception($"下升降机满托{target.stackingposition}送到 写入失败"); - } - // 绑定料架 await _db.Updateable().SetColumns(r => new WmsMechanicalArmH { @@ -1014,7 +998,7 @@ namespace Tnb.WarehouseMgr if (rackAreaPointsUp.Contains(disTask.endlocation_code) || rackAreaPointsDown.Contains(disTask.endlocation_code)) { - Logger.Information($"【二楼机械臂Floor2MechanicalComplete】{disTask.bill_code} AGV在暂存仓取货完成"); + Logger.Information($"【二楼机械臂Floor2MechanicalComplete】{disTask.bill_code} AGV在暂存仓取货确认完成"); } else // 去料架区取货 { @@ -1042,7 +1026,9 @@ namespace Tnb.WarehouseMgr .Select((a, b) => b).FirstAsync(); if (wmsMaterialTransferD == null) { - throw new Exception($@"【上升降机】 发生异常!,转库单{target.outbill}没有载具明细"); + Logger.LogWarning($@"【上升降机】 发生异常!,转库单{target.outbill}没有载具明细"); + // 转库单删除 不执行后续,不返回失败是为了不卡流程 + return; } string targetWorkstation = wmsMaterialTransferD.station_code; @@ -1094,6 +1080,95 @@ namespace Tnb.WarehouseMgr } } + + + /// + /// 二楼机械臂 + /// + /// + public async Task Floor2MechanicalComplete(WmsDistaskH disTask, string action) + { + List rackAreaPointsUp = new List(); + List rackAreaPointsDown = new List(); + // 二楼上升降区料架区点位 + rackAreaPointsUp.Add("AS01"); + rackAreaPointsUp.Add("AS02"); + // 二楼下升降区料架区点位 + rackAreaPointsDown.Add("AX01"); + rackAreaPointsDown.Add("AX02"); + + try + { + List basLocations = _db.Queryable().Where(r => (r.location_code == disTask.endlocation_code || r.location_code == disTask.startlocation_code) + && r.wh_id != "33780009364245").ToList(); + + // 暂存仓内任务 + if (disTask.area_code == "E" && basLocations.Count() == 0) + { + Logger.Information($"【二楼机械臂Floor2MechanicalComplete】收到到货完成信号 传入参数: {disTask.bill_code} {action}"); + + if (action == "UNLOAD") + { + // 去料架区放货 + if (rackAreaPointsUp.Contains(disTask.endlocation_code) || rackAreaPointsDown.Contains(disTask.endlocation_code)) + { + ISugarQueryable WmsMechanicalArmHs = _db.Queryable().Where(r => r.location_code == disTask.endlocation_code); + if (WmsMechanicalArmHs.Count() == 0) + { + Logger.Information($"【二楼机械臂Floor2MechanicalComplete】 任务执行终点{disTask.endpoint_code} 与料架区的点位不匹配"); + throw new Exception($"【二楼机械臂Floor2MechanicalComplete】 任务执行终点{disTask.endpoint_code} 与料架区的点位不匹配"); + } + WmsMechanicalArmH target = WmsMechanicalArmHs.First(); + + // 下升降机写满托数量和送到信号 + if (rackAreaPointsDown.Contains(disTask.endlocation_code)) + { + int LXCount = _db.Queryable().Where(a => a.carry_id == disTask.carry_id).Count(); + + bool result = await Floor2UpDownMachinecode_SetTag($"下升降机满托{target.stackingposition}数量", LXCount.ToString()); + Logger.LogInformation($@"【送满托到下升降区】设定下升降机满托{target.stackingposition}满托数量为 {LXCount} 结果为 {result}"); + if (!result) + { + throw new Exception($"下升降机满托{target.stackingposition}数量 写入失败"); + } + + // 尝试写入满托送到信号 + bool result下升降机空托送到 = await Floor2UpDownMachinecode_SetTag($"下升降机满托{target.stackingposition}送到", "true"); + Logger.LogInformation($@"【送满托到下升降区】回写 下升降机满托{target.stackingposition}送到 结果为{result下升降机空托送到}"); + if (!result下升降机空托送到) + { + throw new Exception($"下升降机满托{target.stackingposition}送到 写入失败"); + } + } + } + else // 去暂存仓放货 + { + + } + } + else + { + // 去暂存仓取货 + if (rackAreaPointsUp.Contains(disTask.endlocation_code) || rackAreaPointsDown.Contains(disTask.endlocation_code)) + { + Logger.Information($"【二楼机械臂Floor2MechanicalComplete】{disTask.bill_code} AGV在暂存仓取货完成"); + } + else // 去料架区取货 + { + } + } + } + } + catch (Exception ex) + { + Logger.LogError("【Floor2MechanicalComplete】" + ex.ToString()); + throw; + } + } + + + + private async Task Floor2UpDownMachinecode_SetTag(string tag, string value) { string DevName = "东面提升机输送线"; @@ -1420,7 +1495,7 @@ namespace Tnb.WarehouseMgr /// /// - protected async Task FindElevatorFromPars(ElevagorInfoQuery input) + public async Task FindElevatorFromPars(ElevagorInfoQuery input) { var whereExpable = Expressionable.Create() .And((a, b, c) => a.enabled == 1); @@ -1459,6 +1534,8 @@ namespace Tnb.WarehouseMgr return ele; } + + #region CTU /// /// 生成CTU任务执行 @@ -1884,7 +1961,7 @@ namespace Tnb.WarehouseMgr /// /// /// - private async Task ExecuteTargetFloorTask(WmsDistaskH disTask) + public async Task ExecuteTargetFloorTask(WmsDistaskH disTask) { //收到放货确认通知,向电梯发送到3楼的指令 Logger.Information($"开始执行电梯任务,任务ID:{disTask.id}"); diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsPackInstockService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsPackInstockService.cs index b7961927..63f33a0d 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsPackInstockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsPackInstockService.cs @@ -164,10 +164,10 @@ namespace Tnb.WarehouseMgr if (endLocations?.Count > 0) { WmsCarryH carry = await _db.Queryable().SingleAsync(it => it.carry_code == input.carry_code); - if (carry.carry_status == "1") - { - throw new AppFriendlyException("载具已占用!", 500); - } + //if (carry.carry_status == "1") + //{ + // throw new AppFriendlyException("载具已占用!", 500); + //} if (carry.is_lock == 1) { throw new AppFriendlyException("载具已锁定!", 500); @@ -197,6 +197,7 @@ namespace Tnb.WarehouseMgr if (sPoint.area_code != ePoint.area_code) { points = await _wareHouseService.PathAlgorithms(sPoint.id, ePoint.id); + Logger.LogError($"【PackInstock】 选择了 {sPoint.point_code} {ePoint.point_code}"); if (points.Count <= 2) { throw new AppFriendlyException($"sPoint {sPoint.point_code} ePoint{ePoint.point_code}该路径不存在", 500); @@ -310,6 +311,8 @@ namespace Tnb.WarehouseMgr } catch (Exception ex) { + Logger.LogError($"【PackInstock】 {ex.Message}"); + Logger.LogError($"【PackInstock】 {ex.StackTrace}"); await _db.Ado.RollbackTranAsync(); return await ToApiResult(HttpStatusCode.InternalServerError, ex.Message); }