From db451b6c0956722a1eadfc4a99a43296429d7a83 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 28 Sep 2023 17:44:02 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=EF=BC=8C=E5=8F=96=E8=B4=A7?= =?UTF-8?q?=E3=80=81=E6=94=BE=E8=B4=A7=20=E7=A1=AE=E8=AE=A4=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Entity/WmsElevatorUnexecute.cs | 4 + .../IElevatorControlService.cs | 10 +- .../Tnb.WarehouseMgr/DeviceProviderService.cs | 51 +++++++- .../ElevatorControlService.cs | 31 ++++- .../Tnb.WarehouseMgr/WareHouseService.cs | 121 ++++++++++++------ 5 files changed, 167 insertions(+), 50 deletions(-) diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs index 881d7e15..e26a943d 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs @@ -43,5 +43,9 @@ public partial class WmsElevatorUnexecute : BaseEntity /// 创建时间 /// public DateTime? create_time { get; set; } + /// + /// 执行任务ID + /// + public string distask_id { get; set; } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs index e189dd7c..255d43da 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs @@ -46,6 +46,14 @@ namespace Tnb.WarehouseMgr.Interfaces /// 6后门关门 /// /// - Task SendOpenCloseCmd(string devName,int value); + Task SendOpenCloseCmd(string devName, int value); + /// + /// 呼梯操作 + /// + /// 设备名称 + /// 呼叫楼层 + /// 取消令牌 + /// + Task CallLift(string devName, int floor, CancellationToken cancellationToken); } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs index ff116b8a..1c0dbcb4 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs @@ -84,10 +84,28 @@ namespace Tnb.WarehouseMgr { try { - //var eles = await _db.Queryable().LeftJoin((a, b) => a.id == b.bill_id) - // .LeftJoin((a, b, c) => b.location_id == c.startlocation_id) - // .Where((a, b, c) => c.startlocation_code == input.sourceName && c.bill_code == input.taskCode) - // .ToListAsync(); + var elevator = await _db.Queryable().LeftJoin((a, b) => a.id == b.bill_id) + .LeftJoin((a, b, c) => b.location_id == c.startlocation_id) + .Where((a, b, c) => c.startlocation_code == input.sourceName && c.bill_code == input.taskCode) + .FirstAsync(); + (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(elevator.elevator_code, CancellationToken.None); + Log.Information($"电梯当前状态->系统状态:{sysStatus.ToEnum().ToString()},运行状态:{runStatus.ToEnum().ToString()},Agv状态:{agvStatus.ToEnum().ToString()},当前楼层:{floorNo}"); + if (floorNo == 3) + { + if (doorStatus.ToEnum() != EnumDoorStatus.开门到位保持) + { + await _elevatorControlService.SendOpenCloseCmd(elevator.elevator_code, 3); //发送电梯前门开门指令 + } + if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 + && doorStatus.ToEnum() == EnumDoorStatus.开门到位保持 && floorNo == 3) + { + elevator.current_floor = floorNo; + await _db.Updateable(elevator).UpdateColumns(it => it.current_floor).ExecuteCommandAsync(); + return await ToApiResult(HttpStatusCode.OK, "成功"); + } + return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!"); + } + } catch (Exception) { @@ -113,16 +131,19 @@ namespace Tnb.WarehouseMgr .Where((a, b, c) => c.endlocation_code == input.targetName && c.bill_code == input.taskCode) .OrderBy(a => a.elevator_code) .FirstAsync(); - (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(elevator.elevator_code,CancellationToken.None); + (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(elevator.elevator_code, CancellationToken.None); Log.Information($"电梯当前状态->系统状态:{sysStatus.ToEnum().ToString()},运行状态:{runStatus.ToEnum().ToString()},Agv状态:{agvStatus.ToEnum().ToString()},当前楼层:{floorNo}"); //判断Agv电梯是否进入状态 if (agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态) { await _elevatorControlService.WriteTagAsync(elevator.elevator_code, ElevatorConsts.AGVControl, 1); } - - //电梯到达目标楼层后,判断当前电梯门状态是否为开门到位保持状态 + //电梯到达目标楼层后,判断当前电梯门状态是否为开门到位保持状态 + if (doorStatus.ToEnum() != EnumDoorStatus.开门到位保持) + { + await _elevatorControlService.SendOpenCloseCmd(elevator.elevator_code, 3); //发送电梯前门开门指令 + } if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 && doorStatus.ToEnum() == EnumDoorStatus.开门到位保持 && floorNo == 4) { @@ -227,6 +248,22 @@ namespace Tnb.WarehouseMgr disTaskIds = disTasks.Select(x => x.id).ToList() }; await _wareHouseService.TaskComplate(taskCompleUpInput); + //收到放货确认通知,向电梯发送到3楼的指令 + var elevatorQueueItem = await _db.Queryable().FirstAsync(it => disTasks.Select(x => x.id).Contains(it.distask_id) && it.task_status == "执行中"); + if (elevatorQueueItem != null) + { + var disTask = disTasks.Find(x => x.id == elevatorQueueItem.distask_id); + if (disTask?.status == WmsWareHouseConst.TASK_BILL_STATUS_COMPLE_ID) + { + var doorStatus = await _elevatorControlService.GetTagAsync(elevatorQueueItem.elevator_code, ElevatorConsts.DoorStatus); + if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) + { + await _elevatorControlService.SendOpenCloseCmd(elevatorQueueItem.elevator_code, 4); //向电梯发送前门关门指令 + } + //发送到3楼的指令 + var reuslt = await _elevatorControlService.WriteTagAsync(elevatorQueueItem.elevator_code, ElevatorConsts.FloorExecute, 4); + } + } } } catch (Exception) diff --git a/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs b/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs index ee6a36ec..596a0a7a 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs @@ -15,6 +15,7 @@ using MimeKit.Cryptography; using Newtonsoft.Json.Linq; using Tnb.Common.Extension; using Tnb.Common.Utils; +using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Configs; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Enums; @@ -157,7 +158,7 @@ namespace Tnb.WarehouseMgr return Task.FromResult(0); } - + private Task SetRequestParameter(string tagName, object value) { @@ -313,6 +314,34 @@ namespace Tnb.WarehouseMgr } return isInAgvStatus; } + /// + /// 呼梯操作 + /// + /// 设备名称 + /// 呼叫楼层 + /// 取消令牌 + /// + public async Task CallLift(string devName, int floor, CancellationToken cancellationToken) + { + var isSuccefuly = false; + (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await GetElevatorStatus(devName, CancellationToken.None); + //判断当前楼层是否是放货楼层,如不是则呼叫电梯到当前楼层 + if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 && + agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态 && floorNo != 4) + { + if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) + { + await SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); + } + var result = await WriteTagAsync(devName, ElevatorConsts.FloorExecute, floor); //呼叫电梯到4楼 + if (!result.IsNullOrEmpty()) + { + JObject jo = JObject.Parse(result); + isSuccefuly = jo?.Value("Result").Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false; + } + } + return isSuccefuly; + } } public class ElevatorData diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs index 96c0cfe4..0c8e93ab 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs @@ -42,6 +42,7 @@ using Tnb.BasicData.Entities; using Tnb.BasicData.Entities.Enums; using Tnb.Common.Extension; using Tnb.Common.Utils; +using Tnb.ProductionMgr.Entities.Dto.PrdManage; using Tnb.WarehouseMgr.Entities; using Tnb.WarehouseMgr.Entities.Attributes; using Tnb.WarehouseMgr.Entities.Configs; @@ -237,14 +238,13 @@ namespace Tnb.WarehouseMgr Stopwatch sw = Stopwatch.StartNew(); CancellationTokenSource agvCts = new(); - if (_elevatorMap.Count < 1) - { - _elevatorMap = await _db.Queryable().ToDictionaryAsync(x => x.elevator_id, x => x.elevator_code); - } - var db = _db.CopyNew(); try { + if (_elevatorMap.Count < 1) + { + _elevatorMap = await _db.Queryable().ToDictionaryAsync(x => x.elevator_id, x => x.elevator_code); + } //获取所有未下发的预任务申请 var preTasks = await db.Queryable().InnerJoin((a, b) => a.startlocation_id == b.location_id && a.carry_id == b.id) .InnerJoin((a, b, c) => a.area_id == c.id) @@ -354,7 +354,47 @@ namespace Tnb.WarehouseMgr Log.Information($"程序运行耗时{sw.ElapsedMilliseconds}ms"); await db.Ado.CommitTranAsync(); + //呼梯操作 + //获取目标库位为电梯库位的任务 + var endLocCodes = disTasks.Select(it => (it.endlocation_code, it.device_id, it.id)).Where(it => it.endlocation_code.StartsWith("DT", StringComparison.OrdinalIgnoreCase)).ToList(); + if (endLocCodes?.Count > 0) + { + var item = endLocCodes.FirstOrDefault(); + if (_elevatorMap.ContainsKey(item.device_id)) + { + var devName = _elevatorMap[item.device_id].ToString(); + var agvStatus = await _elevatorControlService.GetTagAsync(devName, ElevatorConsts.AGVControl); + //判断当前设备是否为运行状态,不是则进入Agv电梯控制状态 + if (agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态) + { + await _elevatorControlService.WriteTagAsync(devName, ElevatorConsts.AGVControl, 1); + } + } + foreach (var (_, devId, disTaskId) in endLocCodes) + { + WmsElevatorUnexecute elevatorQueueItem = new() + { + distask_id = disTaskId, + elevator_id = devId, + elevator_code = _elevatorMap[devId].ToString(), + floor = 5, //5代表4楼 + task_status = "待执行", + create_id = _userManager.UserId, + create_time = DateTime.Now + }; + var elevatorQueue = await _db.Queryable().Where(it => it.elevator_id == devId && it.task_status == "执行中").ToListAsync(); + if (_elevatorMap.ContainsKey(devId) && (elevatorQueue.IsNull() || elevatorQueue.Count < 1)) + { + var devName = _elevatorMap[devId].ToString(); + elevatorQueueItem.task_status = "执行中"; + await _elevatorControlService.CallLift(devName, 5, CancellationToken.None); + } + + //如果当前电梯有任务在做,将当前呼梯任务放入待执行队列 + await _db.Insertable(elevatorQueueItem).ExecuteCommandAsync(); + } + } //调用AGV创建任务链接口 var requestCfg = App.Configuration.Build(); var url = requestCfg.AgvRequestUrls.CreateTaskChainUrl; @@ -379,42 +419,6 @@ namespace Tnb.WarehouseMgr var respBody = await HttpClientHelper.PostStreamAsync(url, reqBody, agvCts.Token); Log.Information($"调用Agv接口响应结果:{respBody}"); } - //呼梯操作 - var endLocCodes = disTasks.Select(it => (it.endlocation_code, it.device_id)).Where(it => it.endlocation_code.StartsWith("DT", StringComparison.OrdinalIgnoreCase)).ToList(); - if (endLocCodes?.Count > 0) - { - foreach (var (_, devId) in endLocCodes) - { - var elevatorQueue = await _db.Queryable().Where(it => it.elevator_id == devId).ToListAsync(); - if (_elevatorMap.ContainsKey(devId) && elevatorQueue?.Count < 1) - { - var devName = _elevatorMap[devId].ToString(); - (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, CancellationToken.None); - //判断当前楼层是否是放货楼层,如不是则呼叫电梯到当前楼层 - if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 && - agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态 && floorNo != 4) - { - if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) - { - await _elevatorControlService.SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); - } - await _elevatorControlService.WriteTagAsync(devName, ElevatorConsts.FloorExecute, 5); //呼叫电梯到4楼 - //将当前呼梯任务放入待执行队列 - WmsElevatorUnexecute elevatorQueueItem = new() - { - elevator_id = devId, - elevator_code = _elevatorMap[devId].ToString(), - floor = 4, - create_id = _userManager.UserId, - create_time = DateTime.Now - }; - await _db.Storageable(elevatorQueueItem).ExecuteCommandAsync(); - } - } - - } - } - } } catch (Exception ex) when (ex is HttpRequestException hReqEx) @@ -432,6 +436,41 @@ namespace Tnb.WarehouseMgr agvCts.Dispose(); } } + /// + /// Agv调度 + /// + /// + /// + /// + private async Task AgvDispatch(Dictionary> taskChainCodeDic, CancellationToken token) + { + //调用AGV创建任务链接口 + var requestCfg = App.Configuration.Build(); + var url = requestCfg.AgvRequestUrls.CreateTaskChainUrl; + //var taskChainCodeDic = disTasks.Where(t => !t.groups.IsNullOrWhiteSpace()).GroupBy(g => g.groups!) + // .ToDictionary(x => x.Key, x => x.Select(it => new + // { + // taskCode = it.bill_code, + // sourceName = it.startpoint_code, + // targetName = it.endpoint_code, + // containerCode = it.carry_code, + // })); + Log.Information($"请求地址:{url}"); + foreach (var (k, v) in taskChainCodeDic) + { + dynamic reqBody = new ExpandoObject(); + reqBody.taskChainCode = k; + reqBody.type = (int)EnumTaskChainType.AGV; + reqBody.sequential = false; + reqBody.taskChainPriority = 0; + reqBody.taskList = v; + Log.Information($"请求参数:{JsonConvert.SerializeObject(reqBody)}"); + var respBody = await HttpClientHelper.PostStreamAsync(url, reqBody, token); + Log.Information($"调用Agv接口响应结果:{respBody}"); + } + } + + /// /// 任务执行 ///