You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

215 lines
6.9 KiB
C#

#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.HoistDispatchHub
* 764B880E-8084-48A5-B773-95E8EA044319
*
* WenJY
*
* 2026-06-01 13:24:25
* V1.0.0
*
*
*--------------------------------------------------------------------
*
*
*
*
* V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
using Newtonsoft.Json;
using Sln.Wcs.HoistAdapter.Domain.Dto.GetHoistStatus;
using Sln.Wcs.HoistAdapter.Domain.Dto.HoistTaskExecutor;
using Sln.Wcs.HoistAdapter.Domain.Dto.SetHoistAction;
using Sln.Wcs.HoistAdapter.Domain.Dto.SetHoistTask;
using Sln.Wcs.HoistAdapter.Domain.Enum;
using Sln.Wcs.HoistAdapter.Service;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Serilog;
namespace Sln.Wcs.HoistDispatcher;
/// <summary>
/// 提升机调度中心
/// </summary>
public class HoistDispatchHub
{
private readonly SerilogHelper _logger;
private readonly IHoistService _hoistAdapter;
public HoistDispatchHub(IHoistService hoistAdapter, SerilogHelper logger)
{
_hoistAdapter = hoistAdapter;
_logger = logger;
}
/// <summary>
/// 接收托盘
/// </summary>
/// <param name="taskDetail"></param>
/// <param name="deviceInfo"></param>
public void ReceivePallet(LiveTaskDetail taskDetail,BaseDeviceInfo deviceInfo)
{
//读取托盘RFID信息
string palletStr = "202606030001";
if (taskDetail.palletBarcode == palletStr)
{
this.TaskRun(deviceInfo);
}
else
{
_logger.Info($"托盘条码与计划不符");
}
}
/// <summary>
/// 提升机启动:放置完成下发
/// </summary>
/// <param name="hoistCode"></param>
public void TaskRun(BaseDeviceInfo deviceInfo)
{
try
{
SetHoistActionResultDto res = _hoistAdapter.SetHoistAction(new SetHoistActionDto()
{
hoistCode = deviceInfo.hostCode,
deviceSerialNo = deviceInfo.deviceSerialNo,
action = ControlAction.Start
});
if (res.code == HoistStatusEnum.)
{
_logger.Info($"提升机启动指令(放置完成)下发成功");
}
else
{
_logger.Info($"提升机启动指令(放置完成)下发失败:{res.msg},SDK返回信息:{res.data.message}");
}
}
catch (Exception e)
{
_logger.Info($"提升机启动指令(放置完成)下发异常:{e.Message}");
}
}
/// <summary>
/// 提升机任务下发执行可根据现场节拍进行提前下发AGV 确定接驳位后即可下发)
/// </summary>
/// <param name="deviceInfo"></param>
/// <param name="liveTaskDetail"></param>
public void TaskDispatch(BaseDeviceInfo deviceInfo,LiveTaskDetail liveTaskDetail)
{
try
{
//解析起始点,组合 PLC 所需的起始点
TryParsePointCode(liveTaskDetail.startPoint, out string startBuilding, out string startFloor,
out string startLocation);
TryParsePointCode(liveTaskDetail.endPoint, out string endBuilding, out string endFloor,
out string endLocation);
int endPoint = Convert.ToInt32(deviceInfo.deviceSerialNo + startFloor + endFloor);
//调用适配层下发 提升机调度任务
SetHoistTaskResultDto res = _hoistAdapter.SetHoistTask(new SetHoistTaskDto()
{
hoistCode = deviceInfo.hostCode,
taskCode = liveTaskDetail.taskCode,
deviceSerialNo = deviceInfo.deviceSerialNo,
endPoint = endPoint,
});
if (res.code == HoistStatusEnum.)
{
_logger.Info($"提升机任务{liveTaskDetail.taskCode}下发成功:目标位置-{endPoint}");
}
else
{
_logger.Info($"提升机任务{liveTaskDetail.taskCode}下发失败:{res.msg},SDK返回信息:{res.data.message}");
}
}
catch (Exception e)
{
_logger.Info($"提升机任务下发异常:{e.Message}");
}
}
/// <summary>
/// 获取空闲提升机
/// </summary>
/// <param name="hostCode"></param>
/// <returns></returns>
public async Task<BaseDeviceInfo> GetFreeHoistAsync(string hostCode)
{
while (true)
{
RefreshDeviceParams(hostCode, out List<BaseDeviceInfo> deviceInfos);
var freeHoist = deviceInfos?.FirstOrDefault(info =>
info.deviceParams.Any(item =>
item.paramName.Contains("提升机反馈任务状态") && item.paramValue == 0
)
);
if (freeHoist != null)
return freeHoist;
await Task.Delay(1000);
}
}
/// <summary>
/// 刷新设备参数:根据设备参数地址通过 PLC 获取参数值
/// hostCode为空时获取配置的所有参数值
/// </summary>
/// <param name="hostCode"></param>
/// <param name="deviceParams"></param>
private void RefreshDeviceParams(string hostCode,out List<BaseDeviceInfo> deviceParams)
{
deviceParams = null;
GetHoistStatusResultDto getRes = _hoistAdapter.GetHoistStatus(new GetHoistStatusDto(){hoistCode = hostCode});
if (getRes.code == HoistStatusEnum.)
{
deviceParams = JsonConvert.DeserializeObject<List<BaseDeviceInfo>>(getRes.data.deviceParamStr);
}
else
{
_logger.Info($"设备参数获取失败:{getRes.msg}");
}
}
/// <summary>
/// 解析起始点内容
/// 14#_L2_02 => 14栋、2层、02货位
/// </summary>
/// <param name="taskCode"></param>
/// <param name="building"></param>
/// <param name="floor"></param>
/// <param name="location"></param>
/// <returns></returns>
private bool TryParsePointCode(string taskCode, out string building, out string floor, out string location)
{
building = null;
floor = null;
location = null;
if (string.IsNullOrWhiteSpace(taskCode))
return false;
// 使用正则表达式匹配格式:数字+#+_+L+数字+_+数字(至少一位)
// 示例14#_L2_03
var match = System.Text.RegularExpressions.Regex.Match(taskCode, @"^(\d+)#_L(\d+)_(\d+)$");
if (!match.Success)
return false;
building = match.Groups[1].Value;
floor = match.Groups[2].Value;
location = match.Groups[3].Value;
return true;
}
}