diff --git a/Sln.Wcs.HoistAdapter/Domain/Dto/HoistControl/HoistControlDto.cs b/Sln.Wcs.HoistAdapter/Domain/Dto/HoistControl/HoistControlDto.cs
index e189a67..1b74790 100644
--- a/Sln.Wcs.HoistAdapter/Domain/Dto/HoistControl/HoistControlDto.cs
+++ b/Sln.Wcs.HoistAdapter/Domain/Dto/HoistControl/HoistControlDto.cs
@@ -34,6 +34,11 @@ public class HoistControlDto
///
public string hoistCode { get; set; }
+ ///
+ /// 设备序号
+ ///
+ public int deviceSerialNo{get;set;}
+
///
/// 动作
///
diff --git a/Sln.Wcs.HoistAdapter/Domain/Dto/HoistTaskExecutor/HoistTaskExeDto.cs b/Sln.Wcs.HoistAdapter/Domain/Dto/HoistTaskExecutor/HoistTaskExeDto.cs
index aa3e217..a6cc66d 100644
--- a/Sln.Wcs.HoistAdapter/Domain/Dto/HoistTaskExecutor/HoistTaskExeDto.cs
+++ b/Sln.Wcs.HoistAdapter/Domain/Dto/HoistTaskExecutor/HoistTaskExeDto.cs
@@ -37,6 +37,11 @@ public class HoistTaskExeDto
///
public string taskCode { get; set; }
+ ///
+ /// 设备序号
+ ///
+ public int deviceSerialNo{get;set;}
+
///
/// 起点
///
diff --git a/Sln.Wcs.HoistAdapter/Service/Impl/HoistService.cs b/Sln.Wcs.HoistAdapter/Service/Impl/HoistService.cs
index cc2a5c5..0ea50b0 100644
--- a/Sln.Wcs.HoistAdapter/Service/Impl/HoistService.cs
+++ b/Sln.Wcs.HoistAdapter/Service/Impl/HoistService.cs
@@ -114,6 +114,7 @@ public class HoistService:IHoistService
{
hoistCode = hoistTaskExeDto.hoistCode,
taskCode = hoistTaskExeDto.taskCode,
+ deviceSerialNo = hoistTaskExeDto.deviceSerialNo,
startPoint = hoistTaskExeDto.startPoint,
endPoint = hoistTaskExeDto.endPoint,
diff --git a/Sln.Wcs.HoistDispatcher/HoistDispatchHub.cs b/Sln.Wcs.HoistDispatcher/HoistDispatchHub.cs
new file mode 100644
index 0000000..54334a1
--- /dev/null
+++ b/Sln.Wcs.HoistDispatcher/HoistDispatchHub.cs
@@ -0,0 +1,192 @@
+#region << 版 本 注 释 >>
+
+/*--------------------------------------------------------------------
+* 版权所有 (c) 2026 WenJY 保留所有权利。
+* CLR版本:4.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;
+ }
+
+ ///
+ /// 提升机启动:放置完成下发
+ ///
+ ///
+ 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}");
+ }
+ }
+
+ ///
+ /// 提升机任务下发执行:可根据现场节拍进行提前下发(AGV 确定接驳位后即可下发)
+ ///
+ ///
+ ///
+ 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}");
+ }
+ }
+
+ ///
+ /// 获取空闲提升机
+ ///
+ ///
+ ///
+ public async Task GetFreeHoistAsync(string hostCode)
+ {
+ while (true)
+ {
+ RefreshDeviceParams(hostCode, out List 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);
+ }
+ }
+
+ ///
+ /// 刷新设备参数:根据设备参数地址通过 PLC 获取参数值
+ /// hostCode为空时获取配置的所有参数值
+ ///
+ ///
+ ///
+ private void RefreshDeviceParams(string hostCode,out List deviceParams)
+ {
+ deviceParams = null;
+
+ GetHoistStatusResultDto getRes = _hoistAdapter.GetHoistStatus(new GetHoistStatusDto(){hoistCode = hostCode});
+
+ if (getRes.code == HoistStatusEnum.成功)
+ {
+ deviceParams = JsonConvert.DeserializeObject>(getRes.data.deviceParamStr);
+ }
+ else
+ {
+ _logger.Info($"设备参数获取失败:{getRes.msg}");
+ }
+ }
+
+ ///
+ /// 解析起始点内容
+ /// 14#_L2_02 => 14栋、2层、02货位
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/Sln.Wcs.HoistDispatcher/HoistDispatcher.cs b/Sln.Wcs.HoistDispatcher/HoistDispatcher.cs
deleted file mode 100644
index e16993b..0000000
--- a/Sln.Wcs.HoistDispatcher/HoistDispatcher.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-#region << 版 本 注 释 >>
-
-/*--------------------------------------------------------------------
-* 版权所有 (c) 2026 WenJY 保留所有权利。
-* CLR版本:4.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 deviceInfos);
-
- }
-
-
- public void RefreshDeviceParams(string hostCode,out List deviceParams)
- {
- deviceParams = null;
-
- GetHoistStatusResultDto getRes = _hoistAdapter.GetHoistStatus(new GetHoistStatusDto(){hoistCode = hostCode});
-
- if (getRes.code == HoistStatusEnum.成功)
- {
- deviceParams = JsonConvert.DeserializeObject>(getRes.data.deviceParamStr);
- }
- else
- {
- _logger.Info($"设备参数获取失败:{getRes.msg}");
- }
- }
-}
\ No newline at end of file
diff --git a/Sln.Wcs.HoistSdk/Dto/HoistControl/HoistControlDto.cs b/Sln.Wcs.HoistSdk/Dto/HoistControl/HoistControlDto.cs
index 87714f4..0ff97ff 100644
--- a/Sln.Wcs.HoistSdk/Dto/HoistControl/HoistControlDto.cs
+++ b/Sln.Wcs.HoistSdk/Dto/HoistControl/HoistControlDto.cs
@@ -34,6 +34,11 @@ public class HoistControlDto
///
public string hoistCode { get; set; }
+ ///
+ /// 设备序号
+ ///
+ public int deviceSerialNo{get;set;}
+
///
/// 动作
///
diff --git a/Sln.Wcs.HoistSdk/Dto/HoistTaskExecutor/HoistTaskExeDto.cs b/Sln.Wcs.HoistSdk/Dto/HoistTaskExecutor/HoistTaskExeDto.cs
index 4d7d457..8e12def 100644
--- a/Sln.Wcs.HoistSdk/Dto/HoistTaskExecutor/HoistTaskExeDto.cs
+++ b/Sln.Wcs.HoistSdk/Dto/HoistTaskExecutor/HoistTaskExeDto.cs
@@ -37,6 +37,11 @@ public class HoistTaskExeDto
///
public string taskCode { get; set; }
+ ///
+ /// 设备序号
+ ///
+ public int deviceSerialNo{get;set;}
+
///
/// 起点
///
diff --git a/Sln.Wcs.HoistSdk/HoistSdk.cs b/Sln.Wcs.HoistSdk/HoistSdk.cs
index 08e8bce..ec3b48a 100644
--- a/Sln.Wcs.HoistSdk/HoistSdk.cs
+++ b/Sln.Wcs.HoistSdk/HoistSdk.cs
@@ -24,6 +24,7 @@
#endregion << 版 本 注 释 >>
using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using Sln.Wcs.HoistSdk.Config;
using Sln.Wcs.HoistSdk.Dto.GetHoistStatus;
using Sln.Wcs.HoistSdk.Dto.HoistControl;
@@ -50,8 +51,9 @@ public class HoistSdk:IHoistSdk
HoistControlResultDto result = new HoistControlResultDto();
try
{
+ string paramAddress = GetPlcParam(hoistControlDto.hoistCode,hoistControlDto.deviceSerialNo,"放置完成");
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)
{
result.code = "0";
@@ -73,7 +75,29 @@ public class HoistSdk:IHoistSdk
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)
@@ -97,18 +121,18 @@ public class HoistSdk:IHoistSdk
if (item.hostCode == hoistStatusDto.hoistCode)
{
- // var plc = _plcs.Where(x => x.ConfigKey.Equals(item.hostCode)).FirstOrDefault();
- // if (plc == null)
- // {
- // result.code = "99";
- // result.message = $"未找到PLC: {item.hostCode}";
- // result.hoistCode = hoistStatusDto.hoistCode;
- // return result;
- // }
- //
+ var plc = _plcs.Where(x => x.ConfigKey.Equals(item.hostCode)).FirstOrDefault();
+ if (plc == null)
+ {
+ result.code = "99";
+ result.message = $"未找到PLC: {item.hostCode}";
+ result.hoistCode = hoistStatusDto.hoistCode;
+ return result;
+ }
+
foreach (var param in item.deviceParams)
{
- //int value = plc.readInt16ByAddress(param.paramAddress);
+ int value = plc.readInt16ByAddress(param.paramAddress);
param.paramValue = param.objId;
@@ -138,5 +162,20 @@ public class HoistSdk:IHoistSdk
}
return result;
}
+
+ private string GetPlcParam(string hostCode,int deviceSerialNo,string paramName)
+ {
+ List paramStr = JsonConvert.DeserializeObject>(_hoistConfig.hoist_plc_param);
+
+ dynamic deviceInfo = paramStr.Where(x => x.hostCode == hostCode && x.deviceSerialNo == deviceSerialNo)
+ .FirstOrDefault();
+
+ List deviceParams = (deviceInfo.deviceParams as JArray)?.ToObject>();
+
+ dynamic deviceParam = deviceParams
+ .Where(x => ((string)x.paramName).Contains(paramName) && (int)x.operationType == 2).FirstOrDefault();
+
+ return deviceParam.paramAddress;
+ }
}
\ No newline at end of file
diff --git a/Sln.Wcs.Model/Domain/BaseDeviceInfo.cs b/Sln.Wcs.Model/Domain/BaseDeviceInfo.cs
index c786aca..f6b50a2 100644
--- a/Sln.Wcs.Model/Domain/BaseDeviceInfo.cs
+++ b/Sln.Wcs.Model/Domain/BaseDeviceInfo.cs
@@ -60,12 +60,16 @@ namespace Sln.Wcs.Model.Domain
public string deviceName { get; set; }
///
- /// Desc:主机编号
- /// Default:
- /// Nullable:False
+ /// 设备别名
///
- [SugarColumn(ColumnName = "host_code")]
- public string hostCode { get; set; }
+ [SugarColumn(ColumnName = "device_alias")]
+ public string deviceAlias { get; set; }
+
+ ///
+ /// 设备序号
+ ///
+ [SugarColumn(ColumnName = "device_serialNo")]
+ public int deviceSerialNo { get; set; }
///
/// Desc:设备类型:0-输送线;1-AGV;2-提升机
@@ -82,6 +86,14 @@ namespace Sln.Wcs.Model.Domain
///
[SugarColumn(ColumnName = "device_status")]
public int? deviceStatus { get; set; }
+
+ ///
+ /// Desc:主机编号
+ /// Default:
+ /// Nullable:False
+ ///
+ [SugarColumn(ColumnName = "host_code")]
+ public string hostCode { get; set; }
///
/// Desc:是否标识:1-是;0-否
diff --git a/Sln.Wcs.Repository/service/Impl/BaseDeviceInfoServiceImpl.cs b/Sln.Wcs.Repository/service/Impl/BaseDeviceInfoServiceImpl.cs
index 60b1343..f1062ed 100644
--- a/Sln.Wcs.Repository/service/Impl/BaseDeviceInfoServiceImpl.cs
+++ b/Sln.Wcs.Repository/service/Impl/BaseDeviceInfoServiceImpl.cs
@@ -52,6 +52,8 @@ namespace Sln.Wcs.Repository.service.Impl
deviceName = device.deviceName,
deviceType = device.deviceType,
deviceStatus = device.deviceStatus,
+ deviceSerialNo = device.deviceSerialNo,
+ deviceAlias = device.deviceAlias,
hostCode = device.hostCode,
isFlag = device.isFlag,
remark = device.remark,
diff --git a/Sln.Wcs/Program.cs b/Sln.Wcs/Program.cs
index a400623..20e9500 100644
--- a/Sln.Wcs/Program.cs
+++ b/Sln.Wcs/Program.cs
@@ -13,8 +13,11 @@ using Sln.Wcs.HikRoBotAdapter.Domain.Dto.GenAgvSchedulingTask;
using Sln.Wcs.HikRoBotAdapter.Service;
using Sln.Wcs.HikRoBotAdapter.Service.Impl;
using Sln.Wcs.HoistAdapter.Service;
+using Sln.Wcs.HoistDispatcher;
using Sln.Wcs.HoistSdk;
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.Repository;
using Sln.Wcs.Repository.service;
@@ -70,9 +73,6 @@ namespace Sln.Wcs
// }
// });
- var service = serviceProvider.GetService();
- service.Run(string.Empty,"tagCode",1,2);
-
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.HikRoBotSdk.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.Plc.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.HoistDispatcher.dll")),
};
services.Scan(scan => scan.FromAssemblies(assemblies)