已添加12个文件
已删除1个文件
已修改21个文件
900 ■■■■ 文件已修改
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/DeviceAddressConst.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneCommandTypeEnum.cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneConst.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneRoadwayConst.cs 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneWorkActionEnum.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Common/CommonStackerCrane.cs 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Enum/StackerCraneStatus.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Spec/SpeFormationStackerCrane.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Spec/SpeTemperatureStackerCrane.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server.sln 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/libman.json 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob/CommonConveyorLineJob.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/README.md 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneCommandBuilder.cs 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneDBName.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskCommand.cs 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/.vscode/launch.json 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/.vscode/tasks.json 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/StockConstants.cs 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_GradingMachine.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_WCS.cs 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目资料/设备协议/高常温堆垛机与输送线/~$堆垛机与上位机交互信息.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
项目资料/设备协议/高常温堆垛机与输送线/堆垛机与上位机交互信息.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/DeviceAddressConst.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
namespace WIDESEAWCS_Common.Constants
{
    /// <summary>
    /// è®¾å¤‡åœ°å€å…¬å…±å¸¸é‡
    /// </summary>
    /// <remarks>
    /// å®šä¹‰è®¾å¤‡é€šä¿¡ä¸­ä½¿ç”¨çš„公共常量,如地址格式、信号值等。
    /// </remarks>
    public class DeviceAddressConst
    {
        /// <summary>
        /// äº¤äº’信号复位值
        /// </summary>
        /// <remarks>
        /// è®¾å¤‡å®Œæˆä»»åŠ¡åŽï¼Œå†™å…¥æ­¤å€¼åˆ°äº¤äº’ä¿¡å·å¯„å­˜å™¨ä»¥å¤ä½ã€‚
        /// ç”¨äºŽè¾“送线等设备的任务完成确认。
        /// </remarks>
        public const int InteractiveSignalReset = 0;
        /// <summary>
        /// åœ°å€å­—符串分隔符
        /// </summary>
        /// <remarks>
        /// åœ°å€æ ¼å¼ä¸º "行-列-层",例如 "1-2-3" è¡¨ç¤ºç¬¬1行、第2列、第3层。
        /// </remarks>
        public const char AddressSeparator = '-';
        /// <summary>
        /// åœ°å€å­—符串分隔符(字符串形式)
        /// </summary>
        /// <remarks>
        /// ç”¨äºŽå­—符串 Split æ“ä½œã€‚
        /// </remarks>
        public const string AddressSeparatorString = "-";
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneCommandTypeEnum.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
namespace WIDESEAWCS_Common.Constants
{
    /// <summary>
    /// å †åž›æœºå‘½ä»¤ç±»åž‹æžšä¸¾
    /// </summary>
    /// <remarks>
    /// æ ¹æ®å··é“类型的不同,堆垛机可能使用不同的命令格式。
    /// </remarks>
    public enum StackerCraneCommandTypeEnum
    {
        /// <summary>
        /// æ ‡å‡†å‘½ä»¤æ ¼å¼
        /// </summary>
        /// <remarks>
        /// ç”¨äºŽ GW、CW å¼€å¤´å··é“的堆垛机。
        /// </remarks>
        Standard,
        /// <summary>
        /// æˆåž‹å‘½ä»¤æ ¼å¼
        /// </summary>
        /// <remarks>
        /// ç”¨äºŽ HC å¼€å¤´å··é“的堆垛机。
        /// åŒ…含条码字段,用于电池追溯。
        /// </remarks>
        Formation
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneConst.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
namespace WIDESEAWCS_Common.Constants
{
    /// <summary>
    /// å †åž›æœºç›¸å…³å¸¸é‡
    /// </summary>
    public class StackerCraneConst
    {
        /// <summary>
        /// ç©ºæ‰˜ç›˜ä»»åŠ¡ç±»åž‹
        /// </summary>
        /// <remarks>
        /// å½“任务类型为空托盘出库/入库时,使用此特殊类型值代替原任务类型。
        /// ç”¨äºŽä¸Žç«™å°è·¯ç”±é…ç½®åŒ¹é…ã€‚
        /// </remarks>
        public const int EmptyPalletTaskType = 100;
        /// <summary>
        /// ç«è­¦çŠ¶æ€æ­£å¸¸
        /// </summary>
        /// <remarks>
        /// ç«è­¦ä¿¡å·ä¸º 0 è¡¨ç¤ºæ­£å¸¸ï¼Œæ— ç«ç¾æŠ¥è­¦ã€‚
        /// </remarks>
        public const short FireAlarmNormal = 0;
        /// <summary>
        /// å¿ƒè·³åˆå§‹å€¼
        /// </summary>
        /// <remarks>
        /// å †åž›æœºå‘½ä»¤ä¸­çš„心跳字段初始值。
        /// </remarks>
        public const short HeartBeatInitial = 0;
        /// <summary>
        /// ä½œä¸šç±»åž‹ - å…¥åº“
        /// </summary>
        /// <remarks>
        /// æ ‡è¯†ä»»åŠ¡ä¸ºå…¥åº“ä½œä¸šç±»åž‹ã€‚
        /// </remarks>
        public const short WorkTypeInbound = 1;
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneRoadwayConst.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
using System.Collections.Generic;
namespace WIDESEAWCS_Common.Constants
{
    /// <summary>
    /// å †åž›æœºå··é“前缀常量
    /// </summary>
    /// <remarks>
    /// å®šä¹‰å··é“编码的前缀与命令类型的映射关系。
    /// </remarks>
    public class StackerCraneRoadwayConst
    {
        /// <summary>
        /// æˆåž‹å †åž›æœºå··é“前缀
        /// </summary>
        /// <remarks>
        /// ä»¥ HC å¼€å¤´çš„巷道使用成型堆垛机命令格式。
        /// </remarks>
        public const string FormationPrefix = "HC";
        /// <summary>
        /// æ ‡å‡†å †åž›æœºå··é“前缀(GW)
        /// </summary>
        /// <remarks>
        /// ä»¥ GW å¼€å¤´çš„巷道使用标准堆垛机命令格式。
        /// </remarks>
        public const string StandardPrefixGW = "GW";
        /// <summary>
        /// æ ‡å‡†å †åž›æœºå··é“前缀(CW)
        /// </summary>
        /// <remarks>
        /// ä»¥ CW å¼€å¤´çš„巷道使用标准堆垛机命令格式。
        /// </remarks>
        public const string StandardPrefixCW = "CW";
        /// <summary>
        /// å··é“前缀到命令类型的默认映射
        /// </summary>
        /// <remarks>
        /// Key: å··é“编码前缀
        /// Value: å‘½ä»¤ç±»åž‹åç§°
        /// </remarks>
        public static readonly Dictionary<string, StackerCraneCommandTypeEnum> DefaultRoadwayCommandMapping = new()
        {
            { FormationPrefix, StackerCraneCommandTypeEnum.Formation },
            { StandardPrefixGW, StackerCraneCommandTypeEnum.Standard },
            { StandardPrefixCW, StackerCraneCommandTypeEnum.Standard }
        };
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/Constants/StackerCraneWorkActionEnum.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
namespace WIDESEAWCS_Common.Constants
{
    /// <summary>
    /// å †åž›æœºä½œä¸šæŒ‡ä»¤æžšä¸¾
    /// </summary>
    /// <remarks>
    /// æŽ§åˆ¶å †åž›æœºçš„动作指令,通过 PLC å¯„存器与堆垛机通信。
    /// </remarks>
    public enum StackerCraneWorkActionEnum
    {
        /// <summary>
        /// å¼€å§‹æ‰§è¡Œä»»åŠ¡
        /// </summary>
        StartTask = 1,
        /// <summary>
        /// ä»»åŠ¡å®Œæˆ/停止
        /// </summary>
        TaskComplete = 2,
        /// <summary>
        /// æ¶ˆé˜²ä»»åС开始
        /// </summary>
        FireAlarmStart = 3
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Common/CommonStackerCrane.cs
@@ -225,7 +225,7 @@
                {
                    return DeviceStatus.Idle;
                }
                else if (StackerCraneWorkStatusValue == StackerCraneWorkStatus.Putting || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PickUp || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PickUpCompleted || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PutCompleted)
                else if (StackerCraneWorkStatusValue == StackerCraneWorkStatus.Putting || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PickUp || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PutMove || StackerCraneWorkStatusValue == StackerCraneWorkStatus.PutCompleted)
                {
                    return DeviceStatus.Working;
                }
@@ -315,10 +315,10 @@
                    {
                        return deviceProtocolDetail.ProtocolDetailType;
                    }
                    return StackerCraneStatus.Unkonw.ToString();
                    return StackerCraneStatus.Unknown.ToString();
                }
            }
            return StackerCraneStatus.Unkonw.ToString();
            return StackerCraneStatus.Unknown.ToString();
        }
        private void CheckConnect()
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Enum/StackerCraneStatus.cs
@@ -32,10 +32,10 @@
    public enum StackerCraneStatus
    {
        /// <summary>
        /// æ­£å¸¸
        /// ç©ºé—²&联机
        /// </summary>
        [Description("正常")]
        Normal,
        [Description("空闲&联机")]
        Normal = 1,
        /// <summary>
        /// æ•…éšœ
@@ -53,7 +53,7 @@
        /// æœªçŸ¥
        /// </summary>
        [Description("未知")]
        Unkonw
        Unknown
    }
    /// <summary>
@@ -65,7 +65,7 @@
        /// ç»´ä¿®/维护/保养
        /// </summary>
        [Description("ç»´ä¿®")]
        Maintenance,
        Maintenance = 2,
        /// <summary>
        /// æ‰‹åЍ
@@ -89,7 +89,7 @@
        /// æœªçŸ¥
        /// </summary>
        [Description("未知")]
        Unkonw
        Unknown
    }
    /// <summary>
@@ -101,7 +101,19 @@
        /// å¾…机
        /// </summary>
        [Description("待机")]
        Standby,
        Standby = 1,
        /// <summary>
        /// æŽ¥æ”¶ä»»åŠ¡
        /// </summary>
        [Description("接收任务")]
        AcceptTask,
        /// <summary>
        /// å–货移动中
        /// </summary>
        [Description("取货移动中")]
        PickMove,
        /// <summary>
        /// å–货中
@@ -110,10 +122,10 @@
        PickUp,
        /// <summary>
        /// å–货完成
        /// æ”¾è´§ç§»åЍ䏭
        /// </summary>
        [Description("取货完成")]
        PickUpCompleted,
        [Description("放货移动中")]
        PutMove,
        /// <summary>
        /// æ”¾è´§ä¸­
@@ -143,7 +155,7 @@
        /// æœªçŸ¥
        /// </summary>
        [Description("未知")]
        Unkonw
        Unknown
    }
    /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Spec/SpeFormationStackerCrane.cs
@@ -170,7 +170,7 @@
        {
            if (!Communicator.IsConnected)
            {
                return StackerCraneStatus.Unkonw.ToString();
                return StackerCraneStatus.Unknown.ToString();
            }
            List<DeviceProDTO> devicePros = _deviceProDTOs.Where(x => x.DeviceProParamType == protocolParamType).ToList();
@@ -193,7 +193,7 @@
                }
            }
            return StackerCraneStatus.Unkonw.ToString();
            return StackerCraneStatus.Unknown.ToString();
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_QuartzJob/StackerCrane/Spec/SpeTemperatureStackerCrane.cs
@@ -197,7 +197,7 @@
        {
            if (!Communicator.IsConnected)
            {
                return StackerCraneStatus.Unkonw.ToString();
                return StackerCraneStatus.Unknown.ToString();
            }
            List<DeviceProDTO> devicePros = _deviceProDTOs.Where(x => x.DeviceProParamType == protocolParamType).ToList();
@@ -220,7 +220,7 @@
                }
            }
            return StackerCraneStatus.Unkonw.ToString();
            return StackerCraneStatus.Unknown.ToString();
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 18
VisualStudioVersion = 18.2.11415.280 d18.0
VisualStudioVersion = 18.2.11415.280
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WIDESEAWCS_Server", "WIDESEAWCS_Server\WIDESEAWCS_Server.csproj", "{487FA45B-EA1A-4ACA-BB5B-0F6708F462C0}"
EndProject
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/libman.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,5 @@
{
  "version": "3.0",
  "defaultProvider": "cdnjs",
  "libraries": []
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/InboundTaskFlowService.cs
@@ -100,7 +100,7 @@
                return content.Error($"通知WMS系统堆垛机入库完成失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【{result.Data?.Message}】");
            }
            return content.Error($"通知WMS系统堆垛机入库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
            return content.OK($"通知WMS系统堆垛机入库完成成功,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】");
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineJob/CommonConveyorLineJob.cs
@@ -24,6 +24,7 @@
using MapsterMapper;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using Quartz;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Communicator;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.Helper;
@@ -144,7 +145,7 @@
            Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode);
            if (task != null)
            {
                conveyorLine.SetValue(ConveyorLineDBName.WriteInteractiveSignal, 0, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName.WriteInteractiveSignal, DeviceAddressConst.InteractiveSignalReset, childDeviceCode);
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                Console.Out.WriteLine(content.Serialize());
            }
@@ -201,7 +202,7 @@
            Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNum, childDeviceCode);
            if (task != null)
            {
                conveyorLine.SetValue(ConveyorLineDBName.WriteInteractiveSignal, 0, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBName.WriteInteractiveSignal, DeviceAddressConst.InteractiveSignalReset, childDeviceCode);
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                Console.Out.WriteLine(content.Serialize());
            }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -4,8 +4,6 @@
using Newtonsoft.Json;
using Quartz;
using SqlSugar;
using System.Text;
using System.Text.Json;
using WIDESEA_Core;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
@@ -79,6 +77,13 @@
        private readonly ILogger<CommonConveyorLineNewJob> _logger;
        /// <summary>
        /// ç›®æ ‡åœ°å€åˆ°è®¾å¤‡ç±»åž‹çš„æ˜ å°„
        /// </summary>
        /// <remarks>
        /// </remarks>
        private static List<string> AddressToDeviceType = new List<string> { "11020", "11028" };
        /// <summary>
        /// æž„造函数
        /// </summary>
        /// <param name="taskService">任务服务</param>
@@ -139,8 +144,8 @@
                    //    MaxDegreeOfParallelism = Math.Min(childDeviceCodes.Count, Environment.ProcessorCount * 2),
                    //};
                    _logger.LogDebug("Execute:开始并行处理输送线 {DeviceCode},子设备数量: {Count}", conveyorLine.DeviceCode, childDeviceCodes.Count);
                    QuartzLogger.Debug($"开始并行处理输送线,子设备数量: {childDeviceCodes.Count}", conveyorLine.DeviceCode);
                    //_logger.LogDebug("Execute:开始并行处理输送线 {DeviceCode},子设备数量: {Count}", conveyorLine.DeviceCode, childDeviceCodes.Count);
                    //QuartzLogger.Debug($"开始并行处理输送线,子设备数量: {childDeviceCodes.Count}", conveyorLine.DeviceCode);
                    // å¹¶è¡Œå¤„理每个子设备
                    //Parallel.For(0, childDeviceCodes.Count, parallelOptions, i =>
@@ -161,9 +166,6 @@
                                continue;
                            }
                            // å¦‚æžœ WCS_ACK ä¸º 1,先清除(表示处理过上一次请求)
                            if (command.WCS_ACK == 1)
                                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 0, childDeviceCode);
                            // ========== æ£€æŸ¥ç‰¹å®šä½ç½®æ˜¯å¦æœ‰æ‰˜ç›˜ ==========
                            // ä»Žé…ç½®ä¸­è¯»å–需要检查托盘的位置列表
@@ -207,7 +209,10 @@
                            // åªæœ‰å½“ PLC_STB ä¸º 1 æ—¶æ‰å¤„理任务
                            if (command.PLC_STB != 1)
                            {
                                return Task.CompletedTask;
                                // å¦‚æžœ WCS_ACK ä¸º 1,先清除(表示处理过上一次请求)
                                if (command.WCS_ACK == 1)
                                    conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)0, childDeviceCode);
                                continue;
                            }
                            // ========== å¤„理无托盘条码的情况 ==========
@@ -217,7 +222,7 @@
                                _logger.LogDebug("Execute:子设备 {ChildDeviceCode} æ— æ‰˜ç›˜æ¡ç ï¼Œè¯·æ±‚出库任务", childDeviceCode);
                                QuartzLogger.Debug($"子设备 {childDeviceCode} æ— æ‰˜ç›˜æ¡ç ï¼Œè¯·æ±‚出库任务", conveyorLine.DeviceCode);
                                _conveyorLineDispatch.RequestOutbound(conveyorLine, command, childDeviceCode);
                                return Task.CompletedTask;
                                continue;
                            }
                            // ========== å¤„理已有任务号的情况 ==========
@@ -286,7 +291,13 @@
            {
                case InExecuting:
                    // å…¥åº“执行中,调用下一地址处理
                    _conveyorLineDispatch.RequestInNextAddress(conveyorLine, command, childDeviceCode);
                    if (AddressToDeviceType.Contains(childDeviceCode))
                        // åˆ°è¾¾ç›®æ ‡åœ°å€ï¼Œè°ƒç”¨å…¥åº“完成
                        _conveyorLineDispatch.ConveyorLineInFinish(conveyorLine, command, childDeviceCode);
                    else
                        // æœªåˆ°è¾¾ç›®æ ‡åœ°å€ï¼Œè°ƒç”¨å…¥åº“下一地址处理
                        _conveyorLineDispatch.RequestInNextAddress(conveyorLine, command, childDeviceCode);
                    break;
                case OutExecuting:
@@ -311,4 +322,4 @@
            }
        }
    }
}
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -187,7 +187,7 @@
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            // è®¾ç½® WCS_STB æ ‡å¿—,表示 WCS å·²å¤„理
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_STB, 1, childDeviceCode);
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
        }
        /// <summary>
@@ -206,11 +206,15 @@
            Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode);
            if (task != null)
            {
                // å›žå¤ ACK ç¡®è®¤
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€é˜¶æ®µï¼ˆé€šå¸¸æ˜¯å®Œæˆï¼‰
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                if (_taskService.UpdateTaskStatusToNext(task).Status)
                {
                }
                // å›žå¤ ACK ç¡®è®¤
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                _logger.LogInformation("ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
                QuartzLogger.Info($"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode);
@@ -246,7 +250,7 @@
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, task.NextAddress, childDeviceCode);
                // å›žå¤ ACK ç¡®è®¤
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€
                _taskService.UpdateTaskStatusToNext(task);
@@ -290,7 +294,7 @@
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            // å›žå¤ ACK ç¡®è®¤
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
        }
        /// <summary>
@@ -313,7 +317,7 @@
                WebResponseContent content = _taskService.UpdateTaskStatusToNext(task);
                // å›žå¤ ACK ç¡®è®¤
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, 1, childDeviceCode);
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                _logger.LogInformation("ConveyorLineOutFinish:出库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", task.TaskNum, childDeviceCode);
                QuartzLogger.Info($"出库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode);
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -337,8 +337,8 @@
                // è®¾ç½®è¾“送线的任务号
                conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, taskInfo.TaskNum, sourceAddress);
                // è§¦å‘输送线开始执行(写入 WCS_STB = 1)
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_STB, 1, sourceAddress);
                // è§¦å‘输送线开始执行(写入 WCS_ACK = 1)
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, sourceAddress);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€é˜¶æ®µ
                if (_taskService.UpdateTaskStatusToNext(taskInfo).Status)
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/CommonStackerCraneJob.cs
@@ -1,19 +1,17 @@
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading.Tasks;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEA_Core;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.StackerCrane;
using WIDESEAWCS_Tasks.StackerCraneJob;
using WIDESEA_Core;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_QuartzJob.StackerCrane;
using WIDESEAWCS_QuartzJob.StackerCrane.Enum;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Tasks.StackerCraneJob;
namespace WIDESEAWCS_Tasks
{
@@ -173,7 +171,7 @@
            {
                // ä»Ž JobDataMap èŽ·å–å †åž›æœºè®¾å¤‡å‚æ•°
                bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
                if (!flag || value is not IStackerCrane commonStackerCrane)
                if (!flag || value is not CommonStackerCrane commonStackerCrane)
                {
                    // å‚数无效,直接返回
                    _logger.LogWarning("Execute:参数无效");
@@ -194,11 +192,12 @@
                // ========== æ£€æŸ¥å †åž›æœºä»»åŠ¡å®ŒæˆçŠ¶æ€ ==========
                commonStackerCrane.CheckStackerCraneTaskCompleted();
                _logger.LogDebug("Execute:检查任务完成状态,设备: {DeviceCode}", _deviceCode);
                QuartzLogger.Debug($"检查任务完成状态,设备: {_deviceCode}", _deviceCode);
                //_logger.LogDebug("Execute:检查任务完成状态,设备: {DeviceCode}", _deviceCode);
                //QuartzLogger.Debug($"检查任务完成状态,设备: {_deviceCode}", _deviceCode);
                // ========== æ£€æŸ¥æ˜¯å¦å¯ä»¥å‘送新任务 ==========
                if (!commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs))
                //if (!commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs))
                if (commonStackerCrane.StackerCraneStatusValue != StackerCraneStatus.Normal)
                {
                    // å †åž›æœºä¸å¯ç”¨ï¼ˆå¦‚正在执行上一任务),直接返回
                    _logger.LogDebug("Execute:堆垛机不可用,设备: {DeviceCode}", _deviceCode);
@@ -212,13 +211,13 @@
                if (task == null)
                {
                    // æ²¡æœ‰å¯ç”¨ä»»åŠ¡
                    _logger.LogDebug("Execute:没有可用任务,设备: {DeviceCode}", _deviceCode);
                    QuartzLogger.Debug($"没有可用任务,设备: {_deviceCode}", _deviceCode);
                    //_logger.LogDebug("Execute:没有可用任务,设备: {DeviceCode}", _deviceCode);
                    //QuartzLogger.Debug($"没有可用任务,设备: {_deviceCode}", _deviceCode);
                    return Task.CompletedTask;
                }
                _logger.LogInformation("Execute:选择任务,设备: {DeviceCode},任务号: {TaskNum}", _deviceCode, task.TaskNum);
                QuartzLogger.Info($"选择任务,任务号: {task.TaskNum}", _deviceCode);
                //_logger.LogInformation("Execute:选择任务,设备: {DeviceCode},任务号: {TaskNum}", _deviceCode, task.TaskNum);
                //QuartzLogger.Info($"选择任务,任务号: {task.TaskNum}", _deviceCode);
                // ========== æž„建命令 ==========
                // å‘½ä»¤æž„建下沉到专用构建器
@@ -235,6 +234,8 @@
                bool sendFlag = SendStackerCraneCommand(commonStackerCrane, stackerCraneTaskCommand);
                if (sendFlag)
                {
                    Task.Delay(1000).Wait();
                    commonStackerCrane.SetValue(StackerCraneDBName.WorkAction, (short)StackerCraneWorkActionEnum.StartTask);
                    // å‘送成功,更新状态
                    commonStackerCrane.LastTaskType = task.TaskType;
                    _taskService.UpdateTaskStatusToNext(task.TaskNum);
@@ -280,10 +281,11 @@
                QuartzLogger.Info($"任务完成,任务号: {e.TaskNum}", stackerCrane.DeviceCode);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸ºå®Œæˆ
                _taskService.StackCraneTaskCompleted(e.TaskNum);
                // æ¸…除堆垛机的作业指令(设置为 2,表示空闲)
                stackerCrane.SetValue(StackerCraneDBName.WorkAction, 2);
                if (_taskService.StackCraneTaskCompleted(e.TaskNum).Status)
                {
                    // æ¸…除堆垛机的作业指令(设置为空闲)
                    stackerCrane.SetValue(StackerCraneDBName.WorkAction, (short)StackerCraneWorkActionEnum.TaskComplete);
                }
            }
        }
@@ -310,4 +312,4 @@
            };
        }
    }
}
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/README.md
ÎļþÒÑɾ³ý
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneCommandBuilder.cs
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_ITaskInfoService;
@@ -74,18 +75,19 @@
        /// <returns>堆垛机命令对象,转换失败返回 null</returns>
        public object? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task)
        {
            return  BuildCommand(task, CreateStandardCommand(task));
            // æ ¹æ®å··é“获取命令类型
            string commandType = GetCommandType(task.Roadway);
            //string commandType = GetCommandType(task.Roadway);
            _logger.LogInformation("ConvertToStackerCraneTaskCommand:构建命令,任务号: {TaskNum},巷道: {Roadway},命令类型: {CommandType}", task.TaskNum, task.Roadway, commandType);
            QuartzLogger.Info($"构建命令,任务号: {task.TaskNum},巷道: {task.Roadway},命令类型: {commandType}", task.Roadway);
            //_logger.LogInformation("ConvertToStackerCraneTaskCommand:构建命令,任务号: {TaskNum},巷道: {Roadway},命令类型: {CommandType}", task.TaskNum, task.Roadway, commandType);
            //QuartzLogger.Info($"构建命令,任务号: {task.TaskNum},巷道: {task.Roadway},命令类型: {commandType}", task.Roadway);
            // æ ¹æ®å‘½ä»¤ç±»åž‹è°ƒç”¨ç›¸åº”的构建方法
            return commandType switch
            {
                "Formation" => BuildCommand(task, CreateFormationCommand(task)),  // æˆåž‹å‘½ä»¤
                _ => BuildCommand(task, CreateStandardCommand(task))              // æ ‡å‡†å‘½ä»¤
            };
            //// æ ¹æ®å‘½ä»¤ç±»åž‹è°ƒç”¨ç›¸åº”的构建方法
            //return commandType switch
            //{
            //    "Formation" => BuildCommand(task, CreateFormationCommand(task)),  // æˆåž‹å‘½ä»¤
            //    _ => BuildCommand(task, CreateStandardCommand(task))              // æ ‡å‡†å‘½ä»¤
            //};
        }
        /// <summary>
@@ -127,8 +129,8 @@
            return new StackerCraneTaskCommand
            {
                TaskNum = task.TaskNum,   // ä»»åŠ¡å·
                WorkType = 1,             // ä½œä¸šç±»åž‹
                WorkAction = 1            // ä½œä¸šæŒ‡ä»¤ï¼šå¼€å§‹æ‰§è¡Œ
                WorkType = StackerCraneConst.WorkTypeInbound,  // ä½œä¸šç±»åž‹ï¼šå…¥åº“
                //WorkAction = StackerCraneWorkActionEnum.StartTask  // ä½œä¸šæŒ‡ä»¤ï¼šå¼€å§‹æ‰§è¡Œ
            };
        }
@@ -147,10 +149,10 @@
            {
                Barcode = task.PalletCode,   // æ‰˜ç›˜æ¡ç 
                TaskNum = task.TaskNum,      // ä»»åŠ¡å·
                WorkType = 1,               // ä½œä¸šç±»åž‹
                WorkAction = 1,             // ä½œä¸šæŒ‡ä»¤ï¼šå¼€å§‹æ‰§è¡Œ
                FireAlarm = 0,              // ç«è­¦ï¼šæ­£å¸¸
                HeartBeat = 0,              // å¿ƒè·³
                WorkType = StackerCraneConst.WorkTypeInbound,  // ä½œä¸šç±»åž‹ï¼šå…¥åº“
                WorkAction = (short)StackerCraneWorkActionEnum.StartTask,  // ä½œä¸šæŒ‡ä»¤ï¼šå¼€å§‹æ‰§è¡Œ
                FireAlarm = StackerCraneConst.FireAlarmNormal,  // ç«è­¦ï¼šæ­£å¸¸
                HeartBeat = StackerCraneConst.HeartBeatInitial,  // å¿ƒè·³
                FieldName = string.Empty     // ä¿ç•™å­—段
            };
        }
@@ -201,11 +203,11 @@
            _logger.LogInformation("BuildInboundCommand:构建入库命令,任务号: {TaskNum}", task.TaskNum);
            QuartzLogger.Info($"BuildInboundCommand:构建入库命令,任务号: {task.TaskNum}", task.Roadway);
            // ç¡®å®šä»»åŠ¡ç±»åž‹ï¼ˆç©ºæ‰˜ç›˜ç”¨ç‰¹æ®Šç±»åž‹ 100)
            // ç¡®å®šä»»åŠ¡ç±»åž‹ï¼ˆç©ºæ‰˜ç›˜ç”¨ç‰¹æ®Šç±»åž‹ï¼‰
            int taskType = 0;
            if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                taskType = 100;
                taskType = StackerCraneConst.EmptyPalletTaskType;
            }
            else
                taskType = task.TaskType;
@@ -269,7 +271,7 @@
            int taskType = 0;
            if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                taskType = 100;
                taskType = StackerCraneConst.EmptyPalletTaskType;
            }
            else
                taskType = task.TaskType;
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneDBName.cs
@@ -92,9 +92,10 @@
        /// ä½œä¸šæŒ‡ä»¤
        /// </summary>
        /// <remarks>
        /// æŽ§åˆ¶å †åž›æœºçš„动作:
        /// æŽ§åˆ¶å †åž›æœºçš„动作。参见 <see cref="Constants.StackerCraneWorkActionEnum"/>:
        /// - 1: å¼€å§‹æ‰§è¡Œä»»åŠ¡
        /// - 2: ä»»åŠ¡å®Œæˆ/停止
        /// - 3: æ¶ˆé˜²ä»»åС开始
        /// </remarks>
        WorkAction,
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskCommand.cs
@@ -20,6 +20,7 @@
        /// æŽ§åˆ¶å †åž›æœºçš„动作:
        /// - 1: å¼€å§‹æ‰§è¡Œä»»åŠ¡
        /// - 2: ä»»åŠ¡å®Œæˆ/停止
        /// - 3: æ¶ˆé˜²ä»»åС开始
        /// </remarks>
        public short WorkAction { get; set; }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
@@ -2,6 +2,7 @@
using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
@@ -100,8 +101,8 @@
            Dt_Task? candidateTask;
            var deviceCode = commonStackerCrane.DeviceCode;
            _logger.LogInformation("SelectTask:开始选择任务,设备: {DeviceCode},上一任务类型: {LastTaskType}", deviceCode, commonStackerCrane.LastTaskType);
            QuartzLogger.Info($"开始选择任务,设备: {deviceCode},上一任务类型: {commonStackerCrane.LastTaskType}", deviceCode);
            //_logger.LogInformation("SelectTask:开始选择任务,设备: {DeviceCode},上一任务类型: {LastTaskType}", deviceCode, commonStackerCrane.LastTaskType);
            //QuartzLogger.Info($"开始选择任务,设备: {deviceCode},上一任务类型: {commonStackerCrane.LastTaskType}", deviceCode);
            // æ ¹æ®ä¸Šä¸€ä»»åŠ¡ç±»åž‹å†³å®šæŸ¥è¯¢ç­–ç•¥
            if (commonStackerCrane.LastTaskType == null)
@@ -288,7 +289,7 @@
            if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                // ç©ºæ‰˜ç›˜å‡ºåº“
                taskType = 100;
                taskType = StackerCraneConst.EmptyPalletTaskType;
            }
            else
                taskType = task.TaskType;
@@ -323,7 +324,7 @@
            _logger.LogInformation("IsOutTaskStationAvailable:站台 {ChildPosi},是否被占用: {IsOccupied},任务号: {TaskNum}", router.ChildPosi, isOccupied, task.TaskNum);
            QuartzLogger.Info($"IsOutTaskStationAvailable:站台 {router.ChildPosi},是否被占用: {isOccupied}", task.Roadway);
            return !isOccupied;
            return isOccupied;
        }
    }
}
Code/WMS/WIDESEA_WMSServer/.vscode/launch.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
{
    "version": "0.2.0",
    "configurations": [
        {
            // ä½¿ç”¨ IntelliSense æ‰¾å‡º C# è°ƒè¯•存在哪些属性
            // å°†æ‚¬åœç”¨äºŽçŽ°æœ‰å±žæ€§çš„è¯´æ˜Ž
            // æœ‰å…³è¯¦ç»†ä¿¡æ¯ï¼Œè¯·è®¿é—® https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md。
            "name": ".NET Core Launch (web)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build",
            // å¦‚果已更改目标框架,请确保更新程序路径。
            "program": "${workspaceFolder}/WIDESEA_WMSServer/bin/Debug/net8.0/WIDESEA_WMSServer.dll",
            "args": [],
            "cwd": "${workspaceFolder}/WIDESEA_WMSServer",
            "stopAtEntry": false,
            // å¯ç”¨åœ¨å¯åЍ ASP.NET Core æ—¶å¯åЍ Web æµè§ˆå™¨ã€‚有关详细信息: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
            "serverReadyAction": {
                "action": "openExternally",
                "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
            },
            "env": {
                "ASPNETCORE_ENVIRONMENT": "Development"
            },
            "sourceFileMap": {
                "/Views": "${workspaceFolder}/Views"
            }
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach"
        }
    ]
}
Code/WMS/WIDESEA_WMSServer/.vscode/tasks.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary;ForceNoAlign"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "publish",
            "command": "dotnet",
            "type": "process",
            "args": [
                "publish",
                "${workspaceFolder}/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary;ForceNoAlign"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "watch",
            "command": "dotnet",
            "type": "process",
            "args": [
                "watch",
                "run",
                "--project",
                "${workspaceFolder}/WIDESEA_WMSServer/WIDESEA_WMSServer.csproj"
            ],
            "problemMatcher": "$msCompile"
        }
    ]
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/OutboundTimeConstants.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
namespace WIDESEA_Common.Constants
{
    /// <summary>
    /// åº“å­˜Remark路由标记常量
    /// </summary>
    public static class StockRemarkConstants
    {
        /// <summary>
        /// é«˜æ¸©1号路由标记
        /// </summary>
        public const string GW1 = "GW_1";
        /// <summary>
        /// é«˜æ¸©2号路由标记
        /// </summary>
        public const string GW2 = "GW_2";
        /// <summary>
        /// å¸¸æ¸©1号路由标记
        /// </summary>
        public const string CW1 = "CW_1";
    }
    /// <summary>
    /// å‡ºåº“时效常量(小时)
    /// </summary>
    public static class OutboundTimeConstants
    {
        /// <summary>
        /// GW_1首放入库时效(16小时)
        /// </summary>
        public const int OUTBOUND_HOURS_GW1_FIRST = 16;
        /// <summary>
        /// GW_1二放入库时效(24小时)
        /// </summary>
        public const int OUTBOUND_HOURS_GW1_SECOND = 24;
        /// <summary>
        /// CW_1出库时效(12小时)
        /// </summary>
        public const int OUTBOUND_HOURS_CW1 = 12;
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/StockConstants.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
namespace WIDESEA_Common.Constants
{
    /// <summary>
    /// åº“存与MES相关常量
    /// </summary>
    public static class StockConstants
    {
        /// <summary>
        /// é»˜è®¤ç‰©æ–™ç¼–码
        /// </summary>
        public const string MATERIAL_CODE = "电芯";
        /// <summary>
        /// é»˜è®¤ç‰©æ–™åç§°
        /// </summary>
        public const string MATERIAL_NAME = "电芯";
        /// <summary>
        /// é»˜è®¤å•位
        /// </summary>
        public const string UNIT = "PCS";
        /// <summary>
        /// é»˜è®¤åˆ›å»ºè€…
        /// </summary>
        public const string SYSTEM_USER = "system";
        /// <summary>
        /// AGV创建者
        /// </summary>
        public const string AGV_USER = "AGV";
        /// <summary>
        /// è‡ªåŠ¨ä»»åŠ¡åˆ›å»ºè€…
        /// </summary>
        public const string SYSTEM_AUTO_USER = "system_auto";
        /// <summary>
        /// é»˜è®¤è®¢å•号
        /// </summary>
        public const string DEFAULT_ORDER_NO = "111";
        /// <summary>
        /// MES设备编码
        /// </summary>
        public const string MES_EQUIPMENT_CODE = "STK-GROUP-001";
        /// <summary>
        /// MES资源编码
        /// </summary>
        public const string MES_RESOURCE_CODE = "STK-GROUP-001";
        /// <summary>
        /// ç»„盘操作类型(0代表组盘)
        /// </summary>
        public const int MES_BIND_OPERATION_TYPE = 0;
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
namespace WIDESEA_Common.Constants
{
    /// <summary>
    /// ä»»åŠ¡åœ°å€å¸¸é‡
    /// </summary>
    public static class TaskAddressConstants
    {
        /// <summary>
        /// é»˜è®¤/中转地址
        /// </summary>
        public const string DEFAULT_ADDRESS = "10080";
        /// <summary>
        /// é«˜æ¸©1号出库地址列表(轮询)
        /// </summary>
        public static readonly string[] GW1_ADDRESSES = { "11001", "11010" };
        /// <summary>
        /// é«˜æ¸©2号出库地址
        /// </summary>
        public const string GW2_ADDRESS = "CWSC1";
        /// <summary>
        /// å¸¸æ¸©1号出库地址
        /// </summary>
        public const string CW1_ADDRESS = "22001";
        /// <summary>
        /// åˆ†å®¹åº“出库地址
        /// </summary>
        public const string GRADING_OUTBOUND_ADDRESS = "10081";
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_StockService/StockSerivce.cs
@@ -1,4 +1,5 @@
using SqlSugar;
using WIDESEA_Common.Constants;
using WIDESEA_Common.StockEnum;
using WIDESEA_Core;
using WIDESEA_DTO.MES;
@@ -123,12 +124,12 @@
                var now = DateTime.Now;
                var details = stock.Details.Select(item => new Dt_StockInfoDetail
                {
                    MaterielCode = "电芯",
                    MaterielName = "电芯",
                    MaterielCode = StockConstants.MATERIAL_CODE,
                    MaterielName = StockConstants.MATERIAL_NAME,
                    StockQuantity = item.Quantity,
                    Unit = "PCS",
                    Creater = "system",
                    OrderNo = "111",
                    Unit = StockConstants.UNIT,
                    Creater = StockConstants.SYSTEM_USER,
                    OrderNo = StockConstants.DEFAULT_ORDER_NO,
                    ProductionDate = now.ToString(),
                    EffectiveDate = now.AddYears(1).ToString(),
                    SerialNumber = item.CellBarcode,
@@ -139,10 +140,10 @@
                var bindRequest = new BindContainerRequest
                {
                    ContainerCode = stock?.TargetPalletNo,
                    EquipmentCode = "STK-GROUP-001",
                    ResourceCode = "STK-GROUP-001",
                    EquipmentCode = StockConstants.MES_EQUIPMENT_CODE,
                    ResourceCode = StockConstants.MES_RESOURCE_CODE,
                    LocalTime = now,
                    OperationType = 0, // 0代表组盘
                    OperationType = StockConstants.MES_BIND_OPERATION_TYPE,
                    ContainerSfcList = details.Select(d => new ContainerSfcItem
                    {
                        Sfc = d.SerialNumber,
@@ -166,7 +167,7 @@
                        PalletCode = stock.TargetPalletNo,
                        WarehouseId = stock.Roadway == "注液组盘机械手" ? (await _warehouseService.Db.Queryable<Dt_Warehouse>().FirstAsync(w => w.WarehouseCode == "GW1")).WarehouseId : 0,
                        StockStatus = StockStatusEmun.组盘暂存.GetHashCode(),
                        Creater = "system",
                        Creater = StockConstants.SYSTEM_USER,
                        Details = details
                    };
                    result = StockInfoService.Repository.AddData(entity, x => x.Details);
@@ -215,7 +216,7 @@
                            PalletCode = stock.TargetPalletNo,
                            WarehouseId = sourceStock.WarehouseId,
                            StockStatus = StockStatusEmun.组盘暂存.GetHashCode(),
                            Creater = "system",
                            Creater = StockConstants.SYSTEM_USER,
                        };
                        var newId = StockInfoService.Repository.AddData(newStock);
@@ -241,8 +242,8 @@
                    // è°ƒç”¨MES解绑源托盘电芯
                    var unbindRequest = new UnBindContainerRequest
                    {
                        EquipmentCode = "STK-GROUP-001",
                        ResourceCode = "STK-GROUP-001",
                        EquipmentCode = StockConstants.MES_EQUIPMENT_CODE,
                        ResourceCode = StockConstants.MES_RESOURCE_CODE,
                        LocalTime = DateTime.Now,
                        ContainCode = stock.SourcePalletNo,
                        SfcList = detailEntities.Select(d => d.SerialNumber).ToList()
@@ -261,10 +262,10 @@
                    var bindRequest = new BindContainerRequest
                    {
                        ContainerCode = stock.TargetPalletNo,
                        EquipmentCode = "STK-GROUP-001",
                        ResourceCode = "STK-GROUP-001",
                        EquipmentCode = StockConstants.MES_EQUIPMENT_CODE,
                        ResourceCode = StockConstants.MES_RESOURCE_CODE,
                        LocalTime = DateTime.Now,
                        OperationType = 0,
                        OperationType = StockConstants.MES_BIND_OPERATION_TYPE,
                        ContainerSfcList = detailEntities.Select(d => new ContainerSfcItem
                        {
                            Sfc = d.SerialNumber,
@@ -324,8 +325,8 @@
                    // è°ƒç”¨MES解绑电芯
                    var unbindRequest = new UnBindContainerRequest
                    {
                        EquipmentCode = "STK-GROUP-001",
                        ResourceCode = "STK-GROUP-001",
                        EquipmentCode = StockConstants.MES_EQUIPMENT_CODE,
                        ResourceCode = StockConstants.MES_RESOURCE_CODE,
                        LocalTime = DateTime.Now,
                        ContainCode = stock.SourcePalletNo,
                        SfcList = detailEntities.Select(d => d.SerialNumber).ToList()
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -4,6 +4,7 @@
using SqlSugar;
using System.DirectoryServices.Protocols;
using System.Text.Json;
using WIDESEA_Common.Constants;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
@@ -146,7 +147,7 @@
        private string DetermineTargetAddress(string roadway, Dictionary<string, List<string>> addressMap)
        {
            if (string.IsNullOrWhiteSpace(roadway))
                return "10080";
                return TaskAddressConstants.DEFAULT_ADDRESS;
            string? matchedPrefix = null;
            foreach (var kvp in addressMap)
@@ -159,15 +160,36 @@
            }
            if (matchedPrefix == null)
                return "10080";
                return TaskAddressConstants.DEFAULT_ADDRESS;
            if (!addressMap.TryGetValue(matchedPrefix, out var addresses) || addresses == null || addresses.Count == 0)
                return "10080";
                return TaskAddressConstants.DEFAULT_ADDRESS;
            if (addresses.Count == 1)
                return addresses[0];
            return _roundRobinService.GetNextAddress(matchedPrefix, addresses);
        }
        /// <summary>
        /// æ ¹æ®åº“å­˜ Remark ç¡®å®šç›®æ ‡åœ°å€ï¼ˆGW_1→[11001,11010]轮询,GW_2→CWSC1,CW_1→22001)。
        /// </summary>
        private string DetermineTargetAddressByRemark(string remark, string roadway, Dictionary<string, List<string>> addressMap)
        {
            // æ ¹æ® Remark ç¡®å®šç›®æ ‡åœ°å€
            if (!string.IsNullOrWhiteSpace(remark))
            {
                return remark switch
                {
                    StockRemarkConstants.GW1 => _roundRobinService.GetNextAddress(StockRemarkConstants.GW1, TaskAddressConstants.GW1_ADDRESSES.ToList()),
                    StockRemarkConstants.GW2 => TaskAddressConstants.GW2_ADDRESS,
                    StockRemarkConstants.CW1 => TaskAddressConstants.CW1_ADDRESS,
                    _ => DetermineTargetAddress(roadway, addressMap)
                };
            }
            // Remark ä¸ºç©ºæ—¶ï¼Œå›žé€€åˆ°å··é“配置
            return DetermineTargetAddress(roadway, addressMap);
        }
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_GradingMachine.cs
@@ -4,6 +4,7 @@
using SqlSugar;
using System.DirectoryServices.Protocols;
using System.Text.Json;
using WIDESEA_Common.Constants;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
@@ -137,8 +138,8 @@
                        PalletType = stock.PalletType,
                        SourceAddress = stock.LocationCode,
                        CurrentAddress = stock.LocationCode,
                        NextAddress = "10080",
                        TargetAddress = "10081",
                        NextAddress = TaskAddressConstants.DEFAULT_ADDRESS,
                        TargetAddress = TaskAddressConstants.GRADING_OUTBOUND_ADDRESS,
                        Roadway = stock.LocationDetails.RoadwayNo,
                        TaskType = TaskTypeEnum.Outbound.GetHashCode(),
                        TaskStatus = TaskStatusEnum.New.GetHashCode(),
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_WCS.cs
@@ -4,6 +4,7 @@
using SqlSugar;
using System.DirectoryServices.Protocols;
using System.Text.Json;
using WIDESEA_Common.Constants;
using WIDESEA_Common.LocationEnum;
using WIDESEA_Common.StockEnum;
using WIDESEA_Common.TaskEnum;
@@ -193,12 +194,42 @@
                    WebResponseContent content = new WebResponseContent();
                    stockInfo.LocationCode = location.LocationCode;
                    stockInfo.LocationId = location.Id;
                    stockInfo.OutboundDate = task.Roadway switch
                    var now = DateTime.Now;
                    if (task.Roadway.Contains("GW"))
                    {
                        var r when r.Contains("GW") => DateTime.Now.AddHours(2),
                        var r when r.Contains("CW") => DateTime.Now.AddHours(1),
                        _ => DateTime.Now
                    };
                        if (stockInfo.Remark.IsNullOrEmpty())
                        {
                            stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST);
                            stockInfo.Remark = StockRemarkConstants.GW1;
                        }
                        else if (stockInfo.Remark == StockRemarkConstants.GW1)
                        {
                            stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_SECOND);
                            stockInfo.Remark = StockRemarkConstants.GW2;
                        }
                        else
                        {
                            stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST);
                        }
                    }
                    else if (task.Roadway.Contains("CW"))
                    {
                        if (stockInfo.Remark == StockRemarkConstants.GW2)
                        {
                            stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1);
                            stockInfo.Remark = StockRemarkConstants.CW1;
                        }
                        else
                        {
                            stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1);
                        }
                    }
                    else
                    {
                        stockInfo.OutboundDate = now;
                    }
                    stockInfo.StockStatus = StockStatusEmun.入库完成.GetHashCode();
                    location.LocationStatus = LocationStatusEnum.InStock.GetHashCode();
@@ -208,18 +239,18 @@
                    if (!updateLocationResult || !updateStockResult)
                        return WebResponseContent.Instance.Error("任务完成失败");
                    // è°ƒç”¨MES托盘进站
                    var inboundRequest = new InboundInContainerRequest
                    {
                        EquipmentCode = "STK-GROUP-001",
                        ResourceCode = "STK-GROUP-001",
                        LocalTime = DateTime.Now,
                        ContainerCode = taskDto.PalletCode
                    };
                    var inboundResult = _mesService.InboundInContainer(inboundRequest);
                    if (inboundResult == null || inboundResult.Data == null || !inboundResult.Data.IsSuccess)
                    {
                        return content.Error($"任务完成失败:MES进站失败: {inboundResult?.Data?.Msg ?? inboundResult?.ErrorMessage ?? "未知错误"}");
                    }
                    //var inboundRequest = new InboundInContainerRequest
                    //{
                    //    EquipmentCode = "STK-GROUP-001",
                    //    ResourceCode = "STK-GROUP-001",
                    //    LocalTime = DateTime.Now,
                    //    ContainerCode = taskDto.PalletCode
                    //};
                    //var inboundResult = _mesService.InboundInContainer(inboundRequest);
                    //if (inboundResult == null || inboundResult.Data == null || !inboundResult.Data.IsSuccess)
                    //{
                    //    return content.Error($"任务完成失败:MES进站失败: {inboundResult?.Data?.Msg ?? inboundResult?.ErrorMessage ?? "未知错误"}");
                    //}
                    return await CompleteTaskAsync(task, "入库完成");
                });
            }
@@ -272,19 +303,19 @@
                        return WebResponseContent.Instance.Error("任务完成失败");
                    // è°ƒç”¨MES托盘出站
                    var outboundRequest = new OutboundInContainerRequest
                    {
                        EquipmentCode = "STK-GROUP-001",
                        ResourceCode = "STK-GROUP-001",
                        LocalTime = DateTime.Now,
                        ContainerCode = taskDto.PalletCode,
                        ParamList = new List<ParamItem>()
                    };
                    var outboundResult = _mesService.OutboundInContainer(outboundRequest);
                    if (outboundResult == null || outboundResult.Data == null || !outboundResult.Data.IsSuccess)
                    {
                        return content.Error($"任务完成失败:MES出站失败: {outboundResult?.Data?.Msg ?? outboundResult?.ErrorMessage ?? "未知错误"}");
                    }
                    //var outboundRequest = new OutboundInContainerRequest
                    //{
                    //    EquipmentCode = "STK-GROUP-001",
                    //    ResourceCode = "STK-GROUP-001",
                    //    LocalTime = DateTime.Now,
                    //    ContainerCode = taskDto.PalletCode,
                    //    ParamList = new List<ParamItem>()
                    //};
                    //var outboundResult = _mesService.OutboundInContainer(outboundRequest);
                    //if (outboundResult == null || outboundResult.Data == null || !outboundResult.Data.IsSuccess)
                    //{
                    //    return content.Error($"任务完成失败:MES出站失败: {outboundResult?.Data?.Msg ?? outboundResult?.ErrorMessage ?? "未知错误"}");
                    //}
                    return await CompleteTaskAsync(task, "出库完成");
                });
@@ -607,8 +638,9 @@
                var taskList = new List<Dt_Task>();
                foreach (var stock in stocksToProcess)
                {
                    // æ ¹æ®å··é“确定目标地址
                    var targetAddress = DetermineTargetAddress(
                    // æ ¹æ®å··é“确定目标地址(优先根据 Remark ç¡®å®šï¼ŒRemark ä¸ºç©ºåˆ™æ ¹æ®å··é“配置)
                    var targetAddress = DetermineTargetAddressByRemark(
                        stock.Remark ?? "",
                        stock.LocationDetails?.RoadwayNo ?? "",
                        targetAddressMap);
@@ -793,7 +825,7 @@
                    if (stockInfo.LocationId > 0 || !string.IsNullOrWhiteSpace(stockInfo.LocationCode))
                        return WebResponseContent.Instance.Error($"托盘[{stockPalletCode}]库存已绑定货位,不能创建机械手{taskName}任务");
                }
                var section = App.Configuration.GetSection("RobotTaskAddressRules").GetSection(targetLineNo).GetChildren().Select(c => c.Value).ToArray();
                var section = App.Configuration.GetSection("RobotTaskAddressRules").GetSection(targetLineNo).GetChildren().Select(c => c.Value).ToArray();
                var task = new Dt_Task
                {
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -62,8 +62,8 @@
  "DBSeedEnable": false,
  "PDAVersion": "4",
  "WebSocketPort": 9296,
  "AutoOutboundTask": {
    "Enable": false, /// æ˜¯å¦å¯ç”¨è‡ªåŠ¨å‡ºåº“ä»»åŠ¡
  "AutoOutboundTask": {
    "Enable": true, /// æ˜¯å¦å¯ç”¨è‡ªåŠ¨å‡ºåº“ä»»åŠ¡
    "CheckIntervalSeconds": 300, /// æ£€æŸ¥é—´éš”(秒)
    "TargetAddresses": { /// æŒ‰å··é“前缀配置目标地址(支持多出库口)
      "GW": [ "11001", "11010", "11068" ],
ÏîÄ¿×ÊÁÏ/É豸ЭÒé/¸ß³£Î¶Ѷâ»úÓëÊäËÍÏß/~$¶Ñ¶â»úÓëÉÏλ»ú½»»¥ÐÅÏ¢.xlsx
Binary files differ
ÏîÄ¿×ÊÁÏ/É豸ЭÒé/¸ß³£Î¶Ѷâ»úÓëÊäËÍÏß/¶Ñ¶â»úÓëÉÏλ»ú½»»¥ÐÅÏ¢.xlsx
Binary files differ