diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ElevatorConsts.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ElevatorConsts.cs new file mode 100644 index 00000000..7cff5b42 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Consts/ElevatorConsts.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Consts +{ + public class ElevatorConsts + { + /// + /// 系统状态 + /// + public const string SysStatus = "SysStatus"; + /// + /// 运行状态 + /// + public const string RunStatus = "RunStatus"; + /// + /// 门状态 + /// + public const string DoorStatus = "DoorStatus"; + /// + /// 门状态 + /// + public const string FloorNo = "FloorNo"; + /// + /// 载重信息 + /// + public const string LoadInfor = "LoadInfor"; + /// + /// 故障码 + /// + public const string ErrCode = "ErrCode"; + /// + /// 门触发 + /// + public const string DoorExecute = "DoorExecute"; + /// + /// 通讯状态 + /// + public const string CommStatus = "CommStatus"; + /// + /// 楼层触发 + /// + public const string FloorExecute = "FloorExecute"; + /// + /// AGV控制 + /// + public const string AGVControl = "AGVControl"; + /// + /// AGV状态 + /// + public const string AGVStatus = "AGVStatus"; + /// + /// AGV心跳 + /// + public const string AGVKeepalive = "AGVKeepalive"; + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorH.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorH.cs index d4f6730b..6fafa4bf 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorH.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorH.cs @@ -1,4 +1,5 @@ -using JNPF.Common.Contracts; +using System.Security.Principal; +using JNPF.Common.Contracts; using JNPF.Common.Security; using SqlSugar; @@ -88,5 +89,13 @@ public partial class WmsElevatorH : BaseEntity /// 时间戳(用于并发控制) /// public DateTime? timestamp { get; set; } + /// + /// 门状态 + /// + public int door_status { get; set; } + /// + /// 当前电梯所在楼层 + /// + public int current_floor { get; set; } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs new file mode 100644 index 00000000..881d7e15 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Entity/WmsElevatorUnexecute.cs @@ -0,0 +1,47 @@ +using JNPF.Common.Contracts; +using JNPF.Common.Security; +using SqlSugar; + +namespace Tnb.WarehouseMgr.Entities; + +/// +/// +/// +[SugarTable("wms_elevator_unexecute")] +public partial class WmsElevatorUnexecute : BaseEntity +{ + public WmsElevatorUnexecute() + { + id = SnowflakeIdHelper.NextId(); + } + /// + /// 电梯Id + /// + public string? elevator_id { get; set; } + + /// + /// 电梯编号 + /// + public string? elevator_code { get; set; } + + /// + /// 目标楼层 + /// + public int? floor { get; set; } + + /// + /// 任务状态 + /// + public string? task_status { get; set; } + + /// + /// 创建人 + /// + public string? create_id { get; set; } + + /// + /// 创建时间 + /// + public DateTime? create_time { get; set; } + +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumAgvControl.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumAgvControl.cs new file mode 100644 index 00000000..938b5917 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumAgvControl.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Enums +{ + public enum EnumAgvControl + { + 前门开门 = 3, + 前门关门 = 4, + 后门开门 = 5, + 后门关门 = 6, + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumAgvStatus.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumAgvStatus.cs new file mode 100644 index 00000000..570fe908 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumAgvStatus.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Enums +{ + public enum EnumAgvStatus + { + 正常状态 = 0, + 等待进入AGV状态 = 1, + AGV运行状态 = 2, + + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumDoorStatus.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumDoorStatus.cs new file mode 100644 index 00000000..283ffedf --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumDoorStatus.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Enums +{ + public enum EnumDoorStatus + { + 未知状态 = 0, + 开门过程 = 1, + 开门到位保持 = 2, + 关门过程 = 3, + 关门到位保持 = 4, + + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumRunStatus.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumRunStatus.cs new file mode 100644 index 00000000..f3b6d1b0 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumRunStatus.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Enums +{ + /// + /// 电梯运行状态 + /// + public enum EnumRunStatus + { + 停梯 = 0, + 上运行 = 2, + 下运行 = 2, + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumSysStatus.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumSysStatus.cs new file mode 100644 index 00000000..cbfeb966 --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Enums/EnumSysStatus.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Enums +{ + /// + /// 电梯系统状态枚举 + /// + public enum EnumSysStatus + { + 故障状态 = 0, + 消防状态 = 1, + 其他非服务状态 = 2, + 正常状态 = 3, + 地震状态 = 4 + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs new file mode 100644 index 00000000..e189dd7c --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Interfaces/IElevatorControlService.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Interfaces +{ + /// + /// 电梯控制服务接口 + /// + public interface IElevatorControlService + { + /// + /// 向指定的标签属性写入值 + /// + /// 标签名称 + /// 标签值 + /// + Task WriteTagAsync(string devName, string tagName, int value); + /// + /// 根据标签名称获取标签单个属性值 + /// + /// + /// + Task GetTagAsync(string devName, string tagName); + /// + /// 获取电梯状态 + /// + /// 取消标志 + /// + Task<(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus)> GetElevatorStatus(string devName, CancellationToken token); + /// + /// 检查Agv状态 + /// + /// + /// + Task CheckAgvStatus(string devName, CancellationToken cancellationToken); + /// + /// 向系统发送开关门指令 + /// + /// + /// 3前门开门 + /// 4前门关门 + /// 5后门开门 + /// 6后门关门 + /// + /// + Task SendOpenCloseCmd(string devName,int value); + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs index dac9ce55..ff116b8a 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs @@ -16,6 +16,7 @@ using JNPF.FriendlyException; using JNPF.Logging; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.System; +using JNPF.WorkFlow.Entitys.Dto.FlowLaunch; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; @@ -24,10 +25,12 @@ using Senparc.NeuChar.ApiHandlers; using SqlSugar; using Tnb.EquipMgr.Entities; using Tnb.WarehouseMgr.Entities; +using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Dto; using Tnb.WarehouseMgr.Entities.Dto.Inputs; using Tnb.WarehouseMgr.Entities.Dto.Outputs; using Tnb.WarehouseMgr.Entities.Entity; +using Tnb.WarehouseMgr.Entities.Enums; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr @@ -43,12 +46,14 @@ namespace Tnb.WarehouseMgr private readonly ICacheManager _cacheManager; private readonly IEventPublisher _eventPublisher; private readonly IUserManager _userManager; + private readonly IElevatorControlService _elevatorControlService; public DeviceProviderService(ISqlSugarRepository repository, IWareHouseService wareHouseService, ICacheManager cacheManager, IEventPublisher eventPublisher, - IUserManager userManger + IUserManager userManger, + IElevatorControlService elevatorControlService ) { _db = repository.AsSugarClient(); @@ -56,6 +61,7 @@ namespace Tnb.WarehouseMgr _cacheManager = cacheManager; _eventPublisher = eventPublisher; _userManager = userManger; + _elevatorControlService = elevatorControlService; } /// @@ -78,10 +84,10 @@ 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 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(); } catch (Exception) { @@ -101,17 +107,38 @@ namespace Tnb.WarehouseMgr { try { - var eles = await _db.Queryable().LeftJoin((a, b) => a.id == b.bill_id) + //根据Agv传递的参数获取,对应的电梯 + var elevator = await _db.Queryable().LeftJoin((a, b) => a.id == b.bill_id) .LeftJoin((a, b, c) => b.location_id == c.endlocation_id) .Where((a, b, c) => c.endlocation_code == input.targetName && c.bill_code == input.taskCode) - .ToListAsync(); + .OrderBy(a => a.elevator_code) + .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}"); + //判断Agv电梯是否进入状态 + if (agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态) + { + await _elevatorControlService.WriteTagAsync(elevator.elevator_code, ElevatorConsts.AGVControl, 1); + } + + //电梯到达目标楼层后,判断当前电梯门状态是否为开门到位保持状态 + + if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 + && doorStatus.ToEnum() == EnumDoorStatus.开门到位保持 && floorNo == 4) + { + 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) { - return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!"); + return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!"); throw; } - return await ToApiResult(HttpStatusCode.OK, "未启用"); } /// diff --git a/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs b/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs index 22692589..ee6a36ec 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs @@ -6,6 +6,7 @@ using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using JNPF; +using JNPF.Common.Extension; using JNPF.DependencyInjection; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; @@ -15,13 +16,16 @@ using Newtonsoft.Json.Linq; using Tnb.Common.Extension; using Tnb.Common.Utils; using Tnb.WarehouseMgr.Entities.Configs; +using Tnb.WarehouseMgr.Entities.Consts; +using Tnb.WarehouseMgr.Entities.Enums; +using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { /// /// 电梯控制业务服务类 /// - public class ElevatorControlService : BaseWareHouseService + public class ElevatorControlService : BaseWareHouseService, IElevatorControlService { private readonly ElevatorControlConfiguration _elevatorCtlCfg = new(); private readonly BackgroundService _agvHeartbeatMonitor; @@ -41,53 +45,57 @@ namespace Tnb.WarehouseMgr [HttpPost] public async Task FirstFloorElevatorFlow(string value) { - CancellationTokenSource cts = new CancellationTokenSource();//扩展用 - //获取电梯状态 - (int sysStatus, int runStatus, int floorNo) multi = (-1, -1, -1); - do - { - multi = await GetElevatorStatus(CancellationToken.None); - await Task.Delay(2000); - } while (multi.sysStatus != 3 && multi.runStatus != 0); - if (multi.sysStatus == 3 && multi.runStatus == 0 && multi.floorNo != 1) - { - //如果不是1楼,判断电梯状态,如果电梯是空闲的向电梯发送一个到一楼的指令 - var wirteRes = await SetAgvControlStatus(0); - JObject jo = JObject.Parse(wirteRes); + //CancellationTokenSource cts = new CancellationTokenSource();//扩展用 + ////如果不是1楼,判断电梯状态,如果电梯是空闲的向电梯发送一个到一楼的指令 + //var wirteRes = await SetAgvControlStatus(1); + //JObject jo = JObject.Parse(wirteRes); + //var propName = "IsStarted"; + //if (!_fetchStartedStausValue.TryGetValue(propName, out var func)) + //{ + // var isStartedProp = _agvHeartbeatMonitor.GetType().GetProperty(propName); + // var paramExp = Expression.Parameter(typeof(BackgroundService), "_agvHeartbeatMonitor"); + // var propExp = Expression.Property(Expression.ConvertChecked(paramExp, isStartedProp.DeclaringType), isStartedProp); + // var body = Expression.Lambda>(propExp, paramExp); + // func = body.Compile(); + // _fetchStartedStausValue[propName] = func; + //} + //var isStarted = func(_agvHeartbeatMonitor); + //if (!isStarted) + //{ + // _agvHeartbeatMonitor.StartAsync(cts.Token); + //} - if (true) //此处为Agv到一楼开门位,通知操作目前默认为true - { - var propName = "IsStarted"; - if (!_fetchStartedStausValue.TryGetValue(propName, out var func)) - { - var isStartedProp = _agvHeartbeatMonitor.GetType().GetProperty(propName); - var paramExp = Expression.Parameter(typeof(BackgroundService), "_agvHeartbeatMonitor"); - var propExp = Expression.Property(Expression.ConvertChecked(paramExp, isStartedProp.DeclaringType), isStartedProp); - var body = Expression.Lambda>(propExp, paramExp); - func = body.Compile(); - _fetchStartedStausValue[propName] = func; - } - var isStarted = func(_agvHeartbeatMonitor); - if (!isStarted) - { - _agvHeartbeatMonitor.StartAsync(cts.Token); - } - //向电梯发送前门开门指令 - await SendOpenCloseCmd(3); - //获取门状态 是否为 开门到位保持 - var doorStatus = await GetTagAsync("DoorStatus"); - if (doorStatus == 3) - { - //通知Agv进入电梯,放货,默认为true - if (true) - { - //向电梯发送关门指令 - await SendOpenCloseCmd(4); - } - } + ////获取电梯状态 + //(int sysStatus, int runStatus, int floorNo) multi = (-1, -1, -1); + //do + //{ + // //multi = await GetElevatorStatus(CancellationToken.None); + // await Task.Delay(2000); + //} while (multi.sysStatus != 3 && multi.runStatus != 0); + //if (multi.sysStatus == 3 && multi.runStatus == 0 && multi.floorNo != 1) + //{ + // await WriteTagAsync("FloorExecute", 1); - } - } + + // if (true) //此处为Agv到一楼开门位,通知操作目前默认为true + // { + + // //向电梯发送前门开门指令 + // await SendOpenCloseCmd(3); + // //获取门状态 是否为 开门到位保持 + // var doorStatus = await GetTagAsync("DoorStatus"); + // if (doorStatus == 3) + // { + // //通知Agv进入电梯,放货,默认为true + // if (true) + // { + // //向电梯发送关门指令 + // await SendOpenCloseCmd(4); + // } + // } + + // } + //} return Task.FromResult(0); } /// @@ -97,78 +105,59 @@ namespace Tnb.WarehouseMgr [HttpPost] public async Task ThreeFloorElevatorFlow() { + //test by close door + _agvHeartbeatMonitor.StartAsync(CancellationToken.None); + //await SendOpenCloseCmd(4); + //await SetAgvControlStatus(1); //监听电梯门是否为关闭的状态 - var dataStatus = 0; - do - { - dataStatus = await GetTagAsync("DoorStatus"); - } while (dataStatus != 4); - if (dataStatus == 4) - { - //根据状态确认关闭后,向电梯发送指令从1~3楼 //FloorExecute 楼层触发 - await WriteTagAsync("FloorExecute", 48); - //获取电梯到达3楼的到位信号 - (_, int runStatus, int floorNo) = (-1, -1, -1); - do - { - var multi = await GetElevatorStatus(CancellationToken.None); - runStatus = multi.sysStatus; floorNo = multi.floorNo; - } while (runStatus != 0 && floorNo != 3); - // 控制电梯到达指定楼层默认开门的行为,改为默认不开门 条件:Agv 到达3楼开门位时,为true - if (true)//3楼Agv到达开门位后,向电梯发送开门指令, 默认true 当前 - { + //var dataStatus = 0; + //do + //{ + // dataStatus = await GetTagAsync("DoorStatus"); + //} while (dataStatus != 4); + + //if (dataStatus == 4) + //{ + // //根据状态确认关闭后,向电梯发送指令从1~3楼 //FloorExecute 楼层触发 + // await WriteTagAsync("FloorExecute", 1); + // //获取电梯到达3楼的到位信号 + // (_, int runStatus, int floorNo) = (-1, -1, -1); + // do + // { + // var multi = await GetElevatorStatus(CancellationToken.None); + // runStatus = multi.sysStatus; floorNo = multi.floorNo; + // } while (runStatus != 0 && floorNo != 3); + // // 控制电梯到达指定楼层默认开门的行为,改为默认不开门 条件:Agv 到达3楼开门位时,为true + // if (true)//3楼Agv到达开门位后,向电梯发送开门指令, 默认true 当前 + // { - //向电梯发送前门开门指令 - await SendOpenCloseCmd(3); - //获取门状态 是否为 开门到位保持 - var doorStatus = await GetTagAsync("DoorStatus"); - if (doorStatus == 3) //开门到位保持状态 - { - //通知Agv进入电梯,取货 - //向电梯发送关门指令 - await SendOpenCloseCmd(4); - doorStatus = await GetTagAsync("DoorStatus"); - if (doorStatus == 4) //门状态,为关门到位保持 - { - //解锁,Agv状态,将其至为 - var agvStatus = await GetTagAsync("AGVStatus"); - if (agvStatus != 2) - { - await SetAgvControlStatus(0); - } - } - } - } - } + // //向电梯发送前门开门指令 + // await SendOpenCloseCmd(3); + // //获取门状态 是否为 开门到位保持 + // var doorStatus = await GetTagAsync("DoorStatus"); + // if (doorStatus == 3) //开门到位保持状态 + // { + // //通知Agv进入电梯,取货 + // //向电梯发送关门指令 + // await SendOpenCloseCmd(4); + // doorStatus = await GetTagAsync("DoorStatus"); + // if (doorStatus == 4) //门状态,为关门到位保持 + // { + // //解锁,Agv状态,将其至为 + // var agvStatus = await GetTagAsync("AGVStatus"); + // if (agvStatus != 2) + // { + // await SetAgvControlStatus(0); + // } + // } + // } + // } + //} return Task.FromResult(0); } - /// - /// x2server测试 - /// - /// - [HttpGet] - public async Task X2ServerTest() - { - //var r = new Random(); - int currentValue = 0; - - while (true) - { - var readRes = await GetElevatorStatus(CancellationToken.None); - await Console.Out.WriteLineAsync($"接收结果:{readRes}"); - - currentValue = 1 - currentValue; // 切换为0或1 - dynamic obj = new ExpandoObject(); - obj.TagName = "AGVControl"; - obj.Value = currentValue; - var parameter = await SetParameter(obj); - var wirteRes = await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: parameter); - await Console.Out.WriteLineAsync($"写入结果:{wirteRes}"); - await Task.Delay(1000); - } - } + private Task SetRequestParameter(string tagName, object value) { @@ -206,14 +195,23 @@ namespace Tnb.WarehouseMgr /// /// 开关门指令 /// - private async Task SendOpenCloseCmd(int value) + public async Task SendOpenCloseCmd(string devName, int value) { var dicCommand = new Dictionary(StringComparer.OrdinalIgnoreCase); - dicCommand["DevName"] = _elevatorCtlCfg.DevName; + dicCommand["DevName"] = devName; dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = "DoorExecute"; dicCommand["Value"] = value.ToString(); - await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); + var result = await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); + if (result.IsNotEmptyOrNull()) + { + JObject jo = JObject.Parse(result); + if (jo != null) + { + return jo.Value("Result").Equals("Ok", StringComparison.OrdinalIgnoreCase); + } + } + return false; } /// /// 设置Agv控制请求状态 @@ -225,9 +223,9 @@ namespace Tnb.WarehouseMgr { var dicCommand = new Dictionary(StringComparer.OrdinalIgnoreCase); dicCommand["DevName"] = _elevatorCtlCfg.DevName; - dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = "AGVControl"; dicCommand["Value"] = value.ToString(); + dicCommand["token"] = _elevatorCtlCfg.token; return await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); } @@ -237,10 +235,10 @@ namespace Tnb.WarehouseMgr /// /// /// - private async Task WriteTagAsync(string tagName, int value) + public async Task WriteTagAsync(string devName, string tagName, int value) { var dicCommand = new Dictionary(StringComparer.OrdinalIgnoreCase); - dicCommand["DevName"] = _elevatorCtlCfg.DevName; + dicCommand["DevName"] = devName; dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = tagName; dicCommand["Value"] = value.ToString(); @@ -253,10 +251,10 @@ namespace Tnb.WarehouseMgr /// /// - private async Task GetTagAsync(string tagName) + public async Task GetTagAsync(string devName, string tagName) { var dicCommand = new Dictionary(); - dicCommand["DevName"] = _elevatorCtlCfg.DevName; + dicCommand["DevName"] = devName; dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = tagName; var result = await HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: dicCommand); @@ -264,47 +262,17 @@ namespace Tnb.WarehouseMgr return jo.Value("V"); } - /// - /// 获取Agv状态 0:正常状态 1:等待进入 AGV 状态 2: AGV 运行状态 - /// - /// - //private async Task GetAgvStatus() - //{ - // var dicCommand = new Dictionary(); - // dicCommand["DevName"] = _elevatorCtlCfg.DevName; - // dicCommand["token"] = _elevatorCtlCfg.token; - // dicCommand["TagName"] = "AGVStatus"; - // var result = await HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: dicCommand); - // JObject jo = JObject.Parse(result); - // return jo.Value("V"); - //} - - /// - /// 获取门状态 - /// - /// - //private async Task GetDoorStatus() - //{ - // var doorStatusParam = new Dictionary(); - // doorStatusParam["DevName"] = _elevatorCtlCfg.DevName; - // doorStatusParam["token"] = _elevatorCtlCfg.token; - // doorStatusParam["TagName"] = "DoorStatus"; - // var result = await HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: doorStatusParam); - // JObject jo = JObject.Parse(result); - // return jo.Value("V"); - //} - /// /// 获取电梯状态 /// /// /// - private async Task<(int sysStatus, int runStatus, int floorNo)> GetElevatorStatus(CancellationToken token) + public async Task<(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus)> GetElevatorStatus(string devName, CancellationToken token) { - (int sysStatus, int runStatus, int floorNo) multi = (-1, -1, -1); + (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) multi = (-1, -1, -1, -1, -1); var pars = new Dictionary(); - pars["DevName"] = _elevatorCtlCfg.DevName; + pars["DevName"] = devName; pars["Pos"] = "1"; pars["Count"] = "4"; pars["token"] = _elevatorCtlCfg.token; @@ -318,11 +286,38 @@ namespace Tnb.WarehouseMgr && objs[1].Value("Name").Equals("RunStatus") && objs[3].Value("Name").Equals("FloorNo")) { - multi = ((objs[0].Value("V")), objs[1].Value("V"), objs[2].Value("V")); + multi = (objs[0].Value("V"), objs[1].Value("V"), objs[3].Value("V"), objs[2].Value("V"), objs[10].Value("V")); } } return multi; } + + /// + /// 检查Agv状态 + /// + /// + /// + public async Task CheckAgvStatus(string devName, CancellationToken cancellationToken) + { + var isInAgvStatus = false; + var agvStatus = await GetTagAsync(devName, ElevatorConsts.AGVStatus); + if (agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态) + { + var result = await WriteTagAsync(devName, ElevatorConsts.AGVControl, 1); + JObject jo = JObject.Parse(result); + if (jo != null && jo.Value("Result").Equals("Ok", StringComparison.OrdinalIgnoreCase)) + { + isInAgvStatus = true; + } + } + return isInAgvStatus; + } + } + + public class ElevatorData + { + public string name { get; set; } + public string value { get; set; } } } diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs index be2f8cc4..96c0cfe4 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs @@ -65,14 +65,19 @@ namespace Tnb.WarehouseMgr private readonly IBillRullService _billRullService; private readonly IUserManager _userManager; private readonly ICacheManager _cacheManager; + private readonly IElevatorControlService _elevatorControlService; + private static Dictionary _elevatorMap = new Dictionary(); - public WareHouseService(ISqlSugarRepository repository, IDictionaryDataService dictionaryDataService, IBillRullService billRullService, IUserManager userManager, ICacheManager cacheManager) + + public WareHouseService(ISqlSugarRepository repository, IDictionaryDataService dictionaryDataService, + IBillRullService billRullService, IUserManager userManager, ICacheManager cacheManager, IElevatorControlService elevatorControlService) { _db = repository.AsSugarClient(); _dictionaryDataService = dictionaryDataService; _billRullService = billRullService; _userManager = userManager; _cacheManager = cacheManager; + _elevatorControlService = elevatorControlService; } @@ -232,6 +237,11 @@ 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 { @@ -369,6 +379,42 @@ 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) @@ -582,7 +628,7 @@ namespace Tnb.WarehouseMgr { //如果预任务出现起终库位相同,则删除对应预任务 //modifiy by ly on 20230922 将当前预任务操作者设为四场管理员 - preTasks.ForEach(pt => + preTasks.ForEach(pt => { pt.org_id = WmsWareHouseConst.AdministratorOrgId; pt.create_id = WmsWareHouseConst.AdministratorUserId;