change - 提升机调度逻辑修改

dev
WenJY 1 week ago
parent 0927dce3a6
commit a1f7315d68

@ -34,6 +34,11 @@ public class HoistControlDto
/// </summary> /// </summary>
public string hoistCode { get; set; } public string hoistCode { get; set; }
/// <summary>
/// 设备序号
/// </summary>
public int deviceSerialNo{get;set;}
/// <summary> /// <summary>
/// 动作 /// 动作
/// </summary> /// </summary>

@ -37,6 +37,11 @@ public class HoistTaskExeDto
/// </summary> /// </summary>
public string taskCode { get; set; } public string taskCode { get; set; }
/// <summary>
/// 设备序号
/// </summary>
public int deviceSerialNo{get;set;}
/// <summary> /// <summary>
/// 起点 /// 起点
/// </summary> /// </summary>

@ -114,6 +114,7 @@ public class HoistService:IHoistService
{ {
hoistCode = hoistTaskExeDto.hoistCode, hoistCode = hoistTaskExeDto.hoistCode,
taskCode = hoistTaskExeDto.taskCode, taskCode = hoistTaskExeDto.taskCode,
deviceSerialNo = hoistTaskExeDto.deviceSerialNo,
startPoint = hoistTaskExeDto.startPoint, startPoint = hoistTaskExeDto.startPoint,
endPoint = hoistTaskExeDto.endPoint, endPoint = hoistTaskExeDto.endPoint,

@ -0,0 +1,192 @@
#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.HoistControl;
using Sln.Wcs.HoistAdapter.Domain.Dto.HoistTaskExecutor;
using Sln.Wcs.HoistAdapter.Domain.Enum;
using Sln.Wcs.HoistAdapter.Service;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Serilog;
namespace Sln.Wcs.HoistDispatcher;
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="hoistCode"></param>
public void TaskRun(BaseDeviceInfo deviceInfo)
{
try
{
HoistControlResultDto res = _hoistAdapter.HoistControl(new HoistControlDto()
{
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);
//调用适配层下发 提升机调度任务
HoistTaskExeResultDto res = _hoistAdapter.HoistTaskExecutor(new HoistTaskExeDto()
{
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;
}
}

@ -1,112 +0,0 @@
#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* (c) 2026 WenJY
* CLR4.0.30319.42000
* Mr.Wen's MacBook Pro
* Sln.Wcs.HoistDispatcher
* 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.Enum;
using Sln.Wcs.HoistAdapter.Service;
using Sln.Wcs.Model.Domain;
using Sln.Wcs.Plc.Service;
using Sln.Wcs.Repository.service;
using Sln.Wcs.Serilog;
namespace Sln.Wcs.HoistDispatcher;
public class HoistDispatcher
{
private readonly SerilogHelper _logger;
private readonly IHoistService _hoistAdapter;
public HoistDispatcher(IHoistService hoistAdapter, SerilogHelper logger)
{
_hoistAdapter = hoistAdapter;
_logger = logger;
}
public void Run()
{
_logger.Info("提升机调度就绪,输入 start 启动stop 停止quit 退出");
while (true)
{
var input = Console.ReadLine()?.Trim().ToLower();
switch (input)
{
case "start":
Start();
break;
case "stop":
Stop();
break;
case "quit":
Stop();
return;
default:
_logger.Info("未知指令,可用: start | stop | quit");
break;
}
}
}
private void Start()
{
}
private void Stop()
{
}
public void Run(string hostCode,string tagCode,int startPoint,int endPoint)
{
//收到提升机调度任务
// 1、读取 RFID 条码
// 2、下发提升机任务起点、终点
// 3、等待提升机完成任务
RefreshDeviceParams(hostCode,out List<BaseDeviceInfo> deviceInfos);
}
public 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}");
}
}
}

@ -34,6 +34,11 @@ public class HoistControlDto
/// </summary> /// </summary>
public string hoistCode { get; set; } public string hoistCode { get; set; }
/// <summary>
/// 设备序号
/// </summary>
public int deviceSerialNo{get;set;}
/// <summary> /// <summary>
/// 动作 /// 动作
/// </summary> /// </summary>

@ -37,6 +37,11 @@ public class HoistTaskExeDto
/// </summary> /// </summary>
public string taskCode { get; set; } public string taskCode { get; set; }
/// <summary>
/// 设备序号
/// </summary>
public int deviceSerialNo{get;set;}
/// <summary> /// <summary>
/// 起点 /// 起点
/// </summary> /// </summary>

@ -24,6 +24,7 @@
#endregion << 版 本 注 释 >> #endregion << 版 本 注 释 >>
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sln.Wcs.HoistSdk.Config; using Sln.Wcs.HoistSdk.Config;
using Sln.Wcs.HoistSdk.Dto.GetHoistStatus; using Sln.Wcs.HoistSdk.Dto.GetHoistStatus;
using Sln.Wcs.HoistSdk.Dto.HoistControl; using Sln.Wcs.HoistSdk.Dto.HoistControl;
@ -50,8 +51,9 @@ public class HoistSdk:IHoistSdk
HoistControlResultDto result = new HoistControlResultDto(); HoistControlResultDto result = new HoistControlResultDto();
try try
{ {
string paramAddress = GetPlcParam(hoistControlDto.hoistCode,hoistControlDto.deviceSerialNo,"放置完成");
var plc = _plcs.Where(x => x.ConfigKey.Equals(hoistControlDto.hoistCode)).ToList().First(); var plc = _plcs.Where(x => x.ConfigKey.Equals(hoistControlDto.hoistCode)).ToList().First();
var res = plc.writeInt16ByAddress(_hoistConfig.hoist_control_addr, (int)hoistControlDto.action); var res = plc.writeInt16ByAddress(paramAddress, (int)hoistControlDto.action);
if (res) if (res)
{ {
result.code = "0"; result.code = "0";
@ -73,7 +75,29 @@ public class HoistSdk:IHoistSdk
public HoistTaskExeResultDto HoistTaskExecutor(HoistTaskExeDto hoistTaskExeDto) public HoistTaskExeResultDto HoistTaskExecutor(HoistTaskExeDto hoistTaskExeDto)
{ {
throw new NotImplementedException(); HoistTaskExeResultDto result = new HoistTaskExeResultDto();
try
{
string paramAddress = GetPlcParam(hoistTaskExeDto.hoistCode,hoistTaskExeDto.deviceSerialNo,"任务执行指令");
var plc = _plcs.Where(x => x.ConfigKey.Equals(hoistTaskExeDto.hoistCode)).ToList().First();
var res = plc.writeInt16ByAddress(paramAddress, hoistTaskExeDto.endPoint);
if (res)
{
result.code = "0";
result.message = "写入成功";
}
else
{
result.code = "99";
result.message = "写入失败";
}
}
catch (Exception e)
{
result.code = "99";
result.message = e.Message;
}
return result;
} }
public GetHoistStatusResultDto GetHoistStatus(GetHoistStatusDto hoistStatusDto) public GetHoistStatusResultDto GetHoistStatus(GetHoistStatusDto hoistStatusDto)
@ -97,18 +121,18 @@ public class HoistSdk:IHoistSdk
if (item.hostCode == hoistStatusDto.hoistCode) if (item.hostCode == hoistStatusDto.hoistCode)
{ {
// var plc = _plcs.Where(x => x.ConfigKey.Equals(item.hostCode)).FirstOrDefault(); var plc = _plcs.Where(x => x.ConfigKey.Equals(item.hostCode)).FirstOrDefault();
// if (plc == null) if (plc == null)
// { {
// result.code = "99"; result.code = "99";
// result.message = $"未找到PLC: {item.hostCode}"; result.message = $"未找到PLC: {item.hostCode}";
// result.hoistCode = hoistStatusDto.hoistCode; result.hoistCode = hoistStatusDto.hoistCode;
// return result; return result;
// } }
//
foreach (var param in item.deviceParams) foreach (var param in item.deviceParams)
{ {
//int value = plc.readInt16ByAddress(param.paramAddress); int value = plc.readInt16ByAddress(param.paramAddress);
param.paramValue = param.objId; param.paramValue = param.objId;
@ -138,5 +162,20 @@ public class HoistSdk:IHoistSdk
} }
return result; return result;
} }
private string GetPlcParam(string hostCode,int deviceSerialNo,string paramName)
{
List<dynamic> paramStr = JsonConvert.DeserializeObject<List<dynamic>>(_hoistConfig.hoist_plc_param);
dynamic deviceInfo = paramStr.Where(x => x.hostCode == hostCode && x.deviceSerialNo == deviceSerialNo)
.FirstOrDefault();
List<dynamic> deviceParams = (deviceInfo.deviceParams as JArray)?.ToObject<List<dynamic>>();
dynamic deviceParam = deviceParams
.Where(x => ((string)x.paramName).Contains(paramName) && (int)x.operationType == 2).FirstOrDefault();
return deviceParam.paramAddress;
}
} }

@ -60,12 +60,16 @@ namespace Sln.Wcs.Model.Domain
public string deviceName { get; set; } public string deviceName { get; set; }
/// <summary> /// <summary>
/// Desc:主机编号 /// 设备别名
/// Default:
/// Nullable:False
/// </summary> /// </summary>
[SugarColumn(ColumnName = "host_code")] [SugarColumn(ColumnName = "device_alias")]
public string hostCode { get; set; } public string deviceAlias { get; set; }
/// <summary>
/// 设备序号
/// </summary>
[SugarColumn(ColumnName = "device_serialNo")]
public int deviceSerialNo { get; set; }
/// <summary> /// <summary>
/// Desc:设备类型0-输送线1-AGV2-提升机 /// Desc:设备类型0-输送线1-AGV2-提升机
@ -82,6 +86,14 @@ namespace Sln.Wcs.Model.Domain
/// </summary> /// </summary>
[SugarColumn(ColumnName = "device_status")] [SugarColumn(ColumnName = "device_status")]
public int? deviceStatus { get; set; } public int? deviceStatus { get; set; }
/// <summary>
/// Desc:主机编号
/// Default:
/// Nullable:False
/// </summary>
[SugarColumn(ColumnName = "host_code")]
public string hostCode { get; set; }
/// <summary> /// <summary>
/// Desc:是否标识1-是0-否 /// Desc:是否标识1-是0-否

@ -52,6 +52,8 @@ namespace Sln.Wcs.Repository.service.Impl
deviceName = device.deviceName, deviceName = device.deviceName,
deviceType = device.deviceType, deviceType = device.deviceType,
deviceStatus = device.deviceStatus, deviceStatus = device.deviceStatus,
deviceSerialNo = device.deviceSerialNo,
deviceAlias = device.deviceAlias,
hostCode = device.hostCode, hostCode = device.hostCode,
isFlag = device.isFlag, isFlag = device.isFlag,
remark = device.remark, remark = device.remark,

@ -13,8 +13,11 @@ using Sln.Wcs.HikRoBotAdapter.Domain.Dto.GenAgvSchedulingTask;
using Sln.Wcs.HikRoBotAdapter.Service; using Sln.Wcs.HikRoBotAdapter.Service;
using Sln.Wcs.HikRoBotAdapter.Service.Impl; using Sln.Wcs.HikRoBotAdapter.Service.Impl;
using Sln.Wcs.HoistAdapter.Service; using Sln.Wcs.HoistAdapter.Service;
using Sln.Wcs.HoistDispatcher;
using Sln.Wcs.HoistSdk; using Sln.Wcs.HoistSdk;
using Sln.Wcs.HoistSdk.Dto.GetHoistStatus; using Sln.Wcs.HoistSdk.Dto.GetHoistStatus;
using Sln.Wcs.HoistSdk.Dto.HoistControl;
using Sln.Wcs.HoistSdk.Enum;
using Sln.Wcs.Model.Domain; using Sln.Wcs.Model.Domain;
using Sln.Wcs.Repository; using Sln.Wcs.Repository;
using Sln.Wcs.Repository.service; using Sln.Wcs.Repository.service;
@ -70,9 +73,6 @@ namespace Sln.Wcs
// } // }
// }); // });
var service = serviceProvider.GetService<HoistDispatcher.HoistDispatcher>();
service.Run(string.Empty,"tagCode",1,2);
Task.Delay(-1).Wait(); Task.Delay(-1).Wait();
} }
@ -89,11 +89,11 @@ namespace Sln.Wcs
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HikRoBotAdapter.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HikRoBotAdapter.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HikRoBotSdk.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HikRoBotSdk.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistAdapter.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistAdapter.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistDispatcher.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistSdk.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistSdk.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Plc.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Plc.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Business.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Business.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Strategy.dll")), Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Strategy.dll")),
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.HoistDispatcher.dll")),
}; };
services.Scan(scan => scan.FromAssemblies(assemblies) services.Scan(scan => scan.FromAssemblies(assemblies)

Loading…
Cancel
Save