| | |
| | | package com.zy.asrs.task; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.baomidou.mybatisplus.mapper.Wrapper; |
| | | import com.core.common.Cools; |
| | |
| | | import com.zy.asrs.service.WrkMastLogService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.asrs.task.handler.AgvHandler; |
| | | import com.zy.common.constant.ApiInterfaceConstant; |
| | | import com.zy.common.properties.SchedulerProperties; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.service.ConfigService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | |
| | | /** |
| | |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | log.warn("定时任务allocateSite:延迟被中断", e); |
| | | isAllocateSite.set(false); |
| | | break; // 如果被中断,退出循环 |
| | | } |
| | | } |
| | |
| | | displayTaskId, task.getWrkNo(), task.getIoType(), task.getStaNo()); |
| | | boolean processed = agvHandler.callAgv(Collections.singletonList(task)); |
| | | |
| | | // 只有当任务成功处理(成功呼叫AGV,状态从7变为8)时,才更新lastProcessedTaskId |
| | | // 如果任务被跳过(站点被占用等),不更新lastProcessedTaskId,下次会重新尝试 |
| | | if (processed) { |
| | | lastProcessedTaskId = task.getId(); |
| | |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | log.warn("呼叫AGV定时任务:延迟被中断", e); |
| | | isAllocateSite.set(false); |
| | | break; // 如果被中断,退出循环 |
| | | } |
| | | } |
| | |
| | | if (agvTask.getIoType() != null && |
| | | (agvTask.getIoType() == 1 || agvTask.getIoType() == 10 || |
| | | agvTask.getIoType() == 53 || agvTask.getIoType() == 57)) { |
| | | |
| | | // taskId使用工作号(wrk_no),如果工作号为空则使用任务ID |
| | | String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId()); |
| | | |
| | | // 更新AGV任务状态为完成 |
| | | agvTask.setWrkSts(9L); |
| | | agvTask.setModiTime(now); |
| | | if (taskService.updateById(agvTask)) { |
| | | completedTasks.add(agvTask); |
| | | completedCount++; |
| | | // taskId使用工作号(wrk_no),如果工作号为空则使用任务ID |
| | | String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId()); |
| | | log.info("入库任务工作档已入库成功,完结AGV呼叫单,taskId:{},wrkNo:{},barcode:{}", |
| | | displayTaskId, wrkMast.getWrkNo(), wrkMast.getBarcode()); |
| | | } |
| | |
| | | reason, displayTaskId, agvTask.getWrkNo(), agvTask.getBarcode(), agvTask.getStaNo()); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | // 检查订单创建时间,超过五分钟后才查询AGV订单状态 |
| | | Date appeTime = agvTask.getAppeTime(); |
| | | boolean shouldCheckAgvStatus = false; |
| | | if (appeTime != null) { |
| | | long timeDiff = now.getTime() - appeTime.getTime(); |
| | | long fiveMinutesInMillis = 5 * 60 * 1000; // 5分钟 |
| | | if (timeDiff >= fiveMinutesInMillis) { |
| | | shouldCheckAgvStatus = true; |
| | | } |
| | | } else { |
| | | // 如果没有创建时间,默认检查 |
| | | shouldCheckAgvStatus = true; |
| | | } |
| | | // taskId使用工作号(wrk_no),如果工作号为空则使用任务ID |
| | | String displayTaskId = (agvTask.getWrkNo() != null) ? String.valueOf(agvTask.getWrkNo()) : String.valueOf(agvTask.getId()); |
| | | // 如果订单创建超过五分钟,查询AGV订单状态 |
| | | if (shouldCheckAgvStatus) { |
| | | String agvOrderStatus = queryAgvOrderStatus(agvTask, displayTaskId); |
| | | if (agvOrderStatus != null) { |
| | | // 根据订单状态处理 |
| | | boolean shouldComplete = processAgvOrderStatus(agvTask, agvOrderStatus, displayTaskId, now); |
| | | if (shouldComplete) { |
| | | completedTasks.add(agvTask); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | // 立即将完成的AGV任务转移到历史表,不保留在Task表中 |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 查询AGV订单状态 |
| | | * @param agvTask AGV任务 |
| | | * @param displayTaskId 显示的任务ID |
| | | * @return 订单状态(Building/Created/Assigned/Failed/Done/Cancelled),如果查询失败返回null |
| | | */ |
| | | private String queryAgvOrderStatus(Task agvTask, String displayTaskId) { |
| | | try { |
| | | // 构建订单ID,格式为 "T" + wrkNo |
| | | String orderId = null; |
| | | if (agvTask.getWrkNo() != null) { |
| | | orderId = "T" + agvTask.getWrkNo(); |
| | | } else { |
| | | String errorMsg = String.format("查询AGV订单状态失败:任务ID:%s,wrkNo为空", displayTaskId); |
| | | log.warn("查询AGV订单状态失败 - 任务ID:{},{}", displayTaskId, errorMsg); |
| | | agvTask.setErrorMemo(errorMsg); |
| | | agvTask.setErrorTime(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | |
| | | // 构建请求JSON |
| | | JSONObject requestJson = new JSONObject(); |
| | | requestJson.put("entityName", "ContainerTransportOrder"); |
| | | requestJson.put("id", orderId); |
| | | String requestBody = requestJson.toJSONString(); |
| | | |
| | | // 构建请求头 |
| | | Map<String, Object> headers = new HashMap<>(); |
| | | headers.put("xyy-app-id", "seer"); |
| | | headers.put("xyy-app-key", "123456"); |
| | | |
| | | // 发送请求 |
| | | String response = null; |
| | | try { |
| | | response = new HttpHandler.Builder() |
| | | .setUri(ApiInterfaceConstant.AGV_IP) |
| | | .setPath(ApiInterfaceConstant.AGV_FIND_ONE_PATH) |
| | | .setJson(requestBody) |
| | | .setHeaders(headers) |
| | | .build() |
| | | .doPost(); |
| | | } catch (IOException e) { |
| | | String errorMsg = String.format("查询AGV订单状态API调用失败:%s,请求:%s", e.getMessage(), requestBody); |
| | | log.error("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg, e); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | |
| | | // 解析响应 |
| | | if (response == null || response.trim().isEmpty()) { |
| | | String errorMsg = String.format("查询AGV订单状态API返回为空,请求:%s", requestBody); |
| | | log.warn("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | |
| | | try { |
| | | JSONObject responseJson = JSON.parseObject(response); |
| | | |
| | | // 检查是否有错误码 |
| | | String code = responseJson.getString("code"); |
| | | if (code != null && "errNoSuchEntity".equals(code)) { |
| | | // 找不到业务对象,记录到errorMemo但忽略(不阻止后续处理) |
| | | String errorMsg = String.format("查询AGV订单状态:找不到订单(errNoSuchEntity),请求:%s,响应:%s", requestBody, response); |
| | | log.debug("查询AGV订单状态:找不到订单 - 任务ID:{},订单ID:{}", displayTaskId, orderId); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | |
| | | // 获取订单信息 |
| | | JSONObject entityValue = responseJson.getJSONObject("entityValue"); |
| | | if (entityValue != null) { |
| | | String status = entityValue.getString("status"); |
| | | if (status != null) { |
| | | log.info("查询AGV订单状态成功 - 任务ID:{},订单ID:{},状态:{}", displayTaskId, orderId, status); |
| | | return status; |
| | | } else { |
| | | String errorMsg = String.format("查询AGV订单状态响应中缺少status字段,请求:%s,响应:%s", requestBody, response); |
| | | log.warn("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | } else { |
| | | String errorMsg = String.format("查询AGV订单状态响应中缺少entityValue字段,请求:%s,响应:%s", requestBody, response); |
| | | log.warn("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | } catch (com.alibaba.fastjson.JSONException e) { |
| | | String errorMsg = String.format("解析AGV订单状态响应JSON失败:%s,请求:%s,响应:%s", e.getMessage(), requestBody, response); |
| | | log.error("查询AGV订单状态失败 - 任务ID:{},订单ID:{},{}", displayTaskId, orderId, errorMsg, e); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | } catch (Exception e) { |
| | | String errorMsg = String.format("查询AGV订单状态异常:%s", e.getMessage()); |
| | | log.error("查询AGV订单状态异常 - 任务ID:{},{}", displayTaskId, errorMsg, e); |
| | | agvTask.setErrorMemo2(errorMsg); |
| | | agvTask.setErrorTime2(new Date()); |
| | | taskService.updateById(agvTask); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理AGV订单状态 |
| | | * @param agvTask AGV任务 |
| | | * @param status 订单状态 |
| | | * @param displayTaskId 显示的任务ID |
| | | * @param now 当前时间 |
| | | * @return true表示应该完结订单,false表示不应该完结(跳过) |
| | | */ |
| | | private boolean processAgvOrderStatus(Task agvTask, String status, String displayTaskId, Date now) { |
| | | if (status == null) { |
| | | return false; // 状态为空,跳过 |
| | | } |
| | | |
| | | switch (status) { |
| | | case "Building": |
| | | // Building=未提交,正常没有此状态,忽略 |
| | | log.debug("AGV订单状态为Building(未提交),忽略 - 任务ID:{}", displayTaskId); |
| | | return true; // 继续处理 |
| | | case "Created": |
| | | // Created=已提交,等待期间,不处理 |
| | | log.debug("AGV订单状态为Created(已提交),等待期间,不处理 - 任务ID:{}", displayTaskId); |
| | | return false; // 不处理,跳过 |
| | | case "Assigned": |
| | | case "Assined": |
| | | // Assigned=已派车,正常状态,不处理 |
| | | log.debug("AGV订单状态为{}(已派车),正常状态,不处理 - 任务ID:{}", status, displayTaskId); |
| | | return false; // 不处理,跳过 |
| | | case "Failed": |
| | | case "Failde": |
| | | // Failed=失败,标记为失败订单 |
| | | log.warn("AGV订单状态为{}(失败),标记为失败订单 - 任务ID:{}", status, displayTaskId); |
| | | agvTask.setWrkSts(10L); |
| | | agvTask.setErrorTime(now); |
| | | agvTask.setErrorMemo(String.format("AGV订单状态为%s(失败)", status)); |
| | | taskService.updateById(agvTask); |
| | | return false; // 不处理,跳过 |
| | | case "Done": |
| | | // Done=已完成,完结订单 |
| | | log.info("AGV订单状态为Done(已完成),完结订单 - 任务ID:{}", displayTaskId); |
| | | return true; // 继续处理,完结订单 |
| | | case "Cancelled": |
| | | // Cancelled=取消,取消订单 |
| | | log.warn("AGV订单状态为Cancelled(取消),取消订单 - 任务ID:{}", displayTaskId); |
| | | agvTask.setWrkSts(10L); |
| | | agvTask.setErrorTime(now); |
| | | agvTask.setErrorMemo("AGV订单状态为Cancelled(取消)"); |
| | | taskService.updateById(agvTask); |
| | | return false; // 不处理,跳过 |
| | | default: |
| | | // 未知状态,记录日志但继续处理 |
| | | log.warn("AGV订单状态未知:{},继续处理 - 任务ID:{}", status, displayTaskId); |
| | | return true; // 继续处理 |
| | | } |
| | | } |
| | | |
| | | } |
| | | |