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.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.Configs;
namespace Tnb.WarehouseMgr
{
///
/// 电梯控制业务服务类
///
public class ElevatorControlService : BaseWareHouseService
{
private readonly ElevatorControlConfiguration _elevatorCtlCfg = new();
private readonly BackgroundService _agvHeartbeatMonitor;
private static Dictionary> _fetchStartedStausValue = new();
private bool isFrontDoorBit = false; //是否到前门位
public ElevatorControlService(BackgroundService agvHeartbeatMonitorService)
{
_elevatorCtlCfg = App.Configuration.Build();
_agvHeartbeatMonitor = agvHeartbeatMonitorService;
}
///
/// 一楼电梯操作流程
///
///
[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);
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);
}
}
}
}
return Task.FromResult(0);
}
///
/// 三楼电梯操作流程
///
///
[HttpPost]
public async Task ThreeFloorElevatorFlow()
{
//监听电梯门是否为关闭的状态
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 当前
{
//向电梯发送前门开门指令
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