wanshenmean
10 小时以前 627371d0ffdf50239313f2c86d022a0c5c69550d
refactor(logging): 重构日志记录模块,统一使用Serilog和QuartzLogHelper

重构日志记录模块,删除重复的QuartzLogHelper文件,将其移动到Core项目。修改所有相关文件使用新的日志记录方式,增加WMS接口调用的详细日志记录。调整日志级别配置,优化日志输出格式。

更新appsettings.json中的日志级别配置,增加Quartz的调试日志输出。修改RobotJob、ConveyorLineNewJob等模块的日志记录方式,统一使用QuartzLogHelper进行日志记录。增加WMS接口调用的耗时和参数记录,便于问题排查。
已重命名1个文件
已修改21个文件
845 ■■■■ 文件已修改
Code/.omc/state/last-tool-error.json 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/mission-state.json 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/subagent-tracking.json 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/LogHelper/QuartzLogHelper.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Storage.cs 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs 55 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RelocationTaskFlowService.cs 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService/TaskService.Status.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ManualInbound/ManualInboundTaskHandler.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/.omc/state/last-tool-error.json
@@ -1,7 +1,7 @@
{
  "tool_name": "Bash",
  "tool_input_preview": "{\"command\":\"cd \\\"D:/Git/ShanMeiXinNengYuan/Code\\\" && dotnet build WMS/WIDESEA_WMSServer/WIDESEA_WMSServer.sln 2>&1\",\"timeout\":120000,\"description\":\"Build WMS solution to verify changes\"}",
  "error": "Exit code 1\n  æ­£åœ¨ç¡®å®šè¦è¿˜åŽŸçš„é¡¹ç›®â€¦\r\n  æ‰€æœ‰é¡¹ç›®å‡æ˜¯æœ€æ–°çš„,无法还原。\r\nD:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\AOP\\LogAOP.cs(169,123): warning CS8625: æ— æ³•å°† null å­—面量转换为非 null çš„引用类型。 [D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\WIDESEA_Core.csproj]\r\nD:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\Authorization\\AuthorizationResponse.cs(21,30): warning CS8625: æ— æ³•å°† null å­—面量转换为非 null çš„引用类型。 [D:\\Git\\ShanMeiXinNengYuan\\Code\\WMS\\WIDESEA_WMSServer\\WIDESEA_Core\\WIDES...",
  "timestamp": "2026-04-20T16:56:32.862Z",
  "tool_input_preview": "{\"command\":\"cd \\\"D:/Git/ShanMeiXinNengYuan/Code\\\" && dotnet build WCS/WIDESEAWCS_Server/WIDESEAWCS_Server.sln 2>&1\",\"timeout\":120000,\"description\":\"Build WCS solution to verify compilation\"}",
  "error": "Exit code 1\n  æ­£åœ¨ç¡®å®šè¦è¿˜åŽŸçš„é¡¹ç›®â€¦\r\n  æ‰€æœ‰é¡¹ç›®å‡æ˜¯æœ€æ–°çš„,无法还原。\r\n  WIDESEAWCS_Common -> D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Common\\bin\\Debug\\net8.0\\WIDESEAWCS_Common.dll\r\n  WIDESEAWCS_Communicator -> D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Communicator\\bin\\Debug\\net8.0\\WIDESEAWCS_Communicator.dll\r\n  WIDESEAWCS_Core -> D:\\Git\\ShanMeiXinNengYuan\\Code\\WCS\\WIDESEAWCS_Server\\WIDESEAWCS_Core\\bin\\Debug\\net8.0\\WIDESEAWCS_Core.dll\r\n  WIDESEAWCS_Model -> D:\\Git\\ShanMeiXinN...",
  "timestamp": "2026-04-21T09:39:52.122Z",
  "retry_count": 1
}
Code/.omc/state/mission-state.json
@@ -1,5 +1,5 @@
{
  "updatedAt": "2026-04-20T17:02:18.624Z",
  "updatedAt": "2026-04-21T11:39:09.598Z",
  "missions": [
    {
      "id": "session:9007b9ea-1eb6-4d24-8fe7-2c3a949eac88:none",
@@ -2350,6 +2350,174 @@
          "sourceKey": "session-stop:a82856d42f4ef095b"
        }
      ]
    },
    {
      "id": "session:4b203ec2-4358-4df5-9d57-f3bf8801fd43:none",
      "source": "session",
      "name": "none",
      "objective": "Session mission",
      "createdAt": "2026-04-21T08:05:57.739Z",
      "updatedAt": "2026-04-21T11:39:09.598Z",
      "status": "done",
      "workerCount": 9,
      "taskCounts": {
        "total": 9,
        "pending": 0,
        "blocked": 0,
        "inProgress": 0,
        "completed": 9,
        "failed": 0
      },
      "agents": [
        {
          "name": "general-purpose:adfd244",
          "role": "general-purpose",
          "ownership": "adfd244986e678c43",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T11:39:09.598Z"
        },
        {
          "name": "general-purpose:afe58ad",
          "role": "general-purpose",
          "ownership": "afe58add5c15b5456",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T08:10:25.852Z"
        },
        {
          "name": "code-reviewer:a5f227d",
          "role": "code-reviewer",
          "ownership": "a5f227d0165c2b9d7",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T08:15:02.522Z"
        },
        {
          "name": "general-purpose:a9be028",
          "role": "general-purpose",
          "ownership": "a9be028ac5ebd371e",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T08:16:40.974Z"
        },
        {
          "name": "general-purpose:a1284f6",
          "role": "general-purpose",
          "ownership": "a1284f6498da348c8",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T08:17:29.877Z"
        },
        {
          "name": "code-reviewer:a4003ef",
          "role": "code-reviewer",
          "ownership": "a4003ef7b99171bad",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T08:20:36.471Z"
        },
        {
          "name": "general-purpose:a05860c",
          "role": "general-purpose",
          "ownership": "a05860ca07c208160",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T09:36:30.257Z"
        },
        {
          "name": "general-purpose:afb9663",
          "role": "general-purpose",
          "ownership": "afb9663c306b7ffb2",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T09:37:29.377Z"
        },
        {
          "name": "code-reviewer:a5387bf",
          "role": "code-reviewer",
          "ownership": "a5387bf0397247d5c",
          "status": "done",
          "currentStep": null,
          "latestUpdate": "completed",
          "completedSummary": null,
          "updatedAt": "2026-04-21T09:39:25.226Z"
        }
      ],
      "timeline": [
        {
          "id": "session-start:afb9663c306b7ffb2:2026-04-21T09:36:45.991Z",
          "at": "2026-04-21T09:36:45.991Z",
          "kind": "update",
          "agent": "general-purpose:afb9663",
          "detail": "started general-purpose:afb9663",
          "sourceKey": "session-start:afb9663c306b7ffb2"
        },
        {
          "id": "session-stop:afb9663c306b7ffb2:2026-04-21T09:37:29.377Z",
          "at": "2026-04-21T09:37:29.377Z",
          "kind": "completion",
          "agent": "general-purpose:afb9663",
          "detail": "completed",
          "sourceKey": "session-stop:afb9663c306b7ffb2"
        },
        {
          "id": "session-start:a5387bf0397247d5c:2026-04-21T09:37:41.613Z",
          "at": "2026-04-21T09:37:41.613Z",
          "kind": "update",
          "agent": "code-reviewer:a5387bf",
          "detail": "started code-reviewer:a5387bf",
          "sourceKey": "session-start:a5387bf0397247d5c"
        },
        {
          "id": "session-stop:a5387bf0397247d5c:2026-04-21T09:39:25.226Z",
          "at": "2026-04-21T09:39:25.226Z",
          "kind": "completion",
          "agent": "code-reviewer:a5387bf",
          "detail": "completed",
          "sourceKey": "session-stop:a5387bf0397247d5c"
        },
        {
          "id": "session-stop:a93c9aa6de8251ecb:2026-04-21T09:43:18.886Z",
          "at": "2026-04-21T09:43:18.886Z",
          "kind": "completion",
          "agent": "general-purpose:adfd244",
          "detail": "completed",
          "sourceKey": "session-stop:a93c9aa6de8251ecb"
        },
        {
          "id": "session-stop:a34767c74aa84d9d8:2026-04-21T11:30:52.701Z",
          "at": "2026-04-21T11:30:52.701Z",
          "kind": "completion",
          "agent": "general-purpose:adfd244",
          "detail": "completed",
          "sourceKey": "session-stop:a34767c74aa84d9d8"
        },
        {
          "id": "session-stop:aecf873500f38d936:2026-04-21T11:39:09.598Z",
          "at": "2026-04-21T11:39:09.598Z",
          "kind": "completion",
          "agent": "general-purpose:adfd244",
          "detail": "completed",
          "sourceKey": "session-stop:aecf873500f38d936"
        }
      ]
    }
  ]
}
Code/.omc/state/subagent-tracking.json
@@ -1454,10 +1454,91 @@
      "status": "completed",
      "completed_at": "2026-04-20T16:32:32.484Z",
      "duration_ms": 67195
    },
    {
      "agent_id": "adfd244986e678c43",
      "agent_type": "general-purpose",
      "started_at": "2026-04-21T08:05:57.739Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T08:08:07.653Z",
      "duration_ms": 129914
    },
    {
      "agent_id": "afe58add5c15b5456",
      "agent_type": "general-purpose",
      "started_at": "2026-04-21T08:08:38.524Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T08:10:25.851Z",
      "duration_ms": 107327
    },
    {
      "agent_id": "a5f227d0165c2b9d7",
      "agent_type": "oh-my-claudecode:code-reviewer",
      "started_at": "2026-04-21T08:11:16.482Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T08:15:02.520Z",
      "duration_ms": 226038
    },
    {
      "agent_id": "a9be028ac5ebd371e",
      "agent_type": "general-purpose",
      "started_at": "2026-04-21T08:15:35.687Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T08:16:40.972Z",
      "duration_ms": 65285
    },
    {
      "agent_id": "a1284f6498da348c8",
      "agent_type": "general-purpose",
      "started_at": "2026-04-21T08:16:53.264Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T08:17:29.876Z",
      "duration_ms": 36612
    },
    {
      "agent_id": "a4003ef7b99171bad",
      "agent_type": "oh-my-claudecode:code-reviewer",
      "started_at": "2026-04-21T08:17:42.837Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T08:20:36.470Z",
      "duration_ms": 173633
    },
    {
      "agent_id": "a05860ca07c208160",
      "agent_type": "general-purpose",
      "started_at": "2026-04-21T09:35:41.894Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T09:36:30.255Z",
      "duration_ms": 48361
    },
    {
      "agent_id": "afb9663c306b7ffb2",
      "agent_type": "general-purpose",
      "started_at": "2026-04-21T09:36:45.991Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T09:37:29.375Z",
      "duration_ms": 43384
    },
    {
      "agent_id": "a5387bf0397247d5c",
      "agent_type": "oh-my-claudecode:code-reviewer",
      "started_at": "2026-04-21T09:37:41.613Z",
      "parent_mode": "none",
      "status": "completed",
      "completed_at": "2026-04-21T09:39:25.224Z",
      "duration_ms": 103611
    }
  ],
  "total_spawned": 135,
  "total_completed": 157,
  "total_spawned": 144,
  "total_completed": 166,
  "total_failed": 0,
  "last_updated": "2026-04-21T06:46:41.255Z"
  "last_updated": "2026-04-21T11:39:09.704Z"
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/LogHelper/QuartzLogHelper.cs
ÎļþÃû´Ó Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/QuartzLogHelper.cs ÐÞ¸Ä
@@ -42,6 +42,18 @@
    }
    /// <summary>
    /// è®°å½•错误日志(不带异常对象)
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
    /// <param name="loggerMessage">ILogger çš„结构化日志模板(支持占位符)</param>
    /// <param name="deviceCode">设备编码</param>
    public static void LogError(ILogger logger, string loggerMessage, string deviceCode)
    {
        logger.Error(loggerMessage);
        QuartzLogger.Error(loggerMessage, deviceCode);
    }
    /// <summary>
    /// è®°å½•信息日志
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
@@ -83,6 +95,18 @@
    }
    /// <summary>
    /// è®°å½•警告日志
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
    /// <param name="loggerMessage">ILogger çš„结构化日志模板(支持占位符)</param>
    /// <param name="deviceCode">设备编码</param>
    public static void LogWarn(ILogger logger, string loggerMessage,string deviceCode)
    {
        logger.Warning(loggerMessage);
        QuartzLogger.Warn(loggerMessage, deviceCode);
    }
    /// <summary>
    /// è®°å½•调试日志
    /// </summary>
    /// <param name="logger">ILogger å®žä¾‹</param>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/Storage.cs
@@ -1,21 +1,5 @@
using Newtonsoft.Json;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using Quartz;
using SqlSugar;
using System;
using SqlSugar;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_QuartzJob.DeviceBase;
using WIDESEAWCS_QuartzJob.DeviceEnum;
namespace WIDESEAWCS_QuartzJob
{
@@ -62,4 +46,4 @@
            return Pro_Devices.Where(x => deviceCodes.Contains(x.DeviceCode)).ToList();
        }
    }
}
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -5,19 +5,20 @@
      "Default": "Information",
      "Override": {
        "Microsoft": "Information",
        "Microsoft.AspNetCore": "Warning",
        "Microsoft.AspNetCore.Routing": "Warning",
        "Microsoft.AspNetCore.Mvc": "Warning",
        "Microsoft.AspNetCore.Mvc.Infrastructure": "Warning",
        "Microsoft.AspNetCore.Mvc.Filters": "Warning",
        "Microsoft.AspNetCore.Mvc.ModelBinding": "Warning",
        "Microsoft.EntityFrameworkCore": "Warning"
        "Microsoft.AspNetCore": "Information",
        "Microsoft.AspNetCore.Routing": "Information",
        "Microsoft.AspNetCore.Mvc": "Information",
        "Microsoft.AspNetCore.Mvc.Infrastructure": "Information",
        "Microsoft.AspNetCore.Mvc.Filters": "Information",
        "Microsoft.AspNetCore.Mvc.ModelBinding": "Information",
        "Microsoft.EntityFrameworkCore": "Information",
        "Quartz": "Debug"
      }
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Default": "Debug",
      "Microsoft.AspNetCore": "Warning",
      "Quartz": "Debug"
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Serilog;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
@@ -10,6 +11,7 @@
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_Tasks;
namespace WIDESEAWCS_TaskInfoService.Flows
{
@@ -21,16 +23,18 @@
    {
        private readonly IRouterService _routerService;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly ILogger _logger;
        /// <summary>
        /// åˆå§‹åŒ–入库任务流程服务。
        /// </summary>
        /// <param name="routerService">路由服务。</param>
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        public InboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper)
        public InboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, ILogger logger)
        {
            _routerService = routerService;
            _httpClientHelper = httpClientHelper;
            _logger = logger;
        }
        /// <summary>
@@ -100,9 +104,11 @@
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【InboundFinishTaskAsync】,请求参数:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】", "InboundTaskFlowService");
                return content.Error($"通知WMS系统堆垛机入库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【InboundFinishTaskAsync】,响应数据:【{result.Data?.Data}】,耗时:0ms", "InboundTaskFlowService");
            return content.OK($"通知WMS系统堆垛机入库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
@@ -113,12 +119,21 @@
        /// <returns>调用结果。</returns>
        private WebResponseContent GetWMSInboundLocation(Dt_Task task)
        {
            string configKey = nameof(ConfigKey.GetTasksLocation);
            string requestParam = new CreateTaskDto { PalletCode = task.PalletCode }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetTasksLocation),
                new CreateTaskDto { PalletCode = task.PalletCode }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "InboundTaskFlowService");
                return WebResponseContent.Instance.Error($"调用WMS接口获取任务目标地址失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "InboundTaskFlowService");
            string? nextAddress = result.Data.Data?.ToString();
            if (string.IsNullOrEmpty(nextAddress))
@@ -138,13 +153,21 @@
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            string configKey = nameof(ConfigKey.UpdateTaskByStatus);
            string requestParam = new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus, NextAddress = task.NextAddress, CurrentAddress = task.CurrentAddress }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus, NextAddress = task.NextAddress, CurrentAddress = task.CurrentAddress }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "InboundTaskFlowService");
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "InboundTaskFlowService");
            return WebResponseContent.Instance.OK();
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
@@ -1,5 +1,6 @@
using Autofac;
using Newtonsoft.Json;
using Serilog;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
@@ -15,6 +16,7 @@
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_Tasks;
namespace WIDESEAWCS_TaskInfoService.Flows
{
@@ -29,6 +31,7 @@
        private readonly IRobotTaskService _robotTaskService;
        private readonly IComponentContext _componentContext;
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly ILogger _logger;
        /// <summary>
        /// åˆå§‹åŒ–出库任务流程服务。
@@ -37,13 +40,14 @@
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        /// <param name="robotTaskService">机械手任务服务。</param>
        /// <param name="componentContext">Autofac组件上下文(用于延迟解析ITaskService以避免循环依赖)。</param>
        public OutboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService, IComponentContext componentContext, IUnitOfWorkManage unitOfWorkManage)
        public OutboundTaskFlowService(IRouterService routerService, HttpClientHelper httpClientHelper, IRobotTaskService robotTaskService, IComponentContext componentContext, IUnitOfWorkManage unitOfWorkManage, ILogger logger)
        {
            _routerService = routerService;
            _httpClientHelper = httpClientHelper;
            _robotTaskService = robotTaskService;
            _componentContext = componentContext;
            _unitOfWorkManage = unitOfWorkManage;
            _logger = logger;
        }
        /// <summary>
@@ -148,14 +152,21 @@
        private WebResponseContent NotifyWMSOutboundFinish(Dt_Task task)
        {
            WebResponseContent content = new WebResponseContent();
            string configKey = nameof(ConfigKey.OutboundFinishTaskAsync);
            string requestParam = new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson();
            DateTime startTime = DateTime.Now;
            // é€šçŸ¥WMS出库完成并获取返回结果
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskAsync),
                new StockInfoDTO { PalletCode = task.PalletCode, TaskNum = task.TaskNum }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "OutboundTaskFlowService");
                return content.Error($"通知WMS系统堆垛机出库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "OutboundTaskFlowService");
            // å¤„理WMS返回的入库任务(如果有)
            if (result.Data?.Data != null)
            {
@@ -195,13 +206,21 @@
        {
            int warehouseId = _robotTaskService.MapWarehouseIdConfigKey(task.TargetAddress);
            string sourceLineNo = _robotTaskService.ResolveRobotRuleValue(task.TargetAddress, "AddressSourceLineNoMap", task.TargetAddress);
            string configKey = nameof(ConfigKey.GetOutBoundTrayTaskAsync);
            string requestParam = new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.GetOutBoundTrayTaskAsync),
                new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "OutboundTaskFlowService");
                return WebResponseContent.Instance.Error($"获取WMS系统空托盘出库任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "OutboundTaskFlowService");
            WMSTaskDTO? wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
            if (wMSTask == null)
@@ -217,13 +236,21 @@
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            string configKey = nameof(ConfigKey.UpdateTaskByStatus);
            string requestParam = new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus, NextAddress = task.NextAddress, CurrentAddress = task.CurrentAddress }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus, NextAddress = task.NextAddress, CurrentAddress = task.CurrentAddress }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "OutboundTaskFlowService");
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "OutboundTaskFlowService");
            return WebResponseContent.Instance.OK();
        }
@@ -234,13 +261,21 @@
        /// <returns>同步结果。</returns>
        private WebResponseContent OutboundFinishTaskTray(Dt_Task task)
        {
            string configKey = nameof(ConfigKey.OutboundFinishTaskTray);
            string requestParam = new CreateTaskDto { PalletCode = task.PalletCode, SourceAddress = task.SourceAddress }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.OutboundFinishTaskTray),
                new CreateTaskDto { PalletCode = task.PalletCode, SourceAddress = task.SourceAddress }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "OutboundTaskFlowService");
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "OutboundTaskFlowService");
            return WebResponseContent.Instance.OK();
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/RelocationTaskFlowService.cs
@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using Serilog;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
@@ -8,6 +9,7 @@
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_Tasks;
namespace WIDESEAWCS_TaskInfoService.Flows
{
@@ -18,14 +20,16 @@
    public class RelocationTaskFlowService : IRelocationTaskFlowService
    {
        private readonly HttpClientHelper _httpClientHelper;
        private readonly ILogger _logger;
        /// <summary>
        /// åˆå§‹åŒ–移库任务流程服务。
        /// </summary>
        /// <param name="httpClientHelper">WMS接口调用帮助类。</param>
        public RelocationTaskFlowService(HttpClientHelper httpClientHelper)
        public RelocationTaskFlowService(HttpClientHelper httpClientHelper, ILogger logger)
        {
            _httpClientHelper = httpClientHelper;
            _logger = logger;
        }
        /// <summary>
@@ -101,13 +105,21 @@
        /// <returns>同步结果。</returns>
        private WebResponseContent UpdateWMSTaskStatus(Dt_Task task)
        {
            string configKey = nameof(ConfigKey.UpdateTaskByStatus);
            string requestParam = new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus, NextAddress = task.NextAddress, CurrentAddress = task.CurrentAddress }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.UpdateTaskByStatus),
                new UpdateTaskDto { Id = task.TaskNum, NewStatus = task.TaskStatus, NextAddress = task.NextAddress, CurrentAddress = task.CurrentAddress }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "RelocationTaskFlowService");
                return WebResponseContent.Instance.Error($"调用WMS接口更新任务状态失败,任务号:【{task.TaskNum}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RelocationTaskFlowService");
            return WebResponseContent.Instance.OK();
        }
@@ -118,20 +130,28 @@
        /// <returns>通知结果。</returns>
        private WebResponseContent NotifyWMSRelocationFinish(Dt_Task task)
        {
            string configKey = nameof(ConfigKey.RelocationFinishTask);
            string requestParam = new CreateTaskDto
            {
                PalletCode = task.PalletCode,
                SourceAddress = task.CurrentAddress,
                TargetAddress = task.TargetAddress,
                Roadway = task.Roadway,
                TaskType = task.TaskType
            }.ToJson();
            DateTime startTime = DateTime.Now;
            var result = _httpClientHelper.Post<WebResponseContent>(
                nameof(ConfigKey.RelocationFinishTask),
                new CreateTaskDto
                {
                    PalletCode = task.PalletCode,
                    SourceAddress = task.CurrentAddress,
                    TargetAddress = task.TargetAddress,
                    Roadway = task.Roadway,
                    TaskType = task.TaskType
                }.ToJson());
                configKey,
                requestParam);
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "RelocationTaskFlowService");
                return WebResponseContent.Instance.Error($"通知WMS系统移库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RelocationTaskFlowService");
            return WebResponseContent.Instance.OK();
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -20,7 +20,9 @@
using MapsterMapper;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Serilog;
using SqlSugar;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
@@ -36,6 +38,7 @@
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.DTO;
using WIDESEAWCS_Tasks;
namespace WIDESEAWCS_TaskInfoService
{
@@ -44,6 +47,7 @@
        private readonly IMapper _mapper;
        private readonly HttpClientHelper _httpClientHelper;
        private readonly ITaskExecuteDetailService _taskExecuteDetailService;
        private readonly ILogger _logger;
        private Dictionary<string, OrderByType> _taskOrderBy = new()
            {
@@ -60,11 +64,12 @@
        public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList();
        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService) : base(BaseDal)
        public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService, ILogger logger) : base(BaseDal)
        {
            _mapper = mapper;
            _httpClientHelper = httpClientHelper;
            _taskExecuteDetailService = taskExecuteDetailService;
            _logger = logger;
        }
        public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO, StockDTO stockDTO)
@@ -80,13 +85,13 @@
                Dt_RobotTask task = new Dt_RobotTask
                {
                    RobotTaskNum = taskDTO.TaskNum,
                    RobotSourceAddressLineCode = stockDTO.SourceLineNo,
                    RobotTargetAddressLineCode = stockDTO.TargetLineNo,
                    RobotRoadway = stockDTO.Roadway,
                    RobotSourceAddressLineCode = stockDTO?.SourceLineNo ?? string.Empty,
                    RobotTargetAddressLineCode = stockDTO?.TargetLineNo ?? string.Empty,
                    RobotRoadway = stockDTO?.Roadway ?? string.Empty,
                    RobotSourceAddress = taskDTO.SourceAddress,
                    RobotTargetAddress = taskDTO.TargetAddress,
                    RobotSourceAddressPalletCode = stockDTO.SourcePalletNo,
                    RobotTargetAddressPalletCode = stockDTO.TargetPalletNo,
                    RobotSourceAddressPalletCode = stockDTO?.SourcePalletNo ?? string.Empty,
                    RobotTargetAddressPalletCode = stockDTO?.TargetPalletNo ?? string.Empty,
                    RobotTaskType = taskDTO.TaskType,
                    RobotTaskState = taskDTO.TaskStatus,
                    RobotGrade = taskDTO.Grade,
@@ -131,13 +136,20 @@
        {
            string configKey = ResolveRobotTaskConfigKey(task.TargetAddress);
            StockDTO stock = BuildRobotTaskStock(task, configKey);
            string requestParam = stock.ToJson();
            var stopwatch = Stopwatch.StartNew();
            var result = _httpClientHelper.Post<WebResponseContent>(configKey, stock.ToJson());
            var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
            stopwatch.Stop();
            if (!result.IsSuccess || !result.Data.Status)
            {
                QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "RobotTaskService");
                return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,目标地址:【{task.TargetAddress}】,接口:【{configKey}】,错误信息:【{result.Data?.Message}】");
            }
            var wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{stopwatch.ElapsedMilliseconds}ms", "RobotTaskService");
            var wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result?.Data?.Data?.ToString() ?? string.Empty);
            if (wMSTask == null)
                return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】");
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService/TaskService.Status.cs
@@ -2,18 +2,9 @@
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_DTO;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Enums;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_TaskInfoService;
@@ -164,7 +155,6 @@
            string oldCurrentPos = task.CurrentAddress;
            string oldNextPos = task.NextAddress;
            Dt_Router routers = _routerService.QueryNextRoute(oldNextPos, task.TargetAddress);
            if (routers == null) throw new Exception($"未找到设备路由信息");
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -198,23 +198,31 @@
                                    {
                                        // æ²¡æœ‰ä»»åŠ¡ï¼Œå‘ WMS è¯·æ±‚出库托盘任务
                                        var position = checkPalletPositions.FirstOrDefault(x => x.Code == childDeviceCode);
                                        //QuartzLogHelper.LogInfo(_logger, "Execute:检查托盘位置 {ChildDeviceCode},请求WMS出库托盘任务", $"检查托盘位置 {childDeviceCode},请求WMS出库托盘任务", conveyorLine.DeviceCode, childDeviceCode);
                                        var responseResult = _httpClientHelper.Post<WebResponseContent>("GetOutBoundTrayTaskAsync", new CreateTaskDto()
                                        string configKey = "GetOutBoundTrayTaskAsync";
                                        string requestParam = new CreateTaskDto()
                                        {
                                            WarehouseId = position.WarehouseId,
                                            TargetAddress = childDeviceCode
                                        }.Serialize());
                                        }.Serialize();
                                        DateTime startTime = DateTime.Now;
                                        var responseResult = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
                                        _lastPalletCheckTime[childDeviceCode] = DateTime.Now;
                                        // å¦‚果请求成功,接收 WMS è¿”回的任务
                                        if (responseResult.IsSuccess && responseResult.Data.Status)
                                        {
                                            QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,请求参数:【{requestParam}】,响应数据:【{responseResult.Data?.Data}】,耗时:{(DateTime.Now - startTime).TotalMilliseconds}ms", conveyorLine.DeviceCode);
                                            var wmsTask = JsonConvert.DeserializeObject<WMSTaskDTO>(responseResult.Data.Data.ToString());
                                            List<WMSTaskDTO> taskDTOs = new List<WMSTaskDTO> { wmsTask };
                                            if (wmsTask != null)
                                                _taskService.ReceiveWMSTask(taskDTOs);
                                        }
                                        else
                                        {
                                            QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{responseResult.Data?.Message}】", conveyorLine.DeviceCode);
                                        }
                                    }
                                }
@@ -236,7 +244,7 @@
                                    var task = _taskService.QueryManualInboundTask(childDeviceCode);
                                    if (task != null)
                                    {
                                        var handler = new ManualInboundTaskHandler(_taskService);
                                        var handler = new ManualInboundTaskHandler(_taskService, _logger);
                                        handler.WriteTaskToPlc(conveyorLine, childDeviceCode, task);
                                    }
                                }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ManualInbound/ManualInboundTaskHandler.cs
@@ -1,3 +1,4 @@
using Serilog;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
@@ -20,12 +21,19 @@
        private readonly ITaskService _taskService;
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger _logger;
        /// <summary>
        /// æž„造函数
        /// </summary>
        /// <param name="taskService">任务服务</param>
        public ManualInboundTaskHandler(ITaskService taskService)
        /// <param name="logger">日志记录器</param>
        public ManualInboundTaskHandler(ITaskService taskService, ILogger logger)
        {
            _taskService = taskService;
            _logger = logger;
        }
        /// <summary>
@@ -38,7 +46,7 @@
        {
            if (conveyorLine == null || string.IsNullOrEmpty(childDeviceCode) || task == null)
            {
                QuartzLogger.Error("ManualInboundTaskHandler.WriteTaskToPlc: å‚数为空", "ManualInbound");
                QuartzLogHelper.LogError(_logger, "ManualInboundTaskHandler.WriteTaskToPlc: å‚数为空", "ManualInbound");
                return;
            }
@@ -57,18 +65,18 @@
                var updateResult = _taskService.UpdateTaskStatusToNext(task);
                if (!updateResult.Status)
                {
                    QuartzLogger.Error($"ManualInboundTaskHandler: æ›´æ–°ä»»åŠ¡çŠ¶æ€å¤±è´¥ï¼Œä»»åŠ¡å·ã€{task.TaskNum}】,错误信息:{updateResult.Message}", conveyorLine.DeviceCode);
                    QuartzLogHelper.LogError(_logger, $"ManualInboundTaskHandler: æ›´æ–°ä»»åŠ¡çŠ¶æ€å¤±è´¥ï¼Œä»»åŠ¡å·ã€{task.TaskNum}】,错误信息:{updateResult.Message}", conveyorLine.DeviceCode);
                    return;
                }
                // å†™å…¥ACK标志
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                QuartzLogger.Info($"ManualInboundTaskHandler: æ‰‹åŠ¨ä»»åŠ¡å†™å…¥PLC成功,任务号【{task.TaskNum}】,源地址【{task.SourceAddress}】", conveyorLine.DeviceCode);
                QuartzLogHelper.LogInfo(_logger, $"ManualInboundTaskHandler: æ‰‹åŠ¨ä»»åŠ¡å†™å…¥PLC成功,任务号【{task.TaskNum}】,源地址【{task.SourceAddress}】", conveyorLine.DeviceCode);
            }
            catch (Exception ex)
            {
                QuartzLogger.Error($"ManualInboundTaskHandler: å†™å…¥è¾“送线任务异常,错误信息:{ex.Message}", "ManualInbound");
                QuartzLogHelper.LogError(_logger, ex, $"ManualInboundTaskHandler: å†™å…¥è¾“送线任务异常", $"ManualInboundTaskHandler: å†™å…¥è¾“送线任务异常,错误信息:{ex.Message}", "ManualInbound");
            }
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotClientManager.cs
@@ -1,6 +1,6 @@
using Serilog;
using System.Collections.Concurrent;
using System.Net.Sockets;
using Microsoft.Extensions.Logging;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
@@ -101,8 +101,7 @@
                // æ¸…理该客户端的 HandleClientAsync å¯åŠ¨æ ‡å¿—
                // ä»¥ä¾¿ä¸‹æ¬¡é‡è¿žæ—¶å¯ä»¥é‡æ–°å¯åŠ¨å¤„ç†
                _handleClientStarted.TryRemove(ipAddress, out _);
                _logger.LogDebug("客户端未连接,IP: {IpAddress}", ipAddress);
                QuartzLogger.Debug($"客户端未连接,IP: {ipAddress}", robotCrane.DeviceName);
                QuartzLogHelper.LogDebug(_logger, $"客户端未连接,IP: {ipAddress}", robotCrane.DeviceName);
                return false;
            }
@@ -113,8 +112,7 @@
                // ç»‘定客户端断开连接的事件处理
                _tcpSocket.RobotReceived += OnRobotReceived;
                // è®°å½•日志:事件订阅成功
                _logger.LogInformation("机械手TCP消息事件已订阅,设备: {DeviceName}", robotCrane.DeviceName);
                QuartzLogger.Info($"机械手TCP消息事件已订阅", robotCrane.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"机械手TCP消息事件已订阅", robotCrane.DeviceName);
            }
            // ä»Ž TCP æœåŠ¡å™¨çš„å®¢æˆ·ç«¯å­—å…¸ä¸­èŽ·å– TcpClient å¯¹è±¡
@@ -126,8 +124,7 @@
            {
                // ç§»é™¤å¯åŠ¨æ ‡å¿—ï¼Œè¿”å›ž false è¡¨ç¤ºå®¢æˆ·ç«¯ä¸å¯ç”¨
                _handleClientStarted.TryRemove(ipAddress, out _);
                _logger.LogWarning("获取TcpClient失败,IP: {IpAddress}", ipAddress);
                QuartzLogger.Warn($"获取TcpClient失败,IP: {ipAddress}", robotCrane.DeviceName);
                QuartzLogHelper.LogWarn(_logger, $"获取TcpClient失败,IP: {ipAddress}", robotCrane.DeviceName);
                return false;
            }
@@ -138,8 +135,7 @@
            if (!alreadyStarted)
            {
                // è®°å½•日志:启动消息处理
                _logger.LogInformation("启动客户端消息处理,IP: {IpAddress}", ipAddress);
                QuartzLogger.Info($"启动客户端消息处理", robotCrane.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"启动客户端消息处理,IP: {ipAddress}", robotCrane.DeviceName);
                // èŽ·å–æœ€æ–°çš„çŠ¶æ€å¯¹è±¡
                var latestStateForSubscribe = _stateManager.GetState(ipAddress);
@@ -157,8 +153,7 @@
                            if (t.IsFaulted)
                            {
                                // è®°å½•错误日志
                                _logger.LogError(t.Exception, "监听客户端消息事件异常,IP: {IpAddress}", ipAddress);
                                QuartzLogger.Error($"监听客户端消息事件异常", robotCrane.DeviceName, t.Exception);
                                QuartzLogHelper.LogError(_logger, t.Exception, $"监听客户端消息事件异常,IP: {ipAddress}", $"监听客户端消息事件异常,IP: {ipAddress}", robotCrane.DeviceName);
                                // å‘生错误时,移除启动标志,允许下次重试
                                _handleClientStarted.TryRemove(ipAddress, out _);
                            }
@@ -195,8 +190,7 @@
            _handleClientStarted.TryRemove(clientId, out _);
            // è®°å½•日志:客户端断开连接
            _logger.LogInformation("客户端断开连接,IP: {ClientId}", clientId);
            QuartzLogger.Info($"客户端断开连接", clientId);
            QuartzLogHelper.LogInfo(_logger, $"客户端断开连接,IP: {clientId}", clientId);
            // é‡ç½®è¯¥å®¢æˆ·ç«¯çš„状态信息
            _stateManager.TryUpdateStateSafely(clientId, state =>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -1,13 +1,10 @@
using Microsoft.Extensions.Logging;
using Quartz;
using Serilog;
using WIDESEA_Core;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core.Caches;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_Tasks.SocketServer;
using WIDESEAWCS_Tasks.Workflow;
@@ -85,7 +82,7 @@
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger<RobotJob> _logger;
        private readonly ILogger _logger;
        /// <summary>
        /// æž„造函数
@@ -106,7 +103,7 @@
            ITaskService taskService,
            IRobotStateRepository robotStateRepository,
            HttpClientHelper httpClientHelper,
            ILogger<RobotJob> logger,
            ILogger logger,
            IFakeBatteryPositionService fakeBatteryPositionService)
        {
            // åˆå§‹åŒ–状态管理器,传入仓储服务
@@ -125,9 +122,9 @@
            // åˆå§‹åŒ–命令处理器
            // ç®€å•命令处理器:处理状态更新等简单命令
            var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor, socketGateway);
            var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor, socketGateway, _logger);
            // å‰ç¼€å‘½ä»¤å¤„理器:处理 pickfinished、putfinished ç­‰å¸¦å‚数的命令
            var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway, fakeBatteryPositionService);
            var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway, fakeBatteryPositionService, _logger);
            // åˆå§‹åŒ–消息路由器
            _messageRouter = new RobotMessageHandler(socketGateway, _stateManager, simpleCommandHandler, prefixCommandHandler, logger);
@@ -144,8 +141,7 @@
            {
                // å°†æ¶ˆæ¯è·¯ç”±å™¨çš„处理方法绑定到 TCP æœåŠ¡å™¨çš„æ¶ˆæ¯æŽ¥æ”¶äº‹ä»¶
                tcpSocket.MessageReceived += _messageRouter.HandleMessageReceivedAsync;
                _logger.LogError("机器手TCP消息事件已订阅");
                QuartzLogger.Error($"机器手TCP消息事件已订阅");
                QuartzLogHelper.LogError(_logger, $"机器手TCP消息事件已订阅", "Unknown");
            }
        }
@@ -159,8 +155,7 @@
        /// <param name="state">断开连接的机械手状态</param>
        private void OnClientDisconnected(object? sender, RobotSocketState state)
        {
            _logger.LogError("客户端已断开连接");
            QuartzLogger.Error($"客户端已断开连接", state.RobotCrane.DeviceName);
            QuartzLogHelper.LogError(_logger, $"客户端已断开连接", state.RobotCrane.DeviceName);
        }
        /// <summary>
@@ -246,8 +241,7 @@
            {
                // å¼‚常处理已在组件内部进行,Job å±‚保持兜底语义
                // è®°å½•异常而不是静默吞掉,便于排查问题
                _logger?.LogError(ex, "RobotJob执行异常,IP: {IpAddress}", ipAddress);
                QuartzLogger.Error($"RobotJob执行异常,IP: {ipAddress}", state.RobotCrane.DeviceName, ex);
                QuartzLogHelper.LogError(_logger, ex, $"RobotJob执行异常,IP: {ipAddress}", $"RobotJob执行异常,IP: {ipAddress}", state.RobotCrane.DeviceName);
            }
        }
    }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
@@ -1,8 +1,6 @@
using Microsoft.Extensions.Logging;
using Serilog;
using System.Net.Sockets;
using WIDESEAWCS_Common;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_Tasks.Workflow.Abstractions;
namespace WIDESEAWCS_Tasks
@@ -45,7 +43,7 @@
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger<RobotJob> _logger;
        private readonly ILogger _logger;
        /// <summary>
        /// æž„造函数
@@ -60,7 +58,7 @@
            RobotStateManager stateManager,
            IRobotSimpleCommandHandler simpleCommandHandler,
            IRobotPrefixCommandHandler prefixCommandHandler,
            ILogger<RobotJob> logger)
            ILogger logger)
        {
            _socketClientGateway = socketClientGateway;
            _stateManager = stateManager;
@@ -91,20 +89,18 @@
        public async Task<string?> HandleMessageReceivedAsync(string message, bool isJson, TcpClient client)
        {
            var state = _stateManager.GetState(client.Client.RemoteEndPoint.ToString());
            if(state.OperStatus == message)
            if (state.OperStatus == message)
            {
                // å¤„理成功后,将原消息回写到客户端(保持原有行为)
                await _socketClientGateway.SendMessageAsync(client, message);
            }
            // è®°å½•接收到的消息日志
            _logger.LogInformation($"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】");
            QuartzLogger.Info($"接收到客户端消息【{message}】", state.RobotCrane?.DeviceName);
            QuartzLogHelper.LogInfo(_logger, $"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】", state.RobotCrane?.DeviceName);
            // æ£€æŸ¥ä»»åŠ¡æ€»æ•°æ˜¯å¦æœªè¾¾åˆ°ä¸Šé™
            if (state.RobotTaskTotalNum > RobotConst.MaxTaskTotalNum)
            {
                _logger.LogInformation($"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】");
                QuartzLogger.Info($"接收到客户端消息【{message}】", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】", state.RobotCrane?.DeviceName);
                await _socketClientGateway.SendMessageAsync(client, message);
                return null;
            }
@@ -116,11 +112,11 @@
            // ç®€å•命令包括:homing、homed、running、pausing、runmode、controlmode ç­‰
            if (await _simpleCommandHandler.HandleAsync(messageLower, state))
            {
                if(messageLower != "batteryarrived")
                if (messageLower != "batteryarrived")
                {
                    // å¤„理成功后,将原消息回写到客户端(保持原有行为)
                    await _socketClientGateway.SendMessageAsync(client, message);
                    QuartzLogger.Info($"发送消息:【{message}】", state.RobotCrane?.DeviceName);
                    QuartzLogHelper.LogInfo(_logger, $"发送消息:【{message}】", state.RobotCrane?.DeviceName);
                }
                // å®‰å…¨æ›´æ–°çŠ¶æ€åˆ°æ•°æ®åº“
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotStateManager.cs
@@ -1,6 +1,5 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using WIDESEAWCS_Core.LogHelper;
using Serilog;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_Model.Models;
@@ -94,8 +93,7 @@
            if (currentEntity == null)
            {
                _repository.GetOrCreate(newState.IPAddress, newState.RobotCrane ?? new RobotCraneDevice());
                _logger.LogDebug("TryUpdateStateSafely:创建新状态,IP: {IpAddress}", ipAddress);
                QuartzLogger.Debug($"创建新状态,IP: {ipAddress}", ipAddress);
                QuartzLogHelper.LogDebug(_logger, $"创建新状态,IP: {ipAddress}", ipAddress);
                return true;
            }
@@ -112,8 +110,7 @@
            if (!success)
            {
                _logger.LogWarning("TryUpdateStateSafely:版本冲突,更新失败,IP: {IpAddress},期望版本: {ExpectedVersion}", ipAddress, expectedVersion);
                QuartzLogger.Warn($"版本冲突,更新失败,IP: {ipAddress}", ipAddress);
                QuartzLogHelper.LogWarn(_logger, $"TryUpdateStateSafely:版本冲突,更新失败,IP: {ipAddress},期望版本: {expectedVersion}", ipAddress);
            }
            return success;
@@ -161,4 +158,4 @@
            return _repository.ToSocketState(entity);
        }
    }
}
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -1,5 +1,5 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Serilog;
using WIDESEA_Core;
using WIDESEAWCS_Common;
using WIDESEAWCS_Common.HttpEnum;
@@ -176,8 +176,7 @@
            if (result)
            {
                // å‘送成功,记录 Info æ—¥å¿—
                _logger.LogInformation("下发取货指令成功,指令: {TaskString},设备: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
                QuartzLogger.Info($"下发取货指令成功,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"下发取货指令成功,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸º"机器人执行中"
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
@@ -200,8 +199,7 @@
            else
            {
                // å‘送失败,记录 Error æ—¥å¿—
                _logger.LogError("下发取货指令失败,指令: {TaskString},设备: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
                QuartzLogger.Error($"下发取货指令失败,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogError(_logger, $"下发取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
            }
        }
@@ -224,7 +222,7 @@
        {
            if (positions == null || positions.Count == 0)
            {
                _logger.LogWarning("SendSocketRobotFakeBatteryPickAsync:平面点位列表为空,任务号: {TaskNum}", task.RobotTaskNum);
                QuartzLogHelper.LogWarn(_logger, $"SendSocketRobotFakeBatteryPickAsync:平面点位列表为空,任务号: {task.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                return;
            }
@@ -241,9 +239,7 @@
            if (result)
            {
                _logger.LogInformation("下发假电芯取货指令成功,指令: {TaskString},点位: {Positions},设备: {DeviceName}",
                    taskString, string.Join(",", positions), state.RobotCrane?.DeviceName);
                QuartzLogger.Info($"下发假电芯取货指令成功,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"下发假电芯取货指令成功,指令: {taskString},点位: {string.Join(",", positions)},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸º"机器人执行中"
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
@@ -258,8 +254,7 @@
            }
            else
            {
                _logger.LogError("下发假电芯取货指令失败,指令: {TaskString},设备: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
                QuartzLogger.Error($"下发假电芯取货指令失败,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogError(_logger, $"下发假电芯取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
            }
        }
@@ -324,9 +319,7 @@
            if (result)
            {
                _logger.LogInformation("下发批次取货指令成功,指令: {TaskString},批次: {Range},设备: {DeviceName}",
                    taskString, range, state.RobotCrane?.DeviceName);
                QuartzLogger.Info($"下发批次取货指令成功,指令: {taskString},批次: {range}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"下发批次取货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                state.CurrentTask = task;
@@ -338,8 +331,7 @@
            }
            else
            {
                _logger.LogError("下发批次取货指令失败,指令: {TaskString},设备: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
                QuartzLogger.Error($"下发批次取货指令失败,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogError(_logger, $"下发批次取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
            }
        }
@@ -371,9 +363,7 @@
            if (result)
            {
                _logger.LogInformation("下发假电芯批次取货指令成功,指令: {TaskString},批次: {Range},设备: {DeviceName}",
                    taskString, range, state.RobotCrane?.DeviceName);
                QuartzLogger.Info($"下发假电芯批次取货指令成功,指令: {taskString},批次: {range}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"下发假电芯批次取货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                state.CurrentTask = task;
@@ -385,8 +375,7 @@
            }
            else
            {
                _logger.LogError("下发假电芯批次取货指令失败,指令: {TaskString},设备: {DeviceName}", taskString, state.RobotCrane?.DeviceName);
                QuartzLogger.Error($"下发假电芯批次取货指令失败,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogError(_logger, $"下发假电芯批次取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
            }
        }
@@ -419,9 +408,7 @@
            if (result)
            {
                _logger.LogInformation("下发放货指令成功,指令: {TaskString},批次: {Range},设备: {DeviceName}",
                    taskString, range, state.RobotCrane?.DeviceName);
                QuartzLogger.Info($"下发放货指令成功,指令: {taskString},批次: {range}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"下发放货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                state.CurrentTask = task;
@@ -433,9 +420,7 @@
            }
            else
            {
                _logger.LogError("下发放货指令失败,指令: {TaskString},设备: {DeviceName}",
                    taskString, state.RobotCrane?.DeviceName);
                QuartzLogger.Error($"下发放货指令失败,指令: {taskString}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogError(_logger, $"下发放货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
            }
        }
@@ -462,8 +447,7 @@
            var currentTask = state.CurrentTask;
            if (currentTask == null)
            {
                _logger.LogDebug("HandleInboundTaskAsync:当前任务为空");
                QuartzLogger.Debug($"HandleInboundTaskAsync:当前任务为空", state.RobotCrane?.DeviceName ?? "Unknown");
                QuartzLogHelper.LogDebug(_logger, $"HandleInboundTaskAsync:当前任务为空", state.RobotCrane?.DeviceName ?? "Unknown");
                return false;
            }
@@ -573,17 +557,27 @@
            };
            // è®°å½•日志:开始调用 WMS åˆ›å»ºå…¥åº“任务
            _logger.LogInformation("HandleInboundTaskAsync:调用WMS创建入库任务,托盘码: {PalletCode},任务类型: {TaskType}", PalletCode, taskType);
            QuartzLogger.Info($"调用WMS创建入库任务,托盘码: {PalletCode},任务类型: {taskType}", state.RobotCrane?.DeviceName ?? "Unknown");
            QuartzLogHelper.LogInfo(_logger, $"HandleInboundTaskAsync:调用WMS创建入库任务,托盘码: {PalletCode},任务类型: {taskType}", state.RobotCrane?.DeviceName ?? "Unknown");
            // è°ƒç”¨ WMS æŽ¥å£åˆ›å»ºå…¥åº“任务
            var result = _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.CreateTaskInboundAsync), taskDto.ToJson());
            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)
            {
                _logger.LogError("HandleInboundTaskAsync:WMS返回错误状态,Status: {Status}", result.Data.Status);
                QuartzLogger.Error($"HandleInboundTaskAsync:WMS返回错误状态", state.RobotCrane?.DeviceName ?? "Unknown");
                QuartzLogHelper.LogError(_logger, $"HandleInboundTaskAsync:WMS返回错误状态,Status: {result.Data.Status}", state.RobotCrane?.DeviceName ?? "Unknown");
                return false;
            }
@@ -594,8 +588,7 @@
            var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO });
            if (!content.Status)
            {
                _logger.LogError("HandleInboundTaskAsync:接收WMS任务失败");
                QuartzLogger.Error($"HandleInboundTaskAsync:接收WMS任务失败", state.RobotCrane?.DeviceName ?? "Unknown");
                QuartzLogHelper.LogError(_logger, $"HandleInboundTaskAsync:接收WMS任务失败", state.RobotCrane?.DeviceName ?? "Unknown");
                return false;
            }
@@ -698,7 +691,18 @@
        /// <returns>HTTP å“åº”结果</returns>
        public HttpResponseResult<WebResponseContent> PostSplitPalletAsync(StockDTO stockDTO)
        {
            return _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.SplitPalletAsync), stockDTO.ToJson());
            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>
@@ -717,7 +721,17 @@
        /// <returns>HTTP å“åº”结果</returns>
        public HttpResponseResult<WebResponseContent> PostGroupPalletAsync(string configKey, StockDTO stockDTO)
        {
            return _httpClientHelper.Post<WebResponseContent>(configKey, stockDTO.ToJson());
            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>
@@ -731,8 +745,19 @@
        /// <returns>HTTP å“åº”结果</returns>
        public HttpResponseResult<WebResponseContent> PostSplitPalletConfirmAsync(string palletCode, string deviceName)
        {
            string configKey = nameof(ConfigKey.SplitPalletConfirm);
            var request = new { PalletCode = palletCode, DeviceName = deviceName };
            return _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.SplitPalletConfirm), request.ToJson());
            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>
@@ -746,8 +771,19 @@
        /// <returns>HTTP å“åº”结果</returns>
        public HttpResponseResult<WebResponseContent> PostGroupPalletConfirmAsync(string palletCode, string deviceName)
        {
            string configKey = nameof(ConfigKey.GroupPalletConfirm);
            var request = new { PalletCode = palletCode, DeviceName = deviceName };
            return _httpClientHelper.Post<WebResponseContent>(nameof(ConfigKey.GroupPalletConfirm), request.ToJson());
            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;
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotPrefixCommandHandler.cs
@@ -1,7 +1,9 @@
using System.Net.Sockets;
using Serilog;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_Tasks.Workflow.Abstractions;
@@ -66,6 +68,11 @@
        private readonly IFakeBatteryPositionService _fakeBatteryPositionService;
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger _logger;
        /// <summary>
        /// æž„造函数
        /// </summary>
        /// <param name="robotTaskService">任务服务</param>
@@ -73,18 +80,21 @@
        /// <param name="stateManager">状态管理器</param>
        /// <param name="socketClientGateway">Socket ç½‘å…³</param>
        /// <param name="fakeBatteryPositionService">假电芯位置服务</param>
        /// <param name="logger">日志记录器</param>
        public RobotPrefixCommandHandler(
            IRobotTaskService robotTaskService,
            RobotTaskProcessor taskProcessor,
            RobotStateManager stateManager,
            ISocketClientGateway socketClientGateway,
            IFakeBatteryPositionService fakeBatteryPositionService)
            IFakeBatteryPositionService fakeBatteryPositionService,
            ILogger logger)
        {
            _robotTaskService = robotTaskService;
            _taskProcessor = taskProcessor;
            _stateManager = stateManager;
            _socketClientGateway = socketClientGateway;
            _fakeBatteryPositionService = fakeBatteryPositionService;
            _logger = logger;
        }
        /// <summary>
@@ -164,13 +174,13 @@
                }
                else
                {
                    Console.WriteLine($"RobotJob HandleAsync Warning: Current task not found for RobotTaskId {state.CurrentTask.RobotTaskId}");
                    QuartzLogHelper.LogWarn(_logger, $"RobotJob HandleAsync Warning: Current task not found for RobotTaskId {state.CurrentTask.RobotTaskId}", state.RobotCrane?.DeviceName ?? "Unknown");
                }
            }
            catch (Exception ex)
            {
                // æ•获并记录异常,防止异常向上传播导致消息处理中断
                Console.WriteLine($"RobotJob MessageReceived Error: {ex.Message}");
                QuartzLogHelper.LogError(_logger, ex, $"RobotJob MessageReceived Error: {ex.Message}", $"RobotJob MessageReceived Error: {ex.Message}", state.RobotCrane?.DeviceName ?? "Unknown");
            }
        }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -1,3 +1,4 @@
using Serilog;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_Model.Models;
@@ -36,13 +37,20 @@
        private readonly ISocketClientGateway _socketClientGateway;
        /// <summary>
        /// æ—¥å¿—记录器
        /// </summary>
        private readonly ILogger _logger;
        /// <summary>
        /// æž„造函数
        /// </summary>
        /// <param name="taskProcessor">任务处理器实例</param>
        public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor, ISocketClientGateway socketClientGateway)
        /// <param name="logger">日志记录器</param>
        public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor, ISocketClientGateway socketClientGateway, ILogger logger)
        {
            _taskProcessor = taskProcessor;
            _socketClientGateway = socketClientGateway;
            _logger = logger;
        }
        /// <summary>
@@ -157,7 +165,7 @@
                            var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName);
                            if (!confirmResult.IsSuccess)
                            {
                                QuartzLogger.Error($"批量拆盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"批量拆盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
@@ -171,12 +179,12 @@
                                if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
                                {
                                    QuartzLogger.Error($"allpickfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                    QuartzLogHelper.LogError(_logger, $"allpickfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                    return false;
                                }
                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
                                QuartzLogger.Info($"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                                QuartzLogHelper.LogInfo(_logger, $"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                                state.CurrentTask = null;
                                state.RobotTaskTotalNum = 0;
@@ -206,12 +214,12 @@
                            if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
                            {
                                QuartzLogger.Error($"allpickfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"allpickfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
                            QuartzLogger.Info($"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                            QuartzLogHelper.LogInfo(_logger, $"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                            state.ChangePalletPhase = 0;
                            state.CurrentBatchIndex = 1;
@@ -227,7 +235,7 @@
                            var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName);
                            if (!confirmResult.IsSuccess)
                            {
                                QuartzLogger.Error($"批量拆盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"批量拆盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
@@ -239,12 +247,12 @@
                            // å…¥åº“成功,删除任务记录
                            if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
                            {
                                QuartzLogger.Error($"allpickfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"allpickfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
                            QuartzLogger.Info($"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                            QuartzLogHelper.LogInfo(_logger, $"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                            return true;
                        }
                        return false;
@@ -274,7 +282,7 @@
                            var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName);
                            if (!confirmResult.IsSuccess)
                            {
                                QuartzLogger.Error($"批量组盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"批量组盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
@@ -288,7 +296,7 @@
                                if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
                                {
                                    QuartzLogger.Error($"allputfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                    QuartzLogHelper.LogError(_logger, $"allputfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                    return false;
                                }
@@ -297,7 +305,7 @@
                                state.CellBarcode = new List<string>();
                                await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
                                QuartzLogger.Info($"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                                QuartzLogHelper.LogInfo(_logger, $"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                                state.ChangePalletPhase = 0;
                                state.CurrentBatchIndex = 1;
@@ -324,7 +332,7 @@
                            if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
                            {
                                QuartzLogger.Error($"allputfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"allputfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
@@ -333,7 +341,7 @@
                            state.CellBarcode = new List<string>();
                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished");
                            QuartzLogger.Info($"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                            QuartzLogHelper.LogInfo(_logger, $"发送消息:【Swap,diskFinished】", state.RobotCrane.DeviceName);
                            state.ChangePalletPhase = 0;
                            state.CurrentBatchIndex = 1;
@@ -349,7 +357,7 @@
                            var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName);
                            if (!confirmResult.IsSuccess)
                            {
                                QuartzLogger.Error($"批量组盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"批量组盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
@@ -363,7 +371,7 @@
                            // å…¥åº“成功,删除任务记录
                            if (_taskProcessor.DeleteTask(currentTask.RobotTaskId) != true)
                            {
                                QuartzLogger.Error($"allputfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                QuartzLogHelper.LogError(_logger, $"allputfinished:删除任务记录失败,任务号: {currentTask.RobotTaskNum}", state.RobotCrane?.DeviceName ?? "Unknown");
                                return false;
                            }
@@ -373,7 +381,7 @@
                            state.CellBarcode = new List<string>();  // æ¸…空条码列表
                            await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished");
                            QuartzLogger.Info($"发送消息:【Group,diskFinished】", state.RobotCrane.DeviceName);
                            QuartzLogHelper.LogInfo(_logger, $"发送消息:【Group,diskFinished】", state.RobotCrane.DeviceName);
                            return true;
                        }
                        return false;
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -1,11 +1,9 @@
using Microsoft.Extensions.Logging;
using WIDESEA_Core;
using Serilog;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core.Helper;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_Tasks.SocketServer;
using WIDESEAWCS_Tasks.Workflow.Abstractions;
namespace WIDESEAWCS_Tasks.Workflow
@@ -123,8 +121,7 @@
                    && (latestState.RobotArmObject.IsNullOrEmpty() || latestState.RobotArmObject == 1)
                    && task.RobotTaskState == TaskRobotStatusEnum.RobotPickFinish.GetHashCode())
                {
                    _logger.LogInformation("ExecuteAsync:满足放货条件,开始下发放货任务,任务号: {TaskNum}", task.RobotTaskNum);
                    QuartzLogger.Info($"ExecuteAsync:满足放货条件,开始下发放货任务", latestState.RobotCrane?.DeviceName ?? ipAddress);
                    QuartzLogHelper.LogInfo(_logger, $"ExecuteAsync:满足放货条件,开始下发放货任务,任务号: {task.RobotTaskNum}", latestState.RobotCrane?.DeviceName ?? ipAddress);
                    // å‘送放货指令
                    await HandlePickFinishedStateAsync(task, ipAddress);
                }
@@ -137,11 +134,9 @@
                // - ä»»åŠ¡çŠ¶æ€ä¸º RobotPutFinish æˆ–不是 RobotExecuting
                else if ((latestState.CurrentAction == "PutFinished" || latestState.CurrentAction == "AllPutFinished" || latestState.CurrentAction.IsNullOrEmpty())
                    && (latestState.RobotArmObject.IsNullOrEmpty() || latestState.RobotArmObject == 0)
                    && (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode() || task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode())
                    && latestState.BatteryArrived)
                    && (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode() || task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode()))
                {
                    _logger.LogInformation("ExecuteAsync:满足取货条件,开始下发取货任务,任务号: {TaskNum}", task.RobotTaskNum);
                    QuartzLogger.Info($"ExecuteAsync:满足取货条件,开始下发取货任务", latestState.RobotCrane?.DeviceName ?? ipAddress);
                    QuartzLogHelper.LogInfo(_logger, $"ExecuteAsync:满足取货条件,开始下发取货任务,任务号: {task.RobotTaskNum}", latestState.RobotCrane?.DeviceName ?? ipAddress);
                    // å‘送取货指令
                    await HandlePutFinishedStateAsync(task, ipAddress);
                }
@@ -229,7 +224,7 @@
                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
                        if (positions.Count == 0)
                        {
                            _logger.LogError("HandlePickFinishedStateAsync:无可用假电芯点位,任务号: {TaskNum}", task.RobotTaskNum);
                            QuartzLogHelper.LogInfo(_logger, $"HandlePickFinishedStateAsync:无可用假电芯点位,任务号: {task.RobotTaskNum}", state?.RobotCrane?.DeviceName ?? ipAddress);
                            return;
                        }
@@ -267,8 +262,7 @@
            if (result)
            {
                _logger.LogInformation("HandlePickFinishedStateAsync:下发放货指令成功,指令: {TaskString},任务号: {TaskNum}", taskString, task.RobotTaskNum);
                QuartzLogger.Info($"下发放货指令成功,指令: {taskString}", task.RobotRoadway);
                QuartzLogHelper.LogInfo(_logger, $"HandlePickFinishedStateAsync:下发放货指令成功,指令: {taskString},任务号: {task.RobotTaskNum}", state?.RobotCrane?.DeviceName ?? ipAddress);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
@@ -285,8 +279,7 @@
            }
            else
            {
                _logger.LogError("HandlePickFinishedStateAsync:下发放货指令失败,指令: {TaskString},任务号: {TaskNum}", taskString, task.RobotTaskNum);
                QuartzLogger.Error($"下发放货指令失败,指令: {taskString}", task.RobotRoadway);
                QuartzLogHelper.LogInfo(_logger, $"HandlePickFinishedStateAsync:下发放货指令失败,指令: {taskString},任务号: {task.RobotTaskNum}", state?.RobotCrane?.DeviceName ?? ipAddress);
            }
        }
@@ -315,8 +308,7 @@
            RobotSocketState? stateForUpdate = _stateManager.GetState(ipAddress);
            if (stateForUpdate == null)
            {
                _logger.LogWarning("HandlePutFinishedStateAsync:获取状态失败,IP: {IpAddress}", ipAddress);
                QuartzLogger.Warn($"HandlePutFinishedStateAsync:获取状态失败,IP: {ipAddress}", ipAddress);
                QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:获取状态失败,IP: {ipAddress}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                return;
            }
@@ -346,10 +338,7 @@
                {
                    if (stateForUpdate.CellBarcode.Contains(trayBarcode1) || stateForUpdate.CellBarcode.Contains(trayBarcode2))
                    {
                        _logger.LogError("HandlePutFinishedStateAsync:读取的托盘条码已存在,可能存在重复,任务号: {TaskNum}", task.RobotTaskNum);
                        QuartzLogger.Error($"读取的托盘条码已存在,可能存在重复", stateForUpdate.RobotCrane.DeviceName);
                        // æ¡ç é‡å¤ï¼Œè®°å½•错误日志并停止后续操作(后续放货时会用到这些条码信息,供后续放货时使用,调试后可能会取消此逻辑)
                        QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:读取的托盘条码已存在,可能存在重复,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                        // å‘送取货指令 æ ‡è®°æ‰«ç NG,放货时不使用这些条码,并放入NG口
                        //await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true);
@@ -357,8 +346,7 @@
                    }
                    else
                    {
                        _logger.LogInformation("HandlePutFinishedStateAsync:读取的托盘条码唯一,继续执行,任务号: {TaskNum}", task.RobotTaskNum);
                        QuartzLogger.Info($"读取的托盘条码唯一,继续执行", stateForUpdate.RobotCrane.DeviceName);
                        QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:读取的托盘条码唯一,继续执行,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                        // å°†æ¡ç æ·»åŠ åˆ°çŠ¶æ€ä¸­ï¼Œä¾›åŽç»­æ”¾è´§æ—¶ä½¿ç”¨
                        stateForUpdate.CellBarcode = new List<string>()
@@ -368,8 +356,7 @@
                    }
                    // è®°å½•日志:读取托盘条码成功
                    _logger.LogInformation("HandlePutFinishedStateAsync:读取托盘条码成功: {Barcode1}+{Barcode2},任务号: {TaskNum}", trayBarcode1, trayBarcode2, task.RobotTaskNum);
                    QuartzLogger.Info($"读取托盘条码成功: {trayBarcode1}+{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName);
                    QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:读取托盘条码成功: ã€{trayBarcode1}】-----【{trayBarcode2}】,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                    // å‘送取货指令
                    await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate);
@@ -377,9 +364,7 @@
                else
                {
                    // æ¡ç è¯»å–失败,记录错误日志
                    _logger.LogError("HandlePutFinishedStateAsync:读取托盘条码失败,任务号: {TaskNum},一号位: {trayBarcode1},二号位: {trayBarcode2}", task.RobotTaskNum,trayBarcode1,trayBarcode2);
                    QuartzLogger.Error($"读取托盘条码失败,一号位:{trayBarcode1},二号位:{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName);
                    QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:读取托盘条码失败,【{trayBarcode1}】-----【{trayBarcode2}】,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                    // å‘送取货指令 æ ‡è®°æ‰«ç NG,放货时不使用这些条码,并放入NG口
                    //await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true);
@@ -409,8 +394,8 @@
                {
                    stateForUpdate.ChangePalletPhase = 1;
                    stateForUpdate.CurrentBatchIndex = 1;
                    _logger.LogInformation("HandlePutFinishedStateAsync:换盘任务进入批次模式,任务号: {TaskNum},流向: {Flow}",
                        task.RobotTaskNum, isFlowA ? "A" : "B");
                    QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:换盘任务进入批次模式,任务号: {{TaskNum}},流向: {(isFlowA ? "A" : "B")},任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                    _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
                }
@@ -423,7 +408,8 @@
                        // æ­£å¸¸ç”µèŠ¯å–å®Œï¼Œåˆ‡æ¢åˆ° Phase 3 å–假电芯
                        stateForUpdate.ChangePalletPhase = 3;
                        stateForUpdate.CurrentBatchIndex = 1; // å‡ç”µèŠ¯æ‰¹æ¬¡ä»Žå¤´å¼€å§‹
                        _logger.LogInformation("HandlePutFinishedStateAsync:正常电芯取完,切换到Phase 3取假电芯,任务号: {TaskNum}", task.RobotTaskNum);
                        QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:正常电芯取完,切换到Phase 3取假电芯,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                        _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
                        return;
                    }
@@ -451,7 +437,8 @@
                    {
                        // å‡ç”µèŠ¯å…¨éƒ¨å¤„ç†å®Œï¼Œåˆ‡æ¢åˆ° Phase 5 ç­‰å¾…入库
                        stateForUpdate.ChangePalletPhase = 5;
                        _logger.LogInformation("HandlePutFinishedStateAsync:假电芯处理完毕,切换到Phase 5等待入库,任务号: {TaskNum}", task.RobotTaskNum);
                        QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:假电芯处理完毕,切换到Phase 5等待入库,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                        _stateManager.TryUpdateStateSafely(ipAddress, stateForUpdate);
                        return;
                    }
@@ -462,7 +449,7 @@
                        var positions = _taskProcessor.GetNextAvailableFakeBatteryPositions(Math.Min(4, remainingFake));
                        if (positions.Count == 0)
                        {
                            _logger.LogError("HandlePutFinishedStateAsync:无可用假电芯点位,任务号: {TaskNum}", task.RobotTaskNum);
                            QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:无可用假电芯点位,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                            return;
                        }
                        await _taskProcessor.SendSocketRobotFakeBatteryPickAsync(task, stateForUpdate, positions);
@@ -496,4 +483,4 @@
            }
        }
    }
}
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
@@ -174,9 +174,8 @@
                bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
                if (!flag || value is not CommonStackerCrane commonStackerCrane)
                {
                    _logger.Information("Execute:参数无效,未找到 JobParams æˆ–类型不匹配");
                    // å‚数无效,直接返回
                    QuartzLogHelper.LogWarn(_logger, "Execute:参数无效", "Execute:参数无效", "CommonStackerCraneJob");
                    QuartzLogHelper.LogInfo(_logger, "Execute:参数无效", "CommonStackerCraneJob");
                    return Task.CompletedTask;
                }
@@ -218,7 +217,7 @@
                if (stackerCraneTaskCommand == null)
                {
                    // å‘½ä»¤æž„建失败
                    QuartzLogHelper.LogWarn(_logger, "Execute:命令构建失败,设备: {DeviceCode},任务号: {TaskNum}", $"命令构建失败,任务号: {task.TaskNum}", _deviceCode, _deviceCode, task.TaskNum);
                    QuartzLogHelper.LogInfo(_logger, $"Execute:命令构建失败,设备: {_deviceCode},任务号: {task.TaskNum}", _deviceCode);
                    return Task.CompletedTask;
                }
@@ -232,17 +231,17 @@
                    commonStackerCrane.LastTaskType = task.TaskType;
                    _taskService.UpdateTaskStatusToNext(task.TaskNum);
                    QuartzLogHelper.LogInfo(_logger, "Execute:命令发送成功,设备: {DeviceCode},任务号: {TaskNum}", $"命令发送成功,任务号: {task.TaskNum}", _deviceCode, _deviceCode, task.TaskNum);
                    QuartzLogHelper.LogInfo(_logger, $"Execute:命令发送成功,设备: {_deviceCode},任务号: {task.TaskNum}", _deviceCode);
                }
                else
                {
                    QuartzLogHelper.LogError(_logger, "Execute:命令发送失败,设备: {DeviceCode},任务号: {TaskNum}", $"命令发送失败", _deviceCode, _deviceCode, task.TaskNum);
                    QuartzLogHelper.LogInfo(_logger, $"Execute:命令发送失败,设备: {_deviceCode},任务号: {task.TaskNum}", _deviceCode);
                }
            }
            catch (Exception ex)
            {
                // è®°å½•异常
                QuartzLogHelper.LogError(_logger, ex, "Execute:执行异常,设备: {DeviceCode}", $"执行异常: {ex.Message}", _deviceCode, _deviceCode);
                QuartzLogHelper.LogError(_logger, ex, $"Execute:执行异常,设备: {_deviceCode}", $"执行异常: {ex.Message}", _deviceCode, _deviceCode);
            }
            finally
            {
@@ -270,7 +269,7 @@
            if (stackerCrane != null)
            {
                // è®°å½•日志
                QuartzLogHelper.LogInfo(_logger, "CommonStackerCrane_StackerCraneTaskCompletedEventHandler:任务完成,任务号: {TaskNum}", $"任务完成,任务号: {e.TaskNum}", stackerCrane.DeviceCode, e.TaskNum);
                QuartzLogHelper.LogInfo(_logger, $"CommonStackerCrane_StackerCraneTaskCompletedEventHandler:任务完成,任务号: {e.TaskNum}", stackerCrane.DeviceCode);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸ºå®Œæˆ
                if (_taskService.StackCraneTaskCompleted(e.TaskNum).Status)