wanshenmean
4 小时以前 e4921e003cc293fea714bdaf74dc6a6b6b750295
Merge branch 'xiaoyang' into dev
已添加1个文件
已修改22个文件
598 ■■■■■ 文件已修改
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService/TaskService.Query.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService/TaskService.Status.cs 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ManualInbound/ManualInboundTaskHandler.cs 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs 200 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/LocationEnum/LocationTypeEnum.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_GradingMachine.cs 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Outbound.cs 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目资料/设备协议/分容柜接口协议/化成分容柜接口协议1.1.xls 补丁 | 查看 | 原始文档 | blame | 历史
项目资料/设备协议/高常温堆垛机与输送线/WCS输送对接地址表_0420.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/ITaskService.cs
@@ -151,9 +151,9 @@
        /// æ ¹æ®è®¾å¤‡ç¼–号、当前地址按照优先级以及创建时间排序查询任务池出库类型的新增的任务
        /// </summary>
        /// <param name="deviceNo">设备编号</param>
        /// <param name="outStationCodes">当前地址</param>
        /// <param name="outStationCodes">出库站台地址</param>
        /// <returns>返回任务实体对象集合,可能为null</returns>
        List<Dt_Task> QueryStackerCraneOutTasks(string deviceNo, List<string> outStationCodes);
        List<Dt_Task> QueryStackerCraneOutTasks(string deviceNo, List<string> outStationCodes,bool isTrue = true);
        /// <summary>
        /// æ›´æ–°ä»»åŠ¡å¼‚å¸¸ä¿¡æ¯æ˜¾ç¤º
@@ -191,6 +191,15 @@
        Dt_Task? UpdatePosition(int taskNum, string currentAddress);
        /// <summary>
        /// æ ¹æ®ä»»åŠ¡å·ã€å½“å‰åœ°å€ã€ä¸‹ä¸€åœ°å€æ›´æ–°ä»»åŠ¡ä½ç½®ä¿¡æ¯
        /// </summary>
        /// <param name="taskNum">任务号</param>
        /// <param name="currentAddress">当前地址</param>
        /// <param name="nextAddress">下一地址</param>
        /// <returns></returns>
        Dt_Task? UpdatePosition(int taskNum, string currentAddress, string nextAddress);
        /// <summary>
        /// ä»»åŠ¡å®Œæˆ
        /// </summary>
        /// <param name="taskNum">任务编号</param>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
@@ -99,7 +99,7 @@
            if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
            {
                _robotTaskService.CreateLocalRobotTask(task);
               return _robotTaskService.CreateLocalRobotTask(task);
                //if (!content.Status)
                //{
                //    return content;
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -192,10 +192,11 @@
                StockDTO stock = BuildRobotTaskStock(task, configKey);
                // èŽ·å–æŠ“å–å’Œæ”¾ç½®åœ°å€çš„çº¿ä½“é…ç½®ï¼ˆå¦‚æžœæœ‰ï¼‰
                var section = App.Configuration.GetSection("RobotTaskAddressRules").GetSection(stock?.TargetLineNo ?? string.Empty).GetChildren().Select(c => c.Value).ToArray();
                var section = App.Configuration.GetSection("RobotAddressRules").GetSection(stock?.TargetLineNo ?? string.Empty).GetChildren().Select(c => c.Value).ToArray();
                if (section.Length < 2)
                    return WebResponseContent.Instance.Error($"未找到线体[{stock?.TargetLineNo}]的地址配置");
                int taskType = MapConfigKeyToRobotTaskType(configKey);
                // åˆ›å»ºæœ¬åœ°æœºå™¨äººä»»åŠ¡
                Dt_RobotTask robotTask = new()
                {
@@ -204,14 +205,14 @@
                    RobotTargetAddress = section[1]!,
                    RobotSourceAddressLineCode = stock?.SourceLineNo ?? string.Empty,
                    RobotTargetAddressLineCode = stock?.TargetLineNo ?? string.Empty,
                    RobotRoadway = stock?.Roadway ?? string.Empty,
                    RobotRoadway = stock?.TargetLineNo == "11068" ? "注液组盘机械手" : "换盘机械手" ?? string.Empty, // todo
                    RobotSourceAddressPalletCode = stock?.SourcePalletNo ?? string.Empty,
                    RobotTargetAddressPalletCode = stock?.TargetPalletNo ?? string.Empty,
                    RobotTaskType = MapConfigKeyToRobotTaskType(configKey),
                    RobotTaskType = taskType,
                    RobotTaskState = (int)TaskRobotStatusEnum.RobotNew,
                    RobotGrade = task.Grade,
                    Creater = "WCS_Local",
                    RobotTaskTotalNum = 1,
                    RobotTaskTotalNum = taskType == (int)RobotTaskTypeEnum.GroupPallet ? 48 : 1,
                    CreateDate = DateTime.Now
                };
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService/TaskService.Query.cs
@@ -127,9 +127,12 @@
    /// <param name="deviceNo">设备编号</param>
    /// <param name="currentAddress">当前地址</param>
    /// <returns>返回任务实体对象集合,可能为null</returns>
    public List<Dt_Task> QueryStackerCraneOutTasks(string deviceNo, List<string> outStationCodes)
    public List<Dt_Task> QueryStackerCraneOutTasks(string deviceNo, List<string> outStationCodes, bool isTrue = true)
    {
        return BaseDal.QueryData(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskStatus == (int)TaskOutStatusEnum.OutNew && outStationCodes.Contains(x.CurrentAddress), TaskOrderBy);
        if (isTrue)
            return BaseDal.QueryData(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskStatus == (int)TaskOutStatusEnum.OutNew && outStationCodes.Contains(x.NextAddress), TaskOrderBy);
        else
            return BaseDal.QueryData(x => x.Roadway == deviceNo && TaskOutboundTypes.Contains(x.TaskType) && x.TaskStatus == (int)TaskOutStatusEnum.OutNew && !outStationCodes.Contains(x.NextAddress), TaskOrderBy);
    }
    /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService/TaskService.Status.cs
@@ -175,4 +175,41 @@
        }
        return null;
    }
    /// <summary>
    /// æ ¹æ®ä»»åŠ¡å·ã€å½“å‰åœ°å€æ›´æ–°ä»»åŠ¡ä½ç½®ä¿¡æ¯
    /// </summary>
    /// <param name="taskNum">任务号</param>
    /// <param name="currentAddress">当前地址</param>
    /// <param name="nextAddress">下一地址</param>
    /// <returns></returns>
    public Dt_Task? UpdatePosition(int taskNum, string currentAddress, string nextAddress)
    {
        try
        {
            if (string.IsNullOrEmpty(currentAddress))
                throw new ArgumentNullException(nameof(currentAddress), "当前地址不能为空");
            Dt_Task task = BaseDal.QueryFirst(x => x.TaskNum == taskNum && x.CurrentAddress == currentAddress);
            if (task == null) throw new Exception($"未找到该任务信息,任务号:【{taskNum}】");
            string oldCurrentPos = task.CurrentAddress;
            string oldNextPos = task.NextAddress;
            task.CurrentAddress = task.NextAddress;
            task.NextAddress = nextAddress;
            task.ModifyDate = DateTime.Now;
            task.Modifier = "System";
            BaseDal.UpdateData(task);
            _taskExecuteDetailService.AddTaskExecuteDetail(task.TaskId, $"系统自动流程,更新当前位置【{oldCurrentPos} ----> {task.CurrentAddress}】和下一位置【{oldNextPos} ----> {task.NextAddress}】");
            return task;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"UpdatePosition æ›´æ–°ä»»åŠ¡ä½ç½®å¤±è´¥,任务号:【{taskNum}】,错误信息:【{ex.Message}】");
        }
        return null;
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/CommonConveyorLineNewJob.cs
@@ -244,6 +244,7 @@
                                    var task = _taskService.QueryManualInboundTask(childDeviceCode);
                                    if (task != null)
                                    {
                                        QuartzLogHelper.LogInfo(_logger, $"获取到输送线开始任务,任务号:{task.TaskNum},状态: {task.TaskStatus},当前地址:{conveyorLine.DeviceCode}", conveyorLine.DeviceCode);
                                        var handler = new ManualInboundTaskHandler(_taskService, _logger);
                                        handler.WriteTaskToPlc(conveyorLine, childDeviceCode, task);
                                    }
@@ -270,21 +271,21 @@
                                Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNo, childDeviceCode);
                                if (!task.IsNullOrEmpty())
                                {
                                    QuartzLogHelper.LogInfo(_logger, "Execute:子设备 {ChildDeviceCode} å¤„理任务 {TaskNum},状态: {Status}", $"处理任务 {task.TaskNum},状态: {task.TaskStatus}", conveyorLine.DeviceCode, childDeviceCode, task.TaskNum, task.TaskStatus);
                                    QuartzLogHelper.LogInfo(_logger, $"处理任务 {task.TaskNum},状态: {task.TaskStatus}", conveyorLine.DeviceCode);
                                    // å¤„理任务状态(根据状态分发到不同方法)
                                    ProcessTaskState(conveyorLine, command, task, childDeviceCode);
                                    return Task.CompletedTask;
                                }
                                else if (!command.Barcode.IsNullOrEmpty() && childDeviceCode == "11068")
                                {
                                    if (_robotTaskService.Db.Queryable<Dt_RobotTask>().Any(x => x.RobotTargetAddressPalletCode == command.Barcode))
                                    var isWcsTask = _taskService.Db.Queryable<Dt_Task>().Any(x => x.PalletCode == command.Barcode && x.TaskStatus == (int)TaskOutStatusEnum.OutNew);
                                    var isRobotTask = _robotTaskService.Db.Queryable<Dt_RobotTask>().Any(x => x.RobotTargetAddressPalletCode == command.Barcode);
                                    if (isWcsTask || isRobotTask)
                                    {
                                        return Task.CompletedTask;
                                    }
                                    Random rnd = new Random();
                                    int num = rnd.StrictNext();//产生真随机数
                                                               // æ²¡æœ‰ä»»åŠ¡å·ä½†æœ‰æ¡ç å¹¶ä¸”åœ¨11068位置,直接添加机械手组盘任务
                                    // ç›´æŽ¥æ·»åŠ æœºæ¢°æ‰‹ç»„ç›˜ä»»åŠ¡
                                    Dt_RobotTask robotTask = new Dt_RobotTask
                                    {
                                        RobotTargetAddressPalletCode = command.Barcode,
@@ -296,11 +297,12 @@
                                        RobotGrade = 1,
                                        RobotRoadway = "注液组盘机械手",
                                        RobotTargetAddressLineCode = childDeviceCode,
                                        RobotTaskNum = num, // ç”Ÿæˆä»»åŠ¡å·
                                        RobotTaskNum = Random.Shared.StrictNext(), // ç”Ÿæˆä»»åŠ¡å·
                                        RobotDispatchertime = DateTime.Now,
                                    };
                                    if (_robotTaskService.AddData(robotTask).Status)
                                    {
                                        QuartzLogHelper.LogInfo(_logger, $"生产机械手任务成功, {robotTask.RobotTaskNum},状态: {robotTask.RobotTaskState},当前地址:{conveyorLine.DeviceCode}", conveyorLine.DeviceCode);
                                        conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                                    }
                                }
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineDispatchHandler.cs
@@ -1,5 +1,6 @@
using MapsterMapper;
using Serilog;
using System.Threading.Tasks;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_ITaskInfoService;
@@ -171,20 +172,41 @@
            QuartzLogHelper.LogInfo(_logger, $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode);
            //// å¦‚果不是空托盘任务,处理目标地址
            //if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty)
            //{
            bool isEmptyTask = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty;
            Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress);
            if (routers == null) throw new Exception($"未找到设备路由信息");
            // ç¡®å®šç›®æ ‡åœ°å€
            string targetAddress;
            if (isEmptyTask)
            {
                targetAddress = "2125";
                QuartzLogHelper.LogDebug(_logger, $"子设备: {childDeviceCode},入库下一目标地址: {2125}", conveyorLine.DeviceCode);
            }
            else
            {
                Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress);
                if (routers == null) throw new Exception($"未找到设备路由信息");
                targetAddress = routers.ChildPosi;
            }
            _targetAddressSelector.HandleInboundNextAddress(conveyorLine, routers.ChildPosi, childDeviceCode);
            //}
            // å¤„理目标地址:ChildPosi == "2125" æ—¶è·³è¿‡ HandleInboundNextAddress
            if (targetAddress == "2125")
            {
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, "2125", childDeviceCode);
            }
            else if (!_targetAddressSelector.HandleInboundNextAddress(conveyorLine, targetAddress, childDeviceCode))
            {
                return;
            }
            // æ›´æ–°ä»»åŠ¡å½“å‰ä½ç½®
            _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            // è®¾ç½® WCS_STB æ ‡å¿—,表示 WCS å·²å¤„理
            // æ›´æ–°ä»»åŠ¡å½“å‰ä½ç½®å’Œ WCS_ACK
            if (isEmptyTask)
            {
                _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress, "2125");
            }
            else
            {
                _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress);
            }
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
        }
@@ -227,29 +249,42 @@
        /// <param name="conveyorLine">输送线设备对象</param>
        /// <param name="command">PLC å‘½ä»¤æ•°æ®</param>
        /// <param name="childDeviceCode">子设备编码</param>
        public void RequestOutbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        public Task RequestOutbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode)
        {
            // æŸ¥è¯¢å¾…处理任务
            Dt_Task? task = _taskFilter.QueryPendingTask(conveyorLine.DeviceCode, childDeviceCode);
            if (task != null)
            if (task == null) return Task.CompletedTask;
            // ç¡®å®šç›®æ ‡åœ°å€ï¼šç©ºæ‰˜ç›˜ä»»åŠ¡ä½¿ç”¨ "2201",其他任务使用 NextAddress
            var isEmptyTask = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty;
            var targetAddress = task.CurrentAddress == "2217" ? (isEmptyTask ? "2201" : task.NextAddress) : task.NextAddress;
            // å¤„理特殊地址 2217,需要调用目标地址选择器
            if (task.CurrentAddress == "2217" && !_targetAddressSelector.HandleOutboundNextAddress(conveyorLine, targetAddress, childDeviceCode))
            {
                // è®¾ç½®ä»»åŠ¡å·
                conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, task.TaskNum, childDeviceCode);
                // è®¾ç½®æ‰˜ç›˜æ¡ç 
                conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
                // è®¾ç½®ç›®æ ‡åœ°å€
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, task.NextAddress, childDeviceCode);
                // å›žå¤ ACK ç¡®è®¤
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€
                _taskService.UpdateTaskStatusToNext(task);
                QuartzLogHelper.LogInfo(_logger, "RequestOutbound:出库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"出库任务已下发,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
                return Task.CompletedTask; ;
            }
            // è®¾ç½®ä»»åŠ¡å·ã€æ‰˜ç›˜æ¡ç ã€ç›®æ ‡åœ°å€ã€WCS_ACK
            conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, task.TaskNum, childDeviceCode);
            conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
            conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode);
            conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
            // æ›´æ–°ä»»åŠ¡çŠ¶æ€æˆ–ä½ç½®
            if (isEmptyTask && task.NextAddress == "2217")
            {
                task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>();
                task.NextAddress = "2201";
                _taskService.Repository.UpdateData(task);
            }
            else
            {
                _taskService.UpdateTaskStatusToNext(task);
            }
            QuartzLogHelper.LogInfo(_logger, "RequestOutbound:出库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"出库任务已下发,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode);
            return Task.CompletedTask;
        }
        /// <summary>
@@ -257,7 +292,6 @@
        /// </summary>
        /// <remarks>
        /// å½“出库任务执行到某个中间站点时调用。
        /// æ ¹æ®ä¸‹ä¸€åœ°å€åˆ¤æ–­æ˜¯å¦éœ€è¦ä¸Žæ‹˜æŸæœº/插拔钉机等设备交互。
        /// </remarks>
        /// <param name="conveyorLine">输送线设备对象</param>
        /// <param name="command">PLC å‘½ä»¤æ•°æ®</param>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ConveyorLineTargetAddressSelector.cs
@@ -130,7 +130,7 @@
        /// <param name="conveyorLine">输送线设备对象,用于写入目标地址和 ACK ä¿¡å·</param>
        /// <param name="nextAddress">下一地址/目标设备编码,用于识别目标设备类型</param>
        /// <param name="childDeviceCode">当前子设备编码,用于精确定位写入哪个子设备</param>
        public void HandleInboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode)
        public bool HandleInboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode)
        {
            // è®°å½•入库场景的调试日志,包含子设备和目标地址信息
            WriteDebug(conveyorLine, "入库下一地址", childDeviceCode, nextAddress);
@@ -141,8 +141,9 @@
            bool isAvailable = cvState == 2;
            if (isAvailable)
            {
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
                return conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
            }
            return false;
        }
        /// <summary>
@@ -155,7 +156,7 @@
        /// <param name="conveyorLine">输送线设备对象,用于写入目标地址和 ACK ä¿¡å·</param>
        /// <param name="nextAddress">下一地址/目标设备编码,用于识别目标设备类型</param>
        /// <param name="childDeviceCode">当前子设备编码,用于精确定位写入哪个子设备</param>
        public void HandleOutboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode)
        public bool HandleOutboundNextAddress(CommonConveyorLine conveyorLine, string nextAddress, string childDeviceCode)
        {
            // è®°å½•出库场景的调试日志,包含子设备和目标地址信息
            WriteDebug(conveyorLine, "出库下一地址", childDeviceCode, nextAddress);
@@ -166,8 +167,9 @@
            bool isAvailable = cvState == 2;
            if (isAvailable)
            {
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
                return conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode);
            }
            return false;
        }
        /// <summary>
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/ConveyorLineNewJob/ManualInbound/ManualInboundTaskHandler.cs
@@ -53,13 +53,24 @@
            try
            {
                // å†™å…¥ä»»åŠ¡å·
                conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, (short)task.TaskNum, childDeviceCode);
                // å†™å…¥èµ·å§‹åœ°å€
                conveyorLine.SetValue(ConveyorLineDBNameNew.Source, short.Parse(task.SourceAddress ?? "0"), childDeviceCode);
                var isTaskNum = conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, (short)task.TaskNum, childDeviceCode);
                if (!isTaskNum) return;
                QuartzLogHelper.LogInfo(_logger, $"任务号写入PLC成功,任务号【{task.TaskNum}】", conveyorLine.DeviceCode);
                Thread.Sleep(500);
                //// å†™å…¥èµ·å§‹åœ°å€
                //conveyorLine.SetValue(ConveyorLineDBNameNew.Source, short.Parse(task.SourceAddress ?? "0"), childDeviceCode);
                //QuartzLogHelper.LogInfo(_logger, $"任务号写入PLC成功,任务号【{task.TaskNum}】", conveyorLine.DeviceCode);
                //Thread.Sleep(500);
                // å†™å…¥ç›®æ ‡åœ°å€
                conveyorLine.SetValue(ConveyorLineDBNameNew.Target, short.Parse(task.NextAddress ?? "0"), childDeviceCode);
                var isTarget = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, short.Parse(task.NextAddress ?? "0"), childDeviceCode);
                if (!isTarget) return;
                QuartzLogHelper.LogInfo(_logger, $"目标地址写入PLC成功,目标地址【{task.NextAddress}】", conveyorLine.DeviceCode);
                Thread.Sleep(500);
                // å†™å…¥æ‰˜ç›˜å·
                conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
                //conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€åˆ°ä¸‹ä¸€é˜¶æ®µ
                var updateResult = _taskService.UpdateTaskStatusToNext(task);
@@ -72,7 +83,7 @@
                // å†™å…¥ACK标志
                conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode);
                QuartzLogHelper.LogInfo(_logger, $"ManualInboundTaskHandler: æ‰‹åŠ¨ä»»åŠ¡å†™å…¥PLC成功,任务号【{task.TaskNum}】,源地址【{task.SourceAddress}】", conveyorLine.DeviceCode);
                QuartzLogHelper.LogInfo(_logger, $"ManualInboundTaskHandler: æ‰‹åŠ¨ä»»åŠ¡å†™å…¥PLC成功,任务号【{task.TaskNum}】,源地址【{task.SourceAddress}】,目标地址【{task.NextAddress}】", conveyorLine.DeviceCode);
            }
            catch (Exception ex)
            {
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -122,7 +122,7 @@
            // åˆå§‹åŒ–命令处理器
            // ç®€å•命令处理器:处理状态更新等简单命令
            var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor, socketGateway, _logger);
            var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor, socketGateway, _logger, _stateManager);
            // å‰ç¼€å‘½ä»¤å¤„理器:处理 pickfinished、putfinished ç­‰å¸¦å‚数的命令
            var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway, fakeBatteryPositionService, _logger);
@@ -212,10 +212,10 @@
                var task = _taskProcessor.GetTask(robotCrane);
                // å¦‚果没有获取到待处理任务,且RobotArmObject为1(有物料),则获取该设备执行中的任务
                if (task == null && state.RobotArmObject == 1)
                {
                    task = _taskProcessor.GetExecutingTask(robotCrane);
                }
                //if (task == null && state.RobotArmObject == 1)
                //{
                //    task = _taskProcessor.GetExecutingTask(robotCrane);
                //}
                // å¦‚果有待处理任务
                if (task != null)
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
@@ -92,7 +92,7 @@
            if (state.OperStatus == message)
            {
                // å¤„理成功后,将原消息回写到客户端(保持原有行为)
                await _socketClientGateway.SendMessageAsync(client, message);
                //await _socketClientGateway.SendMessageAsync(client, message);
            }
            // è®°å½•接收到的消息日志
            QuartzLogHelper.LogInfo(_logger, $"接收到客户端【{state.RobotCrane?.DeviceName}】发送消息【{message}】", state.RobotCrane?.DeviceName);
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -170,36 +170,35 @@
            // æž„建取货指令,格式:Pickbattery,{源地址}
            string taskString = $"Pickbattery,{task.RobotSourceAddress}";
            // é€šè¿‡ Socket ç½‘关发送指令到机器人客户端
            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
            // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸º"机器人执行中"
            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
            if (result)
            // å°†ä»»åŠ¡å…³è”åˆ°çŠ¶æ€å¯¹è±¡
            state.CurrentTask = task;
            if (isScanNG)
            {
                // å‘送成功,记录 Info æ—¥å¿—
                QuartzLogHelper.LogInfo(_logger, $"下发取货指令成功,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸º"机器人执行中"
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                // å°†ä»»åŠ¡å…³è”åˆ°çŠ¶æ€å¯¹è±¡
                state.CurrentTask = task;
                if (isScanNG)
                {
                    state.IsScanNG = true;
                }
                // ä¿æŒåŽŸè¯­ä¹‰ï¼šä»…åœ¨çŠ¶æ€å®‰å…¨å†™å…¥æˆåŠŸåŽå†æ›´æ–°ä»»åŠ¡çŠ¶æ€
                // è¿™æ ·å¯ä»¥ç¡®ä¿çŠ¶æ€å’Œä»»åŠ¡è®°å½•çš„ä¸€è‡´æ€§
                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
                {
                    await _robotTaskService.UpdateRobotTaskAsync(task);
                }
                state.IsScanNG = true;
            }
            else
            // ä¿æŒåŽŸè¯­ä¹‰ï¼šä»…åœ¨çŠ¶æ€å®‰å…¨å†™å…¥æˆåŠŸåŽå†æ›´æ–°ä»»åŠ¡çŠ¶æ€
            // è¿™æ ·å¯ä»¥ç¡®ä¿çŠ¶æ€å’Œä»»åŠ¡è®°å½•çš„ä¸€è‡´æ€§
            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
            {
                // å‘送失败,记录 Error æ—¥å¿—
                QuartzLogHelper.LogError(_logger, $"下发取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                QuartzLogHelper.LogInfo(_logger, $"状态更新成功,设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // é€šè¿‡ Socket ç½‘关发送指令到机器人客户端
                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
                if (result)
                {
                    // å‘送成功,记录 Info æ—¥å¿—
                    QuartzLogHelper.LogInfo(_logger, $"下发取货指令成功,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                    //await _robotTaskService.UpdateRobotTaskAsync(task);
                }
                else
                {
                    // å‘送失败,记录 Error æ—¥å¿—
                    QuartzLogHelper.LogError(_logger, $"下发取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                }
            }
        }
@@ -234,27 +233,26 @@
            // æ ‡è®°ç‚¹ä½ä¸ºå·²ä½¿ç”¨
            _fakeBatteryPositionService.MarkAsUsed(positions);
            // é€šè¿‡ Socket ç½‘关发送指令到机器人客户端
            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
            // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸º"机器人执行中"
            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
            if (result)
            // å°†ä»»åŠ¡å…³è”åˆ°çŠ¶æ€å¯¹è±¡
            state.CurrentTask = task;
            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
            {
                QuartzLogHelper.LogInfo(_logger, $"下发假电芯取货指令成功,指令: {taskString},点位: {string.Join(",", positions)},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // é€šè¿‡ Socket ç½‘关发送指令到机器人客户端
                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
                // æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸º"机器人执行中"
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                // å°†ä»»åŠ¡å…³è”åˆ°çŠ¶æ€å¯¹è±¡
                state.CurrentTask = task;
                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
                if (result)
                {
                    await _robotTaskService.UpdateRobotTaskAsync(task);
                    QuartzLogHelper.LogInfo(_logger, $"下发假电芯取货指令成功,指令: {taskString},点位: {string.Join(",", positions)},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                    //await _robotTaskService.UpdateRobotTaskAsync(task);
                }
            }
            else
            {
                QuartzLogHelper.LogError(_logger, $"下发假电芯取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                else
                {
                    QuartzLogHelper.LogError(_logger, $"下发假电芯取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                }
            }
        }
@@ -307,31 +305,31 @@
        /// <param name="batchEnd">批次结束编号</param>
        public async Task SendPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
        {
            // å…ˆå‘送总数指令
            string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
            // å†å‘送批次取货指令
            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
            string taskString = $"Pickbattery,{position},{range}";
            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
            state.CurrentTask = task;
            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
            if (result)
            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
            {
                QuartzLogHelper.LogInfo(_logger, $"下发批次取货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // å…ˆå‘送总数指令
                string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                state.CurrentTask = task;
                // å†å‘送批次取货指令
                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
                string taskString = $"Pickbattery,{position},{range}";
                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
                if (result)
                {
                    await _robotTaskService.UpdateRobotTaskAsync(task);
                    QuartzLogHelper.LogInfo(_logger, $"下发批次取货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                    //await _robotTaskService.UpdateRobotTaskAsync(task);
                }
            }
            else
            {
                QuartzLogHelper.LogError(_logger, $"下发批次取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                else
                {
                    QuartzLogHelper.LogError(_logger, $"下发批次取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                }
            }
        }
@@ -351,31 +349,31 @@
        /// <param name="batchEnd">批次结束编号</param>
        public async Task SendFakeBatteryPickWithBatchAsync(Dt_RobotTask task, RobotSocketState state, int batchStart, int batchEnd)
        {
            // å…ˆå‘送总数指令
            string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
            state.CurrentTask = task;
            // å†å‘送批次取货指令(假电芯固定从5号位取)
            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
            string taskString = $"Pickbattery,5,{range}";
            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
            if (result)
            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
            {
                QuartzLogHelper.LogInfo(_logger, $"下发假电芯批次取货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // å…ˆå‘送总数指令
                string totalNumCmd = $"PickTotalNum,{task.RobotTaskTotalNum}";
                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                state.CurrentTask = task;
                // å†å‘送批次取货指令(假电芯固定从5号位取)
                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
                string taskString = $"Pickbattery,5,{range}";
                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
                if (result)
                {
                    await _robotTaskService.UpdateRobotTaskAsync(task);
                    QuartzLogHelper.LogInfo(_logger, $"下发假电芯批次取货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                    //await _robotTaskService.UpdateRobotTaskAsync(task);
                }
            }
            else
            {
                QuartzLogHelper.LogError(_logger, $"下发假电芯批次取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                else
                {
                    QuartzLogHelper.LogError(_logger, $"下发假电芯批次取货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                }
            }
        }
@@ -396,31 +394,31 @@
        /// <param name="batchEnd">批次结束编号</param>
        public async Task SendPutWithBatchAsync(Dt_RobotTask task, RobotSocketState state, string position, int batchStart, int batchEnd)
        {
            // å…ˆå‘送总数指令
            string totalNumCmd = $"PutTotalNum,{task.RobotTaskTotalNum}";
            await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
            task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
            state.CurrentTask = task;
            // å†å‘送批次放货指令
            string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
            string taskString = $"Putbattery,{position},{range}";
            bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
            if (result)
            if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
            {
                QuartzLogHelper.LogInfo(_logger, $"下发放货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                // å…ˆå‘送总数指令
                string totalNumCmd = $"PutTotalNum,{task.RobotTaskTotalNum}";
                await _socketClientGateway.SendToClientAsync(state.IPAddress, totalNumCmd);
                task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
                state.CurrentTask = task;
                // å†å‘送批次放货指令
                string range = batchEnd == 0 ? $"{batchStart}-0" : $"{batchStart}-{batchEnd}";
                string taskString = $"Putbattery,{position},{range}";
                if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
                bool result = await _socketClientGateway.SendToClientAsync(state.IPAddress, taskString);
                if (result)
                {
                    await _robotTaskService.UpdateRobotTaskAsync(task);
                    QuartzLogHelper.LogInfo(_logger, $"下发放货指令成功,指令: {taskString},批次: {range},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                    //await _robotTaskService.UpdateRobotTaskAsync(task);
                }
            }
            else
            {
                QuartzLogHelper.LogError(_logger, $"下发放货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                else
                {
                    QuartzLogHelper.LogError(_logger, $"下发放货指令失败,指令: {taskString},设备: {state.RobotCrane?.DeviceName}", state.RobotCrane?.DeviceName);
                }
            }
        }
@@ -785,5 +783,11 @@
            return result;
        }
        public bool UpdateRobotTask(Dt_RobotTask task)
        {
            WebResponseContent content = _robotTaskService.UpdateData(task);
            return content.Status;
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -1,4 +1,6 @@
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using Serilog;
using System.Net;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core.LogHelper;
using WIDESEAWCS_Model.Models;
@@ -42,15 +44,24 @@
        private readonly ILogger _logger;
        /// <summary>
        /// æœºæ¢°æ‰‹çŠ¶æ€ç®¡ç†å™¨
        /// </summary>
        /// <remarks>
        /// ç”¨äºŽè¯»å–和更新机器人的状态。
        /// </remarks>
        private readonly RobotStateManager _stateManager;
        /// <summary>
        /// æž„造函数
        /// </summary>
        /// <param name="taskProcessor">任务处理器实例</param>
        /// <param name="logger">日志记录器</param>
        public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor, ISocketClientGateway socketClientGateway, ILogger logger)
        public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor, ISocketClientGateway socketClientGateway, ILogger logger, RobotStateManager stateManager)
        {
            _taskProcessor = taskProcessor;
            _socketClientGateway = socketClientGateway;
            _logger = logger;
            _stateManager = stateManager;
        }
        /// <summary>
@@ -140,6 +151,21 @@
                    state.BatteryArrived = false;
                    await _socketClientGateway.SendToClientAsync(state.IPAddress, "batteryarrivedno");
                    return true;
                // ==================== æŽ¥æ”¶ä»»åŠ¡åé¦ˆ ====================
                // å–货接收
                case "pickbatteryover":
                    var isResult = UpdateStatus(state, true);
                    if (!isResult)
                        return false;
                    return true;
                // æ”¾è´§æŽ¥æ”¶
                case "putbatteryover":
                    isResult = UpdateStatus(state, false);
                    if (!isResult)
                        return false;
                    return true;
                // ==================== å…¨éƒ¨å®Œæˆå‘½ä»¤ ====================
@@ -432,5 +458,17 @@
                    return false;
            }
        }
        public bool UpdateStatus(RobotSocketState state, bool isPick)
        {
            var task = _taskProcessor.GetTask(state?.RobotCrane);
            if (task == null)
            {
                QuartzLogHelper.LogError(_logger, $"取货接收失败: æœªæ‰¾åˆ°ã€{state?.RobotCrane}】的任务", state.RobotCrane?.DeviceName ?? "Unknown");
            }
            task.RobotTaskState = (int)TaskRobotStatusEnum.RobotExecuting;
            _taskProcessor.UpdateRobotTask(task);
            return true;
        }
    }
}
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -273,7 +273,7 @@
                    if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate))
                    {
                        await _robotTaskService.UpdateRobotTaskAsync(task);
                        //await _robotTaskService.UpdateRobotTaskAsync(task);
                    }
                }
            }
@@ -337,15 +337,15 @@
                // å¦‚果条码生成成功
                if (!string.IsNullOrEmpty(trayBarcode1) && !string.IsNullOrEmpty(trayBarcode2))
                {
                    if (stateForUpdate.CellBarcode.Contains(trayBarcode1) || stateForUpdate.CellBarcode.Contains(trayBarcode2))
                    {
                        QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:读取的电芯条码已存在,可能存在重复,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                    //if (stateForUpdate.CellBarcode.Contains(trayBarcode1) || stateForUpdate.CellBarcode.Contains(trayBarcode2))
                    //{
                    //    QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsync:读取的电芯条码已存在,可能存在重复,任务号: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress);
                        // å‘送取货指令 æ ‡è®°æ‰«ç NG,放货时不使用这些条码,并放入NG口
                        //await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true);
                        return;
                    }
                    else
                    //    // å‘送取货指令 æ ‡è®°æ‰«ç NG,放货时不使用这些条码,并放入NG口
                    //    //await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true);
                    //    return;
                    //}
                    //else
                    {
                        if (trayBarcode1.Length < 13 || trayBarcode2.Length < 13)
                        {
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/StackerCraneJob/StackerCraneTaskSelector.cs
@@ -1,6 +1,7 @@
using Newtonsoft.Json;
using Serilog;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using WIDESEA_Core;
using WIDESEAWCS_Common.Constants;
using WIDESEAWCS_Common.HttpEnum;
@@ -150,10 +151,10 @@
                return selectedTask;
            }
            // ===== TargetAddress ä¸å¯ç”¨æ—¶ï¼Œå…ˆå°è¯•同 NextAddress çš„其他任务 =====
            // ===== TargetAddress ä¸å¯ç”¨æ—¶ï¼Œå…ˆå°è¯•同 NextAddress不同TargetAddress çš„其他任务 =====
            var sameStationTasks = _taskService
                .QueryStackerCraneOutTasks(deviceCode, new List<string> { candidateTask.NextAddress })
                .Where(x => x.TaskId != candidateTask.TaskId)
                .Where(x => x.TaskId != candidateTask.TaskId && x.TargetAddress != candidateTask.TargetAddress)
                .ToList();
            foreach (var sameStationTask in sameStationTasks)
@@ -168,13 +169,8 @@
            // ===== åŒ NextAddress æ— å¯ç”¨ä»»åŠ¡ï¼Œå°è¯•ä¸åŒ NextAddress çš„任务 =====
            // æŸ¥æ‰¾å…¶ä»–可用的出库站台
            var otherOutStationCodes = _routerService
                .QueryNextRoutes(deviceCode, candidateTask.NextAddress, candidateTask.TaskType)
                .Select(x => x.ChildPosi)
                .ToList();
            // æŸ¥è¯¢å…¶ä»–站台的出库任务
            var tasks = _taskService.QueryStackerCraneOutTasks(deviceCode, otherOutStationCodes);
            var tasks = _taskService.QueryStackerCraneOutTasks(deviceCode, new List<string> { candidateTask.NextAddress }, false);
            foreach (var alternativeTask in tasks)
            {
                selectedTask = TrySelectOutboundTask(alternativeTask);
Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
@@ -141,7 +141,10 @@
            var locations = await BaseDal.QueryDataAsync(x =>
                x.EnableStatus == EnableStatusEnum.Normal.GetHashCode() &&
                x.RoadwayNo == roadwayNo &&
                x.LocationStatus == LocationStatusEnum.Free.GetHashCode());
                x.LocationStatus == LocationStatusEnum.Free.GetHashCode() &&
                (roadwayNo.Contains("HC")
                    ? x.LocationType == (int)LocationTypeEnum.Capacity
                    : x.LocationType == (int)LocationTypeEnum.ShelfCapacity));
            return locations?
                .OrderByDescending(x => x.Depth)  // 1. æ·±åº¦ä¼˜å…ˆï¼ˆä»Žå¤§åˆ°å°ï¼‰
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/Constants/TaskAddressConstants.cs
@@ -28,6 +28,11 @@
        /// <summary>
        /// åˆ†å®¹åº“出库地址
        /// </summary>
        public const string GRADING_OUTBOUND_ADDRESS = "10081";
        public const string GRADING_OUTBOUND_ADDRESS = "2103";
        /// <summary>
        /// åˆ†å®¹åº“出库地址
        /// </summary>
        public const string GRADING_RoadWayNo = "HCSC1";
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_Common/LocationEnum/LocationTypeEnum.cs
@@ -19,10 +19,10 @@
        Undefined = 0,
        /// <summary>
        /// æ¨¡åˆ‡æ®µ
        /// è´§æž¶
        /// </summary>
        [Description("模切段")]
        SmallPallet = 1,
        [Description("货架")]
        ShelfCapacity = 1,
        /// <summary>
        /// å·ç»•段
@@ -43,15 +43,15 @@
        ExtraPallet = 4,
        /// <summary>
        /// åŒ–成空托盘
        /// åˆ†å®¹å·¥è£…æž¶
        /// </summary>
        [Description("化成空托盘")]
        HCTrayPallet = 5,
        [Description("分容工装架")]
        SubRackType = 5,
        /// <summary>
        /// åŒ–成分容托盘
        /// åˆ†å®¹æŸœ
        /// </summary>
        [Description("化成分容托盘")]
        HCFRPallet = 6,
        [Description("分容柜")]
        Capacity = 6,
    }
}
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_GradingMachine.cs
@@ -49,12 +49,19 @@
                if (stockInfo == null)
                {
                    var location = await _locationInfoService.GetLocationInfoAsync(input.LocationCode);
                    locationStatus = location?.LocationStatus ?? 0;
                    locationStatus = location?.LocationStatus == (int)LocationStatusEnum.InStock ? 10 : 0;
                }
                else
                {
                    locationStatus = stockInfo.LocationDetails?.LocationStatus ?? 0;
                    locationStatus = MapLocationStatus(stockInfo.StockStatus);
                }
                int MapLocationStatus(int stockStatus) => stockStatus switch
                {
                    (int)StockStatusEmun.入库完成 => 10,
                    (int)StockStatusEmun.空托盘库存 => 11,
                    _ => 0
                };
                OutputDto outPutDto = new OutputDto()
                {
@@ -91,8 +98,8 @@
                var result = await _locationInfoService.Db.Updateable<Dt_LocationInfo>()
                    .SetColumns(s => new Dt_LocationInfo
                    {
                        LocationStatus = input.LocationStatus
                    }).Where(s => s.LocationCode == input.LocationCode).ExecuteCommandAsync() > 0;
                        EnableStatus = input.LocationStatus == 1 ? 0 : 3,
                    }).Where(s => s.LocationCode == input.LocationCode && s.RoadwayNo == TaskAddressConstants.GRADING_RoadWayNo).ExecuteCommandAsync() > 0;
                if (result)
                {
@@ -127,40 +134,41 @@
                var stock = await _stockInfoService.GetStockInfoAsync(input.PalletCode, input.LocationCode);
                if (stock == null)
                {
                    content.Error("未找到对应的托盘");
                    return content.Error("未找到对应的托盘");
                }
                else
                {
                    var taskList = new Dt_Task
                    {
                        WarehouseId = stock.WarehouseId,
                        PalletCode = stock.PalletCode,
                        PalletType = stock.PalletType,
                        SourceAddress = stock.LocationCode,
                        CurrentAddress = stock.LocationCode,
                        NextAddress = TaskAddressConstants.DEFAULT_ADDRESS,
                        TargetAddress = TaskAddressConstants.GRADING_OUTBOUND_ADDRESS,
                        Roadway = stock.LocationDetails.RoadwayNo,
                        TaskType = TaskOutboundTypeEnum.Outbound.GetHashCode(),
                        TaskStatus = TaskOutStatusEnum.OutNew.GetHashCode(),
                        Grade = 1,
                        TaskNum = await BaseDal.GetTaskNo(),
                        Creater = "system",
                    };
                var taskList = new Dt_Task
                {
                    WarehouseId = stock.WarehouseId,
                    PalletCode = stock.PalletCode,
                    PalletType = stock.PalletType,
                    SourceAddress = stock.LocationCode,
                    CurrentAddress = stock.LocationCode,
                    NextAddress = TaskAddressConstants.DEFAULT_ADDRESS,
                    TargetAddress = TaskAddressConstants.GRADING_OUTBOUND_ADDRESS,
                    Roadway = stock.LocationDetails.RoadwayNo,
                    TaskType = TaskOutboundTypeEnum.Outbound.GetHashCode(),
                    TaskStatus = TaskOutStatusEnum.OutNew.GetHashCode(),
                    Grade = 1,
                    TaskNum = await BaseDal.GetTaskNo(),
                    Creater = "system",
                };
                return await _unitOfWorkManage.BeginTranAsync(async () =>
                {
                    var result = await BaseDal.AddDataAsync(taskList) > 0;
                    var wmstaskDto = result ? _mapper.Map<WMSTaskDTO>(taskList) : null;
                    var httpResponse = _httpClientHelper.Post<WebResponseContent>("http://logistics-service/api/logistics/notifyoutbound", JsonSerializer.Serialize(wmstaskDto)).Data;
                    if (result && httpResponse != null)
                    {
                        content.OK("出库请求成功");
                        return content.OK("出库请求成功");
                    }
                    else
                    {
                        content.Error("出库请求失败");
                        return content.Error("出库请求失败");
                    }
                }
                });
            }
            catch (Exception ex)
            {
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Outbound.cs
@@ -85,9 +85,24 @@
                WebResponseContent content = new WebResponseContent();
                return await _unitOfWorkManage.BeginTranAsync(async () =>
                {
                    if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
                    {
                        location.LocationStatus = LocationStatusEnum.Free.GetHashCode();
                        var updateResult = await _locationInfoService.UpdateLocationInfoAsync(location);
                        var deleteResult = _stockInfoService.DeleteData(stockInfo).Status;
                        if (!updateResult && !deleteResult)
                            return content.Error("任务完成失败");
                        var completeResult1 = await CompleteTaskAsync(task, "出库完成");
                        return content.OK();
                    }
                    stockInfo.LocationId = 0;
                    stockInfo.LocationCode = string.Empty;
                    stockInfo.OutboundDate = DateTime.Now;
                    stockInfo.StockStatus = (int)StockStatusEmun.出库完成;
                    location.LocationStatus = LocationStatusEnum.Free.GetHashCode();
Code/WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/appsettings.json
@@ -34,7 +34,7 @@
  "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true
  //连接字符串
  //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=",
  "ConnectionString": "Data Source=192.168.60.30;Initial Catalog=WIDESEAWMS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //"ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_ShanMei;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //"ConnectionString": "Data Source=10.30.4.92;Initial Catalog=WMS_TC;User ID=sa;Password=duo123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
  //旧WMS数据库连接
ÏîÄ¿×ÊÁÏ/É豸ЭÒé/·ÖÈݹñ½Ó¿ÚЭÒé/»¯³É·ÖÈݹñ½Ó¿ÚЭÒé1.1.xls
Binary files differ
ÏîÄ¿×ÊÁÏ/É豸ЭÒé/¸ß³£Î¶Ѷâ»úÓëÊäËÍÏß/WCSÊäËͶԽӵØÖ·±í_0420.xlsx
Binary files differ