diff --git a/BasicData/Tnb.BasicData.Entities/Entity/BasLocation.cs b/BasicData/Tnb.BasicData.Entities/Entity/BasLocation.cs index 375db58b..019570d6 100644 --- a/BasicData/Tnb.BasicData.Entities/Entity/BasLocation.cs +++ b/BasicData/Tnb.BasicData.Entities/Entity/BasLocation.cs @@ -125,5 +125,5 @@ public partial class BasLocation : BaseEntity /// /// 是否超配(1:不超配 2:超配) /// - public string is_overmatch { get; set; } + public string is_overmatch { get; set; } = 1; } diff --git a/WarehouseMgr/Tnb.WarehouseMgr.Entities/Configs/LocationConfiguration.cs b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Configs/LocationConfiguration.cs new file mode 100644 index 00000000..e4fcff0a --- /dev/null +++ b/WarehouseMgr/Tnb.WarehouseMgr.Entities/Configs/LocationConfiguration.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tnb.WarehouseMgr.Entities.Configs +{ + public class LocationConfiguration + { + public string TestLocation { get; set; } + } +} diff --git a/WarehouseMgr/Tnb.WarehouseMgr/BaseWareHouseService.cs b/WarehouseMgr/Tnb.WarehouseMgr/BaseWareHouseService.cs index 838ce1cb..2e604a6e 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/BaseWareHouseService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/BaseWareHouseService.cs @@ -44,6 +44,7 @@ namespace Tnb.WarehouseMgr }; public OverideVisualDevFunc OverideFuncs { get; } = new OverideVisualDevFunc(); public static SemaphoreSlim s_taskExecuteSemaphore = new(1); + public static SemaphoreSlim s_elevatorStatusSemaphore = new(1); protected IEventPublisher? EventPublisher { set; get; } diff --git a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs index 6e036949..60162e1b 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs @@ -1,4 +1,5 @@ -using JNPF; +using Aop.Api.Domain; +using JNPF; using JNPF.Common.Core.Manager; using JNPF.Common.Enums; using JNPF.Common.Extension; @@ -44,6 +45,7 @@ namespace Tnb.WarehouseMgr private readonly IElevatorControlService _elevatorControlService; private readonly ElevatorControlConfiguration _eleCtlCfg = App.Configuration.Build(); private readonly ILoggerFactory _loggerFactory; + public static Dictionary s_eleLoadedStatusDic = new(); @@ -61,6 +63,13 @@ namespace Tnb.WarehouseMgr _userManager = userManger; _elevatorControlService = elevatorControlService; _ = InitializationTask; + if (s_eleLoadedStatusDic.Count < 1) + { + foreach (var (k, _) in s_elevatorMap) + { + s_eleLoadedStatusDic[k] = 0; + } + } } /// @@ -68,10 +77,10 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify] - public async Task CreateTaskChain() + public async Task CreateTaskChain() { Logger.LogInformation("fasdfadsfadsfasdfasdfadsfasdfadsfadsfasdfasdfasdfasdfas"); - return await Task.FromResult(null); + return await Task.FromResult(null); } /// @@ -80,12 +89,12 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify, AllowAnonymous] - public async Task LoadConfirm(ConfirmInput input) + public async Task LoadConfirm(ConfirmInput input) { - Logger.Information("--------------------------------------------------------"); Logger.Information("取货确认.................."); var whereExp = Expressionable.Create() .And((a, b, c) => c.bill_code == input.taskCode) + .And((a, b, c) => a.enabled == 1) .AndIF(SqlFunc.Contains("DT-R", input.sourceName), (a, b, c) => c.startpoint_code == input.sourceName) .AndIF(SqlFunc.Contains("DT-C", input.sourceName), (a, b, c) => c.endlocation_code == input.sourceName) .ToExpression(); @@ -107,17 +116,49 @@ namespace Tnb.WarehouseMgr } try { + Logger.Information($"当前任务Id:{elevator.distask_id}"); Logger.Information($"elevator.device_id={elevator.device_id}"); if (s_elevatorMap.TryGetValue(elevator.device_id, out object? elevatorCode)) { - string devName = elevatorCode?.ToString() ?? _eleCtlCfg.DevName3; + string devName = elevatorCode?.ToString(); + Logger.Information($"获取设备:{devName},状态"); var tags = new[] { "SysStatus", "RunStatus", "FloorNo", "DoorStatus", "AGVStatus" }; (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, tags, CancellationToken.None); Logger.Information($"电梯当前状态->系统状态:{sysStatus.ToEnum()},运行状态:{runStatus.ToEnum()},Agv状态:{agvStatus.ToEnum()},当前楼层:{floorNo}"); { - if (doorStatus.ToEnum() != EnumDoorStatus.开门到位保持) + var curFloor = await GetRealFloor(elevator.end_floor); + Logger.Information($"目标楼层:{curFloor},电梯当前楼层:{floorNo}"); + Logger.Information($"当前放货设备ID:{elevator.device_id}"); + var loadedStatus = s_eleLoadedStatusDic[elevator.device_id] == 1 ? "完成" : "未完成"; + Logger.Information($"{devName.Match(@"\d+")}#梯,放货-> {loadedStatus}"); + + var devId = elevator.device_id; + KeyValuePair freeElePair = new(); + if (s_eleLoadedStatusDic[elevator.device_id] != 1) + { + var loadedStatusPairs = s_eleLoadedStatusDic.Where(kv => kv.Value == 1).ToList(); + var rIdx = Random.Shared.Next(0, loadedStatusPairs.Count); + freeElePair = loadedStatusPairs[rIdx]; + if (!freeElePair.Key.IsNullOrWhiteSpace() && s_elevatorMap.TryGetValue(freeElePair.Key, out object? v)) + { + devId = freeElePair.Key; + devName = v?.ToString()!; + Logger.Information($"查找到已放货的设备:{devName},设备ID:{freeElePair.Key}"); + } + } + + if (s_eleLoadedStatusDic[devId] == 1 && curFloor != floorNo) + { + _ = await _elevatorControlService.CallLift(devName, elevator.end_floor, CancellationToken.None); + s_eleLoadedStatusDic[devId] = 0; + } + if (curFloor != floorNo) + { + return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!"); + } + if (doorStatus.ToEnum() != EnumDoorStatus.开门到位保持 && floorNo == curFloor) //判断电梯楼层与当前放货在同一楼层在允许放货 { _ = await _elevatorControlService.SendOpenCloseCmd(devName, 3); //发送电梯前门开门指令 } @@ -138,7 +179,6 @@ namespace Tnb.WarehouseMgr throw; } return await ToApiResult(HttpStatusCode.OK, "未启用"); - Logger.Information("--------------------------------------------------------"); } /// @@ -147,7 +187,7 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify, AllowAnonymous] - public async Task UnloadConfirm(ConfirmInput input)// + public async Task UnloadConfirm(ConfirmInput input)// { Logger.Information("放货确认.................."); Logger.Information($"输入参数:{JsonConvert.SerializeObject(input)}"); @@ -155,10 +195,12 @@ namespace Tnb.WarehouseMgr { var whereExp = Expressionable.Create() .And((a, b, c) => c.bill_code == input.taskCode) + .And((a, b, c) => a.enabled == 1) .AndIF(SqlFunc.Contains("DT-R", input.sourceName), (a, b, c) => c.startpoint_code == input.sourceName) .AndIF(SqlFunc.Contains("DT-C", input.sourceName), (a, b, c) => c.endlocation_code == input.sourceName) .ToExpression(); + //根据Agv传递的参数获取,对应的电梯 WmsElevatorH elevator = await _db.Queryable().LeftJoin((a, b) => a.id == b.bill_id) .LeftJoin((a, b, c) => b.location_id == c.endlocation_id) @@ -171,13 +213,15 @@ namespace Tnb.WarehouseMgr .FirstAsync(); if (elevator.IsNull()) { - throw new Exception($"根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务"); + Logger.Error($"根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务"); } if (s_elevatorMap.TryGetValue(elevator.device_id, out object? elevatorCode)) { - string devName = elevatorCode?.ToString() ?? _eleCtlCfg.DevName3; + string devName = elevatorCode?.ToString(); var tags = new[] { "SysStatus", "RunStatus", "FloorNo", "DoorStatus", "AGVStatus" }; + Logger.Information($"获取设备:{devName},状态"); + await Task.Delay(1000); (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, tags, CancellationToken.None);//elevator.elevator_code Logger.Information($"电梯当前状态->系统状态:{sysStatus.ToEnum()},运行状态:{runStatus},门状态:{doorStatus},Agv状态:{agvStatus},当前楼层:{floorNo}"); //判断Agv电梯是否进入状态 @@ -188,11 +232,43 @@ namespace Tnb.WarehouseMgr Logger.Information("目前正常"); + var curFloor = await GetRealFloor(elevator.end_floor); + Logger.Information($"当前放货设备ID:{elevator.device_id}"); + var loadedStatus = s_eleLoadedStatusDic[elevator.device_id] == 1 ? "完成" : "未完成"; + Logger.Information($"{devName.Match(@"\d+")}#梯,放货-> {loadedStatus}"); + + var devId = elevator.device_id; + KeyValuePair freeElePair = new(); + if (s_eleLoadedStatusDic[elevator.device_id] != 1) + { + var loadedStatusPairs = s_eleLoadedStatusDic.Where(kv => kv.Value == 1).ToList(); + var rIdx = Random.Shared.Next(0, loadedStatusPairs.Count); + freeElePair = loadedStatusPairs[rIdx]; + if (!freeElePair.Key.IsNullOrWhiteSpace() && s_elevatorMap.TryGetValue(freeElePair.Key, out object? v)) + { + devId = freeElePair.Key; + devName = v?.ToString()!; + Logger.Information($"查找到已放货的设备:{devName},设备ID:{freeElePair.Key}"); + } + } + + if (s_eleLoadedStatusDic[devId] == 1 && curFloor != floorNo) + { + _ = await _elevatorControlService.CallLift(devName, elevator.end_floor, CancellationToken.None); + s_eleLoadedStatusDic[devId] = 0; + } + if (curFloor != floorNo) + { + return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!"); + } + Logger.Information($"当前楼层:{curFloor},电梯所在楼层:{floorNo}"); //电梯到达目标楼层后,判断当前电梯门状态是否为开门到位保持状态 - if (doorStatus != (int)EnumDoorStatus.开门到位保持) + if (doorStatus != (int)EnumDoorStatus.开门到位保持 && curFloor == floorNo) //判断目标楼层与电梯所在楼层在同一层才可开门放货 { _ = await _elevatorControlService.SendOpenCloseCmd(devName, 3); //发送电梯前门开门指令 } + + if (sysStatus == (int)EnumSysStatus.正常状态 && runStatus == (int)EnumRunStatus.停梯 && doorStatus == (int)EnumDoorStatus.开门到位保持) { @@ -229,7 +305,7 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify, AllowAnonymous] - public async Task TaskChainCallBack(TaskChainCallBackInput input) + public async Task TaskChainCallBack(TaskChainCallBackInput input) { try @@ -306,7 +382,7 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify, AllowAnonymous] - public async Task TaskCallback(TaskCallBackInput input) + public async Task TaskCallback(TaskCallBackInput input) { Logger.Information($"任务状态上报->接收参数:{JsonConvert.SerializeObject(input)}"); @@ -316,7 +392,6 @@ namespace Tnb.WarehouseMgr List disTasks = await _db.Queryable().Where(it => it.bill_code.Contains(input.taskCode)).ToListAsync(); if (input.action == "LOAD") { - Logger.Information("----------Load Begin----------"); TaskExecuteAfterUpInput taskExecuteAfterUpInput = new() { @@ -326,27 +401,45 @@ namespace Tnb.WarehouseMgr Logger.Information($"设备取返回输入参数:{JsonConvert.SerializeObject(taskExecuteAfterUpInput)}"); await _wareHouseService.TaskExecuteAfter(taskExecuteAfterUpInput); Logger.Information($"Agv取货完成,任务Id:{string.Join(",", disTasks.Select(x => x.id))}"); + + var disTask = disTasks.Find(x => x.bill_code == input.taskCode); + + if (disTask != null && !disTask.startlocation_code.StartsWith("DT", StringComparison.OrdinalIgnoreCase)) + { + return await ToApiResult(HttpStatusCode.OK, "成功"); + } + //根据Agv传递的参数获取,对应的电梯 + WmsElevatorH elevator = await _db.Queryable().LeftJoin((a, b) => a.id == b.bill_id) + .Where((a, b) => b.location_id == disTask.startlocation_id) + .Select((a, b) => new WmsElevatorH + { + device_id = a.elevator_id, + }, true) + .FirstAsync(); + + s_eleLoadedStatusDic[elevator.device_id] = 1; + Logger.Information($"当前取货设备ID:{elevator.device_id}"); + //根据disTask StartLocationId 起始库位关联电梯获取设备ID location_code.Continas("") + var devName = s_elevatorMap[elevator.device_id]?.ToString(); + Logger.Information($"{devName.Match(@"\d+")}#梯,设备名称:{devName},开始进入关门流程"); + int doorStatus = await _elevatorControlService.GetTagAsync(devName, ElevatorConsts.DoorStatus); + Logger.Information($"设备:{devName},门状态:{doorStatus.ToEnum().ToString()}"); + if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持 + && !disTask.endlocation_code.StartsWith("DT", StringComparison.OrdinalIgnoreCase) + ) + { + _ = await _elevatorControlService.SendOpenCloseCmd(devName, 4); //向电梯发送前门关门指令 + } WmsElevatorUnexecute elevatorQueueItem = await _db.Queryable().FirstAsync(it => disTasks.Select(x => x.id).Contains(it.distask_id) && it.task_status == "执行中"); if (elevatorQueueItem != null) { - Logger.Information("开始进入关门流程"); - var disTask = disTasks.Find(x => x.id == elevatorQueueItem.distask_id); - int doorStatus = await _elevatorControlService.GetTagAsync(elevatorQueueItem.elevator_code, ElevatorConsts.DoorStatus); - if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持 - && !disTask.endlocation_code.StartsWith("DT", StringComparison.OrdinalIgnoreCase) - ) - { - _ = await _elevatorControlService.SendOpenCloseCmd(elevatorQueueItem.elevator_code, 4); //向电梯发送前门关门指令 - _ = await _db.Deleteable(elevatorQueueItem).ExecuteCommandAsync(); - } - } - Logger.Information("----------Load End----------"); + _ = await _db.Deleteable(elevatorQueueItem).ExecuteCommandAsync(); + } } else if (input.action == "UNLOAD") { - Logger.Information("----------UnLoad Begin----------"); TaskCompleUpInput taskCompleUpInput = new() { @@ -355,12 +448,12 @@ namespace Tnb.WarehouseMgr Logger.Information($"taskCompleUpInput json parameter:{JsonConvert.SerializeObject(taskCompleUpInput)}"); await _wareHouseService.TaskComplate(taskCompleUpInput); - Logger.Information("----------UnLoad end----------"); } } catch (Exception ex) { Logger.Error("任务状态上报出现错误", ex); + Logger.Error("任务状态上报错误堆栈信息", ex.StackTrace); return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!"); throw; } @@ -378,7 +471,7 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify, AllowAnonymous] - public async Task ElevatorConfirm(ConfirmInput input) + public async Task ElevatorConfirm(ConfirmInput input) { try { @@ -465,7 +558,7 @@ namespace Tnb.WarehouseMgr /// /// [HttpPost, NonUnify, AllowAnonymous] - public Task CTUUnloadConfirm(ConfirmInput input) + public Task CTUUnloadConfirm(ConfirmInput input) { var data = ""; try diff --git a/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs b/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs index a5afd009..53faec60 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs @@ -3,6 +3,8 @@ using System.Dynamic; using DingTalk.Api.Request; using JNPF; using JNPF.Common.Extension; +using JNPF.Common.Manager; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -28,38 +30,63 @@ namespace Tnb.WarehouseMgr private readonly bool isFrontDoorBit = false; //是否到前门位 private readonly IServiceProvider _sp; private readonly BackgroundService _backgudSvc; + private readonly ICacheManager _cacheMgr; - public ElevatorControlService(IServiceProvider sp, BackgroundService bgSvc) + public ElevatorControlService(IServiceProvider sp, BackgroundService bgSvc, ICacheManager cacheMgr) { _elevatorCtlCfg = App.Configuration.Build(); _sp = sp; _backgudSvc = bgSvc; + _cacheMgr = cacheMgr; } /// /// 呼梯测试 /// /// - [HttpPost] - public async Task CallLiftTest(string devName, int floor) + [HttpPost, AllowAnonymous] + public async Task CallLiftTest() { bool isSuccefuly = false; + //var tags = new[] { "SysStatus", "RunStatus", "FloorNo", "DoorStatus", "AGVStatus" }; + //(int sysStatus, int runStatus, _, int doorStatus, int agvStatus) = await GetElevatorStatus(devName, tags, CancellationToken.None); + ////判断当前楼层是否是放货楼层,如不是则呼叫电梯到当前楼层 + //if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 && + // agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态) + //{ + // if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) + // { + // _ = await SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); + // } + // dynamic result = await WriteTagAsync(devName, ElevatorConsts.FloorExecute, floor); //呼叫电梯到指定楼层 + // if (!string.IsNullOrEmpty(result)) + // { + // JObject jo = JObject.Parse(result);_ + // isSuccefuly = jo?.Value("Result")?.Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false; + // } + //} + var value = ""; var tags = new[] { "SysStatus", "RunStatus", "FloorNo", "DoorStatus", "AGVStatus" }; - (int sysStatus, int runStatus, _, int doorStatus, int agvStatus) = await GetElevatorStatus(devName, tags, CancellationToken.None); - //判断当前楼层是否是放货楼层,如不是则呼叫电梯到当前楼层 - if (sysStatus.ToEnum() == EnumSysStatus.正常状态 && runStatus.ToEnum() == EnumRunStatus.停梯 && - agvStatus.ToEnum() != EnumAgvStatus.AGV运行状态) + try { - if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) + var statusMap = await RedisHelper.HGetAllAsync("Elevator3"); + + foreach (var tag in tags) { - _ = await SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); - } - dynamic result = await WriteTagAsync(devName, ElevatorConsts.FloorExecute, floor); //呼叫电梯到指定楼层 - if (!string.IsNullOrEmpty(result)) - { - JObject jo = JObject.Parse(result); - isSuccefuly = jo?.Value("Result")?.Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false; + if (statusMap.ContainsKey(tag)) + { + var cacheItem = statusMap[tag]; + var jo = JObject.Parse(cacheItem); + var v = jo.Value("V"); + } } + //value = await _cacheMgr.GetAsync("Elevator3"); + + } + catch (Exception ex) + { + + throw; } return isSuccefuly; } @@ -162,22 +189,25 @@ namespace Tnb.WarehouseMgr /// public async Task SendOpenCloseCmd(string devName, int value) { - Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) + var flag = false; + /*Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = devName, ["token"] = _elevatorCtlCfg.token, ["TagName"] = "DoorExecute", ["Value"] = value.ToString() - }; + };*/ + var eleStatusMap = await RedisHelper.HGetAllAsync(devName); try { - _ = await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); + //_ = await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); + flag = await RedisHelper.HSetAsync(devName, ElevatorConsts.DoorExecute, value); } catch (Exception) { return false; } - return true; + return flag; } /// /// 设置Agv控制请求状态 @@ -206,14 +236,17 @@ namespace Tnb.WarehouseMgr /// public async Task WriteTagAsync(string devName, string tagName, int value) { - Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) + /*Dictionary dicCommand = new(StringComparer.OrdinalIgnoreCase) { ["DevName"] = devName, ["token"] = _elevatorCtlCfg.token, ["TagName"] = tagName, ["Value"] = value.ToString() }; - return await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); + return await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand);*/ + + return await RedisHelper.HSetAsync(devName, tagName, value); + } /// @@ -225,7 +258,7 @@ namespace Tnb.WarehouseMgr public async Task GetTagAsync(string devName, string tagName) { - Dictionary dicCommand = new() + /*Dictionary dicCommand = new() { ["DevName"] = devName, ["token"] = _elevatorCtlCfg.token, @@ -233,7 +266,15 @@ namespace Tnb.WarehouseMgr }; string result = await HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: dicCommand); JObject jo = JObject.Parse(result); - return jo.Value("V"); + return jo.Value("V");*/ + + var eleStatusMap = await RedisHelper.HGetAllAsync(devName); + if (eleStatusMap.ContainsKey(tagName)) + { + JObject jo = JObject.Parse(eleStatusMap[tagName]); + return jo.Value("V"); + } + return -1; } @@ -289,49 +330,65 @@ namespace Tnb.WarehouseMgr [HttpPost("GetElevatorStatus")] public async Task<(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus)> GetElevatorStatus([NotNull] string devName, [FromBody] IEnumerable tags, CancellationToken token) { - Task GetTag(string tag) - { - var dicCommand = new Dictionary - { - ["DevName"] = devName, - ["token"] = _elevatorCtlCfg.token, - ["TagName"] = tag - }; + /* async Task GetTag(string tag) + { + var dicCommand = new Dictionary + { + ["DevName"] = devName, + ["token"] = _elevatorCtlCfg.token, + ["TagName"] = tag + }; - return HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: dicCommand); - } + return await HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: dicCommand); + } + */ + await s_elevatorStatusSemaphore.WaitAsync(token); - var tasks = tags.Select(tag => GetTag(tag)); - var results = await Task.WhenAll(tasks.Select(task => task)); - Logger.Information($"状态结果:{string.Join(",",results)}"); - var jos = results.Select(r => JObject.Parse(r)).ToArray(); var (sysStatus, runStatus, floorNo, doorStatus, agvStatus) = (0, 0, 0, 0, 0); - - var propertyMap = new Dictionary>() + try { - { ElevatorConsts.SysStatus, v => sysStatus = v }, - { ElevatorConsts.RunStatus, v => runStatus = v }, - { ElevatorConsts.FloorNo, v => floorNo = v }, - { ElevatorConsts.DoorStatus, v => doorStatus = v }, - { ElevatorConsts.AGVStatus, v => agvStatus = v }, - }; - - if (jos?.Length > 0) - { - foreach (var jo in jos) + //var tasks = tags.Select(tag => GetTag(tag)); + //var results = await Task.WhenAll(tasks.Select(task => task)); + var statusMap = await RedisHelper.HGetAllAsync(devName); + List jos = new(); + foreach (var tag in tags) { - if (jo == null) + if (statusMap.ContainsKey(tag)) { - continue; - } - string? tagName = jo!.Value("Name"); - int value = jo!.Value("V"); - - if (propertyMap.TryGetValue(tagName!, out var setProperty)) - { - setProperty(value); + jos.Add(JObject.Parse(tag)); } } + + var propertyMap = new Dictionary>() + { + { ElevatorConsts.SysStatus, v => sysStatus = v }, + { ElevatorConsts.RunStatus, v => runStatus = v }, + { ElevatorConsts.FloorNo, v => floorNo = v }, + { ElevatorConsts.DoorStatus, v => doorStatus = v }, + { ElevatorConsts.AGVStatus, v => agvStatus = v }, + }; + + if (jos?.Count > 0) + { + foreach (var jo in jos) + { + if (jo == null) + { + continue; + } + string? tagName = jo!.Value("TagName"); + int value = jo!.Value("V"); + + if (propertyMap.TryGetValue(tagName!, out var setProperty)) + { + setProperty(value); + } + } + } + } + finally + { + s_elevatorStatusSemaphore.Release(); } return (sysStatus, runStatus, floorNo, doorStatus, agvStatus); @@ -400,12 +457,12 @@ namespace Tnb.WarehouseMgr { _ = await SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); } - dynamic result = await WriteTagAsync(devName, ElevatorConsts.FloorExecute, floor); //呼叫电梯到指定楼层 - if (!string.IsNullOrEmpty(result)) - { - JObject jo = JObject.Parse(result); - isSuccefuly = jo?.Value("Result")?.Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false; - } + isSuccefuly = await WriteTagAsync(devName, ElevatorConsts.FloorExecute, floor); //呼叫电梯到指定楼层 + //if (!string.IsNullOrEmpty(result)) + //{ + // JObject jo = JObject.Parse(result); + // isSuccefuly = jo?.Value("Result")?.Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false; + //} } return isSuccefuly; } @@ -418,6 +475,9 @@ namespace Tnb.WarehouseMgr tasks.Add(WriteTagAsync(devName, ElevatorConsts.AGVControl, input.value)); } return tasks; + + + } public async Task CloseElevatorControl(CloseElevatorInput input) @@ -426,8 +486,22 @@ namespace Tnb.WarehouseMgr { throw new ArgumentNullException(nameof(input.devNames)); } - var tasks = ParallelWriteTagAsync(input); - var writeRes = await Task.WhenAll(tasks); + //var tasks = ParallelWriteTagAsync(input); + List> devInfoList = new(); + foreach (var dn in input.devNames) + { + var eleStatusMap = await RedisHelper.HGetAllAsync(dn); + if (eleStatusMap?.Count > 0) + { + devInfoList.Add(eleStatusMap); + } + } + foreach (var devMap in devInfoList) + { + devMap[ElevatorConsts.AGVControl] = input.value.ToString(); + } + + //var writeRes = await Task.WhenAll(tasks); var timedTaskSvc = _backgudSvc as TimedTaskBackgroundService; if (timedTaskSvc != null) { diff --git a/WarehouseMgr/Tnb.WarehouseMgr/LocationDefinitionService.cs b/WarehouseMgr/Tnb.WarehouseMgr/LocationDefinitionService.cs index ca2f76d1..a0cb7565 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/LocationDefinitionService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/LocationDefinitionService.cs @@ -5,6 +5,8 @@ using JNPF.FriendlyException; using JNPF.VisualDev; using JNPF.VisualDev.Entitys.Dto.VisualDev; using Mapster; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.WarehouseMgr.Entities; @@ -117,7 +119,7 @@ namespace Tnb.WarehouseMgr l.org_id = orgId; l.location_name = l.location_code; l.is_lock = 0; - l.carrystd_id = carryStdDic[l.carrystd_id]?.ToString()!; + l.carrystd_id = JsonConvert.SerializeObject(new[] { carryStdDic[l.carrystd_id]?.ToString()! }); l.wh_id = whDic[l.wh_id]?.ToString()!; l.region_id = rgDic[l.region_id]?.ToString(); l.create_id = userId; diff --git a/WarehouseMgr/Tnb.WarehouseMgr/TimedTaskBackgroundService.cs b/WarehouseMgr/Tnb.WarehouseMgr/TimedTaskBackgroundService.cs index cc9cdacc..a13d97ba 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/TimedTaskBackgroundService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/TimedTaskBackgroundService.cs @@ -46,14 +46,16 @@ namespace Tnb.WarehouseMgr { foreach (var devName in s_heartbeatDevNames) { - Dictionary parameter = new() - { - ["DevName"] = devName, - ["TagName"] = ElevatorConsts.AGVKeepalive, - ["Value"] = "123", - ["token"] = _elevatorControlConfiguration.token - }; - string result = await HttpClientHelper.GetAsync(_elevatorControlConfiguration.WriteTagUrl, pars: parameter); + /* Dictionary parameter = new() + { + ["DevName"] = devName, + ["TagName"] = ElevatorConsts.AGVKeepalive, + ["Value"] = "123", + ["token"] = _elevatorControlConfiguration.token + }; + string result = await HttpClientHelper.GetAsync(_elevatorControlConfiguration.WriteTagUrl, pars: parameter); + */ + var result = await RedisHelper.HSetAsync(devName, ElevatorConsts.AGVKeepalive, "123"); await Console.Out.WriteLineAsync($"{devName.Match(@"\d+")}#梯, 心跳检测结果:{result}"); } }, stoppingToken, 30); diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs index 5a706031..dca6433a 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WareHouseService.cs @@ -14,6 +14,7 @@ using Mapster; using Microsoft.AspNetCore.Mvc; using Microsoft.CodeAnalysis; using Newtonsoft.Json; +using NPOI.OpenXmlFormats.Dml; using SqlSugar; using Tnb.BasicData.Entities; using Tnb.Common.Extension; @@ -252,7 +253,6 @@ namespace Tnb.WarehouseMgr floor = b.floor }, true).ToListAsync(); - Logger.Information($"可用电梯信息:{string.Join(",", elevatorList.Select(e => e.elevator_code).Distinct())}"); //获取所有未下发的预任务申请 @@ -386,7 +386,6 @@ namespace Tnb.WarehouseMgr { elevatorList = elevatorList.FindAll(x => endPointIds.Contains(x.point_id)); - Logger.Information($"过滤后的elevatorList:{JsonConvert.SerializeObject(elevatorList)}"); if (elevatorList?.Count > 0) { @@ -438,9 +437,18 @@ namespace Tnb.WarehouseMgr .Select(it => (it.endlocation_code, it.device_id, it.id, it.start_floor)).ToList(); if (endLocCodes?.Count > 0) { - Logger.Information("呼梯操作"); - await CallingLanding(endLocCodes); + if (endLocCodes.Select(x => x.device_id).All(x => !x.IsNullOrWhiteSpace())) + { + Logger.Information("呼梯操作"); + _ = CallingLanding(endLocCodes); + } + else + { + Logger.Error("呼梯失败,没有设备ID"); + return; + } } + //执行电梯任务 List? elevatorTasks = disTasks.Where(it => it.area_code.Contains("ELE", StringComparison.OrdinalIgnoreCase)).ToList(); @@ -449,16 +457,18 @@ namespace Tnb.WarehouseMgr Logger.Information($"当前电梯任务数:{elevatorTasks?.Count ?? 0}"); foreach (WmsDistaskH? elevatorTask in elevatorTasks) { - await ExecuteTargetFloorTask(elevatorTask); + _ = ExecuteTargetFloorTask(elevatorTask); } } + } - ////调用AGV创建任务链接口 + //调用AGV创建任务链接口 List agvTasks = disTasks.Where(it => !it.area_code.Contains("ELE", StringComparison.OrdinalIgnoreCase)).ToList(); + if (agvTasks?.Count > 0) { Logger.Information($"Agv任务数量:{agvTasks.Count},taskCodes:{string.Join(",", agvTasks.Select(x => x.bill_code).Distinct())}"); - await AgvDispatch(agvTasks, agvCts.Token); + _ = AgvDispatch(agvTasks, agvCts.Token); } @@ -489,7 +499,6 @@ namespace Tnb.WarehouseMgr private async Task CallingLanding(List<(string endlocation_code, string device_id, string id, int floorNO)> endLocCodes) { Logger.Information($" 开始呼梯操作............."); - Logger.Information($"电梯信息:{JsonConvert.SerializeObject(s_elevatorMap)}"); try { foreach ((_, string devId, string disTaskId, int floorNO) in endLocCodes) @@ -508,8 +517,7 @@ namespace Tnb.WarehouseMgr (int sysStatus, int runStatus, int curFloorNo, int doorStatus, int agvStatus) eleStatusMulti = (-1, -1, -1, -1, -1); if (!_elevatorAgvCtlStatusMap.TryGetValue(devId, out int agvCtlStatus) || agvCtlStatus != (int)EnumAgvStatus.AGV运行状态) { - Logger.Information("获取电梯状态"); - Logger.Information($"_elevatorControlService ==null{_elevatorControlService == null}"); + Logger.Information("获取电梯AGV运行状态"); var tags = new[] { "SysStatus", "RunStatus", "FloorNo", "DoorStatus", "AGVStatus" }; do { @@ -522,7 +530,7 @@ namespace Tnb.WarehouseMgr Logger.Information($"任务开始目标楼层为:{floorNO}"); - int floorN = await GetRealFloor(floorNO.ParseToInt()); + int floorN = await GetRealFloor(floorNO); //如果电梯在当前楼层则不呼梯 if (floorN == eleStatusMulti.curFloorNo) { @@ -586,9 +594,13 @@ namespace Tnb.WarehouseMgr Logger.Information($"当前:{devName.Match(@"\d+")}#梯"); - _ = await _elevatorControlService.WriteTagAsync(devName, ElevatorConsts.AGVControl, 1); - (int sysStatus, int runStatus, int curFloorNo, int doorStatus, int agvStatus) eleStatusMulti = (-1, -1, -1, -1, -1); var tags = new[] { "SysStatus", "RunStatus", "FloorNo", "DoorStatus", "AGVStatus" }; + (int sysStatus, int runStatus, int curFloorNo, int doorStatus, int agvStatus) eleStatusMulti = await _elevatorControlService.GetElevatorStatus(devName, tags, CancellationToken.None); + if (eleStatusMulti.agvStatus != (int)EnumAgvStatus.AGV运行状态) + { + _ = await _elevatorControlService.WriteTagAsync(devName, ElevatorConsts.AGVControl, 1); + } + if (!_elevatorAgvCtlStatusMap.TryGetValue(disTask.id, out int agvCtlStatus) || agvCtlStatus != (int)EnumAgvStatus.AGV运行状态) { do @@ -661,6 +673,7 @@ namespace Tnb.WarehouseMgr /// private async Task AgvDispatch(List disTasks, CancellationToken token) { + Logger.Information("Agv任务执行...."); //调用AGV创建任务链接口 try { @@ -999,7 +1012,6 @@ namespace Tnb.WarehouseMgr { List roads = await _db.Queryable().Where(it => it.status == 1).ToListAsync(); List points = await LocPathCalcAlgorithms(pStartId, pEndId, roads); - Logger.Information($"points:{string.Join(",", points.Select(p => p.point_code))}"); try { if (points?.FindAll(x => x.location_code != null && x.location_code.Contains("dt", StringComparison.OrdinalIgnoreCase))?.Count > 0) diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsEmptyInstockService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsEmptyInstockService.cs index 92b5e63b..f0d9d671 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsEmptyInstockService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsEmptyInstockService.cs @@ -13,6 +13,7 @@ using JNPF.VisualDev.Entitys; using JNPF.VisualDev.Interfaces; using Mapster; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using NPOI.SS.Formula.PTG; using SqlSugar; @@ -43,6 +44,7 @@ namespace Tnb.WarehouseMgr private readonly IBillRullService _billRullService; private readonly IUserManager _userManager; private readonly ChannelWriter _channelWriter; + private readonly IConfiguration _configuration; public WmsEmptyInstockService( ISqlSugarRepository repository, IRunService runService, @@ -50,7 +52,8 @@ namespace Tnb.WarehouseMgr IWareHouseService wareHouseService, IUserManager userManager, IBillRullService billRullService, - IEventPublisher eventPublisher + IEventPublisher eventPublisher, + IConfiguration configuration ) { _db = repository.AsSugarClient(); @@ -59,6 +62,7 @@ namespace Tnb.WarehouseMgr _wareHouseService = wareHouseService; _userManager = userManager; _billRullService = billRullService; + _configuration = configuration; OverideFuncs.CreateAsync = WmsEmptyIn; } @@ -71,7 +75,9 @@ namespace Tnb.WarehouseMgr //入库取终点 InStockStrategyQuery inStockStrategyInput = new() { warehouse_id = input.data[nameof(InStockStrategyQuery.warehouse_id)].ToString()!, Size = 1 }; - List endLocations = await _wareHouseService.InStockStrategy(inStockStrategyInput); + //test + BasLocation llll = await _db.Queryable().FirstAsync(it=>it.location_code == _configuration["TestLocation"]); + List endLocations = new() { llll }; //await _wareHouseService.InStockStrategy(inStockStrategyInput); WmsPointH? sPoint = null; WmsPointH? ePoint = null; if (input.data.ContainsKey(nameof(WmsPointH.location_id))) diff --git a/WarehouseMgr/Tnb.WarehouseMgr/WmsInternalTempTestService.cs b/WarehouseMgr/Tnb.WarehouseMgr/WmsInternalTempTestService.cs index 581b119a..0c79af2c 100644 --- a/WarehouseMgr/Tnb.WarehouseMgr/WmsInternalTempTestService.cs +++ b/WarehouseMgr/Tnb.WarehouseMgr/WmsInternalTempTestService.cs @@ -3,14 +3,19 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using JNPF; using JNPF.Common.Core.Manager; using JNPF.Common.Extension; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; using NPOI.SS.Formula.Functions; using Org.BouncyCastle.Crypto; using SqlSugar; using Tnb.BasicData.Entities; +using Tnb.Common.Extension; using Tnb.WarehouseMgr.Entities; +using Tnb.WarehouseMgr.Entities.Configs; using Tnb.WarehouseMgr.Entities.Consts; using Tnb.WarehouseMgr.Entities.Entity; using Tnb.WarehouseMgr.Entities.Enums; @@ -21,9 +26,11 @@ namespace Tnb.WarehouseMgr { private readonly ISqlSugarClient _db; private readonly IUserManager _userManager; - public WmsInternalTempTestService(ISqlSugarRepository repo) + private readonly IConfiguration _configuration; + public WmsInternalTempTestService(ISqlSugarRepository repo, IConfiguration configuration) { _db = repo.AsSugarClient(); + _configuration = configuration; } /// /// 修改列 @@ -48,7 +55,7 @@ namespace Tnb.WarehouseMgr public async Task UpdateStkMinsync() { await _db.Ado.BeginTranAsync(); - List list = await _db.Queryable().InnerJoin((a, b) => a.material_code==b.code) + List list = await _db.Queryable().InnerJoin((a, b) => a.material_code == b.code) .InnerJoin((a, b, c) => a.location_code == c.location_code) .Select((a, b, c) => new WmsStkTemp { @@ -57,7 +64,7 @@ namespace Tnb.WarehouseMgr unit_id = b.unit_id }, true).ToListAsync(); - foreach (var carrycode in list) + foreach (var carrycode in list) { //更新载具条码及状态 WmsCarryCode wmsCarryCode = new(); @@ -79,7 +86,7 @@ namespace Tnb.WarehouseMgr wmsCarryCode.material_specification = carrycode.material_specification; wmsCarryCode.container_no = carrycode.container_no; wmsCarryCode.create_time = DateTime.Now; - + if (wmsCarryCode.carry_id != null && wmsCarryCode.location_id != null) { await _db.Updateable().SetColumns(it => new WmsCarryH { carry_status = ((int)EnumCarryStatus.占用).ToString(), location_id = wmsCarryCode.location_id, location_code = wmsCarryCode.location_code }).Where(it => it.id == wmsCarryCode.carry_id).ExecuteCommandAsync(); @@ -99,5 +106,12 @@ namespace Tnb.WarehouseMgr await _db.Ado.CommitTranAsync(); } + + [AllowAnonymous] + public Task GetConfigItem() + { + var locCfg = _configuration.Build(); + return Task.FromResult(_configuration["TestLocation"]); + } } } diff --git a/apihost/Tnb.API.Entry/Configurations/Cache.json b/apihost/Tnb.API.Entry/Configurations/Cache.json index 69116fb8..75b416ac 100644 --- a/apihost/Tnb.API.Entry/Configurations/Cache.json +++ b/apihost/Tnb.API.Entry/Configurations/Cache.json @@ -1,10 +1,10 @@ { "Cache": { "CacheType": "RedisCache", //MemoryCache - "ip": "localhost", + "ip": "192.168.11.109", "port": 6379, "password": "05jWEoJa8v", - "RedisConnectionString": "{0}:{1},password={2}, poolsize=500,ssl=false,defaultDatabase=7" + "RedisConnectionString": "{0}:{1},password={2}, poolsize=500,ssl=false,defaultDatabase=0" }, "Redis": { "ip": "localhost", diff --git a/apihost/Tnb.API.Entry/Configurations/ElevatorControlSettings.json b/apihost/Tnb.API.Entry/Configurations/ElevatorControlSettings.json index 80c31cd7..b5a55f06 100644 --- a/apihost/Tnb.API.Entry/Configurations/ElevatorControlSettings.json +++ b/apihost/Tnb.API.Entry/Configurations/ElevatorControlSettings.json @@ -6,5 +6,5 @@ "GetTagListUrl": "http://192.168.11.110:9100/Dev/GetTagList", "GetTagUrl": "http://192.168.11.110:9100/Dev/GetTag", "WriteTagUrl": "http://192.168.11.110:9100/Dev/writeTag", - "Environment": "" + "Environment": "tianyi" } \ No newline at end of file diff --git a/apihost/Tnb.API.Entry/Configurations/Location.json b/apihost/Tnb.API.Entry/Configurations/Location.json new file mode 100644 index 00000000..17fcbc1d --- /dev/null +++ b/apihost/Tnb.API.Entry/Configurations/Location.json @@ -0,0 +1,3 @@ +{ + "TestLocation": "fffdfadfaf" +} \ No newline at end of file diff --git a/apihost/Tnb.API.Entry/Program.cs b/apihost/Tnb.API.Entry/Program.cs index 1f9701d7..45b830c4 100644 --- a/apihost/Tnb.API.Entry/Program.cs +++ b/apihost/Tnb.API.Entry/Program.cs @@ -6,6 +6,8 @@ public class WebComponent : IWebComponent public void Load(WebApplicationBuilder builder, ComponentContext componentContext) { builder.Host.UseWindowsService(); + builder.Configuration.AddJsonFile("Location.json", optional: true, reloadOnChange: true); + //// 日志过滤 //builder.Logging.AddFilter((provider, category, logLevel) => //{