| Code/.omc/state/mission-state.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/.omc/state/subagent-tracking.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| Code/WCS/WIDESEAWCS_Server/docs/换盘任务流程图.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| 项目资料/设备协议/上位系统对接/高温2常温1及机械手设备账号信息表(1).xlsx | 补丁 | 查看 | 原始文档 | blame | 历史 | |
| 项目资料/设备协议/机械手协议/~$交互流程表(1).xlsx | 补丁 | 查看 | 原始文档 | blame | 历史 |
Code/.omc/state/mission-state.json
@@ -1,5 +1,5 @@ { "updatedAt": "2026-04-18T07:46:50.058Z", "updatedAt": "2026-04-18T08:52:24.581Z", "missions": [ { "id": "session:9007b9ea-1eb6-4d24-8fe7-2c3a949eac88:none", @@ -1212,6 +1212,62 @@ "sourceKey": "session-stop:aa71986c72a8dd1f4" } ] }, { "id": "session:78e67b30-83ce-4757-a175-68c3442c4534:none", "source": "session", "name": "none", "objective": "Session mission", "createdAt": "2026-04-18T08:34:11.529Z", "updatedAt": "2026-04-18T08:52:24.581Z", "status": "done", "workerCount": 1, "taskCounts": { "total": 1, "pending": 0, "blocked": 0, "inProgress": 0, "completed": 1, "failed": 0 }, "agents": [ { "name": "general-purpose:a6a0c97", "role": "general-purpose", "ownership": "a6a0c97facebc27a6", "status": "done", "currentStep": null, "latestUpdate": "completed", "completedSummary": null, "updatedAt": "2026-04-18T08:52:24.581Z" } ], "timeline": [ { "id": "session-start:a6a0c97facebc27a6:2026-04-18T08:34:11.529Z", "at": "2026-04-18T08:34:11.529Z", "kind": "update", "agent": "general-purpose:a6a0c97", "detail": "started general-purpose:a6a0c97", "sourceKey": "session-start:a6a0c97facebc27a6" }, { "id": "session-stop:acc34e8d2cd052b69:2026-04-18T08:42:23.674Z", "at": "2026-04-18T08:42:23.674Z", "kind": "completion", "agent": "general-purpose:a6a0c97", "detail": "completed", "sourceKey": "session-stop:acc34e8d2cd052b69" }, { "id": "session-stop:a6a0c97facebc27a6:2026-04-18T08:52:24.581Z", "at": "2026-04-18T08:52:24.581Z", "kind": "completion", "agent": "general-purpose:a6a0c97", "detail": "completed", "sourceKey": "session-stop:a6a0c97facebc27a6" } ] } ] } Code/.omc/state/subagent-tracking.json
@@ -758,10 +758,19 @@ "status": "completed", "completed_at": "2026-04-18T07:46:15.279Z", "duration_ms": 58126 }, { "agent_id": "a6a0c97facebc27a6", "agent_type": "general-purpose", "started_at": "2026-04-18T08:34:11.529Z", "parent_mode": "none", "status": "completed", "completed_at": "2026-04-18T08:52:24.581Z", "duration_ms": 1093052 } ], "total_spawned": 82, "total_completed": 82, "total_spawned": 83, "total_completed": 83, "total_failed": 0, "last_updated": "2026-04-18T07:46:50.164Z" "last_updated": "2026-04-18T14:04:59.113Z" } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
@@ -197,10 +197,11 @@ /// <remarks> /// é¶æ®µå®ä¹ï¼ /// 0: æªå¼å§ /// 1: 忣叏çµè¯ï¼æµåBï¼ / ååçµè¯ï¼æµåAï¼ /// 2: æ¾æ£å¸¸çµè¯ï¼æµåBï¼ / æ¾åçµè¯ï¼æµåAï¼ /// 3: ååçµè¯ï¼æµåB Phase2ï¼ /// 4: æ¾åçµè¯å°5å·ä½ï¼æµåB Phase2ï¼ /// 1: 忣叏çµè¯ï¼ä¸¤æµåç¸åï¼ /// 2: æ¾æ£å¸¸çµè¯å°ç®æ æçï¼ä¸¤æµåç¸åï¼ /// 3: æµåAï¼æ£å¸¸åå®â空æçååºâååçµè¯ä»5å·ä½ / æµåBï¼æ£å¸¸åå®âååçµè¯ä»æºå°å /// 4: æµåAï¼æ¾åçµè¯å°ç®æ æç / æµåBï¼æ¾åçµè¯å°5å·ä½ /// 5: æµåAï¼åæ¾å®âallputfinishedå ¥åºHCSC1 / æµåBï¼ååå®â空æçååºHCSC1+ç»çå ¥åºGWSC1 /// </remarks> public int ChangePalletPhase { get; set; } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -344,6 +344,53 @@ } /// <summary> /// ä¸ååçµè¯åè´§æä»¤ï¼å¸¦æ¹æ¬¡æ ¼å¼åæ»æ°ï¼ /// </summary> /// <remarks> /// åé顺åºï¼ /// 1. PickTotalNum,{N} -- çå®çµè¯æ»æ° /// 2. Pickbattery,5,{start}-{end} -- æ¹æ¬¡åè´§æä»¤ï¼åºå®ä»5å·ä½åï¼ /// /// ä¸åæååæ´æ°ä»»å¡ç¶æä¸º"æºå¨äººæ§è¡ä¸"ã /// </remarks> /// <param name="task">è¦ä¸åçä»»å¡å¯¹è±¡</param> /// <param name="state">æºå¨äººå½åç¶æ</param> /// <param name="batchStart">æ¹æ¬¡èµ·å§ç¼å·</param> /// <param name="batchEnd">æ¹æ¬¡ç»æç¼å·</param> public async Task SendFakeBatteryPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, int batchStart, int batchEnd) { // å åéæ»æ°æä»¤ string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}"; await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd); // ååéæ¹æ¬¡åè´§æä»¤ï¼åçµè¯åºå®ä»5å·ä½åï¼ string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}"; string taskString = $"Pickbattery,5,{range}"; bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString); if (result) { _logger.LogInformation("ä¸ååçµè¯æ¹æ¬¡åè´§æä»¤æåï¼æä»¤: {TaskString}ï¼æ¹æ¬¡: {Range}ï¼è®¾å¤: {DeviceName}", taskString, range, state.RobotCrane?.DeviceName); QuartzLogger.Info($"ä¸ååçµè¯æ¹æ¬¡åè´§æä»¤æåï¼æä»¤: {taskString}ï¼æ¹æ¬¡: {range}", state.RobotCrane?.DeviceName); task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode(); state.CurrentTask = task; if (_stateManager.TryUpdateStateSafely(state.IPAddress, state)) { await _robotTaskService.UpdateRobotTaskAsync(task); } } else { _logger.LogError("ä¸ååçµè¯æ¹æ¬¡åè´§æä»¤å¤±è´¥ï¼æä»¤: {TaskString}ï¼è®¾å¤: {DeviceName}", taskString, state.RobotCrane?.DeviceName); QuartzLogger.Error($"ä¸ååçµè¯æ¹æ¬¡åè´§æä»¤å¤±è´¥ï¼æä»¤: {taskString}", state.RobotCrane?.DeviceName); } } /// <summary> /// ä¸åæ¾è´§æä»¤ï¼å¸¦æ¹æ¬¡æ ¼å¼åæ»æ°ï¼ /// </summary> /// <remarks> Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
@@ -270,28 +270,47 @@ // æ¢çä»»å¡ï¼æ ¹æ®é¶æ®µåºåå¤ç if (state.ChangePalletPhase == 2) { // Phase 2ï¼æ¾æ£å¸¸çµè¯å°ç®æ æç宿ï¼éå¢è®¡æ° state.RobotTaskTotalNum += positions.Length; if (task != null) task.RobotTaskTotalNum -= positions.Length; if (isFlowA) { // æµåA Phase2ï¼æ¾åçµè¯å°ç®æ æçï¼ä¸è°ç¨ APIï¼ä¸éå¢è®¡æ° // ä» æ´æ°ç¶æ // æµåAï¼ä¸è°ç¨ APIï¼ä» éå¢è®¡æ° } else { // æµåB Phase2ï¼æ¾æ£å¸¸çµè¯ï¼éå¢è®¡æ° state.RobotTaskTotalNum += positions.Length; if (task != null) task.RobotTaskTotalNum -= positions.Length; // æå»ºåºå DTO å¹¶è°ç¨ ChangePalletAsync API // æµåBï¼è°ç¨æ¢ç API var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions); var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.ChangePalletAsync), stockDTO); putSuccess = result.Data.Status && result.IsSuccess; } // åå Phase 1ï¼ç»§ç»åæ£å¸¸çµè¯ state.ChangePalletPhase = 1; } else if (state.ChangePalletPhase == 4) { // æµåB Phase4ï¼æ¾åçµè¯å°5å·ä½ï¼ä¸è°ç¨ APIï¼ä¸éå¢è®¡æ°ï¼éæ¾ç¹ä½ _fakeBatteryPositionService.MarkAsAvailable(positions.ToList()); if (isFlowA) { // æµåAï¼æ¾åçµè¯å°ç®æ æçï¼éå¢è®¡æ°ï¼è°ç¨æ¢ç API state.RobotTaskTotalNum += positions.Length; if (task != null) task.RobotTaskTotalNum -= positions.Length; var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions); var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.ChangePalletAsync), stockDTO); putSuccess = result.Data.Status && result.IsSuccess; } else { // æµåBï¼æ¾åçµè¯å°5å·ä½ï¼éæ¾ç¹ä½ _fakeBatteryPositionService.MarkAsAvailable(positions.ToList()); } // åå Phase 3ï¼ç»§ç»ååçµè¯ state.ChangePalletPhase = 3; } else { Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -143,35 +143,72 @@ // 夿任å¡ç±»å var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; // æ¢çä»»å¡ï¼ä» 彿æé¶æ®µå®ææ¶æå¤çå ¥åº // æ¢çä»»å¡ï¼æ ¹æ®é¶æ®µåºåå¤ç if (robotTaskType == RobotTaskTypeEnum.ChangePallet) { if (state.ChangePalletPhase == 0) // è°ç¨æ¹éæç确认æ¥å£ var sourcePallet = state.CurrentTask.RobotSourceAddressPalletCode; var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName); if (!confirmResult.IsSuccess) { // è°ç¨æ¹éæç确认æ¥å£ï¼æ¢çåå®é¶æ®µï¼ var sourcePallet = state.CurrentTask.RobotSourceAddressPalletCode; var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName); if (!confirmResult.IsSuccess) { QuartzLogger.Error($"æ¹éæç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); } // ææé¶æ®µå®æï¼å¤çå ¥åº if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); // éç½®æ¹æ¬¡ç¶æ state.ChangePalletPhase = 0; state.CurrentBatchIndex = 1; state.IsInFakeBatteryMode = false; return true; } QuartzLogger.Error($"æ¹éæç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } // ä¸é´é¶æ®µä¸å¤çï¼ä» æ´æ°ç¶æ if (state.ChangePalletPhase == 5) { // FlowB æç»é¶æ®µï¼åçµè¯åå®ï¼æºç©ºæçååº HCSC1 if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { return false; } if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true) { QuartzLogger.Error($"allpickfinishedï¼å é¤ä»»å¡è®°å½å¤±è´¥ï¼ä»»å¡å·: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); state.CurrentTask = null; state.RobotTaskTotalNum = 0; state.CellBarcode = new List<string>(); state.ChangePalletPhase = 0; state.CurrentBatchIndex = 1; state.IsInFakeBatteryMode = false; return true; } else if (state.ChangePalletPhase != 0) { // FlowA ä¸é´é¶æ®µï¼æ£å¸¸çµè¯åå®ï¼æºç©ºæçååº GWSC1 // ä¸å é¤ä»»å¡ï¼ä¸éç½®ç¶æï¼ç»§ç» Phase 3-4 åçµè¯æµç¨ if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { return false; } return true; } // Phase == 0: éæ¹æ¬¡æ¨¡å¼ï¼ç®æ æ»æ°==48ï¼ if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { return false; } if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true) { QuartzLogger.Error($"allpickfinishedï¼å é¤ä»»å¡è®°å½å¤±è´¥ï¼ä»»å¡å·: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); state.ChangePalletPhase = 0; state.CurrentBatchIndex = 1; state.IsInFakeBatteryMode = false; return true; } @@ -184,16 +221,24 @@ if (!confirmResult.IsSuccess) { QuartzLogger.Error($"æ¹éæç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); return true; return false; } // å ¥åºæåï¼å é¤ä»»å¡è®°å½ if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true) { QuartzLogger.Error($"allpickfinishedï¼å é¤ä»»å¡è®°å½å¤±è´¥ï¼ä»»å¡å·: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); return true; } return false; } @@ -214,41 +259,77 @@ // 夿任å¡ç±»å var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; // æ¢çä»»å¡ï¼ä» 彿æé¶æ®µå®ææ¶æå¤çå ¥åº // æ¢çä»»å¡ï¼æ ¹æ®é¶æ®µåºåå¤ç if (robotTaskType == RobotTaskTypeEnum.ChangePallet) { if (state.ChangePalletPhase == 0) // è°ç¨æ¹éç»ç确认æ¥å£ var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName); if (!confirmResult.IsSuccess) { // è°ç¨æ¹éç»ç确认æ¥å£ï¼æ¢çæ¾å®é¶æ®µï¼ var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName); if (!confirmResult.IsSuccess) { QuartzLogger.Error($"æ¹éç»ç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); } // ææé¶æ®µå®æï¼å¤çå ¥åº if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); // æ¸ çç¶æï¼ä¸ºä¸ä¸ä¸ªä»»å¡ååå¤ state.CurrentTask = null; // æ¸ é¤å½åä»»å¡ state.RobotTaskTotalNum = 0; // é置任å¡è®¡æ° state.CellBarcode = new List<string>(); // æ¸ ç©ºæ¡ç å表 await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); // éç½®æ¹æ¬¡ç¶æ state.ChangePalletPhase = 0; state.CurrentBatchIndex = 1; state.IsInFakeBatteryMode = false; return true; } QuartzLogger.Error($"æ¹éç»ç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } // ä¸é´é¶æ®µä¸å¤çï¼ä» æ´æ°ç¶æ if (state.ChangePalletPhase == 5) { // FlowA æç»é¶æ®µï¼åçµè¯æ¾å®ï¼ç®æ æç满48å ¥åº HCSC1 if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { return false; } if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true) { QuartzLogger.Error($"allputfinishedï¼å é¤ä»»å¡è®°å½å¤±è´¥ï¼ä»»å¡å·: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } state.CurrentTask = null; state.RobotTaskTotalNum = 0; state.CellBarcode = new List<string>(); await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); state.ChangePalletPhase = 0; state.CurrentBatchIndex = 1; state.IsInFakeBatteryMode = false; return true; } else if (state.ChangePalletPhase != 0) { // FlowB ä¸é´é¶æ®µï¼æ£å¸¸çµè¯æ¾å®ï¼æè´§æçç»çå ¥åº GWSC1 // ä¸å é¤ä»»å¡ï¼ä¸éç½®ç¶æï¼ç»§ç» Phase 3-4 åçµè¯æµç¨ if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { return false; } return true; } // Phase == 0: éæ¹æ¬¡æ¨¡å¼ï¼ç®æ æ»æ°==48ï¼ if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { return false; } if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true) { QuartzLogger.Error($"allputfinishedï¼å é¤ä»»å¡è®°å½å¤±è´¥ï¼ä»»å¡å·: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } state.CurrentTask = null; state.RobotTaskTotalNum = 0; state.CellBarcode = new List<string>(); await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); state.ChangePalletPhase = 0; state.CurrentBatchIndex = 1; state.IsInFakeBatteryMode = false; return true; } @@ -256,25 +337,36 @@ if (robotTaskType == RobotTaskTypeEnum.GroupPallet) { // è°ç¨æ¹éç»ç确认æ¥å£ //var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; //_taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName); var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName); if (!confirmResult.IsSuccess) { QuartzLogger.Error($"æ¹éç»ç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } // å¤çå ¥åºä»»å¡åä¼ // useSourceAddress: false 表示使ç¨ç®æ å°åï¼ç»çåºæ¯ï¼ if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) if (!await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); // æ¸ çç¶æï¼ä¸ºä¸ä¸ä¸ªä»»å¡ååå¤ state.CurrentTask = null; // æ¸ é¤å½åä»»å¡ state.RobotTaskTotalNum = 0; // é置任å¡è®¡æ° state.CellBarcode = new List<string>(); // æ¸ ç©ºæ¡ç å表 await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); return true; return false; } // å ¥åºæåï¼å é¤ä»»å¡è®°å½ if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true) { QuartzLogger.Error($"allputfinishedï¼å é¤ä»»å¡è®°å½å¤±è´¥ï¼ä»»å¡å·: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown"); return false; } // æ¸ çç¶æï¼ä¸ºä¸ä¸ä¸ªä»»å¡ååå¤ state.CurrentTask = null; // æ¸ é¤å½åä»»å¡ state.RobotTaskTotalNum = 0; // é置任å¡è®¡æ° state.CellBarcode = new List<string>(); // æ¸ ç©ºæ¡ç å表 await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); return true; } return false; } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -166,7 +166,7 @@ var state = _stateManager.GetState(ipAddress); // æ¢çä»»å¡ä½¿ç¨æ¹æ¬¡æ ¼å¼ // æ¢ç任塿¹æ¬¡æ¨¡å¼ if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()) { int targetNormalCount = task.RobotTaskTotalNum; @@ -174,78 +174,94 @@ bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010"; // æµåA Phase 2ï¼æ¾åçµè¯å°ç®æ æç if (isFlowA && state?.ChangePalletPhase == 2) // ==================== Phase 2: æ¾æ£å¸¸çµè¯å°ç®æ æçï¼ä¸¤æµåç¸åï¼==================== // PickFinished å°è¾¾ï¼Phase 1 ç Pick å½ä»¤å®æï¼ç°å¨ä¸å Put å½ä»¤æ¾æ£å¸¸çµè¯ if (state?.ChangePalletPhase == 2) { int remaining = 48 - currentCompletedCount; if (remaining <= 0) return; int remainingNormal = targetNormalCount - currentCompletedCount; if (remainingNormal <= 0) { // æ£å¸¸çµè¯å ¨é¨æ¾å®ï¼çå¾ HandlePutFinishedAsync åæ¢å° Phase 3 return; } int batchStart = targetNormalCount + 1 + (state.CurrentBatchIndex - 1); int putCount = Math.Min(4, remaining); 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; } // æµåB Phase 4ï¼æ¾åçµè¯å°5å·ä½ if (!isFlowA && state?.ChangePalletPhase == 4) // ==================== Phase 4: æ¾åçµè¯ï¼ä¸¤æµåååï¼==================== // PickFinished å°è¾¾ï¼Phase 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) return; var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake)); if (positions.Count == 0) if (remainingFake <= 0) { _logger.LogError("HandlePickFinishedStateAsyncï¼æ å¯ç¨åçµè¯ç¹ä½ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); // åçµè¯å ¨é¨æ¾å®ï¼çå¾ allputfinished 触å Phase 5 å ¥åº return; } int start = positions.Min(); int end = positions.Max(); await _taskProcessor.SendPutWithBatchAsync(task, state, "5", start, end); return; } // æµåB Phase 2ï¼æ¾æ£å¸¸çµè¯å°ç®æ æç if (!isFlowA && state?.ChangePalletPhase == 2) { int remainingNormal = targetNormalCount - currentCompletedCount; if (remainingNormal <= 0) return; int batchStart = ((currentCompletedCount - 1) / 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); return; } // é»è®¤ï¼ä½¿ç¨åææ ¼å¼ taskString = $"Putbattery,{task.RobotTargetAddress}"; } else { // 鿢çä»»å¡ï¼ä½¿ç¨åææ ¼å¼ if (state != null && state.IsGroupPallet && task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode()) { // ç»çä»»å¡ï¼æ¾è´§é夿æ¯å¦NGï¼å¦æNGåæ¾å°NGå£ if (state.IsScanNG) if (isFlowA) { taskString = $"Putbattery,4"; // æµå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 { taskString = $"Putbattery,{task.RobotTargetAddress}"; // æµå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,4"; } else { taskString = $"Putbattery,{task.RobotTargetAddress}"; } } else taskString = $"Putbattery,{task.RobotTargetAddress}"; bool result = await _clientManager.SendToClientAsync(ipAddress, taskString); @@ -376,7 +392,9 @@ else if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()) { const int targetTotal = 48; // æ¢çä»»å¡è¿å ¥æ¹æ¬¡æ¨¡å¼ï¼åé¶æ®µå¤çæ£å¸¸çµè¯ååçµè¯ ï¼æºå¨äººä»»å¡æ»æ°ï¼ int targetNormalCount = task.RobotTaskTotalNum; // å½å已宿æ°éï¼åè´§å®æçæ°éï¼ï¼åå§ä¸ºç¶æä¸ç RobotTaskTotalNumï¼åç»æ ¹æ®åè´§å®æçæ°éå¨ææ´æ° int currentCompletedCount = stateForUpdate.RobotTaskTotalNum; // 夿æµåï¼null-safeï¼ @@ -396,159 +414,82 @@ stateForUpdate.CurrentBatchIndex = 1; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æ¢çä»»å¡è¿å ¥æ¹æ¬¡æ¨¡å¼ï¼ä»»å¡å·: {TaskNum}ï¼æµå: {Flow}", task.RobotTaskNum, isFlowA ? "A" : "B"); _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate); } // ==================== æµåAï¼è¡¥åçµè¯å°ç®æ æç ==================== if (isFlowA) // ==================== Phase 1: 忣叏çµè¯ï¼ä¸¤æµåç¸åï¼==================== if (stateForUpdate.ChangePalletPhase == 1) { // Phase 1: ååçµè¯ï¼ä»5å·ä½ï¼ä½¿ç¨ PositionIndexï¼ if (stateForUpdate.ChangePalletPhase == 1) int remainingNormal = targetNormalCount - currentCompletedCount; if (remainingNormal <= 0) { int remaining = targetTotal - currentCompletedCount; if (remaining <= 0) { stateForUpdate.ChangePalletPhase = 0; stateForUpdate.CurrentBatchIndex = 1; stateForUpdate.IsInFakeBatteryMode = false; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æµåA宿ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } int pickCount = Math.Min(4, remaining); var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(pickCount); if (positions.Count == 0) { _logger.LogError("HandlePutFinishedStateAsyncï¼æ å¯ç¨åçµè¯ç¹ä½ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } await _taskProcessor.SendSocketRobotFakeBatteryPickAsync(task, stateForUpdate, positions); stateForUpdate.ChangePalletPhase = 2; // æ£å¸¸çµè¯åå®ï¼åæ¢å° Phase 3 ååçµè¯ stateForUpdate.ChangePalletPhase = 3; stateForUpdate.CurrentBatchIndex = 1; // åçµè¯æ¹æ¬¡ä»å¤´å¼å§ _logger.LogInformation("HandlePutFinishedStateAsyncï¼æ£å¸¸çµè¯åå®ï¼åæ¢å°Phase 3ååçµè¯ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate); return; } // Phase 2: æ¾åçµè¯å°ç®æ æçï¼ä» targetNormalCount+1 å¼å§éå¢ï¼ else if (stateForUpdate.ChangePalletPhase == 2) { int remaining = targetTotal - currentCompletedCount; if (remaining <= 0) { stateForUpdate.ChangePalletPhase = 0; stateForUpdate.CurrentBatchIndex = 1; stateForUpdate.IsInFakeBatteryMode = false; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æµåA宿ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } // è®¡ç®æ¾è´§æ¹æ¬¡ç¼å·ï¼ä» targetNormalCount + 1 å¼å§ int batchStart = targetNormalCount + 1 + (stateForUpdate.CurrentBatchIndex - 1); int putCount = Math.Min(4, remaining); var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount); int pickCount = Math.Min(4, remainingNormal); var (start, end) = _taskProcessor.BuildBatchRange(stateForUpdate.CurrentBatchIndex, pickCount); await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, task.RobotTargetAddress, start, end); await _taskProcessor.SendPickWithBatchAsync(task, stateForUpdate, task.RobotSourceAddress, start, end); stateForUpdate.CurrentBatchIndex += putCount; stateForUpdate.ChangePalletPhase = 1; } stateForUpdate.CurrentBatchIndex += pickCount; // åå® Pick ååæ¢å° Phase=2ï¼ç PickFinished 触å HandlePickFinishedStateAsync ä¸åæ¾è´§æä»¤ stateForUpdate.ChangePalletPhase = 2; _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate); return; } // ==================== æµåBï¼åæ£å¸¸çµè¯ + åæ¶åçµè¯ ==================== else // ==================== Phase 3: å¤çåçµè¯ï¼æµåA/B ååï¼ï¼èªå·±å¾ªç¯ ==================== if (stateForUpdate.ChangePalletPhase == 3) { // Phase 1: 忣叏çµè¯ï¼ä»æºå°åï¼ä»1å¼å§éå¢ï¼ if (stateForUpdate.ChangePalletPhase == 1) int fakeCount = targetTotal - targetNormalCount; int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount); int remainingFake = fakeCount - completedFake; if (remainingFake <= 0) { int remainingNormal = targetNormalCount - currentCompletedCount; if (remainingNormal <= 0) { // æ£å¸¸çµè¯åå®ï¼åæ¢å° Phase 3 stateForUpdate.ChangePalletPhase = 3; stateForUpdate.CurrentBatchIndex = targetNormalCount + 1; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æ£å¸¸çµè¯å ¨é¨åå®ï¼è¿å ¥Phase 3åæ¶åçµè¯ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } 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; stateForUpdate.ChangePalletPhase = 2; // åçµè¯å ¨é¨å¤çå®ï¼åæ¢å° Phase 5 çå¾ å ¥åº stateForUpdate.ChangePalletPhase = 5; _logger.LogInformation("HandlePutFinishedStateAsyncï¼åçµè¯å¤ç宿¯ï¼åæ¢å°Phase 5çå¾ å ¥åºï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate); return; } // Phase 2: æ¾æ£å¸¸çµè¯å°ç®æ æçï¼æ¾è´§ç¼å·ä¸åè´§ç¼å·ä¸è´ï¼ else if (stateForUpdate.ChangePalletPhase == 2) if (isFlowA) { int remainingNormal = targetNormalCount - currentCompletedCount; if (remainingNormal <= 0) { // æ£å¸¸çµè¯æ¾å®ï¼åæ¢å° Phase 3 stateForUpdate.ChangePalletPhase = 3; stateForUpdate.CurrentBatchIndex = targetNormalCount + 1; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æ£å¸¸çµè¯å ¨é¨æ¾å®ï¼è¿å ¥Phase 3åæ¶åçµè¯ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } // è®¡ç®æ¬æ¹æ¾è´§ç¼å·ï¼åºäº currentCompletedCount æ¨å¯¼æ¹æ¬¡èµ·å§ int batchStart = ((currentCompletedCount - 1) / 4) * 4 + 1; int putCount = Math.Min(4, remainingNormal); var (start, end) = _taskProcessor.BuildBatchRange(batchStart, putCount); await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, task.RobotTargetAddress, start, end); stateForUpdate.ChangePalletPhase = 1; } // Phase 3: ååçµè¯ï¼ä»æºå°åï¼ä» targetNormalCount+1 å¼å§éå¢ï¼ else if (stateForUpdate.ChangePalletPhase == 3) { int fakeCount = targetTotal - targetNormalCount; int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount); int remainingFake = fakeCount - completedFake; if (remainingFake <= 0) { stateForUpdate.ChangePalletPhase = 0; stateForUpdate.CurrentBatchIndex = 1; stateForUpdate.IsInFakeBatteryMode = false; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æµåB宿ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } 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; stateForUpdate.ChangePalletPhase = 4; } // Phase 4: æ¾åçµè¯å°5å·ä½ï¼ä½¿ç¨ PositionIndexï¼ else if (stateForUpdate.ChangePalletPhase == 4) { int fakeCount = targetTotal - targetNormalCount; int completedFake = Math.Max(0, currentCompletedCount - targetNormalCount); int remainingFake = fakeCount - completedFake; if (remainingFake <= 0) { stateForUpdate.ChangePalletPhase = 0; stateForUpdate.CurrentBatchIndex = 1; stateForUpdate.IsInFakeBatteryMode = false; _logger.LogInformation("HandlePutFinishedStateAsyncï¼æµåB宿ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } // æµåAï¼ä»5å·ä½ååçµè¯ var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake)); if (positions.Count == 0) { _logger.LogError("HandlePutFinishedStateAsyncï¼æ å¯ç¨åçµè¯ç¹ä½ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); return; } int start = positions.Min(); int end = positions.Max(); await _taskProcessor.SendPutWithBatchAsync(task, stateForUpdate, "5", start, end); stateForUpdate.ChangePalletPhase = 3; await _taskProcessor.SendSocketRobotFakeBatteryPickAsync(task, stateForUpdate, positions); } else { // æµå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: å®æå ¥åºï¼allputfinished / allpickfinished 触åï¼==================== if (stateForUpdate.ChangePalletPhase == 5) { // Phase 5 ç± allpickfinished/allputfinished 触åå ¥åºï¼æ¬æ¹æ³ä¸åä¸åæä»¤ return; } } else Code/WCS/WIDESEAWCS_Server/docs/»»ÅÌÈÎÎñÁ÷³Ìͼ.md
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,291 @@ # æ¢çä»»å¡å®æ´æµç¨åæ ## ä»»å¡åæ° | åæ° | å¼ | |------|-----| | æµå | **Flow A** (isFlowA = true, æºå°å LineCode = "11001") | | æºå°å | 11001 | | ç®æ å°å | 2101 | | æ£å¸¸çµè¯æ°é | **33** | | åçµè¯æ°é | 48 - 33 = **15** | | ç®æ æ»æ° | 48 | --- ## é¶æ®µç¶æå®ä¹ | Phase | å«ä¹ | |-------|------| | 0 | æªå¼å§ | | 1 | 忣叏çµè¯ | | 2 | æ¾æ£å¸¸çµè¯ | | 3 | ååçµè¯ï¼Flow A: ä»5å·ä½åï¼ | | 4 | æ¾åçµè¯ï¼Flow A: æ¾å°ç®æ æçï¼ | | 5 | çå¾ å ¥åºå®æ | --- ## 宿´ä»£ç æ§è¡æµç¨ï¼33 æ£å¸¸ + 15 å = 48 æ»è®¡ï¼ ### åå§ç¶æ ``` ChangePalletPhase = 0 currentCompletedCount = 0 targetNormalCount = 33 ``` --- ### 第1è½®ï¼Pick 1-4 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 1 | HandlePutFinishedStateAsync | 1 | 0 | 33 - 0 = **33** | PickBatch(1, 4) â Phase=2 | | 2 | (æºæ¢°ææ§è¡åè´§) | - | - | - | - | | 3 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished, taskç¶æ=RobotPickFinish | | 4 | HandlePickFinishedStateAsync | 2 | 0 | 33 - 0 = **33** | PutBatch(1, 4) â Phase=1 | | 5 | (æºæ¢°ææ§è¡æ¾è´§) | - | - | - | - | | 6 | HandlePutFinishedAsync | - | **4** | - | currentCompletedCount+=4, task.RobotTaskTotalNum-=4 | --- ### 第2è½®ï¼Pick 5-8 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 7 | HandlePutFinishedStateAsync | 1 | 4 | 33 - 4 = **29** | PickBatch(5, 8) â Phase=2 | | 8 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 9 | HandlePickFinishedStateAsync | 2 | 4 | 33 - 4 = **29** | PutBatch(1, 4) â Phase=1 | | 10 | HandlePutFinishedAsync | - | **8** | - | currentCompletedCount+=4 | --- ### 第3è½®ï¼Pick 9-12 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 11 | HandlePutFinishedStateAsync | 1 | 8 | 33 - 8 = **25** | PickBatch(9, 12) â Phase=2 | | 12 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 13 | HandlePickFinishedStateAsync | 2 | 8 | 33 - 8 = **25** | PutBatch(1, 4) â Phase=1 | | 14 | HandlePutFinishedAsync | - | **12** | - | currentCompletedCount+=4 | --- ### 第4è½®ï¼Pick 13-16 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 15 | HandlePutFinishedStateAsync | 1 | 12 | 33 - 12 = **21** | PickBatch(13, 16) â Phase=2 | | 16 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 17 | HandlePickFinishedStateAsync | 2 | 12 | 33 - 12 = **21** | PutBatch(1, 4) â Phase=1 | | 18 | HandlePutFinishedAsync | - | **16** | - | currentCompletedCount+=4 | --- ### 第5è½®ï¼Pick 17-20 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 19 | HandlePutFinishedStateAsync | 1 | 16 | 33 - 16 = **17** | PickBatch(17, 20) â Phase=2 | | 20 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 21 | HandlePickFinishedStateAsync | 2 | 16 | 33 - 16 = **17** | PutBatch(1, 4) â Phase=1 | | 22 | HandlePutFinishedAsync | - | **20** | - | currentCompletedCount+=4 | --- ### 第6è½®ï¼Pick 21-24 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 23 | HandlePutFinishedStateAsync | 1 | 20 | 33 - 20 = **13** | PickBatch(21, 24) â Phase=2 | | 24 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 25 | HandlePickFinishedStateAsync | 2 | 20 | 33 - 20 = **13** | PutBatch(1, 4) â Phase=1 | | 26 | HandlePutFinishedAsync | - | **24** | - | currentCompletedCount+=4 | --- ### 第7è½®ï¼Pick 25-28 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 27 | HandlePutFinishedStateAsync | 1 | 24 | 33 - 24 = **9** | PickBatch(25, 28) â Phase=2 | | 28 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 29 | HandlePickFinishedStateAsync | 2 | 24 | 33 - 24 = **9** | PutBatch(1, 4) â Phase=1 | | 30 | HandlePutFinishedAsync | - | **28** | - | currentCompletedCount+=4 | --- ### 第8è½®ï¼Pick 29-32 æ£å¸¸çµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 31 | HandlePutFinishedStateAsync | 1 | 28 | 33 - 28 = **5** | PickBatch(29, 32) â Phase=2 | | 32 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 33 | HandlePickFinishedStateAsync | 2 | 28 | 33 - 28 = **5** | PutBatch(1, 4) â Phase=1 | | 34 | HandlePutFinishedAsync | - | **32** | - | currentCompletedCount+=4 | --- ### 第9è½®ï¼Pick 33 æ£å¸¸çµè¯ï¼æå1ä¸ªï¼ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 35 | HandlePutFinishedStateAsync | 1 | 32 | 33 - 32 = **1** | PickBatch(33, 33) â Phase=2 | | 36 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 37 | HandlePickFinishedStateAsync | 2 | 32 | 33 - 32 = **1** | PutBatch(33, 33) â Phase=1 | | 38 | HandlePutFinishedAsync | - | **33** | - | currentCompletedCount+=1 | --- ### 第10è½®ï¼æ£å¸¸çµè¯å ¨é¨å®æ â 忢 Phase 3 | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingNormal | æä½ | |------|------|-------|---------------------|----------------|------| | 39 | HandlePutFinishedStateAsync | 1 | **33** | 33 - 33 = **0** â â¤0 | **忢 Phase=3**, Pick fake from 5å·ä½ | > **Flow A ç¹æ§**ï¼æ£å¸¸çµè¯åå®åï¼æºæçï¼11001ï¼å·²ç©ºãæ¤æ¶æºæ¢°ææºå¸¦æå䏿¹æ£å¸¸çµè¯æ¾å°ç®æ æçåï¼æºæçèªå¨ç©ºåºååºã代ç ä¸ä¸éè¦æ¾å¼å¤çè¿ä¸ªååºå¨ä½ââç±è¾é线èªå¨å®æã --- ### 第11è½®ï¼Pick 1-4 åçµè¯ï¼ä»5å·ä½ï¼ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingFake | æä½ | |------|------|-------|---------------------|--------------|------| | 40 | HandlePutFinishedStateAsync | 3 | 33 | 15 - 0 = **15** | Pick fake from 5å·ä½(1,4) â Phase=4 | | 41 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 42 | HandlePickFinishedStateAsync | 4 | 33 | 15 - 0 = **15** | Put fake to target(BatchStart=34, 4个) â Phase=3 | | 43 | HandlePutFinishedAsync | - | **37** | - | currentCompletedCount+=4 | --- ### 第12è½®ï¼Pick 5-8 åçµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingFake | æä½ | |------|------|-------|---------------------|--------------|------| | 44 | HandlePutFinishedStateAsync | 3 | 37 | 15 - 4 = **11** | Pick fake from 5å·ä½(5,8) â Phase=4 | | 45 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 46 | HandlePickFinishedStateAsync | 4 | 37 | 15 - 4 = **11** | Put fake to target(BatchStart=38, 4个) â Phase=3 | | 47 | HandlePutFinishedAsync | - | **41** | - | currentCompletedCount+=4 | --- ### 第13è½®ï¼Pick 9-12 åçµè¯ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingFake | æä½ | |------|------|-------|---------------------|--------------|------| | 48 | HandlePutFinishedStateAsync | 3 | 41 | 15 - 8 = **7** | Pick fake from 5å·ä½(9,12) â Phase=4 | | 49 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 50 | HandlePickFinishedStateAsync | 4 | 41 | 15 - 8 = **7** | Put fake to target(BatchStart=42, 4个) â Phase=3 | | 51 | HandlePutFinishedAsync | - | **45** | - | currentCompletedCount+=4 | --- ### 第14è½®ï¼Pick 13-15 åçµè¯ï¼æå3ä¸ªï¼ | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingFake | æä½ | |------|------|-------|---------------------|--------------|------| | 52 | HandlePutFinishedStateAsync | 3 | 45 | 15 - 12 = **3** | Pick fake from 5å·ä½(13,15) â Phase=4 | | 53 | HandlePickFinishedAsync | - | - | - | CurrentAction=PickFinished | | 54 | HandlePickFinishedStateAsync | 4 | 45 | 15 - 12 = **3** | Put fake to target(BatchStart=46, 3个) â Phase=3 | | 55 | HandlePutFinishedAsync | - | **48** | - | currentCompletedCount+=3 | --- ### 第15è½®ï¼åçµè¯å ¨é¨å®æ â 忢 Phase 5 | æ¥éª¤ | æ¹æ³ | Phase | currentCompletedCount | remainingFake | æä½ | |------|------|-------|---------------------|--------------|------| | 56 | HandlePutFinishedStateAsync | 3 | **48** | 15 - 15 = **0** â â¤0 | **忢 Phase=5**, çå¾ å ¥åº | --- ### 第16è½®ï¼å ¨é¨æ¾è´§å®æ â å ¥åº | æ¥éª¤ | æ¹æ³ | Phase | æä½ | |------|------|-------|------| | 57 | HandlePutFinishedAsync | - | PutFinished â allputfinished | | 58 | ExecuteAsync | - | æ£æµ allputfinished â RobotSimpleCommandHandler å¤ç | | 59 | RobotSimpleCommandHandler | **5** | Phase=5 â è°ç¨ HandleInboundTaskAsync(useSourceAddress=false) å ¥åºå° **HCSC1** | | 60 | - | - | å é¤ä»»å¡è®°å½ï¼éç½®ç¶æï¼åé "Group,diskFinished" | --- ## æ°æ®æµæ±æ» ### currentCompletedCount åå ``` 0 â 4 â 8 â 12 â 16 â 20 â 24 â 28 â 32 â 33 â 37 â 41 â 45 â 48 | | | | | | | | | | | | | | æ£å¸¸çµè¯æ¹æ¬¡ æ£å¸¸å®æ åçµè¯æ¹æ¬¡ æ»å®æ (æ¯æ¹4个) +0 (æ¯æ¹4个) +3 ``` ### Phase åæ¢å¾ ``` Phase=0 ââ(åå§å)ââ⺠Phase=1 ââ⺠Phase=2 ââ⺠Phase=1 ââ⺠... ââ⺠Phase=1 (Pick 1-4) (Put 1-4) (Pick 5-8) (Pick 33) â Phase=2 ââ⺠... ââ⺠Phase=2 (Put 5-8) (Put 33) â ââââââââââââââââââââââââââââââââââââââââ â Phase=1 (remainingNormal=0) â â â â â Phase=3 (ååçµè¯) â â Pick fake â Phase=4 â Put fake â â ⺠â â ç´å° remainingFake=0 â â â â â Phase=5 (å ¥åº) â ââââââââââââââââââââââââââââââââââââââââ ``` ### å ³é®æ°æ®å¯¹ç §è¡¨ | 轮次 | Phase | æä½ | currentCompletedCount | remainingNormal | remainingFake | åéæä»¤ | |------|-------|------|---------------------|----------------|--------------|---------| | 1 | 1â2 | Pick 1-4 | 0 | 33 | - | PickBatch(1,4) | | 1 | 2â1 | Put 1-4 | 4 | 33 | - | PutBatch(1,4) | | 2 | 1â2 | Pick 5-8 | 4 | 29 | - | PickBatch(5,8) | | 2 | 2â1 | Put 5-8 | 8 | 29 | - | PutBatch(1,4) | | 3 | 1â2 | Pick 9-12 | 8 | 25 | - | PickBatch(9,12) | | 3 | 2â1 | Put 9-12 | 12 | 25 | - | PutBatch(1,4) | | 4 | 1â2 | Pick 13-16 | 12 | 21 | - | PickBatch(13,16) | | 4 | 2â1 | Put 13-16 | 16 | 21 | - | PutBatch(1,4) | | 5 | 1â2 | Pick 17-20 | 16 | 17 | - | PickBatch(17,20) | | 5 | 2â1 | Put 17-20 | 20 | 17 | - | PutBatch(1,4) | | 6 | 1â2 | Pick 21-24 | 20 | 13 | - | PickBatch(21,24) | | 6 | 2â1 | Put 21-24 | 24 | 13 | - | PutBatch(1,4) | | 7 | 1â2 | Pick 25-28 | 24 | 9 | - | PickBatch(25,28) | | 7 | 2â1 | Put 25-28 | 28 | 9 | - | PutBatch(1,4) | | 8 | 1â2 | Pick 29-32 | 28 | 5 | - | PickBatch(29,32) | | 8 | 2â1 | Put 29-32 | 32 | 5 | - | PutBatch(1,4) | | 9 | 1â2 | Pick 33 | 32 | 1 | - | PickBatch(33,33) | | 9 | 2â1 | Put 33 | 33 | 0 | - | PutBatch(33,33) | | 10 | 1â**3** | **忢** | 33 | **0** | 15 | Pick fake(5å·ä½ 1-4) | | 11 | 3â4 | Pick fake 1-4 | 33 | 0 | 15 | PickBattery,5,1-4 | | 11 | 4â3 | Put fake 34-37 | 37 | 0 | 11 | PutBatch(34,37) | | 12 | 3â4 | Pick fake 5-8 | 37 | 0 | 11 | PickBattery,5,5-8 | | 12 | 4â3 | Put fake 38-41 | 41 | 0 | 7 | PutBatch(38,41) | | 13 | 3â4 | Pick fake 9-12 | 41 | 0 | 7 | PickBattery,5,9-12 | | 13 | 4â3 | Put fake 42-45 | 45 | 0 | 3 | PutBatch(42,45) | | 14 | 3â4 | Pick fake 13-15 | 45 | 0 | 3 | PickBattery,5,13-15 | | 14 | 4â3 | Put fake 46-48 | 48 | 0 | 0 | PutBatch(46,48) | | 15 | 3â**5** | **忢** | 48 | 0 | **0** | çå¾ å ¥åº | | 16 | 5 | **å ¥åº** | - | - | - | allputfinished â HandleInboundTaskAsync â HCSC1 | --- ## 代ç èè´£å¯¹ç § | æ¹æ³ | 使¶è°ç¨ | èè´£ | |------|---------|------| | HandlePutFinishedStateAsync | `ExecuteAsync` æ£æµ PutFinished | åé **Pick** æä»¤ï¼æ´æ° Phase | | HandlePickFinishedStateAsync | `ExecuteAsync` æ£æµ PickFinished | åé **Put** æä»¤ | | HandlePickFinishedAsync | prefix command `pickfinished` | æ´æ°ç¶æ CurrentAction | | HandlePutFinishedAsync | prefix command `putfinished` | æ´æ° currentCompletedCount è®¡æ° | | RobotSimpleCommandHandler | å½ä»¤ `allpickfinished` / `allputfinished` | 触åå ¥åºï¼æ¸ çç¶æ | ÏîÄ¿×ÊÁÏ/É豸ÐÒé/ÉÏλϵͳ¶Ô½Ó/¸ßÎÂ2³£ÎÂ1¼°»úеÊÖÉ豸Õ˺ÅÐÅÏ¢±í(1).xlsxBinary files differ
ÏîÄ¿×ÊÁÏ/É豸ÐÒé/»úеÊÖÐÒé/~$½»»¥Á÷³Ì±í(1).xlsxBinary files differ