| | |
| | | using MapsterMapper; |
| | | using Microsoft.Extensions.Configuration; |
| | | using Newtonsoft.Json; |
| | | using Serilog; |
| | | using SqlSugar; |
| | | using System.Diagnostics; |
| | | using System.Diagnostics.CodeAnalysis; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.BaseServices; |
| | | using WIDESEAWCS_Core.Enums; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_Core.Utilities; |
| | | using WIDESEAWCS_DTO.Stock; |
| | | using WIDESEAWCS_DTO.TaskInfo; |
| | | using WIDESEAWCS_ITaskInfoRepository; |
| | |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_QuartzJob.DTO; |
| | | using WIDESEAWCS_Tasks; |
| | | |
| | | namespace WIDESEAWCS_TaskInfoService |
| | | { |
| | |
| | | private readonly IMapper _mapper; |
| | | private readonly HttpClientHelper _httpClientHelper; |
| | | private readonly ITaskExecuteDetailService _taskExecuteDetailService; |
| | | private readonly ILogger _logger; |
| | | |
| | | private Dictionary<string, OrderByType> _taskOrderBy = new() |
| | | { |
| | |
| | | |
| | | public List<int> TaskRobotTypes => typeof(TaskOtherTypeEnum).GetEnumIndexList(); |
| | | |
| | | public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService) : base(BaseDal) |
| | | public RobotTaskService(IRobotTaskRepository BaseDal, IMapper mapper, HttpClientHelper httpClientHelper, ITaskExecuteDetailService taskExecuteDetailService, ILogger logger) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _httpClientHelper = httpClientHelper; |
| | | _taskExecuteDetailService = taskExecuteDetailService; |
| | | _logger = logger; |
| | | }
|
| | | public override WebResponseContent DeleteData(object[] keys)
|
| | | {
|
| | | List<int> taskKeys = new List<int>();
|
| | | for (int i = 0; i < keys.Length; i++)
|
| | | {
|
| | | taskKeys.Add(Convert.ToInt32(keys[i]));
|
| | | }
|
| | | List<Dt_RobotTask> tasks = BaseDal.QueryData(x => taskKeys.Contains(x.RobotTaskId));
|
| | | BaseDal.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.人工删除);
|
| | | return WebResponseContent.Instance.OK($"成功删除{tasks.Count}条数据");
|
| | |
|
| | | }
|
| | | public bool DeleteRobotTask(int id) |
| | | { |
| | | Dt_RobotTask task = BaseDal.QueryFirst(x => x.RobotTaskId == id); |
| | | return BaseDal.DeleteAndMoveIntoHty(task, OperateTypeEnum.自动完成); |
| | | } |
| | | |
| | | public WebResponseContent ReceiveWMSTask([NotNull] WMSTaskDTO taskDTO, StockDTO stockDTO) |
| | |
| | | Dt_RobotTask task = new Dt_RobotTask |
| | | { |
| | | RobotTaskNum = taskDTO.TaskNum, |
| | | RobotSourceAddressLineCode = stockDTO.SourceLineNo, |
| | | RobotTargetAddressLineCode = stockDTO.TargetLineNo, |
| | | RobotRoadway = stockDTO.Roadway, |
| | | RobotSourceAddressLineCode = stockDTO?.SourceLineNo ?? string.Empty, |
| | | RobotTargetAddressLineCode = stockDTO?.TargetLineNo ?? string.Empty, |
| | | RobotRoadway = stockDTO?.Roadway ?? string.Empty, |
| | | RobotSourceAddress = taskDTO.SourceAddress, |
| | | RobotTargetAddress = taskDTO.TargetAddress, |
| | | RobotSourceAddressPalletCode = stockDTO.SourcePalletNo, |
| | | RobotTargetAddressPalletCode = stockDTO.TargetPalletNo, |
| | | RobotSourceAddressPalletCode = stockDTO?.SourcePalletNo ?? string.Empty, |
| | | RobotTargetAddressPalletCode = stockDTO?.TargetPalletNo ?? string.Empty, |
| | | RobotTaskType = taskDTO.TaskType, |
| | | RobotTaskState = taskDTO.TaskStatus, |
| | | RobotGrade = taskDTO.Grade, |
| | | Creater = "WMS", |
| | | RobotTaskTotalNum = 0, |
| | | RobotTaskTotalNum = taskDTO.TaskQuantity, |
| | | }; |
| | | |
| | | BaseDal.AddData(task); |
| | |
| | | { |
| | | string configKey = ResolveRobotTaskConfigKey(task.TargetAddress); |
| | | StockDTO stock = BuildRobotTaskStock(task, configKey); |
| | | string requestParam = stock.ToJson(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | |
| | | var result = _httpClientHelper.Post<WebResponseContent>(configKey, stock.ToJson()); |
| | | |
| | | var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam); |
| | | stopwatch.Stop(); |
| | | if (!result.IsSuccess || !result.Data.Status) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"调用WMS接口失败,接口:【{configKey}】,请求参数:【{requestParam}】,错误信息:【{result.Data?.Message}】", "RobotTaskService"); |
| | | return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,目标地址:【{task.TargetAddress}】,接口:【{configKey}】,错误信息:【{result.Data?.Message}】"); |
| | | } |
| | | |
| | | var wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty); |
| | | QuartzLogHelper.LogInfo(_logger, $"调用WMS接口成功,接口:【{configKey}】,响应数据:【{result.Data?.Data}】,耗时:{stopwatch.ElapsedMilliseconds}ms", "RobotTaskService"); |
| | | |
| | | var wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result?.Data?.Data?.ToString() ?? string.Empty); |
| | | if (wMSTask == null) |
| | | return WebResponseContent.Instance.Error($"获取WMS系统机械手任务失败,任务号:【{task.TaskNum}】,托盘号:【{task.PalletCode}】,错误信息:【WMS未返回有效任务数据】"); |
| | | |
| | | return ReceiveWMSTask(wMSTask, stock); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 在本地直接创建机械手任务,不调用WMS接口。 |
| | | /// 根据目标地址解析任务类型,构建任务数据并写入数据库。 |
| | | /// </summary> |
| | | /// <param name="task">出库任务实体</param> |
| | | /// <returns>操作结果</returns> |
| | | public WebResponseContent CreateLocalRobotTask(Dt_Task task) |
| | | { |
| | | WebResponseContent content = new(); |
| | | try |
| | | { |
| | | // 根据目标地址解析任务类型配置键 |
| | | string configKey = ResolveRobotTaskConfigKey(task.TargetAddress); |
| | | |
| | | // 构建Stock数据 |
| | | StockDTO stock = BuildRobotTaskStock(task, configKey); |
| | | |
| | | // 获取抓取和放置地址的线体配置(如果有) |
| | | 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() |
| | | { |
| | | RobotTaskNum = Random.Shared.Next(), |
| | | RobotSourceAddress = section[0]!, |
| | | RobotTargetAddress = section[1]!, |
| | | RobotSourceAddressLineCode = stock?.SourceLineNo ?? string.Empty, |
| | | RobotTargetAddressLineCode = stock?.TargetLineNo ?? string.Empty, |
| | | RobotRoadway = stock?.TargetLineNo == "11068" ? "注液组盘机械手" : "换盘机械手" ?? string.Empty, // todo |
| | | RobotSourceAddressPalletCode = stock?.SourcePalletNo ?? string.Empty, |
| | | RobotTargetAddressPalletCode = stock?.TargetPalletNo ?? string.Empty, |
| | | RobotTaskType = taskType, |
| | | RobotTaskState = (int)TaskRobotStatusEnum.RobotNew, |
| | | RobotGrade = task.Grade, |
| | | Creater = "WCS_Local", |
| | | RobotTaskTotalNum = taskType == (int)RobotTaskTypeEnum.GroupPallet ? 48 : 1, |
| | | CreateDate = DateTime.Now |
| | | }; |
| | | |
| | | BaseDal.AddData(robotTask); |
| | | |
| | | _taskExecuteDetailService.AddTaskExecuteDetail(new List<int> { robotTask.RobotTaskNum }, "本地创建机器人任务"); |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"本地创建机器人任务成功,任务号:【{robotTask.RobotTaskNum}】,源地址:【{robotTask.RobotSourceAddress}】,目标地址:【{robotTask.RobotTargetAddress}】,任务类型:【{configKey}】", "RobotTaskService"); |
| | | |
| | | content = WebResponseContent.Instance.OK("本地创建机器人任务成功", robotTask); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"本地创建机器人任务失败,任务号:【{task.TaskNum}】,错误信息:{ex.Message}", "RobotTaskService"); |
| | | content = WebResponseContent.Instance.Error($"本地创建机器人任务失败,错误信息:{ex.Message}"); |
| | | } |
| | | return content; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 将配置键映射到机械手任务类型枚举值。 |
| | | /// </summary> |
| | | /// <param name="configKey">配置键名称</param> |
| | | /// <returns>任务类型枚举值</returns> |
| | | public int MapConfigKeyToRobotTaskType(string? configKey) |
| | | { |
| | | return configKey switch |
| | | { |
| | | nameof(ConfigKey.CreateRobotGroupPalletTask) => (int)RobotTaskTypeEnum.GroupPallet, |
| | | nameof(ConfigKey.CreateRobotSplitPalletTask) => (int)RobotTaskTypeEnum.SplitPallet, |
| | | _ => (int)RobotTaskTypeEnum.ChangePallet |
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | return stock; |
| | | } |
| | | |
| | | public override WebResponseContent AddData(SaveModel saveModel) |
| | | { |
| | | try |
| | | { |
| | | if (saveModel == null || saveModel.MainData == null || saveModel.MainData.Count == 0) |
| | | { |
| | | return WebResponseContent.Instance.Error("传参错误,参数不能为空"); |
| | | } |
| | | |
| | | string validResult = typeof(Dt_RobotTask).ValidateDicInEntity(saveModel.MainData, true, TProperties); |
| | | if (!string.IsNullOrEmpty(validResult)) |
| | | { |
| | | return WebResponseContent.Instance.Error(validResult); |
| | | } |
| | | |
| | | object? taskNumObj = saveModel.MainData[nameof(Dt_RobotTask.RobotTaskNum)]; |
| | | if (taskNumObj != null) |
| | | { |
| | | int taskNum = Convert.ToInt32(taskNumObj); |
| | | if (BaseDal.QueryFirst(x => x.RobotTaskNum == taskNum) != null) |
| | | { |
| | | return WebResponseContent.Instance.Error($"任务编号 {taskNum} 已存在"); |
| | | } |
| | | } |
| | | |
| | | Dt_RobotTask entity = saveModel.MainData.DicToModel<Dt_RobotTask>(); |
| | | entity.Creater = "手动创建"; |
| | | entity.CreateDate = DateTime.Now; |
| | | |
| | | if (saveModel.DetailData == null || saveModel.DetailData.Count == 0) |
| | | { |
| | | BaseDal.AddData(entity); |
| | | return WebResponseContent.Instance.OK("新增成功", entity); |
| | | } |
| | | |
| | | return base.AddData(saveModel); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error($"新增失败,错误信息:{ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据目标地址按「精确 > 回退值」解析规则值。 |
| | | /// </summary> |