#region << 版 本 注 释 >> /*---------------------------------------------------------------- * 命名空间:WIDESEAWCS_TaskInfoService * 创建者:胡童庆 * 创建时间:2024/8/2 16:13:36 * 版本:V1.0.0 * 描述: * * ---------------------------------------------------------------- * 修改人: * 修改时间: * 版本:V1.0.1 * 修改说明: * *----------------------------------------------------------------*/ #endregion << 版 本 注 释 >> using MapsterMapper; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using SqlSugar; using System.Diagnostics.CodeAnalysis; using WIDESEA_Core; using WIDESEAWCS_Common.HttpEnum; using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core; using WIDESEAWCS_Core.BaseServices; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_DTO.Stock; using WIDESEAWCS_DTO.TaskInfo; using WIDESEAWCS_ITaskInfoRepository; using WIDESEAWCS_ITaskInfoService; using WIDESEAWCS_Model.Models; using WIDESEAWCS_QuartzJob; using WIDESEAWCS_QuartzJob.DTO; namespace WIDESEAWCS_TaskInfoService { public class RobotTaskService : ServiceBase, IRobotTaskService { private readonly IMapper _mapper; private readonly HttpClientHelper _httpClientHelper; private readonly ITaskExecuteDetailService _taskExecuteDetailService; private Dictionary _taskOrderBy = new() { {nameof(Dt_RobotTask.RobotGrade),OrderByType.Desc }, {nameof(Dt_RobotTask.CreateDate),OrderByType.Asc}, }; public Dictionary TaskOrderBy { get { return _taskOrderBy; } set { _taskOrderBy = value; } } public List TaskInboundTypes => typeof(TaskInboundTypeEnum).GetEnumIndexList(); public List TaskOutboundTypes => typeof(TaskOutboundTypeEnum).GetEnumIndexList(); public List TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList(); public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService) : base(BaseDal) { _mapper = mapper; _httpClientHelper = httpClientHelper; _taskExecuteDetailService = taskExecuteDetailService; } public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO, StockDTO stockDTO) { WebResponseContent content = new WebResponseContent(); try { if (BaseDal.QueryFirst(x => x.RobotTaskNum == taskDTO.TaskNum || x.RobotSourceAddressPalletCode == taskDTO.PalletCode) != null) { return content.Error("任务已存在"); } Dt_RobotTask task = new Dt_RobotTask { RobotTaskNum = taskDTO.TaskNum, RobotSourceAddressLineCode = stockDTO.SourceLineNo, RobotTargetAddressLineCode = stockDTO.TargetLineNo, RobotRoadway = stockDTO.Roadway, RobotSourceAddress = stockDTO.SourceLineNo, RobotTargetAddress = stockDTO.TargetLineNo, RobotSourceAddressPalletCode = stockDTO.SourcePalletNo, RobotTargetAddressPalletCode = stockDTO.TargetPalletNo, RobotTaskType = taskDTO.TaskType, RobotTaskState = taskDTO.TaskState, RobotGrade = taskDTO.Grade, Creater = "WMS" }; BaseDal.AddData(task); _taskExecuteDetailService.AddTaskExecuteDetail(new List { task.RobotTaskNum }, "接收WMS任务"); content = WebResponseContent.Instance.OK("成功", task); } catch (Exception ex) { content = WebResponseContent.Instance.Error($"任务接收错误,错误信息:{ex.Message}"); } return content; } public Dt_RobotTask? QueryRobotCraneTask(string deviceCode) { return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState != (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy); } public async Task UpdateRobotTaskAsync(Dt_RobotTask robotTask) { return await BaseDal.UpdateDataAsync(robotTask); } /// /// 获取WMS系统机械手任务 /// /// /// public WebResponseContent GetWMSRobotTask(Dt_Task task) { string configKey = ResolveRobotTaskConfigKey(task.TargetAddress); StockDTO stock = BuildRobotTaskStock(task, configKey); var result = _httpClientHelper.Post(configKey, stock.ToJson()); if (!result.IsSuccess || !result.Data.Status) return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,目标地址:【{task.TargetAddress}】,接口:【{configKey}】,错误信息:【{result.Data?.Message}】"); var wMSTask = JsonConvert.DeserializeObject(result.Data.Data?.ToString() ?? string.Empty); if (wMSTask == null) return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】"); return ReceiveWMSTask(wMSTask, stock); } /// /// 根据输送线目标地址解析机械手任务接口。 /// 规则: /// 1. 从配置读取精确地址映射(AddressMap) /// 2. 未命中时默认换盘 /// public string ResolveRobotTaskConfigKey(string? targetAddress) { string address = (targetAddress ?? string.Empty).Trim(); if (string.IsNullOrWhiteSpace(address)) return nameof(ConfigKey.CreateRobotChangePalletTask); var section = App.Configuration.GetSection("RobotTaskAddressRules"); var addressMap = ReadRobotRuleMap(section.GetSection("AddressMap")); if (addressMap.TryGetValue(address, out string? exactTaskType)) return MapRobotTaskTypeToConfigKey(exactTaskType); return nameof(ConfigKey.CreateRobotChangePalletTask); } public int MapWarehouseIdConfigKey(string? targetAddress) { return targetAddress switch { "11068" => 1, "11001" => 3, "11010" => 3, "10010" => 1, "10030" => 1, _ => 1 }; } /// /// 将配置任务类型转换为接口配置键。 /// 支持值:Split/Group/Change(大小写不敏感) /// private string MapRobotTaskTypeToConfigKey(string? taskType) { string type = (taskType ?? string.Empty).Trim().ToLowerInvariant(); return type switch { "split" => nameof(ConfigKey.CreateRobotSplitPalletTask), "group" => nameof(ConfigKey.CreateRobotGroupPalletTask), _ => nameof(ConfigKey.CreateRobotChangePalletTask) }; } /// /// 根据接口类型构建机械手任务入参。 /// private StockDTO BuildRobotTaskStock(Dt_Task task, string configKey) { string targetAddress = task.TargetAddress ?? string.Empty; string roadway = ResolveRobotRuleValue(targetAddress, "AddressRoadwayMap", task.Roadway); string sourceLineNo = ResolveRobotRuleValue(targetAddress, "AddressSourceLineNoMap", task.SourceAddress); var stock = new StockDTO { Roadway = roadway, SourceLineNo = sourceLineNo, TargetLineNo = task.TargetAddress, SourcePalletNo = task.PalletCode, TargetPalletNo = task.PalletCode }; if (configKey == nameof(ConfigKey.CreateRobotSplitPalletTask)) { stock.TargetPalletNo = string.Empty; } else if (configKey == nameof(ConfigKey.CreateRobotGroupPalletTask)) { stock.SourcePalletNo = string.Empty; } else if (configKey == nameof(ConfigKey.CreateRobotChangePalletTask)) { IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceLineNo)); if (device != null) { CommonConveyorLine conveyorLine = (CommonConveyorLine)device; DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(ConveyorLineDBNameNew.Barcode) && x.DeviceChildCode == sourceLineNo); ConveyorLineTaskCommandNew command = conveyorLine.ReadCustomer(sourceLineNo); // 测试用 //var barcode = conveyorLine.GetValue(ConveyorLineDBNameNew.Barcode, sourceLineNo); stock.SourcePalletNo = string.IsNullOrEmpty(command.Barcode.Replace("\0", "").ToString()) ? string.Empty : command.Barcode.Replace("\0", "").ToString(); } } return stock; } /// /// 根据目标地址按「精确 > 回退值」解析规则值。 /// private string ResolveRobotRuleValue(string? targetAddress, string addressSectionName, string? fallback) { string address = (targetAddress ?? string.Empty).Trim(); string defaultValue = fallback ?? string.Empty; if (string.IsNullOrWhiteSpace(address)) return defaultValue; var section = App.Configuration.GetSection("RobotTaskAddressRules"); var addressMap = ReadRobotRuleMap(section.GetSection(addressSectionName)); if (addressMap.TryGetValue(address, out string? value)) return value; return defaultValue; } /// /// 读取规则映射段。 /// private Dictionary ReadRobotRuleMap(IConfigurationSection section) { return section .GetChildren() .Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value)) .ToDictionary(x => x.Key.Trim(), x => x.Value!.Trim()); } } }