From 1515ffa15c11e106f35e1447bc990b7867c449bb Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期四, 16 四月 2026 16:07:14 +0800
Subject: [PATCH] feat(Robot): 机械手换盘任务特殊处理
---
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs | 254 ++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 230 insertions(+), 24 deletions(-)
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
index 56ea0ab..9eb7830 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
@@ -1,4 +1,4 @@
-锘縰sing System.Net.Sockets;
+using System.Net.Sockets;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_DTO.TaskInfo;
@@ -9,76 +9,200 @@
namespace WIDESEAWCS_Tasks.Workflow
{
/// <summary>
- /// 鍓嶇紑鍛戒护澶勭悊锛氳縼绉诲師 RobotMessageHandler 鐨� pickfinished/putfinished 鍒嗘敮銆�
+ /// 鍓嶇紑鍛戒护澶勭悊鍣�
/// </summary>
+ /// <remarks>
+ /// 杩佺Щ鍘� RobotMessageHandler 鐨� pickfinished/putfinished 鍒嗘敮銆�
+ ///
+ /// 鍓嶇紑鍛戒护鏄寚浠ョ壒瀹氬墠缂�寮�澶寸殑鍛戒护锛屽悗闈㈣窡闅忛�楀彿鍒嗛殧鐨勫弬鏁般��
+ /// 鏍煎紡锛歿鍓嶇紑},{鍙傛暟1},{鍙傛暟2},...
+ ///
+ /// 褰撳墠鏀寔鐨勫墠缂�鍛戒护锛�
+ /// - pickfinished: 鍙栬揣瀹屾垚锛屽悗闈㈣窡闅忓畬鎴愮殑浣嶇疆缂栧彿鍒楄〃
+ /// - putfinished: 鏀捐揣瀹屾垚锛屽悗闈㈣窡闅忓畬鎴愮殑浣嶇疆缂栧彿鍒楄〃
+ ///
+ /// 杩欎簺鍛戒护閫氬父鍖呭惈鍙栬揣鎴栨斁璐х殑浣嶇疆淇℃伅锛岄渶瑕佽В鏋愬苟鏇存柊鐘舵�併��
+ /// </remarks>
public class RobotPrefixCommandHandler : IRobotPrefixCommandHandler
{
+ /// <summary>
+ /// 鏈哄櫒浜轰换鍔℃湇鍔�
+ /// </summary>
+ /// <remarks>
+ /// 鐢ㄤ簬鏌ヨ鍜屾洿鏂颁换鍔¤褰曘��
+ /// </remarks>
private readonly IRobotTaskService _robotTaskService;
+
+ /// <summary>
+ /// 浠诲姟澶勭悊鍣�
+ /// </summary>
+ /// <remarks>
+ /// 鐢ㄤ簬澶勭悊鍙栬揣/鏀捐揣瀹屾垚鏃剁殑涓氬姟閫昏緫锛屽璋冪敤鎷嗙洏/缁勭洏 API銆�
+ /// </remarks>
private readonly RobotTaskProcessor _taskProcessor;
+
+ /// <summary>
+ /// 鐘舵�佺鐞嗗櫒
+ /// </summary>
+ /// <remarks>
+ /// 鐢ㄤ簬瀹夊叏鏇存柊鏈哄櫒浜虹殑鐘舵�併��
+ /// </remarks>
private readonly RobotStateManager _stateManager;
+
+ /// <summary>
+ /// Socket 缃戝叧
+ /// </summary>
+ /// <remarks>
+ /// 鐢ㄤ簬鍚戝鎴风鍙戦�佸搷搴旀秷鎭��
+ /// </remarks>
private readonly ISocketClientGateway _socketClientGateway;
+ /// <summary>
+ /// 鍋囩數鑺綅缃湇鍔�
+ /// </summary>
+ /// <remarks>
+ /// 鐢ㄤ簬閲婃斁鍋囩數鑺偣浣嶃��
+ /// </remarks>
+ private readonly IFakeBatteryPositionService _fakeBatteryPositionService;
+
+ /// <summary>
+ /// 鏋勯�犲嚱鏁�
+ /// </summary>
+ /// <param name="robotTaskService">浠诲姟鏈嶅姟</param>
+ /// <param name="taskProcessor">浠诲姟澶勭悊鍣�</param>
+ /// <param name="stateManager">鐘舵�佺鐞嗗櫒</param>
+ /// <param name="socketClientGateway">Socket 缃戝叧</param>
+ /// <param name="fakeBatteryPositionService">鍋囩數鑺綅缃湇鍔�</param>
public RobotPrefixCommandHandler(
IRobotTaskService robotTaskService,
RobotTaskProcessor taskProcessor,
RobotStateManager stateManager,
- ISocketClientGateway socketClientGateway)
+ ISocketClientGateway socketClientGateway,
+ IFakeBatteryPositionService fakeBatteryPositionService)
{
_robotTaskService = robotTaskService;
_taskProcessor = taskProcessor;
_stateManager = stateManager;
_socketClientGateway = socketClientGateway;
+ _fakeBatteryPositionService = fakeBatteryPositionService;
}
+ /// <summary>
+ /// 妫�鏌ユ秷鎭槸鍚︿负鍓嶇紑鍛戒护
+ /// </summary>
+ /// <remarks>
+ /// 鍓嶇紑鍛戒护蹇呴』浠� "pickfinished" 鎴� "putfinished" 寮�澶达紙涓嶅尯鍒嗗ぇ灏忓啓锛夈��
+ /// </remarks>
+ /// <param name="message">娑堟伅鍐呭锛堝皬鍐欏舰寮忥級</param>
+ /// <returns>濡傛灉鏄寚缂�鍛戒护杩斿洖 true</returns>
public bool IsPrefixCommand(string message)
{
+ // 妫�鏌ユ秷鎭槸鍚︿互 pickfinished 鎴� putfinished 寮�澶�
return message.StartsWith("pickfinished") || message.StartsWith("putfinished");
}
+ /// <summary>
+ /// 澶勭悊鍓嶇紑鍛戒护
+ /// </summary>
+ /// <remarks>
+ /// 澶勭悊娴佺▼锛�
+ /// 1. 瑙f瀽娑堟伅锛屾彁鍙栦綅缃弬鏁�
+ /// 2. 鏌ヨ褰撳墠浠诲姟
+ /// 3. 鏍规嵁鍛戒护绫诲瀷璋冪敤鐩稿簲鐨勫鐞嗘柟娉�
+ /// 4. 鍥炲啓鍘熸秷鎭埌瀹㈡埛绔�
+ ///
+ /// 娑堟伅鏍煎紡锛歿鍛戒护鍓嶇紑},{浣嶇疆1},{浣嶇疆2},...
+ /// 绀轰緥锛歱ickfinished,1,2,3 琛ㄧず鍙栬揣瀹屾垚锛屼綅缃� 1銆�2銆�3 鐨勮揣鐗╁凡鍙栬蛋
+ /// </remarks>
+ /// <param name="message">鍘熷娑堟伅鍐呭</param>
+ /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+ /// <param name="client">TCP 瀹㈡埛绔繛鎺ワ紝鐢ㄤ簬鍙戦�佸搷搴�</param>
public async Task HandleAsync(string message, RobotSocketState state, TcpClient client)
{
try
{
+ // 鎸夐�楀彿鍒嗛殧娑堟伅锛屾彁鍙栧懡浠ゅ拰鍙傛暟
+ // 渚嬪锛歱ickfinished,1,2,3 -> ["pickfinished", "1", "2", "3"]
var parts = message.Split(',');
+
+ // 妫�鏌ユ秷鎭牸寮忔槸鍚︽湁鏁堬細鑷冲皯瑕佹湁鍛戒护鍓嶇紑锛屼笖鐘舵�佷腑鏈夊綋鍓嶄换鍔�
if (parts.Length < 1 || state.CurrentTask == null)
{
return;
}
+ // 鎻愬彇鍛戒护鍓嶇紑骞惰浆鎹负灏忓啓
var cmd = parts[0].ToLowerInvariant();
+
+ // 瑙f瀽浣嶇疆鍙傛暟锛堣烦杩囧懡浠ゅ墠缂�锛屽鐞嗗悗闈㈢殑鏁板瓧锛�
+ // 杩囨护鎺夋棤娉曡В鏋愪负鏁板瓧鎴栧�间负 0 鐨勪綅缃�
int[] positions = parts.Skip(1)
- .Select(p => int.TryParse(p, out int value) ? value : (int?)null)
- .Where(v => v.HasValue && v.Value != 0)
- .Select(v => v!.Value)
+ .Select(p => int.TryParse(p, out int value) ? value : (int?)null) // 灏濊瘯瑙f瀽涓烘暣鏁�
+ .Where(v => v.HasValue && v.Value != 0) // 杩囨护鎺� null 鍜� 0
+ .Select(v => v!.Value) // 鎻愬彇鍊硷紙宸茬煡闈� null锛�
.ToArray();
+ // 浠庢暟鎹簱閲嶆柊鏌ヨ褰撳墠浠诲姟锛堢‘淇濊幏鍙栨渶鏂扮姸鎬侊級
var task = await _robotTaskService.Repository.QueryFirstAsync(x => x.RobotTaskId == state.CurrentTask.RobotTaskId);
+ // 鏍规嵁鍛戒护鍓嶇紑鍒嗗彂澶勭悊
if (cmd.StartsWith("pickfinished"))
{
+ // 澶勭悊鍙栬揣瀹屾垚
await HandlePickFinishedAsync(state, positions, task);
}
else if (cmd.StartsWith("putfinished"))
{
+ // 澶勭悊鏀捐揣瀹屾垚
await HandlePutFinishedAsync(state, positions, task);
}
+ // 鍥炲啓鍘熸秷鎭埌瀹㈡埛绔紙淇濇寔鍘熸湁琛屼负锛�
await _socketClientGateway.SendMessageAsync(client, message);
}
catch (Exception ex)
{
+ // 鎹曡幏骞惰褰曞紓甯革紝闃叉寮傚父鍚戜笂浼犳挱瀵艰嚧娑堟伅澶勭悊涓柇
Console.WriteLine($"RobotJob MessageReceived Error: {ex.Message}");
}
}
+ /// <summary>
+ /// 澶勭悊鍙栬揣瀹屾垚锛坧ickfinished锛夊懡浠�
+ /// </summary>
+ /// <remarks>
+ /// 澶勭悊閫昏緫锛�
+ /// 1. 濡傛灉鏄媶鐩樹换鍔★紝鏋勫缓搴撳瓨 DTO 骞惰皟鐢ㄦ媶鐩� API
+ /// 2. 鎹㈢洏浠诲姟 Phase3 鍙栧亣鐢佃姱鏃朵笉璋冪敤鎷嗙洏 API
+ /// 3. 鏇存柊褰撳墠鍔ㄤ綔涓�"鍙栬揣瀹屾垚"
+ /// 4. 璁板綍鍙栬揣瀹屾垚鐨勪綅缃�
+ /// 5. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜哄彇璐у畬鎴�"
+ /// 6. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
+ /// </remarks>
+ /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+ /// <param name="positions">鍙栬揣瀹屾垚鐨勪綅缃紪鍙锋暟缁�</param>
+ /// <param name="task">鏈哄櫒浜轰换鍔¤褰�</param>
private async Task HandlePickFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task)
{
- if (state.IsSplitPallet)
- {
- var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
- state.LastPickPositions = positions;
+ // 璁板綍鍙栬揣瀹屾垚鐨勪綅缃�
+ state.LastPickPositions = positions;
+ // 鎹㈢洏浠诲姟 Phase3 鍙栧亣鐢佃姱锛氫笉璋冪敤鎷嗙洏 API
+ if (state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()
+ && state.ChangePalletPhase == 3)
+ {
+ state.CurrentAction = "PickFinished";
+ }
+ // 鎷嗙洏浠诲姟
+ else if (state.IsSplitPallet)
+ {
+ // 鏋勫缓搴撳瓨 DTO锛屽寘鍚綅缃俊鎭拰鎵樼洏鏉$爜
+ var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+
+ // 璋冪敤鎷嗙洏 API
var result = _taskProcessor.PostSplitPalletAsync(stockDTO);
+
+ // 濡傛灉 API 璋冪敤鎴愬姛
if (result.Data.Status && result.IsSuccess)
{
state.CurrentAction = "PickFinished";
@@ -86,13 +210,17 @@
}
else
{
+ // 闈炴媶鐩樹换鍔★紝鐩存帴鏇存柊鍔ㄤ綔
state.CurrentAction = "PickFinished";
}
- state.LastPickPositions = positions;
+ // 濡傛灉浠诲姟瀛樺湪
if (task != null)
{
+ // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜哄彇璐у畬鎴�"
task.RobotTaskState = TaskRobotStatusEnum.RobotPickFinish.GetHashCode();
+
+ // 瀹夊叏鏇存柊鐘舵�佸埌 Redis锛岀‘淇濇洿鏂版垚鍔熷悗鍐嶆洿鏂版暟鎹簱
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
{
await _robotTaskService.Repository.UpdateDataAsync(task);
@@ -100,34 +228,112 @@
}
}
+ /// <summary>
+ /// 澶勭悊鏀捐揣瀹屾垚锛坧utfinished锛夊懡浠�
+ /// </summary>
+ /// <remarks>
+ /// 澶勭悊閫昏緫锛�
+ /// 1. 濡傛灉鏄粍鐩樹换鍔★紝鏋勫缓搴撳瓨 DTO 骞惰皟鐢ㄧ粍鐩�/鎹㈢洏 API
+ /// 2. 鎹㈢洏浠诲姟鏍规嵁闃舵鍖哄垎澶勭悊锛氭祦鍚慉 Phase2 涓嶈皟鐢� API锛涙祦鍚態 Phase2 姝e父璋冪敤锛汸hase4 璋冪敤 MarkAsAvailable
+ /// 3. 濡傛灉缁勭洏鎴愬姛锛屽鍔犱换鍔¤鏁�
+ /// 4. 鏇存柊褰撳墠鍔ㄤ綔涓�"鏀捐揣瀹屾垚"
+ /// 5. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘斁璐у畬鎴�"
+ /// 6. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
+ /// </remarks>
+ /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+ /// <param name="positions">鏀捐揣瀹屾垚鐨勪綅缃紪鍙锋暟缁�</param>
+ /// <param name="task">鏈哄櫒浜轰换鍔¤褰�</param>
private async Task HandlePutFinishedAsync(RobotSocketState state, int[] positions, Dt_RobotTask? task)
{
+ // 鍋囪鏀捐揣鎴愬姛锛堝鏋滃悗缁� API 璋冪敤澶辫触涔熶笉鍥為��璁℃暟锛�
bool putSuccess = true;
+
+ // 濡傛灉鏄粍鐩樹换鍔★紙鍖呭惈鎹㈢洏锛�
if (state.IsGroupPallet)
{
+ // 璁板綍鏀捐揣瀹屾垚鐨勪綅缃�
state.LastPutPositions = positions;
- var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
- var configKey = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()
- ? nameof(ConfigKey.ChangePalletAsync)
- : nameof(ConfigKey.GroupPalletAsync);
- var result = _taskProcessor.PostGroupPalletAsync(configKey, stockDTO);
- putSuccess = result.Data.Status && result.IsSuccess;
- }
+ // 鍒ゆ柇鏄惁涓烘崲鐩樹换鍔�
+ var isChangePallet = state.CurrentTask?.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode();
+ var isFlowA = state.CurrentTask?.RobotSourceAddressLineCode is "11001" or "11010";
- if (putSuccess)
- {
- state.CurrentAction = "PutFinished";
- state.RobotTaskTotalNum += positions.Length;
- if (task != null)
+ if (isChangePallet)
{
- task.RobotTaskTotalNum += positions.Length;
+ // 鎹㈢洏浠诲姟锛氭牴鎹樁娈靛尯鍒嗗鐞�
+ if (state.ChangePalletPhase == 2)
+ {
+ if (isFlowA)
+ {
+ // 娴佸悜A Phase2锛氭斁鍋囩數鑺埌鐩爣鎵樼洏锛屼笉璋冪敤 API锛屼笉閫掑璁℃暟
+ // 浠呮洿鏂扮姸鎬�
+ }
+ else
+ {
+ // 娴佸悜B Phase2锛氭斁姝e父鐢佃姱锛岄�掑璁℃暟
+ state.RobotTaskTotalNum += positions.Length;
+ if (task != null)
+ task.RobotTaskTotalNum -= positions.Length;
+
+ // 鏋勫缓搴撳瓨 DTO 骞惰皟鐢� ChangePalletAsync API
+ var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+ var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.ChangePalletAsync), stockDTO);
+ putSuccess = result.Data.Status && result.IsSuccess;
+ }
+ }
+ else if (state.ChangePalletPhase == 4)
+ {
+ // 娴佸悜B Phase4锛氭斁鍋囩數鑺埌5鍙蜂綅锛屼笉璋冪敤 API锛屼笉閫掑璁℃暟锛岄噴鏀剧偣浣�
+ _fakeBatteryPositionService.MarkAsAvailable(positions.ToList());
+ }
+ else
+ {
+ // 闈炴壒娆℃ā寮忥細姝e父閫掑璁℃暟骞惰皟鐢� API
+ state.RobotTaskTotalNum += positions.Length;
+ if (task != null)
+ task.RobotTaskTotalNum -= positions.Length;
+
+ var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+ var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.GroupPalletAsync), stockDTO);
+ putSuccess = result.Data.Status && result.IsSuccess;
+ }
+ }
+ else
+ {
+ // 缁勭洏浠诲姟锛氬師鏈夐�昏緫
+ var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
+ var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.GroupPalletAsync), stockDTO);
+ putSuccess = result.Data.Status && result.IsSuccess;
+
+ // 澧炲姞浠诲姟璁℃暟
+ state.RobotTaskTotalNum += positions.Length;
+ if (task != null)
+ task.RobotTaskTotalNum -= positions.Length;
}
}
+ // 濡傛灉鏀捐揣鎴愬姛
+ if (putSuccess)
+ {
+ // 鏇存柊褰撳墠鍔ㄤ綔涓�"鏀捐揣瀹屾垚"
+ state.CurrentAction = "PutFinished";
+
+ // 闈炵粍鐩樹换鍔℃椂澧炲姞璁℃暟锛堢粍鐩樹换鍔″凡鍦ㄤ笂闈㈤�掑锛�
+ if (!state.IsGroupPallet)
+ {
+ state.RobotTaskTotalNum += positions.Length;
+ if (task != null)
+ task.RobotTaskTotalNum -= positions.Length;
+ }
+ }
+
+ // 濡傛灉浠诲姟瀛樺湪
if (task != null)
{
+ // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘斁璐у畬鎴�"
task.RobotTaskState = TaskRobotStatusEnum.RobotPutFinish.GetHashCode();
+
+ // 瀹夊叏鏇存柊鐘舵�佸埌 Redis
if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
{
await _robotTaskService.Repository.UpdateDataAsync(task);
--
Gitblit v1.9.3