using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; 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; using Microsoft.Extensions.Hosting; 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; using Tnb.WarehouseMgr.Interfaces; namespace Tnb.WarehouseMgr { /// /// 电梯控制业务服务类 /// public class ElevatorControlService : BaseWareHouseService, IElevatorControlService { private readonly ElevatorControlConfiguration _elevatorCtlCfg = new(); private readonly BackgroundService _agvHeartbeatMonitor; private static Dictionary> _fetchStartedStausValue = new(); private bool isFrontDoorBit = false; //是否到前门位 public ElevatorControlService() { _elevatorCtlCfg = App.Configuration.Build(); //_agvHeartbeatMonitor = agvHeartbeatMonitorService; } /// /// 呼梯测试 /// /// [HttpPost] public async Task CallLiftTest(string devName, int floor) { 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运行状态) { if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) { await SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); } var 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; } } return isSuccefuly; } /// /// 三楼电梯操作流程 /// /// [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", 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); // } // } // } // } //} return Task.FromResult(0); } private Task SetRequestParameter(string tagName, object value) { var tcs = new TaskCompletionSource(); dynamic reqParam = new ExpandoObject(); reqParam.DevName = _elevatorCtlCfg.DevName; reqParam.TagName = tagName; reqParam.value = value; reqParam.token = _elevatorCtlCfg.token; tcs.SetResult(reqParam); return tcs.Task; } private Task> SetParameter(dynamic obj) { var parameters = new Dictionary() { ["DevName"] = _elevatorCtlCfg.DevName, ["token"] = _elevatorCtlCfg.token, }; var dynamicDic = obj as IDictionary; if (dynamicDic != null) { foreach (var (k, v) in dynamicDic) { parameters[k] = v?.ToString() ?? string.Empty; } } return Task.FromResult(parameters); } /// /// 向系统发送开关门指令 /// /// 开关门指令 /// public async Task SendOpenCloseCmd(string devName, int value) { var dicCommand = new Dictionary(StringComparer.OrdinalIgnoreCase); dicCommand["DevName"] = devName; dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = "DoorExecute"; dicCommand["Value"] = value.ToString(); try { await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); } catch (Exception) { return false; } return true; } /// /// 设置Agv控制请求状态 /// /// /// private async Task SetAgvControlStatus(int value) { var dicCommand = new Dictionary(StringComparer.OrdinalIgnoreCase); dicCommand["DevName"] = _elevatorCtlCfg.DevName; dicCommand["TagName"] = "AGVControl"; dicCommand["Value"] = value.ToString(); dicCommand["token"] = _elevatorCtlCfg.token; return await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); } /// /// 向指定的标签属性写入值 /// /// /// /// public async Task WriteTagAsync(string devName, string tagName, int value) { var dicCommand = new Dictionary(StringComparer.OrdinalIgnoreCase); dicCommand["DevName"] = devName; dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = tagName; dicCommand["Value"] = value.ToString(); return await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand); } /// /// 根据标签名称获取标签值 /// /// /// public async Task GetTagAsync(string devName, string tagName) { var dicCommand = new Dictionary(); dicCommand["DevName"] = devName; dicCommand["token"] = _elevatorCtlCfg.token; dicCommand["TagName"] = tagName; var result = await HttpClientHelper.GetAsync(_elevatorCtlCfg.GetTagUrl, pars: dicCommand); JObject jo = JObject.Parse(result); return jo.Value("V"); } /// /// 获取电梯状态 /// /// /// public async Task<(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus)> GetElevatorStatus(string devName, CancellationToken token) { (int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) multi = (-1, -1, -1, -1, -1); var pars = new Dictionary(); pars["DevName"] = devName; pars["Pos"] = "1"; pars["Count"] = "11"; pars["token"] = _elevatorCtlCfg.token; var url = _elevatorCtlCfg.GetTagListUrl; var systemInfo = await HttpClientHelper.GetAsync(url, pars: pars); var jo = JObject.Parse(systemInfo); var objs = jo["Items"].Values().ToList(); //if (objs?.Count == 4) { if (objs[0].Value("Name").Equals("SysStatus") && objs[1].Value("Name").Equals("RunStatus") && objs[3].Value("Name").Equals("FloorNo")) { multi = (objs[0].Value("V"), objs[1].Value("V"), objs[3].Value("V"), objs[2].Value("V"), objs[9].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 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运行状态) { if (doorStatus.ToEnum() != EnumDoorStatus.关门到位保持) { await SendOpenCloseCmd(devName, (int)EnumAgvControl.前门关门); } var 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; } } return isSuccefuly; } } public class ElevatorData { public string name { get; set; } public string value { get; set; } } }