Files
tnb.server/WarehouseMgr/Tnb.WarehouseMgr/ElevatorControlService.cs
2023-11-06 19:35:59 +08:00

308 lines
13 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Dynamic;
using JNPF;
using JNPF.Common.Extension;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
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
{
/// <summary>
/// 电梯控制业务服务类
/// </summary>
public class ElevatorControlService : BaseWareHouseService, IElevatorControlService
{
private readonly ElevatorControlConfiguration _elevatorCtlCfg = new();
private readonly BackgroundService _agvHeartbeatMonitor;
private static Dictionary<string, Func<BackgroundService, bool>> _fetchStartedStausValue = new();
private bool isFrontDoorBit = false; //是否到前门位
public ElevatorControlService()
{
_elevatorCtlCfg = App.Configuration.Build<ElevatorControlConfiguration>();
//_agvHeartbeatMonitor = agvHeartbeatMonitorService;
}
/// <summary>
/// 呼梯测试
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<dynamic> 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>() == EnumSysStatus. && runStatus.ToEnum<EnumRunStatus>() == EnumRunStatus. &&
agvStatus.ToEnum<EnumAgvStatus>() != EnumAgvStatus.AGV运行状态)
{
if (doorStatus.ToEnum<EnumDoorStatus>() != 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<string>("Result")?.Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false;
}
}
return isSuccefuly;
}
/// <summary>
/// 三楼电梯操作流程
/// </summary>
/// <returns></returns>
[HttpPost]
public async Task<dynamic> 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<object> SetRequestParameter(string tagName, object value)
{
var tcs = new TaskCompletionSource<object>();
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<Dictionary<string, string>> SetParameter(dynamic obj)
{
var parameters = new Dictionary<string, string>()
{
["DevName"] = _elevatorCtlCfg.DevName,
["token"] = _elevatorCtlCfg.token,
};
var dynamicDic = obj as IDictionary<string, object>;
if (dynamicDic != null)
{
foreach (var (k, v) in dynamicDic)
{
parameters[k] = v?.ToString() ?? string.Empty;
}
}
return Task.FromResult(parameters);
}
/// <summary>
/// 向系统发送开关门指令
/// </summary>
/// <param name="value">开关门指令</param>
/// <returns></returns>
public async Task<bool> SendOpenCloseCmd(string devName, int value)
{
var dicCommand = new Dictionary<string, string>(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;
}
/// <summary>
/// 设置Agv控制请求状态
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private async Task<dynamic> SetAgvControlStatus(int value)
{
var dicCommand = new Dictionary<string, string>(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);
}
/// <summary>
/// 向指定的标签属性写入值
/// </summary>
/// <param name="tagName"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<dynamic> WriteTagAsync(string devName, string tagName, int value)
{
var dicCommand = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
dicCommand["DevName"] = devName;
dicCommand["token"] = _elevatorCtlCfg.token;
dicCommand["TagName"] = tagName;
dicCommand["Value"] = value.ToString();
return await HttpClientHelper.GetAsync(_elevatorCtlCfg.WriteTagUrl, pars: dicCommand);
}
/// <summary>
/// 根据标签名称获取标签值
/// </summary>
/// <param name="tagName"></param>
/// <returns></returns>
public async Task<int> GetTagAsync(string devName, string tagName)
{
var dicCommand = new Dictionary<string, string>();
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<int>("V");
}
/// <summary>
/// 获取电梯状态
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
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<string, string>();
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<JObject>().ToList();
//if (objs?.Count == 4)
{
if (objs[0].Value<string>("Name").Equals("SysStatus")
&& objs[1].Value<string>("Name").Equals("RunStatus")
&& objs[3].Value<string>("Name").Equals("FloorNo"))
{
multi = (objs[0].Value<int>("V"), objs[1].Value<int>("V"), objs[3].Value<int>("V"), objs[2].Value<int>("V"), objs[9].Value<int>("V"));
}
}
return multi;
}
/// <summary>
/// 检查Agv状态
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<bool> CheckAgvStatus(string devName, CancellationToken cancellationToken)
{
var isInAgvStatus = false;
var agvStatus = await GetTagAsync(devName, ElevatorConsts.AGVStatus);
if (agvStatus.ToEnum<EnumAgvStatus>() != EnumAgvStatus.AGV运行状态)
{
var result = await WriteTagAsync(devName, ElevatorConsts.AGVControl, 1);
JObject jo = JObject.Parse(result);
if (jo != null && jo.Value<string>("Result").Equals("Ok", StringComparison.OrdinalIgnoreCase))
{
isInAgvStatus = true;
}
}
return isInAgvStatus;
}
/// <summary>
/// 呼梯操作
/// </summary>
/// <param name="devName">设备名称</param>
/// <param name="floor">呼叫楼层</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns></returns>
public async Task<bool> 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>() == EnumSysStatus. && runStatus.ToEnum<EnumRunStatus>() == EnumRunStatus. &&
agvStatus.ToEnum<EnumAgvStatus>() != EnumAgvStatus.AGV运行状态)
{
if (doorStatus.ToEnum<EnumDoorStatus>() != 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<string>("Result")?.Equals("Ok", StringComparison.OrdinalIgnoreCase) ?? false;
}
}
return isSuccefuly;
}
}
public class ElevatorData
{
public string name { get; set; }
public string value { get; set; }
}
}