using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using System.DirectoryServices.Protocols; using System.Threading.Tasks; using WIDESEA_Common.StockEnum; using WIDESEA_Common.WareHouseEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.Filter; using WIDESEA_Core.LogHelper; using WIDESEA_DTO.Basic; using WIDESEA_ITaskInfoService; using WIDESEA_Model.Models; namespace WIDESEA_WMSServer.Controllers { [Route("api/ESS")] [ApiController] [AllowAnonymous] public class ESSController : Controller { public readonly ITaskService _taskService; private readonly ILogger _logger; private readonly IMemoryCache _memoryCache; private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); public ESSController(ITaskService taskService, ILogger logger, IMemoryCache memoryCache) { _taskService = taskService; _logger = logger; _memoryCache = memoryCache; } /// /// 容器到达上报 /// /// /// [HttpPost("ContainerArrivalReport"), AllowAnonymous] public async Task ContainerArrivalReport([FromBody] ContainerArrivalRequest request) { //这里要判断出库的时候,料箱会到扫码处。也会请求这个接口。 _logger.LogInformation(" ESSController ContainerArrivalReport : CallId={CallId},ContainerCode={ContainerCode},SlotCode={SlotCode}", request.CallId, request.ContainerCode, request.SlotCode); var response = new ApiResponse { Code = 1 }; // 生成请求的唯一标识(基于callId + 时间戳) var requestKey = $"callback_{request.CallId}-{request.ContainerCode}_{DateTime.UtcNow:yyyyMMddHH}"; // 检查是否已经处理过相同的请求 if (_memoryCache.TryGetValue(requestKey, out bool _)) { _logger.LogWarning("检测到重复请求,已忽略: CallId={CallId}", request.CallId); response.Code = 1; response.Msg = null; response.Data = null; return Ok(response); } await _semaphore.WaitAsync(); try { if (_memoryCache.TryGetValue(requestKey, out bool _)) { _logger.LogWarning("双重检查检测到重复请求,已忽略: CallId={CallId}", request.CallId); response.Code = 1; response.Msg = null; response.Data = null; return Ok(response); } WebResponseContent result = await _taskService.RequestInboundTask(request.ContainerCode, request.SlotCode); var cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(20) }; _memoryCache.Set(requestKey, true, cacheOptions); response = new ApiResponse { Code = 0, Msg = "", Data = new ContainerArrivalResponseData { direction = "100" } }; if (result != null && !string.IsNullOrEmpty( result.Message ) && result.Message.Contains("该托盘已生成任务")) { return Ok(response); } if (result != null && result.Status) { return Ok(response); } else { response.Code = 1; response.Msg = null; response.Data = null; _logger.LogError(" ESSController ContainerArrivalReport Error: Message={Message}", result.Message); return Ok(response); } } catch (Exception ex) { _logger.LogError(ex, "处理任务状态回调时发生异常: CallId={CallId}", request.CallId); return Ok($"处理回调时发生异常: {ex.Message}"); } finally { _semaphore.Release(); } } /// /// 异常上报 /// /// /// [HttpPost("ExceptionReporting"), AllowAnonymous] public async Task> ExceptionReporting( [FromBody] RobotAbnormalEventRequest request) { _logger.LogInformation("异常上报接口request: " + JsonConvert.SerializeObject(request)); return StatusCallbackResponse.Success(); } //任务状态上报接口 [HttpPost("TaskStatusCcallback"), AllowAnonymous] public async Task> TaskStatusCallback( [FromBody] StatusCallbackRequest request) { _logger.LogInformation("任务状态上报接口request: " + JsonConvert.SerializeObject(request)); try { _logger.LogInformation("收到任务状态回调: CallId={CallId}, EventType={EventType}, Status={Status}", request.CallId, request.EventType, request.Status); // 根据事件类型和状态进行不同的业务处理 switch (request.EventType) { case EventType.tote_load: await HandleToteLoad(request); break; case EventType.tote_unload: await HandleToteUnload(request); break; case EventType.robot_reach: await HandleRobotReach(request); break; case EventType.task: await HandleTaskStatusChange(request); break; case EventType.task_allocated: await HandleTaskAllocated(request); break; default: _logger.LogWarning("未知的事件类型: {EventType}", request.EventType); break; } _logger.LogInformation("任务状态回调处理完成: CallId={CallId}", request.CallId); return StatusCallbackResponse.Success(); } catch (Exception ex) { _logger.LogError(ex, "处理任务状态回调时发生异常: CallId={CallId}", request?.CallId); return StatusCallbackResponse.Error($"处理回调时发生异常: {ex.Message}"); } } /// /// 处理任务状态变化 /// private async Task HandleTaskStatusChange(StatusCallbackRequest request) { // 根据任务状态进行不同的处理 switch (request.Status) { case WIDESEA_DTO.Basic.TaskStatus.success: await HandleTaskCompleted(request); break; case WIDESEA_DTO.Basic.TaskStatus.fail: await HandleTaskFailed(request); break; case WIDESEA_DTO.Basic.TaskStatus.cancel: await HandleTaskCancelled(request); break; case WIDESEA_DTO.Basic.TaskStatus.suspend: await HandleTaskSuspended(request); break; } } /// /// 处理任务完成 /// private async Task HandleTaskCompleted(StatusCallbackRequest request) { _logger.LogInformation("任务完成: TaskCode={TaskCode}, Container={Container}, Robot={Robot}", request.TaskCode, request.ContainerCode, request.RobotCode); _taskService.TaskCompleted(request.TaskCode); // 根据不同的任务类型进行特殊处理 if (request.Weight.HasValue) { // 称重任务完成 _logger.LogInformation("称重任务完成: 重量={Weight}g, 托盘层={TrayLevel}", request.Weight, request.TrayLevel); } else if (request.Rfids != null && request.Rfids.Count > 0) { // RFID任务完成 _logger.LogInformation("RFID任务完成: RFID数量={RfidCount}, 托盘层={TrayLevel}", request.Rfids.Count, request.TrayLevel); } else if (request.IsLocationHasContainer.HasValue) { // 扫描任务完成 _logger.LogInformation("扫描任务完成: 库位有容器={HasContainer}", request.IsLocationHasContainer); } else { // 普通任务完成 _logger.LogInformation("普通任务完成"); } // 这里添加您的业务逻辑 await Task.CompletedTask; } /// /// 处理任务失败 /// private async Task HandleTaskFailed(StatusCallbackRequest request) { _logger.LogWarning("任务失败: TaskCode={TaskCode}, 原因={Message}", request.TaskCode, request.Message); // 这里添加您的失败处理逻辑 await Task.CompletedTask; } /// /// 处理任务取消 /// private async Task HandleTaskCancelled(StatusCallbackRequest request) { _logger.LogInformation("任务取消: TaskCode={TaskCode}", request.TaskCode); // 这里添加您的取消处理逻辑 await Task.CompletedTask; } /// /// 处理任务挂起 /// private async Task HandleTaskSuspended(StatusCallbackRequest request) { _logger.LogWarning("任务挂起: TaskCode={TaskCode}, 系统任务码={SysTaskCode}, 原因={Message}", request.TaskCode, request.SysTaskCode, request.Message); // 这里添加您的挂起处理逻辑 await Task.CompletedTask; } /// /// 处理任务分配 /// private async Task HandleTaskAllocated(StatusCallbackRequest request) { _logger.LogInformation("任务分配: TaskCode={TaskCode}, Robot={Robot}", request.TaskCode, request.RobotCode); // 这里添加您的任务分配处理逻辑 await Task.CompletedTask; } /// /// 处理取箱操作 /// private async Task HandleToteLoad(StatusCallbackRequest request) { if (request.Status == WIDESEA_DTO.Basic.TaskStatus.success) { _logger.LogInformation("取箱完成: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode); } else { _logger.LogWarning("取箱失败: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode); } // 这里添加您的取箱处理逻辑 await Task.CompletedTask; } /// /// 处理放箱操作 /// private async Task HandleToteUnload(StatusCallbackRequest request) { if (request.Status == WIDESEA_DTO.Basic.TaskStatus.success) { _logger.LogInformation("放箱完成: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode); } else { _logger.LogWarning("放箱失败: Container={Container}, Location={Location}", request.ContainerCode, request.LocationCode); } // 这里添加您的放箱处理逻辑 await Task.CompletedTask; } /// /// 处理机器人到达工作站 /// private async Task HandleRobotReach(StatusCallbackRequest request) { _logger.LogInformation("机器人到达工作站: Robot={Robot}, Station={Station}, Location={Location}", request.RobotCode, request.StationCode, request.LocationCode); if (request.Trays != null && request.Trays.Count > 0) { _logger.LogInformation("机器人携带托盘信息: 托盘数量={TrayCount}", request.Trays.Count); foreach (var tray in request.Trays) { _logger.LogInformation("托盘: Container={Container}, Level={Level}, Position={Position}, Face={Face}", tray.ContainerCode, tray.TrayLevel, tray.PositionCode, tray.ContainerFace); } } // 这里添加您的机器人到达处理逻辑 await Task.CompletedTask; } } }