318 lines
13 KiB
C#
318 lines
13 KiB
C#
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
|
||
{
|
||
/// <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; }
|
||
}
|
||
}
|