using System.Collections.Concurrent; using Sln.Wcs.HikRoBotApi.Domain.Dto.GenAgvSchedulingTask; using Sln.Wcs.HikRoBotApi.Enum; using Sln.Wcs.HikRoBotApi.Service; using Sln.Wcs.HoistApi.Domain.Dto.HoistTaskExecutor; using Sln.Wcs.HoistApi.Domain.Enum; using Sln.Wcs.HoistApi.Service; using Sln.Wcs.Model.Domain; using Sln.Wcs.Repository.service; namespace Sln.Wcs.Strategy; public class TaskExecuteStrategy : ITaskExecuteStrategy { private readonly ILiveTaskQueueService _taskQueueService; private readonly ILiveTaskDetailService _taskDetailService; private readonly IHikRoBotService _hikRobotService; private readonly IHoistApiService _hoistService; // AGV 多车并发,默认最大 10 个并发 private readonly SemaphoreSlim _agvSemaphore = new(10, 10); // 提升机按设备串行,每台提升机一次只能执行一个任务 private readonly ConcurrentDictionary _hoistSemaphores = new(); public TaskExecuteStrategy( ILiveTaskQueueService taskQueueService, ILiveTaskDetailService taskDetailService, IHikRoBotService hikRobotService, IHoistApiService hoistService) { _taskQueueService = taskQueueService; _taskDetailService = taskDetailService; _hikRobotService = hikRobotService; _hoistService = hoistService; } public Task ExecuteAsync(CancellationToken cancellationToken = default) { return Task.WhenAll( ProcessCategory(1, cancellationToken), // 包材 ProcessCategory(2, cancellationToken), // 成品 ProcessCategory(3, cancellationToken) // 托盘 ); } /// /// 按任务类别轮询待执行任务,同一类别内多个任务并行处理 /// private async Task ProcessCategory(int taskCategory, CancellationToken ct) { while (!ct.IsCancellationRequested) { try { var pendingTasks = _taskQueueService.Query(x => x.taskStatus == 1 && x.taskCategory == taskCategory); if (pendingTasks.Count > 0) { await Parallel.ForEachAsync(pendingTasks, ct, async (task, innerCt) => { await ProcessTask(task, innerCt); }); } } catch (Exception ex) { Console.WriteLine($"任务类别 {taskCategory} 调度异常: {ex.Message}"); } await Task.Delay(1000, ct); } } /// /// 处理单个任务:按顺序遍历明细步骤,依次下发到对应设备 /// private async Task ProcessTask(LiveTaskQueue task, CancellationToken ct) { try { var details = _taskDetailService.Query(x => x.taskCode == task.taskCode && x.taskStatus == 1) .OrderBy(x => x.objId) .ToList(); foreach (var detail in details) { if (ct.IsCancellationRequested) return; var success = await DispatchDetail(detail); if (!success) break; } // 检查是否还有待执行的明细,若无则更新队列状态为执行中 var remainingPending = _taskDetailService.Query(x => x.taskCode == task.taskCode && x.taskStatus == 1); if (remainingPending.Count == 0) { task.taskStatus = 2; _taskQueueService.Update(task); } } catch (Exception ex) { Console.WriteLine($"任务 {task.taskCode} 处理异常: {ex.Message}"); } } /// /// 根据设备类型分发明细到对应设备 API /// private Task DispatchDetail(LiveTaskDetail detail) { return detail.deviceType switch { 1 => DispatchToAgv(detail), 2 => DispatchToHoist(detail), _ => Task.FromResult(false) // ConveyorLine 暂不处理 }; } /// /// 下发 AGV 任务,通过 HikRoBotApi(AGV 多车可并发) /// private async Task DispatchToAgv(LiveTaskDetail detail) { await _agvSemaphore.WaitAsync(); try { var dto = new GenAgvSchedulingTaskDto { reqCode = detail.taskCode, reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), clientCode = "WCS", taskCode = detail.taskCode, taskTyp = detail.taskType switch { 1 => "1", 2 => "2", _ => "0" }, taskMode = detail.taskType switch { 1 => "2", 2 => "1", _ => "0" }, wbCode = detail.startPoint, ctnrCode = detail.palletBarcode, materialLot = detail.materialBarcode, positionCodePath = new List { new() { positionCode = detail.startPoint, type = "00" }, new() { positionCode = detail.endPoint, type = "00" } } }; var result = _hikRobotService.GetGenAgvSchedulingTask(dto); if (result.code.Equals(HikRoBotStatusEnum.成功)) { detail.taskStatus = 2; _taskDetailService.Update(detail); return true; } Console.WriteLine($"AGV 任务 {detail.taskCode} 下发失败: [{result.code}] {result.msg}"); return false; } finally { _agvSemaphore.Release(); } } /// /// 下发提升机任务,通过 HoistApi(每台提升机串行) /// private async Task DispatchToHoist(LiveTaskDetail detail) { var hoistCode = detail.startPoint ?? "default"; var semaphore = _hoistSemaphores.GetOrAdd(hoistCode, _ => new SemaphoreSlim(1, 1)); await semaphore.WaitAsync(); try { var dto = new HoistTaskExeDto { hoistCode = hoistCode, taskCode = detail.taskCode, startPoint = int.TryParse(detail.startPoint, out var s) ? s : 0, endPoint = int.TryParse(detail.endPoint, out var e) ? e : 0 }; var result = _hoistService.HoistTaskExecutor(dto); if (result.code.Equals(HoistStatusEnum.成功)) { detail.taskStatus = 2; _taskDetailService.Update(detail); return true; } Console.WriteLine($"提升机 {hoistCode} 任务 {detail.taskCode} 下发失败: [{result.code}] {result.msg}"); return false; } finally { semaphore.Release(); } } }