Files
tnb.server/WarehouseMgr/Tnb.WarehouseMgr/DeviceProviderService.cs
2024-06-21 15:14:30 +08:00

747 lines
40 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.Drawing.Drawing2D;
using Aliyun.OSS;
using Aop.Api.Domain;
using JNPF;
using JNPF.Common.Core.Manager;
using JNPF.Common.Enums;
using JNPF.Common.Extension;
using JNPF.Common.Manager;
using JNPF.Common.Net;
using JNPF.Common.Security;
using JNPF.EventBus;
using JNPF.EventHandler;
using JNPF.Logging;
using JNPF.Systems.Entitys.System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Org.BouncyCastle.Crypto.Agreement;
using Senparc.CO2NET.Cache;
using SqlSugar;
using Tnb.Common.Extension;
using Tnb.EquipMgr.Entities;
using Tnb.WarehouseMgr.Entities;
using Tnb.WarehouseMgr.Entities.Configs;
using Tnb.WarehouseMgr.Entities.Consts;
using Tnb.WarehouseMgr.Entities.Dto;
using Tnb.WarehouseMgr.Entities.Dto.Inputs;
using Tnb.WarehouseMgr.Entities.Dto.Outputs;
using Tnb.WarehouseMgr.Entities.Dto.Queries;
using Tnb.WarehouseMgr.Entities.Entity;
using Tnb.WarehouseMgr.Entities.Enums;
using Tnb.WarehouseMgr.Interfaces;
namespace Tnb.WarehouseMgr
{
/// <summary>
/// Wms设备接口提供程序服务类
/// </summary>
public class DeviceProviderService : DevServBase<DeviceProviderService>
{
private readonly ISqlSugarClient _db;
private readonly IWareHouseService _wareHouseService;
private readonly ICacheManager _cacheManager;
private readonly IEventPublisher _eventPublisher;
private readonly IUserManager _userManager;
private readonly IElevatorControlService _elevatorControlService;
private readonly ElevatorControlConfiguration _eleCtlCfg = App.Configuration.Build<ElevatorControlConfiguration>();
private readonly ILoggerFactory _loggerFactory;
public DeviceProviderService(ISqlSugarRepository<WmsInstockH> repository, IWareHouseService wareHouseService,
ICacheManager cacheManager,
IEventPublisher eventPublisher,
IUserManager userManger,
IElevatorControlService elevatorControlService
) : base(repository.AsSugarClient())
{
_db = repository.AsSugarClient();
_wareHouseService = wareHouseService;
_cacheManager = cacheManager;
_eventPublisher = eventPublisher;
_userManager = userManger;
_elevatorControlService = elevatorControlService;
}
/// <summary>
/// 创建任务链
/// </summary>
/// <returns></returns>
[HttpPost, NonUnify]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> CreateTaskChain()
{
Logger.LogInformation("fasdfadsfadsfasdfasdfadsfasdfadsfadsfasdfasdfasdfasdfas");
return await Task.FromResult<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result>(null);
}
/// <summary>
/// 取货确认/申请取货
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, NonUnify, AllowAnonymous]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> LoadConfirm(ConfirmInput input)
{
Logger.Information($"【LoadConfirm】接收到WCS取货确认信号.................. {JsonConvert.SerializeObject(input)}");
try
{
var dis = _db.Queryable<WmsDistaskH>().Where(P => P.bill_code == input.taskCode).First();
if (dis.area_code == "ZSCJ001")
{
var flag = await _wareHouseService.Check(dis.startlocation_code, "LOAD");
if (flag)
{
await _wareHouseService.SsxControl(dis, "LOAD");
Logger.Information("【LoadConfirm】 " + dis.startlocation_code + "取货确认..................成功");
return await ToApiResult(HttpStatusCode.OK, "成功");
}
else
{
Logger.Information("【LoadConfirm】 " + dis.startlocation_code + "取货确认..................失败");
return await ToApiResult(HttpStatusCode.InternalServerError, "失败");
}
}
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
Logger.LogError(ex.StackTrace);
return await ToApiResult(HttpStatusCode.InternalServerError, $"取货确认..................失败 原因是{ex.Message}");
throw;
}
/*var whereExp = Expressionable.Create<WmsElevatorH, WmsElevatorD, WmsDistaskH>()
.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();
WmsElevatorH elevator = await _db.Queryable<WmsElevatorH>().InnerJoin<WmsElevatorD>((a, b) => a.id == b.bill_id)
.InnerJoin<WmsDistaskH>((a, b, c) => b.location_id == c.startlocation_id)
.Where(whereExp)
.Select((a, b, c) => new WmsElevatorH
{
distask_id = c.id,
device_id = a.elevator_id,
}, true)
.FirstAsync();*/
Logger.Information($"【LoadConfirm】 当前取货,子任务编号:{input.taskCode}");
ElevagorInfoQuery q = new() { taskCode = input.taskCode, sourceName = input.sourceName };
WmsElevatorH elevator = await FindElevatorFromPars(q);
if (elevator.IsNull())
{
Logger.Error("【LoadConfirm】 未找到匹配的电梯任务", new Exception($"【LoadConfirm】 根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务"));
return await ToApiResult(HttpStatusCode.InternalServerError, $"【LoadConfirm】 根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务");
}
try
{
if (s_elevatorMap.TryGetValue(elevator.device_id, out object? elevatorCode))
{
//s_eleUseStatusDic[elevator.device_id] = (int)EnumElevatorUseStatus.空闲;
string devName = elevatorCode?.ToString();
Logger.Information($"【LoadConfirm】 获取设备:{devName},状态");
var tags = _eleCtlCfg.tags;
await Task.Delay(1000);
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, tags, CancellationToken.None);
Logger.Information($"【LoadConfirm】 电梯当前状态->系统状态:{sysStatus.ToEnum<EnumSysStatus>()},运行状态:{runStatus.ToEnum<EnumRunStatus>()},门状态:{doorStatus},Agv状态:{agvStatus.ToEnum<EnumAgvStatus>()},当前楼层:{floorNo},电梯占用状态{s_eleUseStatusDic[elevator.device_id]}");
{
var curFloor = await GetRealFloor(elevator.end_floor);
/* Logger.Information($"目标楼层:{curFloor},电梯当前楼层:{floorNo}");
Logger.Information($"当前取货设备ID{elevator.device_id}");
var loadedStatus = s_eleUseStatusDic[elevator.device_id] == 1 ? "完成" : "未完成";
Logger.Information($"{devName.Match(@"\d+")}#梯,取货-> {loadedStatus}");
*/
if (s_eleUseStatusDic[elevator.device_id] == (int)EnumElevatorUseStatus. && curFloor != floorNo)
{
_ = await _elevatorControlService.CallLift(devName, curFloor, CancellationToken.None);
}
if (curFloor != floorNo)
{
Logger.Information($"【LoadConfirm】 电梯还未开门请重试curFloor != floorNo");
return await ToApiResult(HttpStatusCode.InternalServerError, "【LoadConfirm】 电梯还未开门,请重试!");
}
if (doorStatus.ToEnum<EnumDoorStatus>() != EnumDoorStatus. && runStatus.ToEnum<EnumRunStatus>() == EnumRunStatus. && floorNo == curFloor) //判断电梯楼层与当前放货在同一楼层在允许放货
{
Logger.Information($"【LoadConfirm】 发送电梯{devName}前门开门指令");
_ = await _elevatorControlService.SendOpenCloseCmd(devName, 3); //发送电梯前门开门指令
}
//if (doorStatus == (int)EnumDoorStatus.开门到位保持 && s_eleUseStatusDic[elevator.device_id] == (int)EnumElevatorUseStatus.占用)
//{
// Logger.Information($"{devName.Match(@"\d+")}#梯,任务未完成");
// await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!");
//}
if (sysStatus.ToEnum<EnumSysStatus>() == EnumSysStatus. && runStatus.ToEnum<EnumRunStatus>() == EnumRunStatus.
&& doorStatus == (int)EnumDoorStatus.)
{
Logger.Information($"【LoadConfirm】 {devName}取货成功");
return await ToApiResult(HttpStatusCode.OK, "成功");
}
}
}
}
catch (Exception)
{
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
throw;
}
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
}
/// <summary>
/// 获取电梯根据任务单号
/// </summary>
/// <param name="input">
/// taskCode:子任务编号
/// endlocation_id:目标库位ID
/// </param>
/// <returns></returns>
protected async Task<WmsElevatorH> FindElevatorFromPars(ElevagorInfoQuery input)
{
Logger.Information($"【FindElevatorFromPars】 根据任务单号获取电梯参数: {JsonConvert.SerializeObject(input)}");
var whereExpable = Expressionable.Create<WmsElevatorH, WmsElevatorD, WmsDistaskH>()
.And((a, b, c) => a.enabled == 1);
if (!input.taskCode.IsNullOrEmpty())
{
whereExpable.AndIF(!SqlFunc.IsNullOrEmpty(input.taskCode), (a, b, c) => c.bill_code == input.taskCode);
}
if (!input.endlocation_id.IsNullOrEmpty())
{
whereExpable.AndIF(!SqlFunc.IsNullOrEmpty(input.endlocation_id), (a, b, c) => b.location_id == input.endlocation_id);
}
if (!input.startlocation_id.IsNullOrEmpty())
{
whereExpable.AndIF(!SqlFunc.IsNullOrEmpty(input.startlocation_id), (a, b, c) => b.location_id == input.startlocation_id);
}
ISugarQueryable<WmsElevatorH> queryable = _db.CopyNew().Queryable<WmsElevatorH>().InnerJoin<WmsElevatorD>((a, b) => a.id == b.bill_id)
.InnerJoin<WmsDistaskH>((a, b, c) => b.location_code == c.endlocation_code || b.location_code == c.startlocation_code)
.Where(whereExpable.ToExpression())
.WhereIF(!SqlFunc.IsNullOrEmpty(input.sourceName) && SqlFunc.StartsWith("DT-R", input.sourceName), (a, b, c) => c.startpoint_code == input.sourceName)
.WhereIF(!SqlFunc.IsNullOrEmpty(input.sourceName) && SqlFunc.StartsWith("DT-C", input.sourceName), (a, b, c) => c.endpoint_code == input.sourceName)
.Select((a, b, c) => new WmsElevatorH
{
bill_code = c.bill_code,
device_id = a.elevator_id,
end_floor = c.end_floor
}, true);
Logger.Information($"【FindElevatorFromPars】 根据任务单号获取电梯sql {queryable.ToSqlString()}");
var ele = await queryable
.FirstAsync();
return ele;
}
/// <summary>
/// 放货确认/申请放货
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, NonUnify, AllowAnonymous]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> UnloadConfirm(ConfirmInput input)//
{
Logger.Information("【UnloadConfirm】 接收到WCS放货确认信号..................");
Logger.Information($"【UnloadConfirm】 当前放货,任务编号:{input.taskCode}");
var dis = _db.Queryable<WmsDistaskH>().Where(P => P.bill_code == input.taskCode).First();
if (dis.area_code == "ZSCJ001")
{
var flag = await _wareHouseService.Check(dis.endlocation_code, "UNLOAD");
if (flag)
{
await _wareHouseService.SsxControl(dis, "UNLOAD");
return await ToApiResult(HttpStatusCode.OK, "成功");
}
else
{
return await ToApiResult(HttpStatusCode.InternalServerError, "失败");
}
}
try
{
/*var whereExp = Expressionable.Create<WmsElevatorH, WmsElevatorD, WmsDistaskH>()
.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<WmsElevatorH>().LeftJoin<WmsElevatorD>((a, b) => a.id == b.bill_id)
.LeftJoin<WmsDistaskH>((a, b, c) => b.location_id == c.endlocation_id)
.Where(whereExp)
.Select((a, b, c) => new WmsElevatorH
{
end_floor = SqlFunc.ToInt32(c.end_floor),
device_id = a.elevator_id,
}, true)
.FirstAsync();*/
ElevagorInfoQuery q = new() { taskCode = input.taskCode, sourceName = input.sourceName };
WmsElevatorH elevator = await FindElevatorFromPars(q);
if (elevator.IsNull())
{
Logger.Error($"【UnloadConfirm】 根据参数,sourceName:{input.sourceName},taskCode:{input.taskCode},未找到匹配的电梯任务");
}
if (s_elevatorMap.TryGetValue(elevator.device_id, out object? elevatorCode))
{
string devName = elevatorCode?.ToString();
Logger.Information($"【UnloadConfirm】 当前放货设备ID{elevator.device_id}");
var loadedStatus = s_eleUseStatusDic[elevator.device_id] == 1 ? "占用" : "空闲";
Logger.Information($"【UnloadConfirm】 {devName.Match(@"\d+")}#梯,状态-> {loadedStatus}");
Logger.Information($"【UnloadConfirm】 获取设备:{devName},状态");
//await Task.Delay(3000);
(int sysStatus, int runStatus, int floorNo, int doorStatus, int agvStatus) = await _elevatorControlService.GetElevatorStatus(devName, _eleCtlCfg.tags, CancellationToken.None);//elevator.elevator_code
Logger.Information($"【UnloadConfirm】 电梯当前状态->系统状态:{sysStatus.ToEnum<EnumSysStatus>()},运行状态:{runStatus},门状态:{doorStatus},Agv状态:{agvStatus},当前楼层:{floorNo}");
//判断Agv电梯是否进入状态
if (agvStatus != (int)EnumAgvStatus.AGV运行状态)
{
dynamic res = await _elevatorControlService.WriteTagAsync(devName, ElevatorConsts.AGVControl, 1);
Logger.Information($"【UnloadConfirm】 发送AGVControl 切换电梯{devName}控制模式结果 {JsonConvert.SerializeObject(res)}");
}
var curFloor = await GetRealFloor(elevator.end_floor);
Logger.Information($"【UnloadConfirm】 电梯状态 {s_eleUseStatusDic[elevator.device_id]} 当前楼层:{curFloor},电梯所在楼层:{floorNo}");
if (s_eleUseStatusDic[elevator.device_id] == (int)EnumElevatorUseStatus. && curFloor != floorNo)
{
_ = await _elevatorControlService.CallLift(devName, curFloor, CancellationToken.None);
}
if (curFloor != floorNo)
{
Logger.Information($"【UnloadConfirm】 电梯还未开门请重试curFloor != floorNo");
return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!");
}
if (doorStatus == (int)EnumDoorStatus. && s_eleUseStatusDic[elevator.device_id] == (int)EnumElevatorUseStatus.)
{
Logger.Information($"【UnloadConfirm】 电梯当前在s_eleUseStatusDic中的状态为占用");
await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!");
}
//电梯到达目标楼层后,判断当前电梯门状态是否为开门到位保持状态
if (doorStatus != (int)EnumDoorStatus. && s_eleUseStatusDic[elevator.device_id] == (int)EnumElevatorUseStatus. && curFloor == floorNo) //判断目标楼层与电梯所在楼层在同一层才可开门放货
{
Logger.Information($"【UnloadConfirm】 发送电梯{devName}前门开门指令");
_ = await _elevatorControlService.SendOpenCloseCmd(devName, 3); //发送电梯前门开门指令
}
if (sysStatus == (int)EnumSysStatus. && runStatus == (int)EnumRunStatus.
&& doorStatus == (int)EnumDoorStatus. && s_eleUseStatusDic[elevator.device_id] == (int)EnumElevatorUseStatus.)
{
Logger.Information($"【UnloadConfirm】 {devName}放货成功 状态变更为占用");
await _db.Updateable<WmsElevatorH>().SetColumns(r => r.is_use == (int)EnumElevatorUseStatus.).Where(r => r.elevator_id == elevator.device_id).ExecuteCommandAsync();
s_eleUseStatusDic[elevator.device_id] = (int)EnumElevatorUseStatus.;
return await ToApiResult(HttpStatusCode.OK, "成功");
}
Logger.Information($"【UnloadConfirm】 电梯还未开门请重试sysStatus: {sysStatus} runStatus:{runStatus} doorStatus: {doorStatus} s_eleUseStatusDic[elevator.device_id]: {s_eleUseStatusDic[elevator.device_id]}");
}
return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!");
}
catch (Exception ex)
{
Logger.Error("【UnloadConfirm】 放货确认失败", ex);
return await ToApiResult(HttpStatusCode.InternalServerError, "电梯还未开门,请重试!");
throw;
}
}
/// <summary>
/// 任务链状态上报
/// </summary>
/// <returns></returns>
[HttpPost, NonUnify, AllowAnonymous]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> TaskChainCallBack(TaskChainCallBackInput input)
{
try
{
Logger.Information($"【TaskChainCallBack】 接收到WCS信号 任务链上报->任务链编号:{input.taskChainCode},状态:{input.status},设备ID{input.deviceID}");
switch (input.status)
{
case "CREATED": break;
case "ALLOCATED": break;
case "PROCESSING":
if (input.taskChainCode.Trim().IsNullOrEmpty())
{
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
}
List<WmsDistaskH> disTasks = await _db.Queryable<WmsDistaskH>().Where(it => it.bill_code.Contains(input.taskChainCode)).ToListAsync();
List<EqpEquipment> eps = await _db.Queryable<EqpEquipment>().Where(it => it.code.Contains(input.deviceID)).ToListAsync();
if (disTasks == null || disTasks.Count < 1)
{
Logger.Error($"【TaskChainCallBack】 根据任务链编号:{input.taskChainCode} ,未获取到任何任务");
}
if (disTasks?.Count > 0)
{
TaskExecuteUpInput taskExecuteUpInput = new()
{
disTaskIds = disTasks?.Select(x => x.id).ToList() ?? Enumerable.Empty<string>().ToList(),
EqpIds = eps?.Select(x => x.id).ToList() ?? Enumerable.Empty<string>().ToList(),
};
await _wareHouseService.TaskExecute(taskExecuteUpInput);
}
break;
case "CANCELLED":
{
Logger.Information("开始处理WCS上传的取消任务");
int row = await _db.Updateable<WmsDistaskH>().SetColumns(r => new WmsDistaskH
{
agreement = "WCS上传取消(CANCELLED)信号 取消时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
status = WmsWareHouseConst.TASK_BILL_STATUS_CANCEL_ID
}).Where(P => P.bill_code.Contains(input.taskChainCode)).ExecuteCommandAsync();
if (row > 0)
{
List<WmsDistaskH> wmsDistaskHs = _db.Queryable<WmsDistaskH>().Where(P => P.bill_code.Contains(input.taskChainCode)).ToList();
List<string> wmsDistaskHCodes = wmsDistaskHs.Select(r => r.pretask_code).ToList();
foreach (WmsDistaskH wmsDistaskH in wmsDistaskHs)
{
if (wmsDistaskH.startlocation_code.Contains("DT") || wmsDistaskH.endlocation_code.Contains("DT"))
{
WmsElevatorUnlockInput wmsElevatorUnlockInput = new ();
wmsElevatorUnlockInput.elevator_id = wmsDistaskH.device_id;
await WmsElevatorUnlock(wmsElevatorUnlockInput);
Logger.Information($"WCS取消任务{wmsDistaskH.bill_code},自动解占用电梯{wmsDistaskH.device_id}");
}
}
await _db.Updateable<WmsPretaskH>().SetColumns(r => new WmsPretaskH
{
note = "WCS上传取消(CANCELLED)信号 取消时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
status = WmsWareHouseConst.PRETASK_BILL_STATUS_CANCEL_ID
}).Where(P => wmsDistaskHCodes.Contains(P.bill_code)).ExecuteCommandAsync();
Logger.Information("成功处理WCS上传的取消任务");
}
else
{
Logger.Information("未处理WCS上传的取消任务");
}
break;
}
case "SUCCEED": break;
case "FAILURE":
{
Logger.Information("开始处理WCS上传的失败任务");
int row = await _db.Updateable<WmsDistaskH>().SetColumns(r => new WmsDistaskH
{
agreement = "WCS上传失败(FAILURE)信号 失败时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
status = WmsWareHouseConst.TASK_BILL_STATUS_CANCEL_ID
}).Where(P => P.bill_code.Contains(input.taskChainCode)).ExecuteCommandAsync();
if (row > 0)
{
List<string> wmsDistaskHCodes = _db.Queryable<WmsDistaskH>().Where(P => P.bill_code.Contains(input.taskChainCode)).Select(r => r.pretask_code).ToList();
await _db.Updateable<WmsPretaskH>().SetColumns(r => new WmsPretaskH
{
note = "WCS上传失败(FAILURE)信号 取消时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
status = WmsWareHouseConst.TASK_BILL_STATUS_CANCEL_ID
}).Where(P => wmsDistaskHCodes.Contains(P.bill_code)).ExecuteCommandAsync();
Logger.Information("成功处理WCS上传的失败任务");
}
else
{
Logger.Information("未处理WCS上传的失败任务");
}
break;
}
case "FINISHED":
break;
default: break;
}
/*ConnectionConfigOptions opts = App.GetOptions<ConnectionConfigOptions>();
UserAgent userAgent = new(App.HttpContext);
//写系统日志
await _eventPublisher.PublishAsync(new LogEventSource("Log:CreateOpLog", opts, new SysLogEntity
{
Id = SnowflakeIdHelper.NextId(),
Category = 4,
UserId = _userManager.UserId,
UserName = _userManager.User.RealName,
IPAddress = NetHelper.Ip,
RequestURL = App.HttpContext.Request.Path,
RequestMethod = App.HttpContext.Request.Method,
Json = $"任务链状态上报,任务链编号:{input.taskChainCode},上报状态:{input.status},设备编号:{input.deviceID}",
PlatForm = string.Format("{0}-{1}", userAgent.OS.ToString(), userAgent.RawValue),
CreatorTime = DateTime.Now
}));*/
}
catch (Exception ex)
{
Logger.Error("【TaskChainCallBack】 任务链状态上报", ex);
Logger.Error($"【TaskChainCallBack】 任务链状态上报错误堆栈{Environment.NewLine}{ex.StackTrace}");
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
throw;
}
return await ToApiResult(HttpStatusCode.OK, "成功");
}
/// <summary>
/// 任务状态上报
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, NonUnify, AllowAnonymous]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> TaskCallback(TaskCallBackInput input)
{
var disTask = await _db.Queryable<WmsDistaskH>().FirstAsync(it => it.bill_code == input.taskCode);
Logger.Information($"【TaskCallback】 【接收】{input.taskCode} WCS信号 任务状态上报->接收参数:{JsonConvert.SerializeObject(input)}");
try
{
List<WmsDistaskH> disTasks = new() { disTask };
if (input.action == "LOAD")
{
TaskExecuteAfterUpInput taskExecuteAfterUpInput = new()
{
disTaskIds = disTasks.Select(x => x.id).ToList()
};
Logger.Information($"【TaskCallback】 设备取返回输入参数:{JsonConvert.SerializeObject(taskExecuteAfterUpInput)}");
await _wareHouseService.TaskExecuteAfter(taskExecuteAfterUpInput);
Logger.Information($"【TaskCallback】 Agv取货完成,任务编号:{string.Join(",", disTasks.Select(x => x.bill_code))}");
//根据Agv传递的参数获取对应的电梯
if (!input.sourceName.IsNullOrWhiteSpace() && (input.sourceName.Contains("DT-R", StringComparison.OrdinalIgnoreCase)))
{
Logger.Information($"【TaskCallback】 开始根据任务单查找电梯 {input.sourceName}");
ElevagorInfoQuery q = new() { taskCode = input.taskCode };
if (!input.sourceName.IsNullOrEmpty())
{
q = new() { taskCode = input.taskCode, sourceName = input.sourceName };
}
WmsElevatorH elevator = await FindElevatorFromPars(q);
Logger.Information($"【TaskCallback】 根据任务单查找电梯结果 {JsonConvert.SerializeObject(elevator)}");
if (!elevator?.device_id.IsNullOrEmpty() ?? false)
{
await _db.Updateable<WmsElevatorH>().SetColumns(r => r.is_use == (int)EnumElevatorUseStatus.).Where(r => r.elevator_id == elevator.device_id).ExecuteCommandAsync();
s_eleUseStatusDic[elevator.device_id] = (int)EnumElevatorUseStatus.;
// 根据disTask StartLocationId 起始库位关联电梯获取设备ID location_code.Continas("")
var devName = s_elevatorMap[elevator.device_id]?.ToString();
Logger.Information($"【TaskCallback】 {devName.Match(@"\d+")}#梯,设备名称:{devName},开始进入关门流程 {devName} 变更为空闲");
int doorStatus = await _elevatorControlService.GetTagAsync(devName, ElevatorConsts.DoorStatus);
Logger.Information($"【TaskCallback】 设备:{devName},门状态:{doorStatus.ToEnum<EnumDoorStatus>().ToString()}");
if (doorStatus.ToEnum<EnumDoorStatus>() != EnumDoorStatus.
)//&& !disTask.endlocation_code.StartsWith("DT", StringComparison.OrdinalIgnoreCase)
{
_ = await _elevatorControlService.SendOpenCloseCmd(devName, 4); //向电梯发送前门关门指令
}
}
else
{
Logger.Information($"【TaskCallback】 没找到电梯,不能解锁电梯状态 {JsonConvert.SerializeObject(elevator)}");
}
}
else
{
//Logger.Information($"【TaskCallback】电梯sourceName不符合条件 {input.sourceName}");
}
WmsElevatorUnexecute elevatorQueueItem = await _db.Queryable<WmsElevatorUnexecute>().FirstAsync(it => disTasks.Select(x => x.id).Contains(it.distask_id) && it.task_status == "执行中");
if (elevatorQueueItem != null)
{
_ = await _db.Deleteable(elevatorQueueItem).ExecuteCommandAsync();
}
// 中储仓KIVA取货确认后不需要再发送信号给输送线
if (disTask.startlocation_code == "ZSSSXCTU01" || disTask.startlocation_code == "ZSSSXCTU02")
{
}
else
{
await _wareHouseService.SsxControl(disTask, "LOAD");
// 二楼机械臂
await _wareHouseService.Floor2MechanicalComplete(disTask, "LOAD");
}
}
else if (input.action == "UNLOAD")
{
TaskCompleUpInput taskCompleUpInput = new()
{
disTaskIds = disTasks.Select(x => x.id).ToList()
};
Logger.Information($"taskCompleUpInput json parameter:{JsonConvert.SerializeObject(taskCompleUpInput)}");
await _wareHouseService.TaskComplate(taskCompleUpInput);
await _wareHouseService.SsxControl(disTask, "UNLOAD");
// 二楼机械臂
await _wareHouseService.Floor2MechanicalComplete(disTask, "UNLOAD");
Logger.Information($"【TaskCallback】 Agv放货完成,任务编号:{string.Join(",", disTasks.Select(x => x.bill_code))}");
}
}
catch (Exception ex)
{
Logger.Error("【TaskCallback】 任务状态上报出现错误", ex);
Logger.Error("【TaskCallback】 任务状态上报错误堆栈信息", ex.StackTrace);
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
throw;
}
finally
{
_ = InvokeGenPretaskExcute();
}
Logger.Information($"【TaskCallback】 【成功】{input.taskCode} WCS信号 任务状态上报->接收参数:{JsonConvert.SerializeObject(input)}");
return await ToApiResult(HttpStatusCode.OK, "成功");
}
[HttpPost]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> WmsElevatorUnlock(WmsElevatorUnlockInput input)
{
try
{
Logger.Information($"【WmsElevatorUnlock】操作电梯{input.elevator_id}手动解锁");
await _db.Updateable<WmsElevatorH>().SetColumns(r => r.is_use == (int)EnumElevatorUseStatus.)
.Where(it => it.elevator_id == input.elevator_id).ExecuteCommandAsync();
s_eleUseStatusDic[input.elevator_id] = (int)EnumElevatorUseStatus.;
}
catch (Exception ex)
{
Logger.Error("【ElevatorConfirm】 申请进出电梯信号错误", ex);
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
throw;
}
return await ToApiResult(HttpStatusCode.OK, "解锁成功");
}
/// <summary>
/// 申请进出电梯
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, NonUnify, AllowAnonymous]
public async Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> ElevatorConfirm(ConfirmInput input)
{
try
{
Logger.Information($"【ElevatorConfirm】 接收到WCS申请进出电梯信号 接收参数:{JsonConvert.SerializeObject(input)}");
List<WmsElevatorH> eles = await _db.Queryable<WmsElevatorH>().LeftJoin<WmsElevatorD>((a, b) => a.id == b.bill_id)
.LeftJoin<WmsDistaskH>((a, b, c) => b.location_id == c.startlocation_id)
.Where((a, b, c) => c.startlocation_code == input.sourceName && c.bill_code == input.taskCode)
.ToListAsync();
}
catch (Exception ex)
{
Logger.Error("【ElevatorConfirm】 申请进出电梯信号错误", ex);
return await ToApiResult(HttpStatusCode.InternalServerError, "请重试!");
throw;
}
return await ToApiResult(HttpStatusCode.OK, "未启用");
}
/// <summary>
/// 根据产线获取Agv列表
/// </summary>
/// <param name="lineId">产线Id默认空(潍柴的只有一条产线所以不用传)</param>
/// <remarks>
/// returns:
/// <br/>{
/// <br/> name:设备名称
/// <br/> code:设备代码
/// <br/>}
/// </remarks>
[HttpGet("lineId"), AllowAnonymous]
public async Task<dynamic> GetAgvListByLineId(string lineId = "")
{
var devList = await _db.Queryable<EqpEquipment>().InnerJoin<EqpEquipType>((a, b) => a.equip_type_id == b.id)
.Where((a, b) => b.code == "003" && b.status == 1)
.Select((a, b) => new
{
a.name,
a.code,
})
.ToListAsync();
return devList;
}
/// <summary>
/// 获取Agv实时信息
/// </summary>
/// <param name="q">查询输入参数</param>
///<remarks>
/// <br/>{
/// <br/> deviceCode:设备序号
/// <br/> devicePostionRec:设备所在二维码的x,y坐标前边的值是x后边的是y
/// <br/> devicePosition:设备当前位置
/// <br/> oritation:方向
/// <br/> speed:速度
/// <br/> shelfNumber当前搬运的货架编号,对应载具编号
/// <br/>}
///</remarks>
[HttpGet, AllowAnonymous]
public async Task<List<AgvRealInfoOutput>> GetAgvRealInfo([FromQuery] AgvRealInfoQuery q)
{
//请求Les接口bing解析返回结果 绑定到AgvRealInfoOutput实例 此处忽略
var devCodes = new[] { "Dev01", "Dev02", "Dev03", "Dev04", "Dev05" };
if (!q.deviceCode.IsNullOrWhiteSpace())
{
devCodes = devCodes.Where(x => q.deviceCode.Contains(x)).ToArray();
}
var result = new List<AgvRealInfoOutput>();
for (int i = 0; i < devCodes.Length; i++)
{
AgvRealInfoOutput output = new();
output.deviceCode = devCodes[i];
output.oritation = 0;
output.speed = Random.Shared.Next(0, 100);
var x = Random.Shared.NextDouble() * 100;
var y = Random.Shared.NextDouble() * 100;
output.devicePostionRec = new[] { x, y };
output.shelfNumber = "xxxx";
result.Add(output);
}
return result;
}
/// <summary>
/// CTU放货申请
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost, NonUnify, AllowAnonymous]
public Task<Tnb.WarehouseMgr.Entities.Dto.Outputs.Result> CTUUnloadConfirm(ConfirmInput input)
{
var data = "";
try
{
data = "允许放货";
}
catch (Exception)
{
data = "不允许放货";
throw;
}
return ToApiResult(HttpStatusCode.OK, data);
}
}
}