From 05999b9c77f009ac9a7e98366bc3d23fbb8e83e7 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期日, 26 四月 2026 17:46:10 +0800
Subject: [PATCH] feat: 更新数据库连接配置和机器人任务处理逻辑

---
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs                    | 1563 +++++++++++++++++++++++++++--------------------------
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs    |    4 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json                                 |    2 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs |   25 
 Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs                               |   24 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs    |   40 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs    |   10 
 Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs         |   16 
 8 files changed, 881 insertions(+), 803 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
index 991f38a..6cc3b23 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -34,7 +34,7 @@
   //5.PostgreSQL
   "DBType": "SqlServer",
   //杩炴帴瀛楃涓�
-  "ConnectionString": "Data Source=192.168.60.30;Initial Catalog=WIDESEAWCS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+  "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
   //"ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_ShanMei;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
 
   //璺ㄥ煙
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
index e875238..38f60f8 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -271,18 +271,19 @@
             Thread.Sleep(100); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
             var isPalletSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
 
-            bool isTargetSet = true;
-            if (targetAddress == "2217" && !isEmptyTask)
-            {
-                QuartzLogHelper.LogDebug(_logger, $"瀛愯澶�: {childDeviceCode}锛屽嚭搴撶洰鏍囧湴鍧�: {targetAddress}", conveyorLine.DeviceCode);
-                Thread.Sleep(100); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
-                isTargetSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode);
-            }
-            if (!isTargetSet || !isTaskNoSet || !isPalletSet)
-            {
-                QuartzLogHelper.LogError(_logger, $"RequestOutbound锛氫笅鍙戝嚭搴撲换鍔″け璐ワ紝浠诲姟鍙�: {task.TaskNum}锛屽瓙璁惧: {childDeviceCode}", conveyorLine.DeviceCode); 
-                return Task.CompletedTask;
-            }
+            Thread.Sleep(100); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
+            bool isTargetSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode);
+            //if (targetAddress == "2217" && !isEmptyTask)
+            //{
+            //    QuartzLogHelper.LogDebug(_logger, $"瀛愯澶�: {childDeviceCode}锛屽嚭搴撶洰鏍囧湴鍧�: {targetAddress}", conveyorLine.DeviceCode);
+            //    Thread.Sleep(100); // 纭繚 PLC 鑳芥纭鍙栦换鍔″彿鍚庡啀鍐欏叆鏉$爜
+            //    isTargetSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode);
+            //}
+            //if (!isTargetSet || !isTaskNoSet || !isPalletSet)
+            //{
+            //    QuartzLogHelper.LogError(_logger, $"RequestOutbound锛氫笅鍙戝嚭搴撲换鍔″け璐ワ紝浠诲姟鍙�: {task.TaskNum}锛屽瓙璁惧: {childDeviceCode}", conveyorLine.DeviceCode); 
+            //    return Task.CompletedTask;
+            //}
 
             bool isWmsResult = false;
             // 鏇存柊浠诲姟鐘舵�佹垨浣嶇疆
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
index 838bd20..97fa4ac 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -1,760 +1,805 @@
-using Newtonsoft.Json;
-using Serilog;
-using WIDESEA_Core;
-using WIDESEAWCS_Common;
-using WIDESEAWCS_Common.HttpEnum;
-using WIDESEAWCS_Common.TaskEnum;
-using WIDESEAWCS_Core;
-using WIDESEAWCS_Core.Helper;
-using WIDESEAWCS_Core.LogHelper;
-using WIDESEAWCS_DTO.Stock;
-using WIDESEAWCS_DTO.TaskInfo;
-using WIDESEAWCS_ITaskInfoService;
-using WIDESEAWCS_Model.Models;
-using WIDESEAWCS_QuartzJob;
-using WIDESEAWCS_Tasks.Workflow.Abstractions;
-
-namespace WIDESEAWCS_Tasks
-{
-    /// <summary>
-    /// 鏈哄櫒浜轰换鍔″鐞嗗櫒 - 璐熻矗浠诲姟鑾峰彇銆佷笅鍙戙�佸叆搴撲换鍔″洖浼犲強搴撳瓨 DTO 鏋勫缓
-    /// </summary>
-    /// <remarks>
-    /// 鏍稿績鑱岃矗锛�
-    /// 1. 浠庢暟鎹簱杞寰呭鐞嗙殑鏈哄櫒浜轰换鍔�
-    /// 2. 鍚戞満鍣ㄤ汉瀹㈡埛绔笅鍙戝彇璐ф寚浠わ紙Pickbattery锛�
-    /// 3. 澶勭悊鍏ュ簱浠诲姟鐨勫洖浼狅紙鎷嗙洏/缁勭洏/鎹㈢洏鍦烘櫙锛�
-    /// 4. 鏋勫缓搴撳瓨鍥炰紶 DTO 骞惰皟鐢� WMS 鎺ュ彛
-    ///
-    /// 閫氳繃缃戝叧璁块棶 Socket锛岄伩鍏嶄笟鍔″眰鐩存帴渚濊禆 TcpSocketServer銆�
-    /// </remarks>
-    public class RobotTaskProcessor
-    {
-        /// <summary>
-        /// Socket 瀹㈡埛绔綉鍏虫帴鍙�
-        /// </summary>
-        /// <remarks>
-        /// 閫氳繃缃戝叧璁块棶 Socket锛岄伩鍏嶄笟鍔″眰鐩存帴渚濊禆 TcpSocketServer銆�
-        /// 鎻愪緵缁熶竴鐨勫鎴风閫氫俊鎺ュ彛銆�
-        /// </remarks>
-        private readonly ISocketClientGateway _socketClientGateway;
-
-        /// <summary>
-        /// 鏈烘鎵嬬姸鎬佺鐞嗗櫒
-        /// </summary>
-        private readonly RobotStateManager _stateManager;
-
-        /// <summary>
-        /// 鏈哄櫒浜轰换鍔℃湇鍔�
-        /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬鏌ヨ銆佹洿鏂般�佸垹闄ゆ満鍣ㄤ汉浠诲姟璁板綍銆�
-        /// </remarks>
-        private readonly IRobotTaskService _robotTaskService;
-
-        /// <summary>
-        /// 閫氱敤浠诲姟鏈嶅姟
-        /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬涓� WMS 绯荤粺浜や簰锛屾帴鏀朵换鍔°�佸鐞嗕换鍔$姸鎬佺瓑銆�
-        /// </remarks>
-        private readonly ITaskService _taskService;
-
-        /// <summary>
-        /// HTTP 瀹㈡埛绔府鍔╃被
-        /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬璋冪敤 WMS 绯荤粺鐨� HTTP 鎺ュ彛銆�
-        /// </remarks>
-        private readonly HttpClientHelper _httpClientHelper;
-
-        /// <summary>
-        /// 鍋囩數鑺钩闈㈢偣浣嶆湇鍔�
-        /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬绠$悊鍋囩數鑺钩闈㈢偣浣嶇殑鍒嗛厤鍜岀姸鎬併��
-        /// </remarks>
-        private readonly IFakeBatteryPositionService _fakeBatteryPositionService;
-
-        /// <summary>
-        /// 鏃ュ織璁板綍鍣�
-        /// </summary>
+using Masuit.Tools;
+using Newtonsoft.Json;
+using Serilog;
+using WIDESEA_Core;
+using WIDESEAWCS_Common;
+using WIDESEAWCS_Common.HttpEnum;
+using WIDESEAWCS_Common.TaskEnum;
+using WIDESEAWCS_Core;
+using WIDESEAWCS_Core.Helper;
+using WIDESEAWCS_Core.LogHelper;
+using WIDESEAWCS_DTO.Stock;
+using WIDESEAWCS_DTO.TaskInfo;
+using WIDESEAWCS_ITaskInfoService;
+using WIDESEAWCS_Model.Models;
+using WIDESEAWCS_QuartzJob;
+using WIDESEAWCS_Tasks.Workflow.Abstractions;
+
+namespace WIDESEAWCS_Tasks
+{
+    /// <summary>
+    /// 鏈哄櫒浜轰换鍔″鐞嗗櫒 - 璐熻矗浠诲姟鑾峰彇銆佷笅鍙戙�佸叆搴撲换鍔″洖浼犲強搴撳瓨 DTO 鏋勫缓
+    /// </summary>
+    /// <remarks>
+    /// 鏍稿績鑱岃矗锛�
+    /// 1. 浠庢暟鎹簱杞寰呭鐞嗙殑鏈哄櫒浜轰换鍔�
+    /// 2. 鍚戞満鍣ㄤ汉瀹㈡埛绔笅鍙戝彇璐ф寚浠わ紙Pickbattery锛�
+    /// 3. 澶勭悊鍏ュ簱浠诲姟鐨勫洖浼狅紙鎷嗙洏/缁勭洏/鎹㈢洏鍦烘櫙锛�
+    /// 4. 鏋勫缓搴撳瓨鍥炰紶 DTO 骞惰皟鐢� WMS 鎺ュ彛
+    ///
+    /// 閫氳繃缃戝叧璁块棶 Socket锛岄伩鍏嶄笟鍔″眰鐩存帴渚濊禆 TcpSocketServer銆�
+    /// </remarks>
+    public class RobotTaskProcessor
+    {
+        /// <summary>
+        /// Socket 瀹㈡埛绔綉鍏虫帴鍙�
+        /// </summary>
+        /// <remarks>
+        /// 閫氳繃缃戝叧璁块棶 Socket锛岄伩鍏嶄笟鍔″眰鐩存帴渚濊禆 TcpSocketServer銆�
+        /// 鎻愪緵缁熶竴鐨勫鎴风閫氫俊鎺ュ彛銆�
+        /// </remarks>
+        private readonly ISocketClientGateway _socketClientGateway;
+
+        /// <summary>
+        /// 鏈烘鎵嬬姸鎬佺鐞嗗櫒
+        /// </summary>
+        private readonly RobotStateManager _stateManager;
+
+        /// <summary>
+        /// 鏈哄櫒浜轰换鍔℃湇鍔�
+        /// </summary>
+        /// <remarks>
+        /// 鐢ㄤ簬鏌ヨ銆佹洿鏂般�佸垹闄ゆ満鍣ㄤ汉浠诲姟璁板綍銆�
+        /// </remarks>
+        private readonly IRobotTaskService _robotTaskService;
+
+        /// <summary>
+        /// 閫氱敤浠诲姟鏈嶅姟
+        /// </summary>
+        /// <remarks>
+        /// 鐢ㄤ簬涓� WMS 绯荤粺浜や簰锛屾帴鏀朵换鍔°�佸鐞嗕换鍔$姸鎬佺瓑銆�
+        /// </remarks>
+        private readonly ITaskService _taskService;
+
+        /// <summary>
+        /// HTTP 瀹㈡埛绔府鍔╃被
+        /// </summary>
+        /// <remarks>
+        /// 鐢ㄤ簬璋冪敤 WMS 绯荤粺鐨� HTTP 鎺ュ彛銆�
+        /// </remarks>
+        private readonly HttpClientHelper _httpClientHelper;
+
+        /// <summary>
+        /// 鍋囩數鑺钩闈㈢偣浣嶆湇鍔�
+        /// </summary>
+        /// <remarks>
+        /// 鐢ㄤ簬绠$悊鍋囩數鑺钩闈㈢偣浣嶇殑鍒嗛厤鍜岀姸鎬併��
+        /// </remarks>
+        private readonly IFakeBatteryPositionService _fakeBatteryPositionService;
+
+        /// <summary>
+        /// 鏃ュ織璁板綍鍣�
+        /// </summary>
         private readonly ILogger _logger;
-
-        /// <summary>
-        /// 鏋勯�犲嚱鏁�
-        /// </summary>
-        /// <param name="socketClientGateway">Socket 缃戝叧</param>
-        /// <param name="stateManager">鐘舵�佺鐞嗗櫒</param>
-        /// <param name="robotTaskService">鏈哄櫒浜轰换鍔℃湇鍔�</param>
-        /// <param name="taskService">閫氱敤浠诲姟鏈嶅姟</param>
-        /// <param name="httpClientHelper">HTTP 瀹㈡埛绔府鍔╃被</param>
-        /// <param name="logger">鏃ュ織璁板綍鍣�</param>
-        public RobotTaskProcessor(
-            ISocketClientGateway socketClientGateway,
-            RobotStateManager stateManager,
-            IRobotTaskService robotTaskService,
-            ITaskService taskService,
-            HttpClientHelper httpClientHelper,
-            ILogger logger,
-            IFakeBatteryPositionService fakeBatteryPositionService)
-        {
-            _socketClientGateway = socketClientGateway;
-            _stateManager = stateManager;
-            _robotTaskService = robotTaskService;
-            _taskService = taskService;
-            _httpClientHelper = httpClientHelper;
-            _logger = logger;
-            _fakeBatteryPositionService = fakeBatteryPositionService;
-        }
-
-        /// <summary>
-        /// 鎸夎澶囩紪鐮佽幏鍙栧綋鍓嶆満鍣ㄤ汉鐨勫緟澶勭悊浠诲姟
-        /// </summary>
-        /// <remarks>
-        /// 浠庢暟鎹簱涓煡璇㈡寚瀹氳澶囩紪鐮佺殑寰呭鐞嗘満鍣ㄤ汉浠诲姟銆�
-        /// 鍙繑鍥炵姸鎬佷负"寰呭鐞�"鐨勪换鍔°��
-        /// </remarks>
-        /// <param name="robotCrane">鏈哄櫒浜鸿澶囦俊鎭紝鍖呭惈璁惧缂栫爜</param>
-        /// <returns>寰呭鐞嗙殑浠诲姟瀵硅薄锛屽鏋滄病鏈夊垯杩斿洖 null</returns>
-        public Dt_RobotTask? GetTask(RobotCraneDevice robotCrane)
-        {
-            return _robotTaskService.QueryRobotCraneTask(robotCrane.DeviceCode);
-        }
-
-        /// <summary>
-        /// 鎸夎澶囩紪鐮佽幏鍙栧綋鍓嶆満鍣ㄤ汉鐨勬墽琛屼腑浠诲姟
-        /// </summary>
-        /// <remarks>
-        /// 浠庢暟鎹簱涓煡璇㈡寚瀹氳澶囩紪鐮佺殑鎵ц涓満鍣ㄤ汉浠诲姟銆�
-        /// 褰揜obotArmObject涓�1锛堟湁鐗╂枡锛変笖娌℃湁寰呭鐞嗕换鍔℃椂璋冪敤銆�
-        /// </remarks>
-        /// <param name="robotCrane">鏈哄櫒浜鸿澶囦俊鎭紝鍖呭惈璁惧缂栫爜</param>
-        /// <returns>鎵ц涓殑浠诲姟瀵硅薄锛屽鏋滄病鏈夊垯杩斿洖 null</returns>
-        public Dt_RobotTask? GetExecutingTask(RobotCraneDevice robotCrane)
-        {
-            return _robotTaskService.QueryRobotCraneExecutingTask(robotCrane.DeviceCode);
-        }
-
-        /// <summary>
-        /// 鍒犻櫎鏈哄櫒浜轰换鍔�
-        /// </summary>
-        /// <remarks>
-        /// 褰撲换鍔″畬鎴愶紙鏃犺鏄垚鍔熻繕鏄け璐ワ級鏃惰皟鐢紝鍒犻櫎鏁版嵁搴撲腑鐨勪换鍔¤褰曘��
-        /// </remarks>
-        /// <param name="ID">瑕佸垹闄ょ殑浠诲姟 ID</param>
-        /// <returns>鍒犻櫎鏄惁鎴愬姛</returns>
-        public bool? DeleteTask(int ID)
-        {
-            return _robotTaskService.DeleteRobotTask(ID);
-        }
-
-        /// <summary>
-        /// 涓嬪彂鍙栬揣鎸囦护锛圥ickbattery锛夊埌鏈哄櫒浜哄鎴风
-        /// </summary>
-        /// <remarks>
-        /// 鍙戦�佹牸寮忥細Pickbattery,{婧愬湴鍧�}
-        /// 渚嬪锛歅ickbattery,A01 琛ㄧず浠� A01 浣嶇疆鍙栬揣
-        ///
-        /// 涓嬪彂鎴愬姛鍚庯細
-        /// 1. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
-        /// 2. 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
-        /// 3. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
-        /// 4. 鏇存柊浠诲姟璁板綍鍒版暟鎹簱
-        /// </remarks>
-        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
-        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
-        /// <param name="isScanNG">鏄惁鎵爜NG</param>
-        public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state, bool isScanNG = false)
-        {
-            // 鏋勫缓鍙栬揣鎸囦护锛屾牸寮忥細Pickbattery,{婧愬湴鍧�}
-            string taskString = $"Pickbattery,{task.RobotSourceAddress}";
-
-            // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
-            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
-
-            // 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
-            state.CurrentTask = task;
-
-            if (isScanNG)
-            {
-                state.IsScanNG = true;
-            }
-
-            // 淇濇寔鍘熻涔夛細浠呭湪鐘舵�佸畨鍏ㄥ啓鍏ユ垚鍔熷悗鍐嶆洿鏂颁换鍔$姸鎬�
-            // 杩欐牱鍙互纭繚鐘舵�佸拰浠诲姟璁板綍鐨勪竴鑷存��
-            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
-            {
-                QuartzLogHelper.LogInfo(_logger, $"鐘舵�佹洿鏂版垚鍔燂紝璁惧: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                // 閫氳繃 Socket 缃戝叧鍙戦�佹寚浠ゅ埌鏈哄櫒浜哄鎴风
-                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
-                if (result)
-                {
-                    // 鍙戦�佹垚鍔燂紝璁板綍 Info 鏃ュ織
-                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                    //await _robotTaskService.UpdateRobotTaskAsync(task);
-                }
-                else
-                {
-                    // 鍙戦�佸け璐ワ紝璁板綍 Error 鏃ュ織
-                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鍙栬揣鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                }
-            }
-        }
-
-        /// <summary>
-        /// 涓嬪彂鍋囩數鑺彇璐ф寚浠ゅ埌鏈哄櫒浜哄鎴风
-        /// </summary>
-        /// <remarks>
-        /// 鍙戦�佹牸寮忥細Pickbattery,5,{startPosition}-{endPosition}
-        /// 渚嬪锛歅ickbattery,5,1-3 琛ㄧず浠庡亣鐢佃姱浣嶇疆5鎶撳彇锛屽钩闈㈢偣浣�1鍒�3
-        ///
-        /// 涓嬪彂鎴愬姛鍚庯細
-        /// 1. 鏍囪鐐逛綅涓哄凡浣跨敤
-        /// 2. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
-        /// 3. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
-        /// </remarks>
-        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
-        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
-        /// <param name="positions">瑕佹姄鍙栫殑骞抽潰鐐逛綅鍒楄〃</param>
-        public async Task SendSocketRobotFakeBatteryPickAsync(Dt_RobotTask task, RobotSocketState state, List<int> positions)
-        {
-            if (positions == null || positions.Count == 0)
-            {
-                QuartzLogHelper.LogWarn(_logger, $"SendSocketRobotFakeBatteryPickAsync锛氬钩闈㈢偣浣嶅垪琛ㄤ负绌猴紝浠诲姟鍙�: {task.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
-                return;
-            }
-
-            // 璁$畻鐐逛綅鑼冨洿锛屾牸寮忥細1-3
-            int startPos = positions.Min();
-            int endPos = positions.Max();
-            string taskString = $"Pickbattery,5,{startPos}-{endPos}";
-
-            // 鏍囪鐐逛綅涓哄凡浣跨敤
-            _fakeBatteryPositionService.MarkAsUsed(positions);
-
-            // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
-            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
-
-            // 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
-            state.CurrentTask = task;
-
-            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
-            {
-                // 閫氳繃 Socket 缃戝叧鍙戦�佹寚浠ゅ埌鏈哄櫒浜哄鎴风
-                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
-
-                if (result)
-                {
-                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鍋囩數鑺彇璐ф寚浠ゆ垚鍔燂紝鎸囦护: {taskString}锛岀偣浣�: {string.Join(",", positions)}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                    //await _robotTaskService.UpdateRobotTaskAsync(task);
-                }
-                else
-                {
-                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鍋囩數鑺彇璐ф寚浠ゅけ璐ワ紝鎸囦护: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                }
-            }
-        }
-
-        /// <summary>
-        /// 鑾峰彇涓婲涓彲鐢ㄧ殑鍋囩數鑺钩闈㈢偣浣�
-        /// </summary>
-        /// <param name="count">闇�瑕佽幏鍙栫殑鐐逛綅鏁伴噺</param>
-        /// <returns>鍙敤鐐逛綅鍒楄〃</returns>
-        public List<int> GetNextAvailableFakeBatteryPositions(int count)
-        {
-            return _fakeBatteryPositionService.GetNextAvailable(count);
-        }
-
-        /// <summary>
-        /// 璁$畻鎵规缂栧彿鑼冨洿
-        /// </summary>
-        /// <remarks>
-        /// 杩斿洖鏍煎紡锛�(start, end)
-        /// - remaining >= 4: (currentIndex, currentIndex + 3)
-        /// - remaining > 1: (currentIndex, currentIndex + remaining - 1)
-        /// - remaining == 1: (currentIndex, 0)  -- 鍗曚釜鐗╁搧鐢� 0 琛ㄧず end
-        /// </remarks>
-        /// <param name="currentIndex">褰撳墠鎵规璧峰缂栧彿</param>
-        /// <param name="remaining">鍓╀綑鏁伴噺</param>
-        /// <returns>(start, end) 鍏冪粍</returns>
-        public (int Start, int End) BuildBatchRange(int currentIndex, int remaining)
-        {
-            if (remaining >= 4)
-                return (currentIndex, currentIndex + 3);
-            else if (remaining > 1)
-                return (currentIndex, currentIndex + remaining - 1);
-            else  // remaining == 1
-                return (currentIndex, 0);
-        }
-
-        /// <summary>
-        /// 涓嬪彂鍙栬揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
-        /// </summary>
-        /// <remarks>
-        /// 鍙戦�侀『搴忥細
-        /// 1. PickTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
-        /// 2. Pickbattery,{浣嶇疆},{start}-{end} -- 鎵规鍙栬揣鎸囦护
-        ///
-        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
-        /// </remarks>
-        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
-        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
-        /// <param name="position">鍙栬揣浣嶇疆</param>
-        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
-        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
-        public async Task SendPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
-        {
-
-            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
-            state.CurrentTask = task;
-
-            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
-            {
-                // 鍏堝彂閫佹�绘暟鎸囦护
-                string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
-                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
-
-                // 鍐嶅彂閫佹壒娆″彇璐ф寚浠�
-                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
-                string taskString = $"Pickbattery,{position},{range}";
-
-                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
-
-                if (result)
-                {
-                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鎵规鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                    //await _robotTaskService.UpdateRobotTaskAsync(task);
-                }
-                else
-                {
-                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鎵规鍙栬揣鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                }
-            }
-        }
-
-        /// <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)
-        {
-            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
-            state.CurrentTask = task;
-
-            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
-            {
-                // 鍏堝彂閫佹�绘暟鎸囦护
-                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)
-                {
-                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鍋囩數鑺壒娆″彇璐ф寚浠ゆ垚鍔燂紝鎸囦护: {taskString}锛屾壒娆�: {range}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-
-                    //await _robotTaskService.UpdateRobotTaskAsync(task);
-                }
-                else
-                {
-                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鍋囩數鑺壒娆″彇璐ф寚浠ゅけ璐ワ紝鎸囦护: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                }
-            }
-        }
-
-        /// <summary>
-        /// 涓嬪彂鏀捐揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
-        /// </summary>
-        /// <remarks>
-        /// 鍙戦�侀『搴忥細
-        /// 1. PutTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
-        /// 2. Putbattery,{浣嶇疆},{start}-{end} -- 鎵规鏀捐揣鎸囦护
-        ///
-        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
-        /// </remarks>
-        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
-        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
-        /// <param name="position">鏀捐揣浣嶇疆</param>
-        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
-        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
-        public async Task SendPutWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
-        {
-            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
-            state.CurrentTask = task;
-
-            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
-            {
-                // 鍏堝彂閫佹�绘暟鎸囦护
-                string totalNumCmd = $"PutTotalNum,{task.RobotTaskTotalNum}";
-                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
-
-                // 鍐嶅彂閫佹壒娆℃斁璐ф寚浠�
-                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
-                string taskString = $"Putbattery,{position},{range}";
-
-                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
-
-                if (result)
-                {
-                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-
-                    //await _robotTaskService.UpdateRobotTaskAsync(task);
-                }
-                else
-                {
-                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
-                }
-            }
-        }
-
-        /// <summary>
-        /// 澶勭悊鍏ュ簱浠诲姟鍥炰紶锛堟媶鐩�/缁勭洏/鎹㈢洏鍦烘櫙锛�
-        /// </summary>
-        /// <remarks>
-        /// 褰撳彇璐у畬鎴愶紙AllPickFinished锛夋垨鏀捐揣瀹屾垚锛圓llPutFinished锛夋椂璋冪敤姝ゆ柟娉曘��
-        /// 鏍规嵁浠诲姟绫诲瀷鍜屽湴鍧�鏉ユ簮鍐冲畾濡備綍鍥炰紶缁� WMS銆�
-        ///
-        /// 澶勭悊閫昏緫锛�
-        /// 1. 鏍规嵁 useSourceAddress 鍐冲畾浣跨敤婧愬湴鍧�杩樻槸鐩爣鍦板潃
-        /// 2. 鏍规嵁浠诲姟绫诲瀷锛堢粍鐩�/鎹㈢洏/鎷嗙洏锛夊喅瀹氫换鍔$被鍨嬶紙鍏ュ簱/绌烘墭鐩樺叆搴擄級
-        /// 3. 鏋勫缓 CreateTaskDto 骞惰皟鐢� WMS 鎺ュ彛鍒涘缓浠诲姟
-        /// 4. 鎺ユ敹 WMS 杩斿洖鐨勪换鍔′俊鎭�
-        /// 5. 鏇存柊杈撻�佺嚎鐨勭洰鏍囧湴鍧�銆佷换鍔″彿绛�
-        /// </remarks>
-        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
-        /// <param name="useSourceAddress">鏄惁浣跨敤婧愬湴鍧�锛坱rue 琛ㄧず鎷嗙洏/鎹㈢洏鍦烘櫙锛宖alse 琛ㄧず缁勭洏/鎹㈢洏鍦烘櫙锛�</param>
-        /// <returns>澶勭悊鏄惁鎴愬姛</returns>
-        public async Task<bool> HandleInboundTaskAsync(RobotSocketState state, bool useSourceAddress, string isRoadway = null)
-        {
-            // 鑾峰彇褰撳墠鍏宠仈鐨勪换鍔�
-            var currentTask = state.CurrentTask;
-            if (currentTask == null)
-            {
-                QuartzLogHelper.LogDebug(_logger, $"HandleInboundTaskAsync锛氬綋鍓嶄换鍔′负绌�", state.RobotCrane?.DeviceName ?? "Unknown");
-                return false;
-            }
-
-            // 鑾峰彇宸烽亾浠g爜
-            string roadway = string.Empty;
-
-            // 鏍规嵁宸烽亾鍚嶇О鍒ゆ柇浠撳簱 ID
-            int warehouseId = 0;
-
-            // 婧愬湴鍧�鍜岀洰鏍囧湴鍧�锛堝垵濮嬪寲锛�
-            string SourceAddress = currentTask.RobotTargetAddressLineCode;
-            string TargetAddress = currentTask.RobotSourceAddressLineCode;
-
-            // 浠诲姟绫诲瀷锛�0 琛ㄧず鏈畾涔夛紝绋嶅悗鏍规嵁浠诲姟绫诲瀷璁剧疆锛�
-            int taskType = 0;
-
-            // 鎵樼洏浠g爜锛堝垵濮嬪寲涓虹┖锛�
-            string PalletCode = string.Empty;
-
-            // 鑾峰彇浠诲姟绫诲瀷鐨勬灇涓惧��
-            var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType;
-
-            // 鏍规嵁 useSourceAddress 鍐冲畾澶勭悊閫昏緫
-            if (useSourceAddress)
-            {
-                // 浣跨敤婧愬湴鍧�鐨勫満鏅細鎷嗙洏銆佹崲鐩橈紙鏀剧┖鎵樼洏锛�
-                switch (robotTaskType)
-                {
-                    case RobotTaskTypeEnum.GroupPallet:
-                        warehouseId = 1;
-                        roadway = "GWSC1";
-                        break;
-
-                    case RobotTaskTypeEnum.ChangePallet:
-                        // 鎹㈢洏/鎷嗙洏鍦烘櫙锛氭墭鐩橀渶瑕佸叆搴�
-                        taskType = TaskTypeEnum.InEmpty.GetHashCode();  // 绌烘墭鐩樺叆搴�
-                        PalletCode = currentTask.RobotSourceAddressPalletCode;  // 浣跨敤婧愬湴鍧�鐨勬墭鐩樼爜
-                        if (isRoadway == "HWSC1")
-                        {
-                            warehouseId = 2;
-                            roadway = "HWSC1";
-                        }
-                        else if (isRoadway == "GWSC1")
-                        {
-                            warehouseId = 1;
-                            roadway = "GWSC1";
-                        }
-
-                        break;
-                    case RobotTaskTypeEnum.SplitPallet:
-                        // 鎹㈢洏/鎷嗙洏鍦烘櫙锛氭墭鐩橀渶瑕佸叆搴�
-                        taskType = TaskTypeEnum.InEmpty.GetHashCode();  // 绌烘墭鐩樺叆搴�
-                        PalletCode = currentTask.RobotSourceAddressPalletCode;  // 浣跨敤婧愬湴鍧�鐨勬墭鐩樼爜
-
-                        warehouseId = 3;
-                        roadway = "CWSC1";
-                        break;
-                }
-            }
-            else
-            {
-                // 浣跨敤鐩爣鍦板潃鐨勫満鏅細缁勭洏銆佹崲鐩橈紙鎴愬搧鍏ュ簱锛�
-                switch (robotTaskType)
-                {
-                    case RobotTaskTypeEnum.ChangePallet:
-                        // 鎹㈢洏/缁勭洏鍦烘櫙锛氳揣鐗╅渶瑕佸叆搴�
-                        taskType = TaskTypeEnum.Inbound.GetHashCode();  // 鎴愬搧鍏ュ簱
-                        PalletCode = currentTask.RobotTargetAddressPalletCode;  // 浣跨敤鐩爣鍦板潃鐨勬墭鐩樼爜
-
-                        if (isRoadway == "HWSC1")
-                        {
-                            warehouseId = 2;
-                            roadway = "HWSC1";
-                        }
-                        else if (isRoadway == "GWSC1")
-                        {
-                            warehouseId = 1;
-                            roadway = "GWSC1";
-                        }
-
-                        break;
-                    case RobotTaskTypeEnum.GroupPallet:
-                        // 鎹㈢洏/缁勭洏鍦烘櫙锛氳揣鐗╅渶瑕佸叆搴�
-                        taskType = TaskTypeEnum.Inbound.GetHashCode();  // 鎴愬搧鍏ュ簱
-                        PalletCode = currentTask.RobotTargetAddressPalletCode;  // 浣跨敤鐩爣鍦板潃鐨勬墭鐩樼爜
-
-                        warehouseId = 1;
-                        roadway = "GWSC1";
-                        break;
-
-                    case RobotTaskTypeEnum.SplitPallet:
-
-                        break;
-                }
-            }
-
-            // 鏋勫缓鍒涘缓浠诲姟鐨� DTO
-            CreateTaskDto taskDto = new CreateTaskDto
-            {
-                PalletCode = PalletCode,                    // 鎵樼洏鏉$爜
-                SourceAddress = SourceAddress ?? string.Empty,  // 婧愬湴鍧�
-                TargetAddress = roadway ?? string.Empty,  // 鐩爣鍦板潃
-                Roadway = roadway ?? string.Empty,             // 宸烽亾
-                WarehouseId = warehouseId,                   // 浠撳簱 ID
-                PalletType = 1,                             // 鎵樼洏绫诲瀷锛堥粯璁や负1锛�
-                TaskType = taskType                         // 浠诲姟绫诲瀷锛堝叆搴�/绌烘墭鐩樺叆搴擄級
-            };
-
-            // 璁板綍鏃ュ織锛氬紑濮嬭皟鐢� WMS 鍒涘缓鍏ュ簱浠诲姟
-            QuartzLogHelper.LogInfo(_logger, $"HandleInboundTaskAsync锛氳皟鐢╓MS鍒涘缓鍏ュ簱浠诲姟锛屾墭鐩樼爜: {PalletCode}锛屼换鍔$被鍨�: {taskType}", state.RobotCrane?.DeviceName ?? "Unknown");
-
-            // 璋冪敤 WMS 鎺ュ彛鍒涘缓鍏ュ簱浠诲姟
-            string configKey = nameof(ConfigKey.CreateTaskInboundAsync);
-            string requestParam = taskDto.ToJson();
-            DateTime startTime = DateTime.Now;
-
-            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
-
-            if (!result.IsSuccess || !result.Data.Status)
-            {
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", state.RobotCrane?.DeviceName ?? "Unknown");
-                return false;
-            }
-
-            QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", state.RobotCrane?.DeviceName ?? "Unknown");
-
-            // 濡傛灉璋冪敤澶辫触鎴栬繑鍥為敊璇姸鎬�
-            if (!result.Data.Status && result.IsSuccess)
-            {
-                QuartzLogHelper.LogError(_logger, $"HandleInboundTaskAsync锛歐MS杩斿洖閿欒鐘舵�侊紝Status: {result.Data.Status}", state.RobotCrane?.DeviceName ?? "Unknown");
-                return false;
-            }
-
-            // 瑙f瀽 WMS 杩斿洖鐨勪换鍔′俊鎭�
-            WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO();
-
-            // 璋冪敤浠诲姟鏈嶅姟鎺ユ敹 WMS 浠诲姟
-            var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO });
-            if (!content.Status)
-            {
-                QuartzLogHelper.LogError(_logger, $"HandleInboundTaskAsync锛氭帴鏀禬MS浠诲姟澶辫触", state.RobotCrane?.DeviceName ?? "Unknown");
-                return false;
-            }
-
-            return true;
-        }
-
-        /// <summary>
-        /// 鏋勫缓搴撳瓨鍥炰紶 DTO
-        /// </summary>
-        /// <remarks>
-        /// 鐢ㄤ簬鎷嗙洏鍜岀粍鐩樻搷浣滄椂锛屽悜 WMS 鍥炰紶搴撳瓨淇℃伅銆�
-        /// DTO 鍖呭惈婧愯揣浣嶃�佺洰鏍囪揣浣嶃�佹墭鐩樼爜浠ュ強姣忎釜浣嶇疆鐨勭數姹犳潯鐮併��
-        /// </remarks>
-        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
-        /// <param name="positions">鐢垫睜浣嶇疆鏁扮粍</param>
-        /// <returns>鏋勫缓濂界殑搴撳瓨 DTO</returns>
-        public static StockDTO BuildStockDTO(RobotSocketState state, int[] positions)
-        {
-            return new StockDTO
-            {
-                // 婧愯緭閫佺嚎缂栧彿
-                SourceLineNo = state.CurrentTask.RobotSourceAddressLineCode,
-
-                // 婧愭墭鐩樺彿
-                SourcePalletNo = state.CurrentTask.RobotSourceAddressPalletCode,
-
-                // 鐩爣鎵樼洏鍙�
-                TargetPalletNo = state.CurrentTask.RobotTargetAddressPalletCode,
-
-                // 鐩爣杈撻�佺嚎缂栧彿
-                TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode,
-
-                // 宸烽亾缂栧彿(鏈哄櫒浜哄悕绉�)
-                Roadway = state.CurrentTask.RobotRoadway,
-
-                // 鐢垫睜浣嶇疆璇︽儏鍒楄〃
-                // 杩囨护鎺変綅缃负 0 鎴栬礋鏁扮殑鏃犳晥鏁版嵁
-                // 鎸変綅缃紪鍙锋帓搴�
-                // 涓烘瘡涓綅缃敓鎴愬搴旂殑搴撳瓨璇︽儏
-                Details = positions
-                    .Where(x => x > 0)  // 杩囨护鏃犳晥浣嶇疆
-                    .OrderBy(x => x)   // 鎸変綅缃帓搴�
-                    .Select((x, idx) => new StockDetailDTO
-                    {
-                        // 鏁伴噺锛氬鏋滃凡鏈変换鍔℃�绘暟锛屼娇鐢ㄤ换鍔℃�绘暟+褰撳墠浣嶇疆鏁帮紱鍚﹀垯鍙娇鐢ㄥ綋鍓嶄綅缃暟
-                        Quantity = 1,
-
-                        // 閫氶亾/浣嶇疆缂栧彿
-                        Channel = x,
-
-                        // 鐢垫睜鏉$爜锛氬鏋滅姸鎬佷腑鏈夋潯鐮佸垪琛紝鍙栧搴斾綅缃殑鏉$爜锛涘惁鍒欎负绌�
-                        //CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : ""
-                        CellBarcode = state.CellBarcode[idx].ToString()
-                    })
-                    .ToList()
-            };
-        }
-
-        /// <summary>
-        /// 璋冪敤鎷嗙洏 API
-        /// </summary>
-        /// <remarks>
-        /// 褰撳彇璐у畬鎴愪笖闇�瑕佹媶鐩樻椂璋冪敤銆�
-        /// 灏嗙數姹犱粠鎵樼洏涓婂彇涓嬶紝閫愪釜鏀剧疆鍒扮洰鏍囦綅缃��
-        /// </remarks>
-        /// <param name="stockDTO">搴撳瓨 DTO锛屽寘鍚鎷嗙洏鐨勭數鑺俊鎭�</param>
-        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
-        public HttpResponseResult<WebResponseContent> PostSplitPalletAsync(StockDTO stockDTO)
-        {
-            string configKey = nameof(ConfigKey.SplitPalletAsync);
-            string requestParam = stockDTO.ToJson();
-            DateTime startTime = DateTime.Now;
-
-            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
-
-            if (!result.IsSuccess || !result.Data.Status)
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
-            else
-                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
-
-            return result;
-        }
-
-        /// <summary>
-        /// 璋冪敤缁勭洏/鎹㈢洏 API
-        /// </summary>
-        /// <remarks>
-        /// 褰撴斁璐у畬鎴愪笖闇�瑕佺粍鐩樻垨鎹㈢洏鏃惰皟鐢ㄣ��
-        /// 灏嗗涓數姹犵粍鍚堝埌鍚屼竴涓墭鐩樹笂銆�
-        ///
-        /// configKey 鍙傛暟鍐冲畾璋冪敤鍝釜 API锛�
-        /// - GroupPalletAsync: 缁勭洏鎺ュ彛
-        /// - ChangePalletAsync: 鎹㈢洏鎺ュ彛
-        /// </remarks>
-        /// <param name="configKey">閰嶇疆閿悕锛屽喅瀹氳皟鐢ㄥ摢涓� API</param>
-        /// <param name="stockDTO">搴撳瓨 DTO锛屽寘鍚缁勭洏鐨勭數鑺俊鎭�</param>
-        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
-        public HttpResponseResult<WebResponseContent> PostGroupPalletAsync(string configKey, StockDTO stockDTO)
-        {
-            string requestParam = stockDTO.ToJson();
-            DateTime startTime = DateTime.Now;
-
-            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
-
-            if (!result.IsSuccess || !result.Data.Status)
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
-            else
-                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
-
-            return result;
-        }
-
-        /// <summary>
-        /// 璋冪敤鎵归噺鎷嗙洏纭 API
-        /// </summary>
-        /// <remarks>
-        /// 褰撴媶鐩樹换鍔″叏閮ㄥ彇瀹屾椂璋冪敤锛屼竴娆℃�т笂浼犳暣涓墭鐩樼殑瑙g粦鏁版嵁鍒� MES銆�
-        /// </remarks>
-        /// <param name="palletCode">婧愭墭鐩樺彿</param>
-        /// <param name="deviceName">璁惧鍚嶇О锛岀敤浜庝紶閫掑埌 WMS</param>
-        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
-        public HttpResponseResult<WebResponseContent> PostSplitPalletConfirmAsync(string palletCode, string deviceName)
-        {
-            string configKey = nameof(ConfigKey.SplitPalletConfirm);
-            var request = new { PalletCode = palletCode, DeviceName = deviceName };
-            string requestParam = request.ToJson();
-            DateTime startTime = DateTime.Now;
-
-            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
-
-            if (!result.IsSuccess || !result.Data.Status)
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
-            else
-                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
-
-            return result;
-        }
-
-        /// <summary>
-        /// 璋冪敤鎵归噺缁勭洏纭 API
-        /// </summary>
-        /// <remarks>
-        /// 褰撶粍鐩樹换鍔″叏閮ㄦ斁瀹屾椂璋冪敤锛屼竴娆℃�т笂浼犳暣涓墭鐩樼殑缁戝畾鏁版嵁鍒� MES銆�
-        /// </remarks>
-        /// <param name="palletCode">鐩爣鎵樼洏鍙�</param>
-        /// <param name="deviceName">璁惧鍚嶇О锛岀敤浜庝紶閫掑埌 WMS</param>
-        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
-        public HttpResponseResult<WebResponseContent> PostGroupPalletConfirmAsync(string palletCode, string deviceName)
-        {
-            string configKey = nameof(ConfigKey.GroupPalletConfirm);
-            var request = new { PalletCode = palletCode, DeviceName = deviceName };
-            string requestParam = request.ToJson();
-            DateTime startTime = DateTime.Now;
-
-            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
-
-            if (!result.IsSuccess || !result.Data.Status)
-                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
-            else
-                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
-
-            return result;
-        }
-
-        public bool UpdateRobotTask(Dt_RobotTask task)
-        {
-            WebResponseContent content = _robotTaskService.UpdateData(task);
-            return content.Status;
-        }
-    }
-}
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="socketClientGateway">Socket 缃戝叧</param>
+        /// <param name="stateManager">鐘舵�佺鐞嗗櫒</param>
+        /// <param name="robotTaskService">鏈哄櫒浜轰换鍔℃湇鍔�</param>
+        /// <param name="taskService">閫氱敤浠诲姟鏈嶅姟</param>
+        /// <param name="httpClientHelper">HTTP 瀹㈡埛绔府鍔╃被</param>
+        /// <param name="logger">鏃ュ織璁板綍鍣�</param>
+        public RobotTaskProcessor(
+            ISocketClientGateway socketClientGateway,
+            RobotStateManager stateManager,
+            IRobotTaskService robotTaskService,
+            ITaskService taskService,
+            HttpClientHelper httpClientHelper,
+            ILogger logger,
+            IFakeBatteryPositionService fakeBatteryPositionService)
+        {
+            _socketClientGateway = socketClientGateway;
+            _stateManager = stateManager;
+            _robotTaskService = robotTaskService;
+            _taskService = taskService;
+            _httpClientHelper = httpClientHelper;
+            _logger = logger;
+            _fakeBatteryPositionService = fakeBatteryPositionService;
+        }
+
+        /// <summary>
+        /// 鎸夎澶囩紪鐮佽幏鍙栧綋鍓嶆満鍣ㄤ汉鐨勫緟澶勭悊浠诲姟
+        /// </summary>
+        /// <remarks>
+        /// 浠庢暟鎹簱涓煡璇㈡寚瀹氳澶囩紪鐮佺殑寰呭鐞嗘満鍣ㄤ汉浠诲姟銆�
+        /// 鍙繑鍥炵姸鎬佷负"寰呭鐞�"鐨勪换鍔°��
+        /// </remarks>
+        /// <param name="robotCrane">鏈哄櫒浜鸿澶囦俊鎭紝鍖呭惈璁惧缂栫爜</param>
+        /// <returns>寰呭鐞嗙殑浠诲姟瀵硅薄锛屽鏋滄病鏈夊垯杩斿洖 null</returns>
+        public Dt_RobotTask? GetTask(RobotCraneDevice robotCrane)
+        {
+            return _robotTaskService.QueryRobotCraneTask(robotCrane.DeviceCode);
+        }
+
+        /// <summary>
+        /// 鎸夎澶囩紪鐮佽幏鍙栧綋鍓嶆満鍣ㄤ汉鐨勬墽琛屼腑浠诲姟
+        /// </summary>
+        /// <remarks>
+        /// 浠庢暟鎹簱涓煡璇㈡寚瀹氳澶囩紪鐮佺殑鎵ц涓満鍣ㄤ汉浠诲姟銆�
+        /// 褰揜obotArmObject涓�1锛堟湁鐗╂枡锛変笖娌℃湁寰呭鐞嗕换鍔℃椂璋冪敤銆�
+        /// </remarks>
+        /// <param name="robotCrane">鏈哄櫒浜鸿澶囦俊鎭紝鍖呭惈璁惧缂栫爜</param>
+        /// <returns>鎵ц涓殑浠诲姟瀵硅薄锛屽鏋滄病鏈夊垯杩斿洖 null</returns>
+        public Dt_RobotTask? GetExecutingTask(RobotCraneDevice robotCrane)
+        {
+            return _robotTaskService.QueryRobotCraneExecutingTask(robotCrane.DeviceCode);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="robotCrane"></param>
+        /// <returns></returns>
+        public Dt_RobotTask? GetRobotTask(RobotCraneDevice robotCrane)
+        {
+            return _robotTaskService.Repository.QueryFirst(x => x.RobotRoadway == robotCrane.DeviceCode);
+        }
+
+        /// <summary>
+        /// 鍒犻櫎鏈哄櫒浜轰换鍔�
+        /// </summary>
+        /// <remarks>
+        /// 褰撲换鍔″畬鎴愶紙鏃犺鏄垚鍔熻繕鏄け璐ワ級鏃惰皟鐢紝鍒犻櫎鏁版嵁搴撲腑鐨勪换鍔¤褰曘��
+        /// </remarks>
+        /// <param name="ID">瑕佸垹闄ょ殑浠诲姟 ID</param>
+        /// <returns>鍒犻櫎鏄惁鎴愬姛</returns>
+        public bool? DeleteTask(int ID)
+        {
+            return _robotTaskService.DeleteRobotTask(ID);
+        }
+
+        /// <summary>
+        /// 涓嬪彂鍙栬揣鎸囦护锛圥ickbattery锛夊埌鏈哄櫒浜哄鎴风
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�佹牸寮忥細Pickbattery,{婧愬湴鍧�}
+        /// 渚嬪锛歅ickbattery,A01 琛ㄧず浠� A01 浣嶇疆鍙栬揣
+        ///
+        /// 涓嬪彂鎴愬姛鍚庯細
+        /// 1. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
+        /// 2. 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
+        /// 3. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
+        /// 4. 鏇存柊浠诲姟璁板綍鍒版暟鎹簱
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="isScanNG">鏄惁鎵爜NG</param>
+        public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state, bool isScanNG = false)
+        {
+            // 鏋勫缓鍙栬揣鎸囦护锛屾牸寮忥細Pickbattery,{婧愬湴鍧�}
+            string taskString = $"Pickbattery,{task.RobotSourceAddress}";
+
+            // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
+            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+
+            // 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
+            state.CurrentTask = task;
+
+            if (isScanNG)
+            {
+                state.IsScanNG = true;
+            }
+
+            // 淇濇寔鍘熻涔夛細浠呭湪鐘舵�佸畨鍏ㄥ啓鍏ユ垚鍔熷悗鍐嶆洿鏂颁换鍔$姸鎬�
+            // 杩欐牱鍙互纭繚鐘舵�佸拰浠诲姟璁板綍鐨勪竴鑷存��
+            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+            {
+                QuartzLogHelper.LogInfo(_logger, $"鐘舵�佹洿鏂版垚鍔燂紝璁惧: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                // 閫氳繃 Socket 缃戝叧鍙戦�佹寚浠ゅ埌鏈哄櫒浜哄鎴风
+                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+                if (result)
+                {
+                    // 鍙戦�佹垚鍔燂紝璁板綍 Info 鏃ュ織
+                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                    //await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+                else
+                {
+                    // 鍙戦�佸け璐ワ紝璁板綍 Error 鏃ュ織
+                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鍙栬揣鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                }
+            }
+        }
+
+
+        public async Task SendSocketRobotNumAsync(Dt_RobotTask task, RobotSocketState state, bool isPick = true)
+        {
+            string taskString = string.Empty;
+
+            if (isPick)
+                // 鏋勫缓鎸囦护锛屾牸寮忥細PickTotalNum,{鏁伴噺}||PutTotalNum,{鏁伴噺}
+                taskString = $"PickTotalNum,{task.RobotTaskTotalNum + state.RobotTaskTotalNum}";
+            else
+                // 鏋勫缓鎸囦护锛屾牸寮忥細PutTotalNum,{鏁伴噺}||PutTotalNum,{鏁伴噺}
+                taskString = $"PutTotalNum,{task.RobotTaskTotalNum + state.RobotTaskTotalNum}";
+
+            // 閫氳繃 Socket 缃戝叧鍙戦�佹寚浠ゅ埌鏈哄櫒浜哄鎴风
+            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+            if (result)
+            {
+                // 鍙戦�佹垚鍔燂紝璁板綍 Info 鏃ュ織
+                QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鎬绘暟鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                //await _robotTaskService.UpdateRobotTaskAsync(task);
+            }
+            else
+            {
+                // 鍙戦�佸け璐ワ紝璁板綍 Error 鏃ュ織
+                QuartzLogHelper.LogError(_logger, $"涓嬪彂鎬绘暟鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+            }
+        }
+
+        /// <summary>
+        /// 涓嬪彂鍋囩數鑺彇璐ф寚浠ゅ埌鏈哄櫒浜哄鎴风
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�佹牸寮忥細Pickbattery,5,{startPosition}-{endPosition}
+        /// 渚嬪锛歅ickbattery,5,1-3 琛ㄧず浠庡亣鐢佃姱浣嶇疆5鎶撳彇锛屽钩闈㈢偣浣�1鍒�3
+        ///
+        /// 涓嬪彂鎴愬姛鍚庯細
+        /// 1. 鏍囪鐐逛綅涓哄凡浣跨敤
+        /// 2. 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
+        /// 3. 瀹夊叏鏇存柊鐘舵�佸埌 Redis
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="positions">瑕佹姄鍙栫殑骞抽潰鐐逛綅鍒楄〃</param>
+        public async Task SendSocketRobotFakeBatteryPickAsync(Dt_RobotTask task, RobotSocketState state, List<int> positions)
+        {
+            if (positions == null || positions.Count == 0)
+            {
+                QuartzLogHelper.LogWarn(_logger, $"SendSocketRobotFakeBatteryPickAsync锛氬钩闈㈢偣浣嶅垪琛ㄤ负绌猴紝浠诲姟鍙�: {task.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
+                return;
+            }
+
+            // 璁$畻鐐逛綅鑼冨洿锛屾牸寮忥細1-3
+            int startPos = positions.Min();
+            int endPos = positions.Max();
+            string taskString = $"Pickbattery,5,{startPos}-{endPos}";
+
+            // 鏍囪鐐逛綅涓哄凡浣跨敤
+            _fakeBatteryPositionService.MarkAsUsed(positions);
+
+            // 鏇存柊浠诲姟鐘舵�佷负"鏈哄櫒浜烘墽琛屼腑"
+            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+
+            // 灏嗕换鍔″叧鑱斿埌鐘舵�佸璞�
+            state.CurrentTask = task;
+
+            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+            {
+                // 閫氳繃 Socket 缃戝叧鍙戦�佹寚浠ゅ埌鏈哄櫒浜哄鎴风
+                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+                if (result)
+                {
+                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鍋囩數鑺彇璐ф寚浠ゆ垚鍔燂紝鎸囦护: {taskString}锛岀偣浣�: {string.Join(",", positions)}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                    //await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+                else
+                {
+                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鍋囩數鑺彇璐ф寚浠ゅけ璐ワ紝鎸囦护: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇涓婲涓彲鐢ㄧ殑鍋囩數鑺钩闈㈢偣浣�
+        /// </summary>
+        /// <param name="count">闇�瑕佽幏鍙栫殑鐐逛綅鏁伴噺</param>
+        /// <returns>鍙敤鐐逛綅鍒楄〃</returns>
+        public List<int> GetNextAvailableFakeBatteryPositions(int count)
+        {
+            return _fakeBatteryPositionService.GetNextAvailable(count);
+        }
+
+        /// <summary>
+        /// 璁$畻鎵规缂栧彿鑼冨洿
+        /// </summary>
+        /// <remarks>
+        /// 杩斿洖鏍煎紡锛�(start, end)
+        /// - remaining >= 4: (currentIndex, currentIndex + 3)
+        /// - remaining > 1: (currentIndex, currentIndex + remaining - 1)
+        /// - remaining == 1: (currentIndex, 0)  -- 鍗曚釜鐗╁搧鐢� 0 琛ㄧず end
+        /// </remarks>
+        /// <param name="currentIndex">褰撳墠鎵规璧峰缂栧彿</param>
+        /// <param name="remaining">鍓╀綑鏁伴噺</param>
+        /// <returns>(start, end) 鍏冪粍</returns>
+        public (int Start, int End) BuildBatchRange(int currentIndex, int remaining)
+        {
+            if (remaining >= 4)
+                return (currentIndex, currentIndex + 3);
+            else if (remaining > 1)
+                return (currentIndex, currentIndex + remaining - 1);
+            else  // remaining == 1
+                return (currentIndex, 0);
+        }
+
+        /// <summary>
+        /// 涓嬪彂鍙栬揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�侀『搴忥細
+        /// 1. PickTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
+        /// 2. Pickbattery,{浣嶇疆},{start}-{end} -- 鎵规鍙栬揣鎸囦护
+        ///
+        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="position">鍙栬揣浣嶇疆</param>
+        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
+        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
+        public async Task SendPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
+        {
+
+            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+            state.CurrentTask = task;
+
+            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+            {
+                // 鍏堝彂閫佹�绘暟鎸囦护
+                string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
+                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
+
+                // 鍐嶅彂閫佹壒娆″彇璐ф寚浠�
+                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
+                string taskString = $"Pickbattery,{position},{range}";
+
+                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+                if (result)
+                {
+                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鎵规鍙栬揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                    //await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+                else
+                {
+                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鎵规鍙栬揣鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                }
+            }
+        }
+
+        /// <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)
+        {
+            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+            state.CurrentTask = task;
+
+            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+            {
+                // 鍏堝彂閫佹�绘暟鎸囦护
+                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)
+                {
+                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鍋囩數鑺壒娆″彇璐ф寚浠ゆ垚鍔燂紝鎸囦护: {taskString}锛屾壒娆�: {range}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+
+                    //await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+                else
+                {
+                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鍋囩數鑺壒娆″彇璐ф寚浠ゅけ璐ワ紝鎸囦护: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 涓嬪彂鏀捐揣鎸囦护锛堝甫鎵规鏍煎紡鍜屾�绘暟锛�
+        /// </summary>
+        /// <remarks>
+        /// 鍙戦�侀『搴忥細
+        /// 1. PutTotalNum,{N} -- 鐪熷疄鐢佃姱鎬绘暟
+        /// 2. Putbattery,{浣嶇疆},{start}-{end} -- 鎵规鏀捐揣鎸囦护
+        ///
+        /// 涓嬪彂鎴愬姛鍚庢洿鏂颁换鍔$姸鎬佷负"鏈哄櫒浜烘墽琛屼腑"銆�
+        /// </remarks>
+        /// <param name="task">瑕佷笅鍙戠殑浠诲姟瀵硅薄</param>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="position">鏀捐揣浣嶇疆</param>
+        /// <param name="batchStart">鎵规璧峰缂栧彿</param>
+        /// <param name="batchEnd">鎵规缁撴潫缂栧彿</param>
+        public async Task SendPutWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
+        {
+            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
+            state.CurrentTask = task;
+
+            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
+            {
+                // 鍏堝彂閫佹�绘暟鎸囦护
+                string totalNumCmd = $"PutTotalNum,{task.RobotTaskTotalNum}";
+                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
+
+                // 鍐嶅彂閫佹壒娆℃斁璐ф寚浠�
+                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
+                string taskString = $"Putbattery,{position},{range}";
+
+                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
+
+                if (result)
+                {
+                    QuartzLogHelper.LogInfo(_logger, $"涓嬪彂鏀捐揣鎸囦护鎴愬姛锛屾寚浠�: {taskString}锛屾壒娆�: {range}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+
+                    //await _robotTaskService.UpdateRobotTaskAsync(task);
+                }
+                else
+                {
+                    QuartzLogHelper.LogError(_logger, $"涓嬪彂鏀捐揣鎸囦护澶辫触锛屾寚浠�: {taskString}锛岃澶�: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 澶勭悊鍏ュ簱浠诲姟鍥炰紶锛堟媶鐩�/缁勭洏/鎹㈢洏鍦烘櫙锛�
+        /// </summary>
+        /// <remarks>
+        /// 褰撳彇璐у畬鎴愶紙AllPickFinished锛夋垨鏀捐揣瀹屾垚锛圓llPutFinished锛夋椂璋冪敤姝ゆ柟娉曘��
+        /// 鏍规嵁浠诲姟绫诲瀷鍜屽湴鍧�鏉ユ簮鍐冲畾濡備綍鍥炰紶缁� WMS銆�
+        ///
+        /// 澶勭悊閫昏緫锛�
+        /// 1. 鏍规嵁 useSourceAddress 鍐冲畾浣跨敤婧愬湴鍧�杩樻槸鐩爣鍦板潃
+        /// 2. 鏍规嵁浠诲姟绫诲瀷锛堢粍鐩�/鎹㈢洏/鎷嗙洏锛夊喅瀹氫换鍔$被鍨嬶紙鍏ュ簱/绌烘墭鐩樺叆搴擄級
+        /// 3. 鏋勫缓 CreateTaskDto 骞惰皟鐢� WMS 鎺ュ彛鍒涘缓浠诲姟
+        /// 4. 鎺ユ敹 WMS 杩斿洖鐨勪换鍔′俊鎭�
+        /// 5. 鏇存柊杈撻�佺嚎鐨勭洰鏍囧湴鍧�銆佷换鍔″彿绛�
+        /// </remarks>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="useSourceAddress">鏄惁浣跨敤婧愬湴鍧�锛坱rue 琛ㄧず鎷嗙洏/鎹㈢洏鍦烘櫙锛宖alse 琛ㄧず缁勭洏/鎹㈢洏鍦烘櫙锛�</param>
+        /// <returns>澶勭悊鏄惁鎴愬姛</returns>
+        public async Task<bool> HandleInboundTaskAsync(RobotSocketState state, bool useSourceAddress, string isRoadway = null)
+        {
+            // 鑾峰彇褰撳墠鍏宠仈鐨勪换鍔�
+            var currentTask = state.CurrentTask;
+            if (currentTask == null)
+            {
+                QuartzLogHelper.LogDebug(_logger, $"HandleInboundTaskAsync锛氬綋鍓嶄换鍔′负绌�", state.RobotCrane?.DeviceName ?? "Unknown");
+                return false;
+            }
+
+            // 鑾峰彇宸烽亾浠g爜
+            string roadway = string.Empty;
+
+            // 鏍规嵁宸烽亾鍚嶇О鍒ゆ柇浠撳簱 ID
+            int warehouseId = 0;
+
+            // 婧愬湴鍧�鍜岀洰鏍囧湴鍧�锛堝垵濮嬪寲锛�
+            string SourceAddress = currentTask.RobotTargetAddressLineCode;
+            string TargetAddress = currentTask.RobotSourceAddressLineCode;
+
+            // 浠诲姟绫诲瀷锛�0 琛ㄧず鏈畾涔夛紝绋嶅悗鏍规嵁浠诲姟绫诲瀷璁剧疆锛�
+            int taskType = 0;
+
+            // 鎵樼洏浠g爜锛堝垵濮嬪寲涓虹┖锛�
+            string PalletCode = string.Empty;
+
+            // 鑾峰彇浠诲姟绫诲瀷鐨勬灇涓惧��
+            var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType;
+
+            // 鏍规嵁 useSourceAddress 鍐冲畾澶勭悊閫昏緫
+            if (useSourceAddress)
+            {
+                // 浣跨敤婧愬湴鍧�鐨勫満鏅細鎷嗙洏銆佹崲鐩橈紙鏀剧┖鎵樼洏锛�
+                switch (robotTaskType)
+                {
+                    case RobotTaskTypeEnum.GroupPallet:
+                        warehouseId = 1;
+                        roadway = "GWSC1";
+                        SourceAddress = currentTask.RobotSourceAddressLineCode;
+                        TargetAddress = currentTask.RobotTargetAddressLineCode;
+                        break;
+
+                    case RobotTaskTypeEnum.ChangePallet:
+                        // 鎹㈢洏/鎷嗙洏鍦烘櫙锛氭墭鐩橀渶瑕佸叆搴�
+                        taskType = TaskTypeEnum.InEmpty.GetHashCode();  // 绌烘墭鐩樺叆搴�
+                        PalletCode = currentTask.RobotSourceAddressPalletCode;  // 浣跨敤婧愬湴鍧�鐨勬墭鐩樼爜
+                        if (isRoadway == "HCSC1")
+                        {
+                            warehouseId = 2;
+                            roadway = "HCSC1";
+                        }
+                        else if (isRoadway == "GWSC1")
+                        {
+                            warehouseId = 1;
+                            roadway = "GWSC1";
+                        }
+
+                        SourceAddress = currentTask.RobotSourceAddressLineCode;
+                        TargetAddress = currentTask.RobotTargetAddressLineCode;
+                        break;
+                    case RobotTaskTypeEnum.SplitPallet:
+                        // 鎹㈢洏/鎷嗙洏鍦烘櫙锛氭墭鐩橀渶瑕佸叆搴�
+                        taskType = TaskTypeEnum.InEmpty.GetHashCode();  // 绌烘墭鐩樺叆搴�
+                        PalletCode = currentTask.RobotSourceAddressPalletCode;  // 浣跨敤婧愬湴鍧�鐨勬墭鐩樼爜
+
+                        warehouseId = 3;
+                        roadway = "CWSC1";
+
+                        SourceAddress = currentTask.RobotSourceAddressLineCode;
+                        TargetAddress = currentTask.RobotTargetAddressLineCode;
+                        break;
+                }
+            }
+            else
+            {
+                // 浣跨敤鐩爣鍦板潃鐨勫満鏅細缁勭洏銆佹崲鐩橈紙鎴愬搧鍏ュ簱锛�
+                switch (robotTaskType)
+                {
+                    case RobotTaskTypeEnum.ChangePallet:
+                        // 鎹㈢洏/缁勭洏鍦烘櫙锛氳揣鐗╅渶瑕佸叆搴�
+                        taskType = TaskTypeEnum.Inbound.GetHashCode();  // 鎴愬搧鍏ュ簱
+                        PalletCode = currentTask.RobotTargetAddressPalletCode;  // 浣跨敤鐩爣鍦板潃鐨勬墭鐩樼爜
+
+                        if (isRoadway == "HCSC1")
+                        {
+                            warehouseId = 2;
+                            roadway = "HCSC1";
+                        }
+                        else if (isRoadway == "GWSC1")
+                        {
+                            warehouseId = 1;
+                            roadway = "GWSC1";
+                        }
+
+                        break;
+                    case RobotTaskTypeEnum.GroupPallet:
+                        // 鎹㈢洏/缁勭洏鍦烘櫙锛氳揣鐗╅渶瑕佸叆搴�
+                        taskType = TaskTypeEnum.Inbound.GetHashCode();  // 鎴愬搧鍏ュ簱
+                        PalletCode = currentTask.RobotTargetAddressPalletCode;  // 浣跨敤鐩爣鍦板潃鐨勬墭鐩樼爜
+
+                        warehouseId = 1;
+                        roadway = "GWSC1";
+                        break;
+
+                    case RobotTaskTypeEnum.SplitPallet:
+
+                        break;
+                }
+            }
+
+            // 鏋勫缓鍒涘缓浠诲姟鐨� DTO
+            CreateTaskDto taskDto = new CreateTaskDto
+            {
+                PalletCode = PalletCode,                    // 鎵樼洏鏉$爜
+                SourceAddress = SourceAddress ?? string.Empty,  // 婧愬湴鍧�
+                TargetAddress = roadway ?? string.Empty,  // 鐩爣鍦板潃
+                Roadway = roadway ?? string.Empty,             // 宸烽亾
+                WarehouseId = warehouseId,                   // 浠撳簱 ID
+                PalletType = 1,                             // 鎵樼洏绫诲瀷锛堥粯璁や负1锛�
+                TaskType = taskType                         // 浠诲姟绫诲瀷锛堝叆搴�/绌烘墭鐩樺叆搴擄級
+            };
+
+            // 璁板綍鏃ュ織锛氬紑濮嬭皟鐢� WMS 鍒涘缓鍏ュ簱浠诲姟
+            QuartzLogHelper.LogInfo(_logger, $"HandleInboundTaskAsync锛氳皟鐢╓MS鍒涘缓鍏ュ簱浠诲姟锛屾墭鐩樼爜: {PalletCode}锛屼换鍔$被鍨�: {taskType}", state.RobotCrane?.DeviceName ?? "Unknown");
+
+            // 璋冪敤 WMS 鎺ュ彛鍒涘缓鍏ュ簱浠诲姟
+            string configKey = nameof(ConfigKey.CreateTaskInboundAsync);
+            string requestParam = taskDto.ToJson();
+            DateTime startTime = DateTime.Now;
+
+            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
+
+            if (!result.IsSuccess || !result.Data.Status)
+            {
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", state.RobotCrane?.DeviceName ?? "Unknown");
+                return false;
+            }
+
+            QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", state.RobotCrane?.DeviceName ?? "Unknown");
+
+            // 濡傛灉璋冪敤澶辫触鎴栬繑鍥為敊璇姸鎬�
+            if (!result.Data.Status && result.IsSuccess)
+            {
+                QuartzLogHelper.LogError(_logger, $"HandleInboundTaskAsync锛歐MS杩斿洖閿欒鐘舵�侊紝Status: {result.Data.Status}", state.RobotCrane?.DeviceName ?? "Unknown");
+                return false;
+            }
+
+            // 瑙f瀽 WMS 杩斿洖鐨勪换鍔′俊鎭�
+            WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO();
+
+            // 璋冪敤浠诲姟鏈嶅姟鎺ユ敹 WMS 浠诲姟
+            var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO });
+            if (!content.Status)
+            {
+                QuartzLogHelper.LogError(_logger, $"HandleInboundTaskAsync锛氭帴鏀禬MS浠诲姟澶辫触", state.RobotCrane?.DeviceName ?? "Unknown");
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// 鏋勫缓搴撳瓨鍥炰紶 DTO
+        /// </summary>
+        /// <remarks>
+        /// 鐢ㄤ簬鎷嗙洏鍜岀粍鐩樻搷浣滄椂锛屽悜 WMS 鍥炰紶搴撳瓨淇℃伅銆�
+        /// DTO 鍖呭惈婧愯揣浣嶃�佺洰鏍囪揣浣嶃�佹墭鐩樼爜浠ュ強姣忎釜浣嶇疆鐨勭數姹犳潯鐮併��
+        /// </remarks>
+        /// <param name="state">鏈哄櫒浜哄綋鍓嶇姸鎬�</param>
+        /// <param name="positions">鐢垫睜浣嶇疆鏁扮粍</param>
+        /// <returns>鏋勫缓濂界殑搴撳瓨 DTO</returns>
+        public static StockDTO BuildStockDTO(RobotSocketState state, int[] positions)
+        {
+            return new StockDTO
+            {
+                // 婧愯緭閫佺嚎缂栧彿
+                SourceLineNo = state.CurrentTask.RobotSourceAddressLineCode,
+
+                // 婧愭墭鐩樺彿
+                SourcePalletNo = state.CurrentTask.RobotSourceAddressPalletCode,
+
+                // 鐩爣鎵樼洏鍙�
+                TargetPalletNo = state.CurrentTask.RobotTargetAddressPalletCode,
+
+                // 鐩爣杈撻�佺嚎缂栧彿
+                TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode,
+
+                // 宸烽亾缂栧彿(鏈哄櫒浜哄悕绉�)
+                Roadway = state.CurrentTask.RobotRoadway,
+
+                // 鐢垫睜浣嶇疆璇︽儏鍒楄〃
+                // 杩囨护鎺変綅缃负 0 鎴栬礋鏁扮殑鏃犳晥鏁版嵁
+                // 鎸変綅缃紪鍙锋帓搴�
+                // 涓烘瘡涓綅缃敓鎴愬搴旂殑搴撳瓨璇︽儏
+                Details = positions
+                    .Where(x => x > 0)  // 杩囨护鏃犳晥浣嶇疆
+                    .OrderBy(x => x)   // 鎸変綅缃帓搴�
+                    .Select((x, idx) => new StockDetailDTO
+                    {
+                        // 鏁伴噺锛氬鏋滃凡鏈変换鍔℃�绘暟锛屼娇鐢ㄤ换鍔℃�绘暟+褰撳墠浣嶇疆鏁帮紱鍚﹀垯鍙娇鐢ㄥ綋鍓嶄綅缃暟
+                        Quantity = 1,
+
+                        // 閫氶亾/浣嶇疆缂栧彿
+                        Channel = x,
+
+                        // 鐢垫睜鏉$爜锛氬鏋滅姸鎬佷腑鏈夋潯鐮佸垪琛紝鍙栧搴斾綅缃殑鏉$爜锛涘惁鍒欎负绌�
+                        //CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : ""
+                        CellBarcode = !state.CellBarcode.IsNullOrEmpty() ? state.CellBarcode[idx].ToString() ?? string.Empty : string.Empty
+                    })
+                    .ToList()
+            };
+        }
+
+        /// <summary>
+        /// 璋冪敤鎷嗙洏 API
+        /// </summary>
+        /// <remarks>
+        /// 褰撳彇璐у畬鎴愪笖闇�瑕佹媶鐩樻椂璋冪敤銆�
+        /// 灏嗙數姹犱粠鎵樼洏涓婂彇涓嬶紝閫愪釜鏀剧疆鍒扮洰鏍囦綅缃��
+        /// </remarks>
+        /// <param name="stockDTO">搴撳瓨 DTO锛屽寘鍚鎷嗙洏鐨勭數鑺俊鎭�</param>
+        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
+        public HttpResponseResult<WebResponseContent> PostSplitPalletAsync(StockDTO stockDTO)
+        {
+            string configKey = nameof(ConfigKey.SplitPalletAsync);
+            string requestParam = stockDTO.ToJson();
+            DateTime startTime = DateTime.Now;
+
+            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
+
+            if (!result.IsSuccess || !result.Data.Status)
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
+            else
+                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
+
+            return result;
+        }
+
+        /// <summary>
+        /// 璋冪敤缁勭洏/鎹㈢洏 API
+        /// </summary>
+        /// <remarks>
+        /// 褰撴斁璐у畬鎴愪笖闇�瑕佺粍鐩樻垨鎹㈢洏鏃惰皟鐢ㄣ��
+        /// 灏嗗涓數姹犵粍鍚堝埌鍚屼竴涓墭鐩樹笂銆�
+        ///
+        /// configKey 鍙傛暟鍐冲畾璋冪敤鍝釜 API锛�
+        /// - GroupPalletAsync: 缁勭洏鎺ュ彛
+        /// - ChangePalletAsync: 鎹㈢洏鎺ュ彛
+        /// </remarks>
+        /// <param name="configKey">閰嶇疆閿悕锛屽喅瀹氳皟鐢ㄥ摢涓� API</param>
+        /// <param name="stockDTO">搴撳瓨 DTO锛屽寘鍚缁勭洏鐨勭數鑺俊鎭�</param>
+        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
+        public HttpResponseResult<WebResponseContent> PostGroupPalletAsync(string configKey, StockDTO stockDTO)
+        {
+            string requestParam = stockDTO.ToJson();
+            DateTime startTime = DateTime.Now;
+
+            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
+
+            if (!result.IsSuccess || !result.Data.Status)
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
+            else
+                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
+
+            return result;
+        }
+
+        /// <summary>
+        /// 璋冪敤鎵归噺鎷嗙洏纭 API
+        /// </summary>
+        /// <remarks>
+        /// 褰撴媶鐩樹换鍔″叏閮ㄥ彇瀹屾椂璋冪敤锛屼竴娆℃�т笂浼犳暣涓墭鐩樼殑瑙g粦鏁版嵁鍒� MES銆�
+        /// </remarks>
+        /// <param name="palletCode">婧愭墭鐩樺彿</param>
+        /// <param name="deviceName">璁惧鍚嶇О锛岀敤浜庝紶閫掑埌 WMS</param>
+        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
+        public HttpResponseResult<WebResponseContent> PostSplitPalletConfirmAsync(string palletCode, string deviceName)
+        {
+            string configKey = nameof(ConfigKey.SplitPalletConfirm);
+            var request = new { PalletCode = palletCode, DeviceName = deviceName };
+            string requestParam = request.ToJson();
+            DateTime startTime = DateTime.Now;
+
+            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
+
+            if (!result.IsSuccess || !result.Data.Status)
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
+            else
+                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
+
+            return result;
+        }
+
+        /// <summary>
+        /// 璋冪敤鎵归噺缁勭洏纭 API
+        /// </summary>
+        /// <remarks>
+        /// 褰撶粍鐩樹换鍔″叏閮ㄦ斁瀹屾椂璋冪敤锛屼竴娆℃�т笂浼犳暣涓墭鐩樼殑缁戝畾鏁版嵁鍒� MES銆�
+        /// </remarks>
+        /// <param name="palletCode">鐩爣鎵樼洏鍙�</param>
+        /// <param name="deviceName">璁惧鍚嶇О锛岀敤浜庝紶閫掑埌 WMS</param>
+        /// <returns>HTTP 鍝嶅簲缁撴灉</returns>
+        public HttpResponseResult<WebResponseContent> PostGroupPalletConfirmAsync(string palletCode, string deviceName)
+        {
+            string configKey = nameof(ConfigKey.GroupPalletConfirm);
+            var request = new { PalletCode = palletCode, DeviceName = deviceName };
+            string requestParam = request.ToJson();
+            DateTime startTime = DateTime.Now;
+
+            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
+
+            if (!result.IsSuccess || !result.Data.Status)
+                QuartzLogHelper.LogError(_logger, $"璋冪敤WMS鎺ュ彛澶辫触,鎺ュ彛:銆恵configKey}銆�,璇锋眰鍙傛暟:銆恵requestParam}銆�,閿欒淇℃伅:銆恵result.Data?.Message}銆�", "RobotTaskProcessor");
+            else
+                QuartzLogHelper.LogInfo(_logger, $"璋冪敤WMS鎺ュ彛鎴愬姛,鎺ュ彛:銆恵configKey}銆�,鍝嶅簲鏁版嵁:銆恵result.Data?.Data}銆�,鑰楁椂:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskProcessor");
+
+            return result;
+        }
+
+        public bool UpdateRobotTask(Dt_RobotTask task)
+        {
+            WebResponseContent content = _robotTaskService.UpdateData(task);
+            return content.Status;
+        }
+    }
+}
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 cf749d9..503b5ec 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
@@ -153,7 +153,7 @@
                     .ToArray();
 
                 // 浠庢暟鎹簱閲嶆柊鏌ヨ褰撳墠浠诲姟锛堢‘淇濊幏鍙栨渶鏂扮姸鎬侊級
-                var task = await _robotTaskService.Repository.QueryFirstAsync(x => x.RobotTaskState == TaskRobotStatusEnum.RobotExecuting.GetHashCode() && x.RobotRoadway == state.RobotCrane.DeviceName);
+                var task = await _robotTaskService.Repository.QueryFirstAsync(x => /*x.RobotTaskState == TaskRobotStatusEnum.RobotExecuting.GetHashCode() &&*/ x.RobotRoadway == state.RobotCrane.DeviceName);
 
                 if (task != null)
                 {
@@ -319,7 +319,7 @@
                             task.RobotTaskTotalNum -= positions.Length;
 
                         var stockDTO = RobotTaskProcessor.BuildStockDTO(state, positions);
-                        var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.GroupPalletAsync), stockDTO);
+                        var result = _taskProcessor.PostGroupPalletAsync(nameof(ConfigKey.ChangePalletAsync), stockDTO);
                         putSuccess = result.Data.Status && result.IsSuccess;
                     }
                 }
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
index 5c709bf..d60d160 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -159,6 +159,8 @@
                     var isResult = UpdateStatus(state, true);
                     if (!isResult)
                         return false;
+
+                    await _socketClientGateway.SendToClientAsync(state.IPAddress, "pickbatteryover");
                     return true;
 
                 // 鏀捐揣鎺ユ敹
@@ -166,6 +168,8 @@
                     isResult = UpdateStatus(state, false);
                     if (!isResult)
                         return false;
+
+                    await _socketClientGateway.SendToClientAsync(state.IPAddress, "putbatteryover");
                     return true;
 
                 // ==================== 鍏ㄩ儴瀹屾垚鍛戒护 ====================
@@ -213,8 +217,8 @@
                                     return false;
                                 }
 
-                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
-                                QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                                QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
 
                                 state.CurrentTask = null;
                                 state.RobotTaskTotalNum = 0;
@@ -242,14 +246,14 @@
                                 return false;
                             }
 
-                            if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
-                            {
-                                QuartzLogHelper.LogError(_logger, $"allpickfinished锛氬垹闄や换鍔¤褰曞け璐ワ紝浠诲姟鍙�: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
-                                return false;
-                            }
+                            //if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
+                            //{
+                            //    QuartzLogHelper.LogError(_logger, $"allpickfinished锛氬垹闄や换鍔¤褰曞け璐ワ紝浠诲姟鍙�: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
+                            //    return false;
+                            //}
 
-                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
-                            QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                            QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
 
                             state.ChangePalletPhase = 0;
                             state.CurrentBatchIndex = 1;
@@ -281,8 +285,8 @@
                                 return false;
                             }
 
-                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
-                            QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                            QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
                             return true;
                         }
                         return false;
@@ -334,8 +338,8 @@
                                 state.RobotTaskTotalNum = 0;
                                 state.CellBarcode = new List<string>();
 
-                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
-                                QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                                QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
 
                                 state.ChangePalletPhase = 0;
                                 state.CurrentBatchIndex = 1;
@@ -370,8 +374,8 @@
                             state.RobotTaskTotalNum = 0;
                             state.CellBarcode = new List<string>();
 
-                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
-                            QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怱wap,diskFinished銆�", state.RobotCrane.DeviceName);
+                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
+                            QuartzLogHelper.LogInfo(_logger, $"鍙戦�佹秷鎭細銆怗roup,diskFinished銆�", state.RobotCrane.DeviceName);
 
                             state.ChangePalletPhase = 0;
                             state.CurrentBatchIndex = 1;
@@ -461,14 +465,14 @@
 
         public bool UpdateStatus(RobotSocketState state, bool isPick)
         {
-            var task = _taskProcessor.GetTask(state?.RobotCrane);
+            var task = _taskProcessor.GetRobotTask(state?.RobotCrane);
             if (task == null)
             {
                 QuartzLogHelper.LogError(_logger, $"鍙栬揣鎺ユ敹澶辫触: 鏈壘鍒般�恵state?.RobotCrane}銆戠殑浠诲姟", state.RobotCrane?.DeviceName ?? "Unknown");
+                return false;
             }
             task.RobotTaskState = (int)TaskRobotStatusEnum.RobotExecuting;
-            _taskProcessor.UpdateRobotTask(task);
-            return true;
+            return _taskProcessor.UpdateRobotTask(task);
         }
     }
 }
\ No newline at end of file
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 2567908..3d5241e 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -169,6 +169,9 @@
 
                 bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
 
+                await _taskProcessor.SendSocketRobotNumAsync(task, state, false);
+                Thread.Sleep(500);
+
                 // ==================== Phase 2: 鏀炬甯哥數鑺埌鐩爣鎵樼洏锛堜袱娴佸悜鐩稿悓锛�====================
                 // PickFinished 鍒拌揪锛歅hase 1 鐨� Pick 鍛戒护瀹屾垚锛岀幇鍦ㄤ笅鍙� Put 鍛戒护鏀炬甯哥數鑺�
                 if (state?.ChangePalletPhase == 2)
@@ -239,8 +242,6 @@
                     return;
                 }
 
-                // 闈炴壒娆℃ā寮忔垨鍏朵粬闃舵涓嶄笅鍙戞寚浠�
-                return;
             }
 
             // 闈炴崲鐩樹换鍔★細浣跨敤鍘熸湁鏍煎紡
@@ -389,8 +390,11 @@
                 // 鍒ゆ柇娴佸悜锛坣ull-safe锛�
                 bool isFlowA = task.RobotSourceAddressLineCode is "11001" or "11010";
 
+                await _taskProcessor.SendSocketRobotNumAsync(task, stateForUpdate);
+                Thread.Sleep(500);
+
                 // 鐩爣鏁伴噺涓�48锛氱洿鎺ヨ蛋鍘熸湁閫昏緫锛屼笉杩涘叆鎵规妯″紡
-                if (targetNormalCount == targetTotal)
+                if (targetNormalCount + currentCompletedCount == targetTotal)
                 {
                     await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
                     return;
diff --git a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
index 6c5b0ef..15fd6f2 100644
--- a/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
+++ b/Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -60,14 +60,14 @@
                         }
 
                         // 鎸夊鎴风鍘婚噸锛氭鏌ユ槸鍚︿笌璇ュ鎴风涓婃娑堟伅鐩稿悓
-                        lock (_syncRoot)
-                        {
-                            if (_clientLastMessage.TryGetValue(clientId, out var prev) && message == prev)
-                            {
-                                continue;
-                            }
-                            _clientLastMessage[clientId] = message;
-                        }
+                        //lock (_syncRoot)
+                        //{
+                        //    if (_clientLastMessage.TryGetValue(clientId, out var prev) && message == prev)
+                        //    {
+                        //        continue;
+                        //    }
+                        //    _clientLastMessage[clientId] = message;
+                        //}
 
                         // 鏇存柊瀹㈡埛绔姸鎬�
                         UpdateClientStatus(clientId, message);
diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
index 2a154b9..7c21540 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
@@ -209,6 +209,30 @@
 
                 return await ExecuteWithinTransactionAsync(async () =>
                 {
+                    // 骞傜瓑鍐欏叆锛氭鏌ヤ复鏃惰〃鏄惁宸叉湁璇ユ墭鐩樿褰曪紝鏃犲垯鍐欏叆
+                    var existingTemp = SqlSugarClient.Queryable<Dt_SplitTemp>()
+                        .Where(t => t.PalletCode == stock.SourcePalletNo)
+                        .First();
+                    if (existingTemp == null)
+                    {
+                        // 鏌ヨ璇ユ墭鐩樺綋鍓嶆墍鏈夌數鑺紝瀛樺叆涓存椂琛�
+                        var sourceStockForTemp = StockInfoService.Repository.QueryFirst(s => s.PalletCode == stock.SourcePalletNo);
+                        if (sourceStockForTemp != null)
+                        {
+                            var allDetails = StockInfoDetailService.Repository.QueryData(d => d.StockId == sourceStockForTemp.Id);
+                            if (allDetails != null && allDetails.Any())
+                            {
+                                var sfcListJson = JsonConvert.SerializeObject(allDetails.Select(d => d.SerialNumber).ToList());
+                                await SqlSugarClient.Insertable(new Dt_SplitTemp
+                                {
+                                    PalletCode = stock.SourcePalletNo,
+                                    SfcList = sfcListJson,
+                                    CreateTime = DateTime.Now
+                                }).ExecuteCommandAsync();
+                            }
+                        }
+                    }
+
                     var sourceStock = await StockInfoService.Repository.QueryDataNavFirstAsync(s => s.PalletCode == stock.SourcePalletNo);
                     if (sourceStock == null) return content.Error("婧愭墭鐩樹笉瀛樺湪");
 

--
Gitblit v1.9.3