From 34ad8ad8e238d54d9695da9e8d101579c42516bb Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期六, 18 四月 2026 22:40:02 +0800
Subject: [PATCH] fix(RobotJob): 修正机器人任务处理逻辑和注释错误

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs |  290 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 219 insertions(+), 71 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
index e0211a5..978f7ee 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -5,6 +5,7 @@
 using WIDESEAWCS_Core.LogHelper;
 using WIDESEAWCS_ITaskInfoService;
 using WIDESEAWCS_Model.Models;
+using WIDESEAWCS_Tasks.SocketServer;
 using WIDESEAWCS_Tasks.Workflow.Abstractions;
 
 namespace WIDESEAWCS_Tasks.Workflow
@@ -111,7 +112,7 @@
             // 1. 杩愯妯″紡涓鸿嚜鍔紙2锛�
             // 2. 鎺у埗妯″紡涓哄鎴风鎺у埗锛�1锛�
             // 3. 杩愯鐘舵�佹槸 Running
-            if (latestState.RobotRunMode == 2 /*&& latestState.RobotControlMode == 1*/ && latestState.OperStatus == "Running" && latestState.Homed == "Homed")
+            if (latestState.RobotRunMode == 2 /*&& latestState.RobotControlMode == 1*/ && latestState.OperStatus == "Running" && (latestState.Homed == "Homed" || latestState.Homed.IsNullOrEmpty()))
             {
                 // ========== 鍙栬揣瀹屾垚鍚庣殑鏀捐揣澶勭悊 ==========
                 // 鏉′欢锛�
@@ -119,11 +120,11 @@
                 // - 鎵嬭噦涓婃湁鐗╂枡锛圧obotArmObject == 1锛�
                 // - 浠诲姟鐘舵�佷负 RobotPickFinish锛堝凡璁板綍鍙栬揣瀹屾垚锛�
                 if ((latestState.CurrentAction == "PickFinished" || latestState.CurrentAction == "AllPickFinished")
-                    && latestState.RobotArmObject == 1
+                    && (latestState.RobotArmObject.IsNullOrEmpty() || latestState.RobotArmObject == 1)
                     && task.RobotTaskState == TaskRobotStatusEnum.RobotPickFinish.GetHashCode())
                 {
-                    _logger.LogInformation("ExecuteAsync锛氭弧瓒虫斁璐ф潯浠讹紝寮�濮嬪鐞嗗彇璐у畬鎴愶紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                    QuartzLogger.Info($"ExecuteAsync锛氭弧瓒虫斁璐ф潯浠讹紝寮�濮嬪鐞嗗彇璐у畬鎴�", latestState.RobotCrane?.DeviceName ?? ipAddress);
+                    _logger.LogInformation("ExecuteAsync锛氭弧瓒虫斁璐ф潯浠讹紝寮�濮嬩笅鍙戞斁璐т换鍔★紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                    QuartzLogger.Info($"ExecuteAsync锛氭弧瓒虫斁璐ф潯浠讹紝寮�濮嬩笅鍙戞斁璐т换鍔�", latestState.RobotCrane?.DeviceName ?? ipAddress);
                     // 鍙戦�佹斁璐ф寚浠�
                     await HandlePickFinishedStateAsync(task, ipAddress);
                 }
@@ -135,12 +136,12 @@
                 // - 鎵嬭噦涓婃棤鐗╂枡锛圧obotArmObject == 0锛�
                 // - 浠诲姟鐘舵�佷负 RobotPutFinish 鎴栦笉鏄� RobotExecuting
                 else if ((latestState.CurrentAction == "PutFinished" || latestState.CurrentAction == "AllPutFinished" || latestState.CurrentAction.IsNullOrEmpty())
-                    && latestState.RobotArmObject == 0
+                    && (latestState.RobotArmObject.IsNullOrEmpty() || latestState.RobotArmObject == 0)
                     && (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode()
                     || task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode()))
                 {
-                    _logger.LogInformation("ExecuteAsync锛氭弧瓒冲彇璐ф潯浠讹紝寮�濮嬪鐞嗘斁璐у畬鎴愶紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                    QuartzLogger.Info($"ExecuteAsync锛氭弧瓒冲彇璐ф潯浠讹紝寮�濮嬪鐞嗘斁璐у畬鎴�", latestState.RobotCrane?.DeviceName ?? ipAddress);
+                    _logger.LogInformation("ExecuteAsync锛氭弧瓒冲彇璐ф潯浠讹紝寮�濮嬩笅鍙戝彇璐т换鍔★紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                    QuartzLogger.Info($"ExecuteAsync锛氭弧瓒冲彇璐ф潯浠讹紝寮�濮嬩笅鍙戝彇璐т换鍔�", latestState.RobotCrane?.DeviceName ?? ipAddress);
                     // 鍙戦�佸彇璐ф寚浠�
                     await HandlePutFinishedStateAsync(task, ipAddress);
                 }
@@ -152,7 +153,7 @@
         /// </summary>
         /// <remarks>
         /// 褰撳彇璐у畬鎴愬悗锛屽悜鏈哄櫒浜哄彂閫佹斁璐ф寚浠わ紙Putbattery锛夈��
-        /// 鏈哄櫒浜烘敹鍒版寚浠ゅ悗浼氬皢璐х墿鏀剧疆鍒扮洰鏍囧湴鍧�銆�
+        /// 鎹㈢洏浠诲姟浣跨敤鎵规鏍煎紡 SendPutWithBatchAsync銆�
         ///
         /// 鎸囦护鏍煎紡锛歅utbattery,{鐩爣鍦板潃}
         /// 渚嬪锛歅utbattery,B01 琛ㄧず灏嗚揣鐗╂斁缃埌 B01 浣嶇疆
@@ -161,38 +162,129 @@
         /// <param name="ipAddress">鏈哄櫒浜� IP 鍦板潃</param>
         private async Task HandlePickFinishedStateAsync(Dt_RobotTask task, string ipAddress)
         {
-            // 鏋勫缓鏀捐揣鎸囦护锛屾牸寮忥細Putbattery,{鐩爣鍦板潃}
-            string taskString = $"Putbattery,{task.RobotTargetAddress}";
+            string taskString;
 
-            // 閫氳繃瀹㈡埛绔鐞嗗櫒鍙戦�佹寚浠ゅ埌鏈哄櫒浜�
+            var state = _stateManager.GetState(ipAddress);
+
+            // 鎹㈢洏浠诲姟鎵规妯″紡
+            if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())
+            {
+                int targetNormalCount = task.RobotTaskTotalNum;
+                int currentCompletedCount = state?.RobotTaskTotalNum ?? 0;
+
+                bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
+
+                // ==================== Phase 2: 鏀炬甯哥數鑺埌鐩爣鎵樼洏锛堜袱娴佸悜鐩稿悓锛�====================
+                // PickFinished 鍒拌揪锛歅hase 1 鐨� Pick 鍛戒护瀹屾垚锛岀幇鍦ㄤ笅鍙� Put 鍛戒护鏀炬甯哥數鑺�
+                if (state?.ChangePalletPhase == 2)
+                {
+                    int remainingNormal = targetNormalCount - currentCompletedCount;
+                    if (remainingNormal <= 0)
+                    {
+                        // 姝e父鐢佃姱鍏ㄩ儴鏀惧畬锛岀瓑寰� HandlePutFinishedAsync 鍒囨崲鍒� Phase 3
+                        return;
+                    }
+
+                    int batchStart = (currentCompletedCount / 4) * 4 + 1;
+                    int putCount = Math.Min(4, remainingNormal);
+                    var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                    await _taskProcessor.SendPutWithBatchAsync(task, state, task.RobotTargetAddress, start, end);
+
+                    // Phase 淇濇寔涓� 2锛岀瓑 HandlePutFinishedAsync 澶勭悊瀹屾斁璐ц鏁板悗鍐嶅垏鍥� Phase 1
+                    _stateManager.TryUpdateStateSafely(ipAddress, state);
+                    return;
+                }
+
+                // ==================== Phase 4: 鏀惧亣鐢佃姱锛堜袱娴佸悜鍒嗗弶锛�====================
+                // PickFinished 鍒拌揪锛歅hase 3 鐨� Pick 鍛戒护瀹屾垚锛岀幇鍦ㄤ笅鍙� Put 鍛戒护鏀惧亣鐢佃姱
+                if (state?.ChangePalletPhase == 4)
+                {
+                    int fakeCount = 48 - targetNormalCount;
+                    int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                    int remainingFake = fakeCount - completedFake;
+
+                    if (remainingFake <= 0)
+                    {
+                        // 鍋囩數鑺叏閮ㄦ斁瀹岋紝绛夊緟 allputfinished 瑙﹀彂 Phase 5 鍏ュ簱
+                        return;
+                    }
+
+                    if (isFlowA)
+                    {
+                        // 娴佸悜A锛氭斁鍋囩數鑺埌鐩爣鎵樼洏
+                        int batchStart = targetNormalCount + 1 + (state.CurrentBatchIndex - 1);
+                        int putCount = Math.Min(4, remainingFake);
+                        var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount);
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, state, task.RobotTargetAddress, start, end);
+
+                        state.CurrentBatchIndex += putCount;
+                        // Phase 淇濇寔涓� 4锛岀瓑 HandlePutFinishedAsync 澶勭悊瀹屽悗鍐嶅垏鍥� Phase 3
+                        _stateManager.TryUpdateStateSafely(ipAddress, state);
+                    }
+                    else
+                    {
+                        // 娴佸悜B锛氭斁鍋囩數鑺埌5鍙蜂綅
+                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
+                        if (positions.Count == 0)
+                        {
+                            _logger.LogError("HandlePickFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                            return;
+                        }
+
+                        int start = positions.Min();
+                        int end = positions.Max();
+
+                        await _taskProcessor.SendPutWithBatchAsync(task, state, "5", start, end);
+
+                        // Phase 淇濇寔涓� 4锛岀瓑 HandlePutFinishedAsync 澶勭悊瀹屽悗鍐嶅垏鍥� Phase 3
+                        _stateManager.TryUpdateStateSafely(ipAddress, state);
+                    }
+                    return;
+                }
+
+                // 闈炴壒娆℃ā寮忔垨鍏朵粬闃舵涓嶄笅鍙戞寚浠�
+                return;
+            }
+
+            // 闈炴崲鐩樹换鍔★細浣跨敤鍘熸湁鏍煎紡
+            if (state != null && state.IsGroupPallet && task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode())
+            {
+                if (state.IsScanNG)
+                {
+                    taskString = $"Putbattery,1";
+                }
+                else
+                {
+                    taskString = $"Putbattery,{task.RobotTargetAddress}";
+                }
+            }
+            else
+                taskString = $"Putbattery,{task.RobotTargetAddress}";
+
             bool result = await _clientManager.SendToClientAsync(ipAddress, taskString);
 
             if (result)
             {
-                // 鍙戦�佹垚鍔燂紝璁板綍 Info 鏃ュ織
                 _logger.LogInformation("HandlePickFinishedStateAsync锛氫笅鍙戞斁璐ф寚浠ゆ垚鍔燂紝鎸囦护: {TaskString}锛屼换鍔″彿: {TaskNum}", taskString, task.RobotTaskNum);
                 QuartzLogger.Info($"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}", task.RobotRoadway);
 
-                // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
                 task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
 
-                // 鑾峰彇鏈�鏂扮姸鎬佸苟鏇存柊浠诲姟鍏宠仈
                 var stateToUpdate = _stateManager.GetState(ipAddress);
                 if (stateToUpdate != null)
                 {
                     stateToUpdate.CurrentTask = task;
 
-                    // 瀹夊叏鏇存柊鐘舵�佸埌 Redis
                     if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate))
                     {
-                        // 鐘舵�佹洿鏂版垚鍔熷悗锛屾洿鏂颁换鍔¤褰�
                         await _robotTaskService.UpdateRobotTaskAsync(task);
                     }
                 }
             }
             else
             {
-                // 鍙戦�佸け璐ワ紝璁板綍 Error 鏃ュ織
                 _logger.LogError("HandlePickFinishedStateAsync锛氫笅鍙戞斁璐ф寚浠ゅけ璐ワ紝鎸囦护: {TaskString}锛屼换鍔″彿: {TaskNum}", taskString, task.RobotTaskNum);
                 QuartzLogger.Error($"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}", task.RobotRoadway);
             }
@@ -240,106 +332,162 @@
             // 濡傛灉鏄粍鐩樹换鍔�
             if (task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode())
             {
-                // 鐢熸垚鎵樼洏鏉$爜鍓嶇紑
-                const string prefix = "TRAY";
-
-                // 鐢熸垚涓や釜鎵樼洏鏉$爜锛堢敤浜庣粍鐩樻搷浣滐級锛堟祴璇曠敤锛屽悗缁鍙栫嚎浣撴潯鐮侊級
-                string trayBarcode1 = RobotBarcodeGenerator.GenerateTrayBarcode(prefix);
-                string trayBarcode2 = RobotBarcodeGenerator.GenerateTrayBarcode(prefix);
+                // 妫�鏌ョ數姹犳槸鍚﹀凡鍒颁綅
+                if (!stateForUpdate.BatteryArrived)
+                {
+                    return;
+                }
+                // 璇诲彇绾夸綋鐢佃姱鏉$爜
+                string trayBarcode1 = RobotBarcodeGenerator.GenerateTrayBarcode("DB40.990");
+                string trayBarcode2 = RobotBarcodeGenerator.GenerateTrayBarcode("DB40.1020");
 
                 // 濡傛灉鏉$爜鐢熸垚鎴愬姛
                 if (!string.IsNullOrEmpty(trayBarcode1) && !string.IsNullOrEmpty(trayBarcode2))
                 {
-                    if(stateForUpdate.CellBarcode.Contains(trayBarcode1)|| stateForUpdate.CellBarcode.Contains(trayBarcode2))
+                    if (stateForUpdate.CellBarcode.Contains(trayBarcode1) || stateForUpdate.CellBarcode.Contains(trayBarcode2))
                     {
-                        _logger.LogError("HandlePutFinishedStateAsync锛氱敓鎴愮殑鎵樼洏鏉$爜宸插瓨鍦紝鍙兘瀛樺湪閲嶅锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
-                        QuartzLogger.Error($"鐢熸垚鐨勬墭鐩樻潯鐮佸凡瀛樺湪锛屽彲鑳藉瓨鍦ㄩ噸澶�", stateForUpdate.RobotCrane.DeviceName);
+                        _logger.LogError("HandlePutFinishedStateAsync锛氳鍙栫殑鎵樼洏鏉$爜宸插瓨鍦紝鍙兘瀛樺湪閲嶅锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                        QuartzLogger.Error($"璇诲彇鐨勬墭鐩樻潯鐮佸凡瀛樺湪锛屽彲鑳藉瓨鍦ㄩ噸澶�", stateForUpdate.RobotCrane.DeviceName);
 
                         // 鏉$爜閲嶅锛岃褰曢敊璇棩蹇楀苟鍋滄鍚庣画鎿嶄綔(鍚庣画鏀捐揣鏃朵細鐢ㄥ埌杩欎簺鏉$爜淇℃伅锛屼緵鍚庣画鏀捐揣鏃朵娇鐢紝璋冭瘯鍚庡彲鑳戒細鍙栨秷姝ら�昏緫)
+
+                        // 鍙戦�佸彇璐ф寚浠� 鏍囪鎵爜NG锛屾斁璐ф椂涓嶄娇鐢ㄨ繖浜涙潯鐮侊紝骞舵斁鍏G鍙�
+                        await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true);
                         return;
                     }
                     else
                     {
-                        _logger.LogInformation("HandlePutFinishedStateAsync锛氱敓鎴愮殑鎵樼洏鏉$爜鍞竴锛岀户缁墽琛岋紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                        QuartzLogger.Info($"鐢熸垚鐨勬墭鐩樻潯鐮佸敮涓�锛岀户缁墽琛�", stateForUpdate.RobotCrane.DeviceName);
+                        _logger.LogInformation("HandlePutFinishedStateAsync锛氳鍙栫殑鎵樼洏鏉$爜鍞竴锛岀户缁墽琛岋紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                        QuartzLogger.Info($"璇诲彇鐨勬墭鐩樻潯鐮佸敮涓�锛岀户缁墽琛�", stateForUpdate.RobotCrane.DeviceName);
+
                         // 灏嗘潯鐮佹坊鍔犲埌鐘舵�佷腑锛屼緵鍚庣画鏀捐揣鏃朵娇鐢�
-                        stateForUpdate.CellBarcode.Add(trayBarcode1);
-                        stateForUpdate.CellBarcode.Add(trayBarcode2);
+                        stateForUpdate.CellBarcode = new List<string>()
+                        {
+                            trayBarcode1,trayBarcode2
+                        };
                     }
 
 
-                    // 璁板綍鏃ュ織锛氱敓鎴愭墭鐩樻潯鐮佹垚鍔�
-                    _logger.LogInformation("HandlePutFinishedStateAsync锛氱敓鎴愭墭鐩樻潯鐮佹垚鍔�: {Barcode1}+{Barcode2}锛屼换鍔″彿: {TaskNum}", trayBarcode1, trayBarcode2, task.RobotTaskNum);
-                    QuartzLogger.Info($"鐢熸垚鎵樼洏鏉$爜鎴愬姛: {trayBarcode1}+{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName);
+                    // 璁板綍鏃ュ織锛氳鍙栨墭鐩樻潯鐮佹垚鍔�
+                    _logger.LogInformation("HandlePutFinishedStateAsync锛氳鍙栨墭鐩樻潯鐮佹垚鍔�: {Barcode1}+{Barcode2}锛屼换鍔″彿: {TaskNum}", trayBarcode1, trayBarcode2, task.RobotTaskNum);
+                    QuartzLogger.Info($"璇诲彇鎵樼洏鏉$爜鎴愬姛: {trayBarcode1}+{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName);
 
                     // 鍙戦�佸彇璐ф寚浠�
                     await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
                 }
                 else
                 {
-                    // 鏉$爜鐢熸垚澶辫触锛岃褰曢敊璇棩蹇�
-                    _logger.LogError("HandlePutFinishedStateAsync锛氱敓鎴愭墭鐩樻潯鐮佸け璐ワ紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                    QuartzLogger.Error($"鐢熸垚鎵樼洏鏉$爜澶辫触", stateForUpdate.RobotCrane.DeviceName);
+                    // 鏉$爜璇诲彇澶辫触锛岃褰曢敊璇棩蹇�
+                    _logger.LogError("HandlePutFinishedStateAsync锛氳鍙栨墭鐩樻潯鐮佸け璐ワ紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
+                    QuartzLogger.Error($"璇诲彇鎵樼洏鏉$爜澶辫触", stateForUpdate.RobotCrane.DeviceName);
+
+
+                    // 鍙戦�佸彇璐ф寚浠� 鏍囪鎵爜NG锛屾斁璐ф椂涓嶄娇鐢ㄨ繖浜涙潯鐮侊紝骞舵斁鍏G鍙�
+                    await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true);
+                    return;
                 }
             }
             else if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode())
             {
-                // 鎹㈢洏浠诲姟
-                // 鐩爣锛氭甯哥數鑺姄鍙栧畬鎴愬悗锛岃ˉ鍏呭亣鐢佃姱鑷�48涓�
                 const int targetTotal = 48;
-                const int fakeBatteryPickPosition = 5;  // 鍋囩數鑺姄鍙栦綅缃�
-                const int pickCountPerExecution = 4;     // 姣忔鎶撳彇鏁伴噺
+                // 鎹㈢洏浠诲姟杩涘叆鎵规妯″紡锛屽垎闃舵澶勭悊姝e父鐢佃姱鍜屽亣鐢佃姱 锛堟満鍣ㄤ汉浠诲姟鎬绘暟锛�
+                int targetNormalCount = task.RobotTaskTotalNum;
+                // 褰撳墠宸插畬鎴愭暟閲忥紙鍙栬揣瀹屾垚鐨勬暟閲忥級锛屽垵濮嬩负鐘舵�佷腑鐨� RobotTaskTotalNum锛屽悗缁牴鎹彇璐у畬鎴愮殑鏁伴噺鍔ㄦ�佹洿鏂�
+                int currentCompletedCount = stateForUpdate.RobotTaskTotalNum;
 
-                int targetNormalCount = task.RobotTaskTotalNum;  // 姝e父鐢佃姱鐩爣鏁伴噺
-                int currentCompletedCount = stateForUpdate.RobotTaskTotalNum;  // 宸插畬鎴愭暟閲�
+                // 鍒ゆ柇娴佸悜锛坣ull-safe锛�
+                bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
 
-                // 濡傛灉鐩爣鏁伴噺涓�48锛岀洿鎺ヤ笅鍙戞甯镐换鍔�
+                // 鐩爣鏁伴噺涓�48锛氱洿鎺ヨ蛋鍘熸湁閫昏緫锛屼笉杩涘叆鎵规妯″紡
                 if (targetNormalCount == targetTotal)
                 {
                     await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
-                }
-                // 濡傛灉宸插畬鎴愭暟閲忓皬浜庣洰鏍囨暟閲忥紝缁х画鎶撳彇姝e父鐢佃姱
-                else if (currentCompletedCount < targetNormalCount)
-                {
-                    await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
-                }
-                // 姝e父鐢佃姱宸插畬鎴愶紝杩涘叆鍋囩數鑺ˉ鍏呮ā寮�
-                else if (currentCompletedCount == targetNormalCount && !stateForUpdate.IsInFakeBatteryMode)
-                {
-                    // 棣栨杩涘叆鍋囩數鑺ā寮忥紝璁剧疆鏍囧織
-                    stateForUpdate.IsInFakeBatteryMode = true;
-                    _logger.LogInformation("HandlePutFinishedStateAsync锛氭甯哥數鑺姄鍙栧畬鎴愶紝杩涘叆鍋囩數鑺ˉ鍏呮ā寮忥紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                    QuartzLogger.Info($"姝e父鐢佃姱鎶撳彇瀹屾垚锛岃繘鍏ュ亣鐢佃姱琛ュ厖妯″紡", stateForUpdate.RobotCrane?.DeviceName);
+                    return;
                 }
 
-                // 濡傛灉澶勪簬鍋囩數鑺ˉ鍏呮ā寮忥紝璁$畻骞朵笅鍙戣ˉ鏁颁换鍔�
-                if (stateForUpdate.IsInFakeBatteryMode)
+                // 鍒濆鍖栨壒娆℃ā寮�
+                if (stateForUpdate.ChangePalletPhase == 0)
                 {
-                    int remaining = targetTotal - currentCompletedCount;
-                    if (remaining > 0)
+                    stateForUpdate.ChangePalletPhase = 1;
+                    stateForUpdate.CurrentBatchIndex = 1;
+                    _logger.LogInformation("HandlePutFinishedStateAsync锛氭崲鐩樹换鍔¤繘鍏ユ壒娆℃ā寮忥紝浠诲姟鍙�: {TaskNum}锛屾祦鍚�: {Flow}",
+                        task.RobotTaskNum, isFlowA ? "A" : "B");
+                    _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
+                }
+
+                // ==================== Phase 1: 鍙栨甯哥數鑺紙涓ゆ祦鍚戠浉鍚岋級====================
+                if (stateForUpdate.ChangePalletPhase == 1)
+                {
+                    int remainingNormal = targetNormalCount - currentCompletedCount;
+                    if (remainingNormal <= 0)
                     {
-                        // 璁$畻姣忔鎶撳彇鐨勬暟閲忥紙鏈�澶�4涓級
-                        int pickCount = Math.Min(pickCountPerExecution, remaining);
+                        // 姝e父鐢佃姱鍙栧畬锛屽垏鎹㈠埌 Phase 3 鍙栧亣鐢佃姱
+                        stateForUpdate.ChangePalletPhase = 3;
+                        stateForUpdate.CurrentBatchIndex = 1; // 鍋囩數鑺壒娆′粠澶村紑濮�
+                        _logger.LogInformation("HandlePutFinishedStateAsync锛氭甯哥數鑺彇瀹岋紝鍒囨崲鍒癙hase 3鍙栧亣鐢佃姱锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                        _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
+                        return;
+                    }
 
-                        // 鑾峰彇鍙敤鐨勫亣鐢佃姱骞抽潰鐐逛綅
-                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(pickCount);
+                    int pickCount = Math.Min(4, remainingNormal);
+                    var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount);
+
+                    await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end);
+
+                    stateForUpdate.CurrentBatchIndex += pickCount;
+                    // 鍙戝畬 Pick 鍚庡垏鎹㈠埌 Phase=2锛岀瓑 PickFinished 瑙﹀彂 HandlePickFinishedStateAsync 涓嬪彂鏀捐揣鎸囦护
+                    stateForUpdate.ChangePalletPhase = 2;
+                    _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
+                    return;
+                }
+
+                // ==================== Phase 3: 澶勭悊鍋囩數鑺紙娴佸悜A/B 鍒嗗弶锛夛紝鑷繁寰幆 ====================
+                if (stateForUpdate.ChangePalletPhase == 3)
+                {
+                    int fakeCount = targetTotal - targetNormalCount;
+                    int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount);
+                    int remainingFake = fakeCount - completedFake;
+
+                    if (remainingFake <= 0)
+                    {
+                        // 鍋囩數鑺叏閮ㄥ鐞嗗畬锛屽垏鎹㈠埌 Phase 5 绛夊緟鍏ュ簱
+                        stateForUpdate.ChangePalletPhase = 5;
+                        _logger.LogInformation("HandlePutFinishedStateAsync锛氬亣鐢佃姱澶勭悊瀹屾瘯锛屽垏鎹㈠埌Phase 5绛夊緟鍏ュ簱锛屼换鍔″彿: {TaskNum}", task.RobotTaskNum);
+                        _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
+                        return;
+                    }
+
+                    if (isFlowA)
+                    {
+                        // 娴佸悜A锛氫粠5鍙蜂綅鍙栧亣鐢佃姱
+                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
                         if (positions.Count == 0)
                         {
                             _logger.LogError("HandlePutFinishedStateAsync锛氭棤鍙敤鍋囩數鑺偣浣嶏紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                            QuartzLogger.Error($"鏃犲彲鐢ㄥ亣鐢佃姱鐐逛綅", stateForUpdate.RobotCrane?.DeviceName);
                             return;
                         }
-
-                        // 涓嬪彂鍋囩數鑺彇璐ф寚浠�
                         await _taskProcessor.SendSocketRobotFakeBatteryPickAsync(task, stateForUpdate, positions);
                     }
                     else
                     {
-                        // 鍋囩數鑺ˉ鍏呭畬鎴愶紝閲嶇疆鏍囧織
-                        stateForUpdate.IsInFakeBatteryMode = false;
-                        _logger.LogInformation("HandlePutFinishedStateAsync锛氭崲鐩樹换鍔″畬鎴愶紝浠诲姟鍙�: {TaskNum}", task.RobotTaskNum);
-                        QuartzLogger.Info($"鎹㈢洏浠诲姟瀹屾垚", stateForUpdate.RobotCrane?.DeviceName);
+                        // 娴佸悜B锛氫粠婧愬湴鍧�鍙栧亣鐢佃姱
+                        int pickCount = Math.Min(4, remainingFake);
+                        var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount);
+                        await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end);
+                        stateForUpdate.CurrentBatchIndex += pickCount;
                     }
+
+                    // 鍙戝畬 Pick 鍚庡垏鎹㈠埌 Phase=4锛岀瓑 PickFinished 瑙﹀彂 HandlePickFinishedStateAsync 涓嬪彂鏀捐揣鎸囦护
+                    stateForUpdate.ChangePalletPhase = 4;
+                    _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
+                    return;
+                }
+
+                // ==================== Phase 5: 瀹屾垚鍏ュ簱锛坅llputfinished / allpickfinished 瑙﹀彂锛�====================
+                if (stateForUpdate.ChangePalletPhase == 5)
+                {
+                    // Phase 5 鐢� allpickfinished/allputfinished 瑙﹀彂鍏ュ簱锛屾湰鏂规硶涓嶅啀涓嬪彂鎸囦护
+                    return;
                 }
             }
             else

--
Gitblit v1.9.3