diff --git a/shkj-admin/src/main/java/com/shkj/ShkjApplication.java b/shkj-admin/src/main/java/com/shkj/ShkjApplication.java index 5ee2cff..9d3085c 100644 --- a/shkj-admin/src/main/java/com/shkj/ShkjApplication.java +++ b/shkj-admin/src/main/java/com/shkj/ShkjApplication.java @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.retry.annotation.EnableRetry; import org.springframework.scheduling.annotation.EnableAsync; /** @@ -15,6 +16,7 @@ import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, MongoAutoConfiguration.class},scanBasePackages = {"org.jeecg.modules.jmreport", "com.shkj"}) //@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, MongoAutoConfiguration.class},scanBasePackages = {"org.jeecg.modules.jmreport", "com.shkj"}) @EnableAsync +@EnableRetry public class ShkjApplication { public static void main(String[] args) { // System.setProperty("spring.devtools.restart.enabled", "false"); diff --git a/shkj-admin/src/main/resources/application.yml b/shkj-admin/src/main/resources/application.yml index d7e7999..4314af8 100644 --- a/shkj-admin/src/main/resources/application.yml +++ b/shkj-admin/src/main/resources/application.yml @@ -90,8 +90,7 @@ token: # 令牌有效期(默认30分钟)-- 修改为720分钟=12个小时 expireTime: 720 -## MyBatis配置 -#mybatis: + #mybatis: # # 搜索指定包别名 # typeAliasesPackage: com.shkj.**.domain # # 配置mapper的扫描,找到所有的mapper.xml映射文件 diff --git a/shkj-admin/src/main/resources/logback.xml b/shkj-admin/src/main/resources/logback.xml index 8137b1a..295172d 100644 --- a/shkj-admin/src/main/resources/logback.xml +++ b/shkj-admin/src/main/resources/logback.xml @@ -55,7 +55,7 @@ 1MB - 15 + 40 diff --git a/shkj-common/src/main/java/com/shkj/common/core/domain/Result.java b/shkj-common/src/main/java/com/shkj/common/core/domain/Result.java index 330be53..da2af61 100644 --- a/shkj-common/src/main/java/com/shkj/common/core/domain/Result.java +++ b/shkj-common/src/main/java/com/shkj/common/core/domain/Result.java @@ -52,6 +52,12 @@ public class Result implements Serializable { this.result=result; } + public Result(int code,String msg) { + super(); + this.code = code; + this.msg=msg; + } + public Result i18n(String key, Object... args) { this.msg = MessageUtils.message(key, args); return this; @@ -90,6 +96,10 @@ public class Result implements Serializable { return new Result(code,result); } + public static Result err(int code,String msg) { + return new Result(code,msg); + } + public static Result err() { return err(HttpStatus.ERROR.getCode()); } diff --git a/shkj-wms/src/main/java/com/shkj/wcs/plc/PlcEventTask.java b/shkj-wms/src/main/java/com/shkj/wcs/plc/PlcEventTask.java index 8f58157..0150e4f 100644 --- a/shkj-wms/src/main/java/com/shkj/wcs/plc/PlcEventTask.java +++ b/shkj-wms/src/main/java/com/shkj/wcs/plc/PlcEventTask.java @@ -8,6 +8,7 @@ import com.shkj.common.constant.RedisConstant; import com.shkj.common.core.domain.Result; import com.shkj.common.enums.BusinessType; import com.shkj.common.utils.DateUtils; +import com.shkj.common.utils.StringUtils; import com.shkj.plc.sdk.device.PlcOperate; import com.shkj.system.service.ISysParameterService; import com.shkj.wcs.bo.AGVFeedbackDepBo; @@ -31,10 +32,7 @@ import com.shkj.wcs.third.workbinWcs.dto.*; import com.shkj.wcs.vo.TaskStatusBody; import com.shkj.wcs.vo.WcsPlcConnectVo; import com.shkj.wcs.vo.WcsResponseVo; -import com.shkj.wms.enums.BusinTaskTypeEnum; -import com.shkj.wms.enums.MapEnum; -import com.shkj.wms.enums.TaskStatusEnum; -import com.shkj.wms.enums.TaskTypeEnum; +import com.shkj.wms.enums.*; import com.shkj.wms.utils.IntIdUtil; import com.shkj.wms.utils.JsonUtil; import com.shkj.wms.vo.PlanOrderLocationVo; @@ -83,7 +81,7 @@ public class PlcEventTask { @Autowired WCSUtil wcsUtil; - @Scheduled(fixedDelay = 2000) + @Scheduled(fixedDelay = 3000) public void init() { //查询需要连接的PLC,初始化连接对象 List plcList = (List) redisTemplate.opsForValue().get(RedisConstant.redisPlcListConnect); @@ -105,7 +103,7 @@ public class PlcEventTask { //输送线心跳 - @Scheduled(fixedDelay = 2000) + @Scheduled(fixedDelay = 3000) public void writePlcheartbeatDps() { PlcOperate plcOperate = plcInit.getPlcOperate_dps(); if (plcOperate != null) { @@ -136,7 +134,7 @@ public class PlcEventTask { } //叠盘机心跳 - @Scheduled(fixedDelay = 2000) + @Scheduled(fixedDelay = 3000) public void writePlcheartbeatStk() { //根据连接的plcId获取属性 PlcOperate plcOperate = plcInit.getPlcOperate_dpj(); @@ -303,6 +301,14 @@ public class PlcEventTask { String retEy = ""; String retEyVt = ""; + //二楼去一楼申请 + String backToOneSeria = ""; + String backToOneSeriaVt = ""; + + //二楼去一楼申请返回 + String retBackToOneSeria = ""; + String retBackToOneSeriaVt = ""; + for (WcsPlcProperty plcProperty : propertyList) { String pointType = plcProperty.getPointType(); @@ -374,8 +380,15 @@ public class PlcEventTask { } else if (pointType.equals("retEy")) { retEy = plcProperty.getAddress(); retEyVt = plcProperty.getValueType(); + } else if (pointType.equals("backToOneSeria")) { + backToOneSeria = plcProperty.getAddress(); + backToOneSeriaVt = plcProperty.getValueType(); + } else if (pointType.equals("retBackToOneSeria")) { + retBackToOneSeria = plcProperty.getAddress(); + retBackToOneSeriaVt = plcProperty.getValueType(); } + } //生产区扫码处入库申请 //&& Boolean.valueOf(pointMap.get(reqInSeria).toString()) @@ -426,26 +439,7 @@ public class PlcEventTask { body.setBussinessType(BusinTaskTypeEnum.stockOut.getValue()); body.setCreateDt(getNowDate()); //调用agv接口查询库区状态 -// Map map1 = new HashMap<>(); -// map1.put("areaInLocation", "SC-A2"); -// map1.put("status", 0); -// -// Map map2 = new HashMap<>(); -// map2.put("areaInLocation", "SC-B2"); -// map2.put("status", 1); -// -// Map map3 = new HashMap<>(); -// map3.put("areaInLocation", "SC-C2"); -// map3.put("status", 1); -// -// Map map4 = new HashMap<>(); -// map4.put("areaInLocation", "SC-D2"); -// map4.put("status", 1); -// -// Object[] areaStatus = new Object[]{map1, map2, map3, map4}; -// log.info("每个库区的状态:" + Arrays.toString(areaStatus)); -// body.setAreaStatus(areaStatus); - log.info("空托申请wz-wcs参数:"+JSONObject.toJSONString(body)); + log.info("空托申请wz-wcs参数:" + JSONObject.toJSONString(body)); WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body); log.info("空托申请wz-wcs返回:" + vo.getHeader()); Map allMap = new HashMap<>(1); @@ -486,7 +480,7 @@ public class PlcEventTask { List orInitializeAreaStatus = iBusinDataTaskService.getOrInitializeAreaStatus(); log.info("每个库区的状态:" + Arrays.toString(orInitializeAreaStatus.toArray())); body.setAreaStatus(orInitializeAreaStatus.toArray()); - log.info("上层实盘出口入库请求wz-wcs参数:"+JSONObject.toJSONString(body)); + log.info("上层实盘出口入库请求wz-wcs参数:" + JSONObject.toJSONString(body)); WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body); log.info("上层实盘出口入库请求wz-wcs返回:" + vo.getHeader()); Map allMap = new HashMap<>(1); @@ -535,7 +529,7 @@ public class PlcEventTask { List orInitializeAreaStatus = iBusinDataTaskService.getOrInitializeAreaStatus(); log.info("每个库区的状态:" + Arrays.toString(orInitializeAreaStatus.toArray())); body.setAreaStatus(orInitializeAreaStatus.toArray()); - log.info("下层实盘出口入库请求wz-wcs参数:"+JSONObject.toJSONString(body)); + log.info("下层实盘出口入库请求wz-wcs参数:" + JSONObject.toJSONString(body)); WcsResponseVo vo = wcsUtil.wcsIncomingTaskRequest(body); log.info("下层实盘出口入库请求wz-wcs返回:" + vo.getHeader()); Map allMap = new HashMap<>(1); @@ -547,7 +541,17 @@ public class PlcEventTask { if (Result.isOk(vo.getHeader().getMsgCode())) { reqMap.put(retOutVt1, 1); } else { - reqMap.put(retOutVt1, 2); + String message = vo.getHeader().getMessage(); + if(message.isEmpty()){ + reqMap.put(retOutVt1, 4); + } + if (message.contains(WmsErrorMessage.error1.getDesc())) { + reqMap.put(retOutVt1, 2); + } else if (message.contains(WmsErrorMessage.error2.getDesc())) { + reqMap.put(retOutVt1, 3); + } else { + reqMap.put(retOutVt1, 4); + } } allMap.put(retOut1, reqMap); String allMapJson = JsonUtil.toJSONString(allMap); @@ -605,55 +609,101 @@ public class PlcEventTask { Map reqMap = new HashMap<>(1); log.info("空托上报完成时,读取的条码内容:" + s); - if(!s.isEmpty()){ - LambdaQueryWrapper lqw = new LambdaQueryWrapper().eq(BusinDataTask::getContainerCode,s) - .eq(BusinDataTask::getTaskStatus,TaskStatusEnum.wait_callback.getValue()); + if (!s.isEmpty()) { + LambdaQueryWrapper lqw = new LambdaQueryWrapper().eq(BusinDataTask::getContainerCode, s) + .eq(BusinDataTask::getTaskStatus, TaskStatusEnum.wait_callback.getValue()); BusinDataTask businDataTask = iBusinDataTaskService.getOne(lqw); - if(businDataTask != null){ - log.info("空托报完成任务号:"+ businDataTask.getTaskCode()); + if (businDataTask != null) { + log.info("空托报完成任务号:" + businDataTask.getTaskCode()); businDataTask.setTaskStatus(TaskStatusEnum.finished.getValue()); businDataTask.setDestination(MapEnum.oneOut.getValue()); businDataTask.setTaskEntime(new Date()); iBusinDataTaskService.updateById(businDataTask); - UploadWCSTaskStatusDto uploadWCSTaskStatusDto = new UploadWCSTaskStatusDto(); - WcsCreateTaskHeader header = new WcsCreateTaskHeader(); - header.setBusinessType("stockOutReturn"); - - uploadWCSTaskStatusDto.setHeader(header); - UploadWCSTaskStatusBody body = new UploadWCSTaskStatusBody(); - List bodyList = new ArrayList<>(); - body.setTaskId(businDataTask.getTaskCode()); - body.setTrayCode(businDataTask.getContainerCode()); - body.setTaskType(businDataTask.getTaskType()); - body.setStatus(businDataTask.getTaskStatus()); - body.setDestination(MapEnum.oneOut.getValue()); - body.setMsgCode("200"); - bodyList.add(body); - uploadWCSTaskStatusDto.setBody(bodyList); - log.info("空托任务状态上报请求zk-wcs参数{}", JSONObject.toJSONString(uploadWCSTaskStatusDto)); - WcsResponseVo vo = wcsUtil.uploadWCSTaskStatus(uploadWCSTaskStatusDto); - log.info("空托任务状态上报反馈:"+ JSONObject.toJSONString(vo)); + WcsResponseVo vo = WcsResponseVo.success(); + if(!businDataTask.getFromSide().equals(MapEnum.twoUpIn.getValue())){ + UploadWCSTaskStatusDto uploadWCSTaskStatusDto = new UploadWCSTaskStatusDto(); + WcsCreateTaskHeader header = new WcsCreateTaskHeader(); + header.setBusinessType("stockOutReturn"); + + uploadWCSTaskStatusDto.setHeader(header); + UploadWCSTaskStatusBody body = new UploadWCSTaskStatusBody(); + List bodyList = new ArrayList<>(); + body.setTaskId(businDataTask.getTaskCode()); + body.setTrayCode(businDataTask.getContainerCode()); + body.setTaskType(businDataTask.getTaskType()); + body.setStatus(businDataTask.getTaskStatus()); + body.setDestination(MapEnum.oneOut.getValue()); + body.setMsgCode("200"); + bodyList.add(body); + uploadWCSTaskStatusDto.setBody(bodyList); + log.info("空托任务状态上报请求zk-wcs参数{}", JSONObject.toJSONString(uploadWCSTaskStatusDto)); + vo = wcsUtil.uploadWCSTaskStatus(uploadWCSTaskStatusDto); + log.info("空托任务状态上报反馈:" + JSONObject.toJSONString(vo)); + } if (Result.isOk(vo.getHeader().getMsgCode())) { reqMap.put(retEyVt, 1); } else { reqMap.put(retEyVt, 2); } - }else{ - log.info("未查询到条码为:"+s+"未完成的任务"); + } else { + log.info("未查询到条码为:" + s + "未完成的任务"); reqMap.put(retEyVt, 2); } - }else{ + } else { reqMap.put(retEyVt, 2); } seriaMap.put(retEyCfmSeriaVt, outSeria); allMap.put(retEy, reqMap); - allMap.put(retEyCfmSeria,seriaMap); + allMap.put(retEyCfmSeria, seriaMap); String allMapJson = JsonUtil.toJSONString(allMap); log.info("空托上报完成时,给输送线写命令数据:{}", allMapJson); Boolean rptOutBoolean = plcReadAndWrite.execWrite(plcOperate, allMapJson); log.info("空托上报完成时,写入的命令返回结果:" + rptOutBoolean.toString()); } + //二楼去一楼 + if (pointMap.containsKey(backToOneSeria) && !pointMap.get(backToOneSeria).equals("0")) { + //读取托盘条码内容 + String barcodeValueOne = Objects.toString(pointMap.get(rptOutBarcod1), ""); + String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", ""); + + log.info("二楼回一楼时,读取的条码内容:" + s); + if (StringUtils.isEmpty(s)) { + handleFailure(retBackToOneSeriaVt, retBackToOneSeria, "条码为空", plcReadAndWrite, plcOperate); + return; + } + BusinDataTask businDataTask = iBusinDataTaskService.getOne(new LambdaQueryWrapper() + .eq(BusinDataTask::getContainerCode, s) + .ne(BusinDataTask::getTaskStatus, TaskStatusEnum.finished.getValue()) + .ne(BusinDataTask::getTaskStatus, TaskStatusEnum.clean.getValue())); + // 如果托盘存在未完成任务 + if (businDataTask != null) { + log.info("此托盘存在未完成任务,本次无需再再次下发:{}", s); + handleFailure(retBackToOneSeriaVt, retBackToOneSeria, "二楼回一楼时,托盘存在为完成任务,无需再次下发", plcReadAndWrite, plcOperate); + return; + } + + BusinDataTask newTask = createNewTask(MapEnum.twoUpIn.getValue(), MapEnum.twoDownIn.getValue()); + newTask.setContainerCode(s); + boolean saveSuccess = iBusinDataTaskService.save(newTask); + if (!saveSuccess) { + log.info("此托盘任务存储失败:{}", s); + handleFailure(retBackToOneSeriaVt, retBackToOneSeria, "二楼回一楼时,任务存储失败!", plcReadAndWrite, plcOperate); + return; + } + + + // 下发任务到RCS + Result result = iBusinDataTaskService.rcsTaskIssued(newTask); + if (!Result.isOk(result)) { + handleFailure(retBackToOneSeriaVt, retBackToOneSeria, "二楼回一楼时,给rcs下发任务失败!", plcReadAndWrite, plcOperate); + return; + } + + // 任务下发成功后的处理 + handleSuccess(newTask, retBackToOneSeriaVt, retBackToOneSeria, plcReadAndWrite, plcOperate); + } + } catch (Exception e) { log.error("dpsRealTimeTask:" + e.getMessage()); } @@ -730,12 +780,12 @@ public class PlcEventTask { } else if (pointType.equals("retDpjCfmSeria")) { retDpjCfmSeria = plcProperty.getAddress(); retDpjCfmSeriaVt = plcProperty.getValueType(); - }else if (pointType.equals("dpjBarcod")) { + } else if (pointType.equals("dpjBarcod")) { dpjBarcod = plcProperty.getAddress(); } else if (pointType.equals("retDpj1")) { retDpj1 = plcProperty.getAddress(); retDpj1Vt = plcProperty.getValueType(); - } else if (pointType.equals("dpjGw1")) { + } else if (pointType.equals("dpjGw1")) { dpjGw1 = plcProperty.getAddress(); } else if (pointType.equals("retDpjGw1")) { retDpjGw1 = plcProperty.getAddress(); @@ -766,7 +816,7 @@ public class PlcEventTask { //读取托盘条码内容 String barcodeValueOne = Objects.toString(pointMap.get(dpjBarcod), ""); String s = barcodeValueOne.replaceAll("[^A-Za-z0-9]", ""); - log.info("叠盘机入库请求读取的条码:"+ s); + log.info("叠盘机入库请求读取的条码:" + s); WcsIncomingTaskRequestBody body = new WcsIncomingTaskRequestBody(); body.setStation(MapEnum.dpj.getValue()); body.setTaskType(TaskTypeEnum.In.getValue()); @@ -784,17 +834,17 @@ public class PlcEventTask { Map reqMap = new HashMap<>(1); Map req1Map = new HashMap<>(1); Map seriaMap = new HashMap<>(1); - seriaMap.put(retDpjCfmSeriaVt,seria); + seriaMap.put(retDpjCfmSeriaVt, seria); if (Result.isOk(vo.getHeader().getMsgCode())) { reqMap.put(retDpjVt, 1); - req1Map.put(retDpj1Vt,1); + req1Map.put(retDpj1Vt, 1); } else { reqMap.put(retDpjVt, 2); - req1Map.put(retDpj1Vt,2); + req1Map.put(retDpj1Vt, 2); } allMap.put(retDpj, reqMap); allMap.put(retDpj1, req1Map); - allMap.put(retDpjCfmSeria,seriaMap); + allMap.put(retDpjCfmSeria, seriaMap); String allMapJson = JsonUtil.toJSONString(allMap); log.info("叠盘机叠满上报时,给输送线写命令数据:{}", allMapJson); Boolean bCR01Boolean = plcReadAndWrite.execWrite(plcOperate, allMapJson); @@ -809,29 +859,35 @@ public class PlcEventTask { // 检查是否有未完成的任务 BusinDataTask businDataTask = checkExistingTask(MapEnum.dpjGw1.getValue()); + if (businDataTask != null) { + + log.info("1号工位已经下发给AGV任务,本次无需再再次下发"); + handleFailure(retDpjGw1Vt, retDpjGw1, "1号工位已经下发给AGV任务,本次无需再再次下发", plcReadAndWrite, plcOperate); + return; + } + + // 如果没有现有任务,创建新任务 - if (businDataTask == null) { - businDataTask = createNewTask(MapEnum.dpjGw1.getValue()); - boolean saveSuccess = iBusinDataTaskService.save(businDataTask); - if (!saveSuccess) { - handleFailure(retDpjGw1Vt, retDpjGw1, "叠盘工位1,任务存储失败!",plcReadAndWrite, plcOperate); - return; - } + BusinDataTask newTask = createNewTask(MapEnum.dpjGw1.getValue(), MapEnum.dpj.getValue()); + boolean saveSuccess = iBusinDataTaskService.save(newTask); + if (!saveSuccess) { + handleFailure(retDpjGw1Vt, retDpjGw1, "叠盘工位1,任务存储失败!", plcReadAndWrite, plcOperate); + return; } // 下发任务到RCS - Result result = iBusinDataTaskService.rcsTaskIssued(businDataTask); + Result result = iBusinDataTaskService.rcsTaskIssued(newTask); if (!Result.isOk(result)) { - handleFailure(retDpjGw1Vt, retDpjGw1, "叠盘工位1,给rcs下发任务失败!",plcReadAndWrite, plcOperate); + handleFailure(retDpjGw1Vt, retDpjGw1, "叠盘工位1,给rcs下发任务失败!", plcReadAndWrite, plcOperate); return; } // 任务下发成功后的处理 - handleSuccess(businDataTask, retDpjGw1Vt, retDpjGw1,plcReadAndWrite, plcOperate); + handleSuccess(newTask, retDpjGw1Vt, retDpjGw1, plcReadAndWrite, plcOperate); } catch (Exception e) { log.error("叠盘工位1处理过程中发生异常", e); - handleFailure(retDpjGw1Vt, retDpjGw1, "叠盘工位1,处理过程中发生异常!",plcReadAndWrite, plcOperate); + handleFailure(retDpjGw1Vt, retDpjGw1, "叠盘工位1,处理过程中发生异常!", plcReadAndWrite, plcOperate); } } @@ -844,29 +900,36 @@ public class PlcEventTask { // 检查是否有未完成的任务 BusinDataTask businDataTask = checkExistingTask(MapEnum.dpjGw2.getValue()); + + if (businDataTask != null) { + + log.info("2号工位已经下发给AGV任务,本次无需再再次下发"); + handleFailure(retDpjGw2Vt, retDpjGw2, "2号工位已经下发给AGV任务,本次无需再再次下发", plcReadAndWrite, plcOperate); + return; + } // 如果没有现有任务,创建新任务 - if (businDataTask == null) { - businDataTask = createNewTask(MapEnum.dpjGw2.getValue()); - boolean saveSuccess = iBusinDataTaskService.save(businDataTask); - if (!saveSuccess) { - handleFailure(retDpjGw2Vt, retDpjGw2, "叠盘工位2,任务存储失败!",plcReadAndWrite, plcOperate); - return; - } + + BusinDataTask newTask = createNewTask(MapEnum.dpjGw2.getValue(), MapEnum.dpj.getValue()); + boolean saveSuccess = iBusinDataTaskService.save(newTask); + if (!saveSuccess) { + handleFailure(retDpjGw2Vt, retDpjGw2, "叠盘工位2,任务存储失败!", plcReadAndWrite, plcOperate); + return; } + // 下发任务到RCS - Result result = iBusinDataTaskService.rcsTaskIssued(businDataTask); + Result result = iBusinDataTaskService.rcsTaskIssued(newTask); if (!Result.isOk(result)) { - handleFailure(retDpjGw2Vt, retDpjGw2, "叠盘工位2,给rcs下发任务失败!",plcReadAndWrite, plcOperate); + handleFailure(retDpjGw2Vt, retDpjGw2, "叠盘工位2,给rcs下发任务失败!", plcReadAndWrite, plcOperate); return; } // 任务下发成功后的处理 - handleSuccess(businDataTask, retDpjGw2Vt, retDpjGw2,plcReadAndWrite, plcOperate); + handleSuccess(newTask, retDpjGw2Vt, retDpjGw2, plcReadAndWrite, plcOperate); } catch (Exception e) { log.error("叠盘工位2处理过程中发生异常", e); - handleFailure(retDpjGw2Vt, retDpjGw2, "叠盘工位2,处理过程中发生异常!",plcReadAndWrite, plcOperate); + handleFailure(retDpjGw2Vt, retDpjGw2, "叠盘工位2,处理过程中发生异常!", plcReadAndWrite, plcOperate); } } @@ -877,30 +940,35 @@ public class PlcEventTask { try { // 检查是否有未完成的任务 BusinDataTask businDataTask = checkExistingTask(MapEnum.dpjGw3.getValue()); + if (businDataTask != null) { + + log.info("3号工位已经下发给AGV任务,本次无需再再次下发"); + handleFailure(retDpjGw3Vt, retDpjGw3, "3号工位已经下发给AGV任务,本次无需再再次下发", plcReadAndWrite, plcOperate); + + return; + } // 如果没有现有任务,创建新任务 - if (businDataTask == null) { - businDataTask = createNewTask(MapEnum.dpjGw3.getValue()); - boolean saveSuccess = iBusinDataTaskService.save(businDataTask); - if (!saveSuccess) { - handleFailure(retDpjGw3Vt, retDpjGw3, "叠盘工位2,任务存储失败!",plcReadAndWrite, plcOperate); - return; - } + BusinDataTask newTask = createNewTask(MapEnum.dpjGw3.getValue(), MapEnum.dpj.getValue()); + boolean saveSuccess = iBusinDataTaskService.save(newTask); + if (!saveSuccess) { + handleFailure(retDpjGw3Vt, retDpjGw3, "叠盘工位3,任务存储失败!", plcReadAndWrite, plcOperate); + return; } // 下发任务到RCS - Result result = iBusinDataTaskService.rcsTaskIssued(businDataTask); + Result result = iBusinDataTaskService.rcsTaskIssued(newTask); if (!Result.isOk(result)) { - handleFailure(retDpjGw3Vt, retDpjGw3, "叠盘工位3,给rcs下发任务失败!",plcReadAndWrite, plcOperate); + handleFailure(retDpjGw3Vt, retDpjGw3, "叠盘工位3,给rcs下发任务失败!", plcReadAndWrite, plcOperate); return; } // 任务下发成功后的处理 - handleSuccess(businDataTask, retDpjGw3Vt, retDpjGw3,plcReadAndWrite, plcOperate); + handleSuccess(newTask, retDpjGw3Vt, retDpjGw3, plcReadAndWrite, plcOperate); } catch (Exception e) { log.error("叠盘工位3处理过程中发生异常", e); - handleFailure(retDpjGw3Vt, retDpjGw3, "叠盘工位3,处理过程中发生异常!",plcReadAndWrite, plcOperate); + handleFailure(retDpjGw3Vt, retDpjGw3, "叠盘工位3,处理过程中发生异常!", plcReadAndWrite, plcOperate); } } @@ -915,7 +983,7 @@ public class PlcEventTask { private BusinDataTask checkExistingTask(String fromSide) { LambdaQueryWrapper lqwTask = new LambdaQueryWrapper() .eq(BusinDataTask::getFromSide, fromSide) - .eq(BusinDataTask::getTaskStatus, TaskStatusEnum.wait_put.getValue()); + .in(BusinDataTask::getTaskStatus, TaskStatusEnum.wait_put.getValue(), TaskStatusEnum.wait_callback.getValue()); BusinDataTask task = iBusinDataTaskService.getOne(lqwTask); if (task != null) { log.info("发现未下发的任务,任务编码:{}", task.getTaskCode()); @@ -923,7 +991,7 @@ public class PlcEventTask { return task; } - private void handleSuccess(BusinDataTask task, String retVt, String ret,PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) { + private void handleSuccess(BusinDataTask task, String retVt, String ret, PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) { // 更新任务状态 task.setTaskStatus(TaskStatusEnum.wait_callback.getValue()); task.setTaskStarttime(DateUtils.getNowDate()); @@ -936,34 +1004,38 @@ public class PlcEventTask { reqMap.put(retVt, 1); allMap.put(ret, reqMap); - sendToPLC(allMap, "叠盘工位1,给rcs下发任务成功!",plcReadAndWrite,plcOperate); + sendToPLC(allMap, "给rcs下发任务成功!", plcReadAndWrite, plcOperate); } - private void sendToPLC(Map allMap, String logMsg,PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) { + private void sendToPLC(Map allMap, String logMsg, PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) { String allMapJson = JsonUtil.toJSONString(allMap); log.info("{} 给输送线写命令数据:{}", logMsg, allMapJson); Boolean writeResult = plcReadAndWrite.execWrite(plcOperate, allMapJson); log.info("写入命令返回结果:{}", writeResult); } - private BusinDataTask createNewTask(String fromSide) { + private BusinDataTask createNewTask(String fromSide, String toSide) { BusinDataTask task = new BusinDataTask(); String taskCode = IntIdUtil.generateIntId().toString(); task.setTaskCode(taskCode); task.setTaskStatus(TaskStatusEnum.wait_put.getValue()); task.setTaskType(TaskTypeEnum.Carry.getValue()); - task.setTaskPath(MapEnum.dpj.getValue()); + task.setTaskPath(toSide); task.setPriority("1"); task.setFromSide(fromSide); - task.setToSide(MapEnum.dpj.getValue()); + task.setToSide(toSide); task.setCreateTime(DateUtils.getNowDate()); - task.setAgvType("B113"); + String agvType = "B113"; + if (fromSide.equals(MapEnum.twoUpIn.getValue())) { + agvType = "B111"; + } + task.setAgvType(agvType); log.info("创建新任务,任务编码:{}", taskCode); return task; } - private void handleFailure(String retVt, String ret, String errorMsg,PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) { + private void handleFailure(String retVt, String ret, String errorMsg, PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) { log.warn(errorMsg); Map allMap = new HashMap<>(); @@ -971,11 +1043,10 @@ public class PlcEventTask { reqMap.put(retVt, 2); allMap.put(ret, reqMap); - sendToPLC(allMap, errorMsg,plcReadAndWrite,plcOperate); + sendToPLC(allMap, errorMsg, plcReadAndWrite, plcOperate); } - public static String getNowDate() { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); return LocalDateTime.now().format(formatter); diff --git a/shkj-wms/src/main/java/com/shkj/wcs/service/impl/BusinDataTaskServiceImpl.java b/shkj-wms/src/main/java/com/shkj/wcs/service/impl/BusinDataTaskServiceImpl.java index 3b243a5..3d7392b 100644 --- a/shkj-wms/src/main/java/com/shkj/wcs/service/impl/BusinDataTaskServiceImpl.java +++ b/shkj-wms/src/main/java/com/shkj/wcs/service/impl/BusinDataTaskServiceImpl.java @@ -123,9 +123,11 @@ public class BusinDataTaskServiceImpl extends ServiceImpl queryWrapper = new LambdaQueryWrapper() .eq(BusinDataTask::getTaskCode, robotTaskCode) - .eq(BusinDataTask::getTaskStatus, TaskStatusEnum.wait_callback.getValue()); + .in(BusinDataTask::getTaskStatus, TaskStatusEnum.wait_callback.getValue(),TaskStatusEnum.wait_put.getValue()); BusinDataTask businDataTask; try { businDataTask = iBusinDataTaskService.getOne(queryWrapper, true); @@ -220,7 +228,7 @@ public class BusinDataTaskServiceImpl extends ServiceImpl { + RetryTemplate retryTemplate = RetryTemplate.builder() + .maxAttempts(3) + .fixedBackoff(10000) + // 覆盖所有可能的网络异常 + .retryOn(ConnectException.class) + .retryOn(HttpServerErrorException.class) // 5xx错误 + .retryOn(SocketTimeoutException.class) // 读写超时 + .retryOn(ResourceAccessException.class) // RestTemplate包装的通用网络异常 + .retryOn(IOException.class) // 底层IO异常 + .build(); + + return retryTemplate.execute(context -> execution.execute(request, body)); + }; + } +} diff --git a/shkj-wms/src/main/java/com/shkj/wcs/third/RetryableHttpUtil.java b/shkj-wms/src/main/java/com/shkj/wcs/third/RetryableHttpUtil.java new file mode 100644 index 0000000..137d67d --- /dev/null +++ b/shkj-wms/src/main/java/com/shkj/wcs/third/RetryableHttpUtil.java @@ -0,0 +1,87 @@ +package com.shkj.wcs.third; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import lombok.extern.slf4j.Slf4j; +import java.net.SocketTimeoutException; +import java.net.ConnectException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.Map; + +@Slf4j +public class RetryableHttpUtil { + + /** + * 仅在超时时重试的POST请求(带请求头) + * @param url 请求地址 + * @param json 请求体JSON + * @param headers 请求头Map + * @param maxRetries 最大重试次数(仅针对超时) + * @param retryIntervalMs 重试间隔(毫秒) + */ + public static String postWithTimeoutRetry(String url, String json, Map headers, + int maxRetries, long retryIntervalMs) throws Exception { + Exception lastException = null; + + for (int i = 0; i < maxRetries; i++) { + try { + HttpRequest request = HttpRequest.post(url) + .body(json) + .timeout(10000); // 设置超时时间(单位毫秒) + + // 添加请求头 + if (headers != null && !headers.isEmpty()) { + for (Map.Entry entry : headers.entrySet()) { + request.header(entry.getKey(), entry.getValue()); + } + } + + HttpResponse response = request.execute(); + + // 非2xx状态码直接抛出(如HTTP 4xx/5xx) + if (!response.isOk()) { + throw new RuntimeException("HTTP " + response.getStatus() + ": " + response.body()); + } + return response.body(); + + } catch (Exception e) { + lastException = e; + + // 仅对以下超时相关异常重试 + boolean isTimeoutError = isTimeoutException(e); + + // 如果不是超时异常,或已达到最大重试次数,则抛出异常 + if (!isTimeoutError || i == maxRetries - 1) { + throw e; + } + + log.warn("超时异常 (尝试 {}/{}), {} 秒后重试. 错误: {}", + i + 1, maxRetries, retryIntervalMs / 1000, e.getMessage()); + + TimeUnit.MILLISECONDS.sleep(retryIntervalMs); + } + } + throw lastException != null ? lastException : new RuntimeException("未知错误"); + } + + /** + * 重载方法:不需要请求头的版本 + */ + public static String postWithTimeoutRetry(String url, String json, + int maxRetries, long retryIntervalMs) throws Exception { + return postWithTimeoutRetry(url, json, null, maxRetries, retryIntervalMs); + } + + /** + * 判断是否为超时异常 + */ + private static boolean isTimeoutException(Exception e) { + return e instanceof SocketTimeoutException // 读写超时 + || e instanceof ConnectException // 连接超时 + || e instanceof TimeoutException // 通用超时 + || (e.getMessage() != null && + (e.getMessage().contains("timeout") || + e.getMessage().contains("timed out"))); + } +} diff --git a/shkj-wms/src/main/java/com/shkj/wcs/third/rcs/RCSUtil.java b/shkj-wms/src/main/java/com/shkj/wcs/third/rcs/RCSUtil.java index 03b57fc..b275a15 100644 --- a/shkj-wms/src/main/java/com/shkj/wcs/third/rcs/RCSUtil.java +++ b/shkj-wms/src/main/java/com/shkj/wcs/third/rcs/RCSUtil.java @@ -14,10 +14,12 @@ import com.shkj.wcs.domain.WcsPlcProperty; import com.shkj.wcs.plc.PlcInit; import com.shkj.wcs.service.IWcsPlcConnectService; import com.shkj.wcs.service.IWcsPlcPropertyService; +import com.shkj.wcs.third.RetryableHttpUtil; import com.shkj.wcs.third.rcs.dto.RcsCancelTaskDto; import com.shkj.wcs.third.rcs.dto.RcsCreateTaskDto; import com.shkj.wcs.third.rcs.dto.RcsIdList; import com.shkj.wcs.third.rcs.dto.RcsThirdResult; +import com.shkj.wcs.vo.WcsResponseVo; import com.shkj.wms.bo.AGVMoveBo; import com.shkj.wcs.mapper.BusinDataTaskMapper; import lombok.extern.slf4j.Slf4j; @@ -95,19 +97,21 @@ public class RCSUtil { */ public Result rcsCreateTask(RcsCreateTaskDto dto) { String json = JSONObject.toJSONString(dto); - log.info("向rcs创建任务参数"+json); + log.info("向rcs创建任务参数{}",json); try { Map headerMap = getHeaderMap(); - String res = HttpRequest.post(agvCreateTaskUrl) - .addHeaders(headerMap) - .body(json) - .execute().body(); - log.info("向rcs创建任务返回:" + res); + String res = RetryableHttpUtil.postWithTimeoutRetry( + agvCreateTaskUrl, + json, + headerMap, + 3, // 最大重试次数 + 10000 // 重试间隔10s + ); + log.info("向rcs创建任务返回:{}",res); return parseThirdRcsResult(res); } catch (Exception e) { - e.printStackTrace(); - log.error("createTask 方法出错了 = {}", e.getMessage()); - return Result.err().msg(e.getMessage()); + log.error("请求最终失败", e); + return Result.err(500, "请求失败: " + e.getMessage()); } } @@ -163,18 +167,20 @@ public class RCSUtil { public Result rcsTaskCancel(RcsCancelTaskDto dto) { String json = JSONObject.toJSONString(dto); log.info("向rcs任务取消参数:" + json); + Map headerMap = getHeaderMap(); try { - Map headerMap = getHeaderMap(); - String res = HttpRequest.post(agvCancelTaskUrl) - .addHeaders(headerMap) - .body(json) - .execute().body(); - log.info("向rcs任务取消返回:" + res); + String res = RetryableHttpUtil.postWithTimeoutRetry( + agvCancelTaskUrl, + json, + headerMap, + 3, // 最大重试次数 + 10000 // 重试间隔10s + ); + log.info("向rcs任务取消返回:{}",res); return parseThirdRcsResult(res); } catch (Exception e) { - e.printStackTrace(); - log.error("rcs taskCancel 方法出错了 = {}", e.getMessage()); - return Result.err().msg(e.getMessage()); + log.error("请求最终失败", e); + return Result.err(500, "请求失败: " + e.getMessage()); } } diff --git a/shkj-wms/src/main/java/com/shkj/wcs/third/workbinWcs/WCSUtil.java b/shkj-wms/src/main/java/com/shkj/wcs/third/workbinWcs/WCSUtil.java index c086e9f..91ca56c 100644 --- a/shkj-wms/src/main/java/com/shkj/wcs/third/workbinWcs/WCSUtil.java +++ b/shkj-wms/src/main/java/com/shkj/wcs/third/workbinWcs/WCSUtil.java @@ -3,6 +3,7 @@ package com.shkj.wcs.third.workbinWcs; import cn.hutool.http.HttpRequest; import com.alibaba.fastjson.JSONObject; +import com.shkj.wcs.third.RetryableHttpUtil; import com.shkj.wcs.third.workbinWcs.dto.*; import com.shkj.wcs.vo.WcsResponseVo; @@ -53,17 +54,19 @@ public class WCSUtil { jsonObject.put("body",queryTaskStatusBodyList); String json = JSONObject.toJSONString(jsonObject); - log.info("KJ向WZ请求是否存在生产区空托出库任务参数"+json); + log.info("KJ向WZ请求是否存在生产区空托出库任务参数{}",json); try { - String res = HttpRequest.post(queryTaskStatusUrl) - .body(json) - .execute().body(); - log.info("KJ向WZ请求是否存在生产区空托出库任务返回:" + res); + String res = RetryableHttpUtil.postWithTimeoutRetry( + queryTaskStatusUrl, + json, + 3, // 最大重试次数 + 10000 // 重试间隔10s + ); + log.info("KJ向WZ请求是否存在生产区空托出库任务返回:{}",res); return parseThirdRcsResult(res); } catch (Exception e) { - e.printStackTrace(); - log.error("KJ向WZ请求是否存在生产区空托出库任务 方法出错了 = {}", e.getMessage()); - return WcsResponseVo.error(500,e.getMessage()); + log.error("请求最终失败", e); + return WcsResponseVo.error(500, "请求失败: " + e.getMessage()); } } @@ -86,15 +89,17 @@ public class WCSUtil { log.info("KJ向WZ请求生产区入库托盘码校验参数"+json); try { - String res = HttpRequest.post(wcsIncomingTrayCheckUrl) - .body(json) - .execute().body(); - log.info("KJ向WZ请求生产区入库托盘码校验返回:" + res); + String res = RetryableHttpUtil.postWithTimeoutRetry( + wcsIncomingTrayCheckUrl, + json, + 3, // 最大重试次数 + 10000 // 重试间隔10秒 + ); + log.info("KJ向WZ请求生产区入库托盘码校验参数返回{}",res); return parseThirdRcsResult(res); } catch (Exception e) { - e.printStackTrace(); - log.error("KJ向WZ请求生产区入库托盘码校验 方法出错了 = {}", e.getMessage()); - return WcsResponseVo.error(500,e.getMessage()); + log.error("请求最终失败", e); + return WcsResponseVo.error(500, "请求失败: " + e.getMessage()); } } @@ -122,15 +127,17 @@ public class WCSUtil { } log.info("KJ向WZ{}申请参数{}",type,json); try { - String res = HttpRequest.post(wcsIncomingTaskRequestUrl) - .body(json) - .execute().body(); + String res = RetryableHttpUtil.postWithTimeoutRetry( + wcsIncomingTaskRequestUrl, + json, + 3, // 最大重试次数 + 10000 // 重试间隔10s + ); log.info("KJ向WZ{}申请返回:{}",type,res); return parseThirdRcsResult(res); } catch (Exception e) { - e.printStackTrace(); - log.error("KJ向WZ{}申请 方法出错了 = {}",type, e.getMessage()); - return WcsResponseVo.error(500,e.getMessage()); + log.error("请求最终失败", e); + return WcsResponseVo.error(500, "请求失败: " + e.getMessage()); } } @@ -147,17 +154,19 @@ public class WCSUtil { jsonObject.put("header",dto.getHeader()); jsonObject.put("body",dto.getBody()); String json = JSONObject.toJSONString(jsonObject); - log.info("KJ向WZ任务上报参数"+json); + log.info("KJ向WZ任务上报参数:{}",json); try { - String res = HttpRequest.post(uploadWCSTaskStatusUrl) - .body(json) - .execute().body(); - log.info("KJ向WZ任务上报返回:" + res); + String res = RetryableHttpUtil.postWithTimeoutRetry( + uploadWCSTaskStatusUrl, + json, + 3, // 最大重试次数 + 10000 // 重试间隔10s + ); + log.info("KJ向WZ任务上报返回:{}",res); return parseThirdRcsResult(res); } catch (Exception e) { - e.printStackTrace(); - log.error("KJ向WZ任务上报 方法出错了 = {}", e.getMessage()); - return WcsResponseVo.error(500,e.getMessage()); + log.error("请求最终失败", e); + return WcsResponseVo.error(500, "请求失败: " + e.getMessage()); } } diff --git a/shkj-wms/src/main/java/com/shkj/wms/enums/MapEnum.java b/shkj-wms/src/main/java/com/shkj/wms/enums/MapEnum.java index efa6d97..db27bdc 100644 --- a/shkj-wms/src/main/java/com/shkj/wms/enums/MapEnum.java +++ b/shkj-wms/src/main/java/com/shkj/wms/enums/MapEnum.java @@ -17,13 +17,13 @@ public enum MapEnum { */ oneOut("SC-G1-00-00-1002", "一楼生产车间出库工作站"), /** - * 二楼连廊入库扫码工作站(上面) + * 二楼连廊入库扫码工作站(下面) */ - twoUpIn("SC-G2-00-00-2001", "二楼连廊入库扫码工作站(上面)"), + twoUpIn("SC-G2-00-00-2001", "二楼连廊入库扫码工作站(下面)"), /** - * 二楼连廊入库扫码工作站(下面) + * 二楼连廊入库扫码工作站(上面) */ - twoDownIn("SC-G2-00-00-2002", "二楼连廊入库扫码工作站(下面)"), + twoDownIn("SC-G2-00-00-2002", "二楼连廊入库扫码工作站(上面)"), /** * 叠盘机工作站 */ diff --git a/shkj-wms/src/main/java/com/shkj/wms/enums/TaskStatusEnum.java b/shkj-wms/src/main/java/com/shkj/wms/enums/TaskStatusEnum.java index 8c244a5..1dbe704 100644 --- a/shkj-wms/src/main/java/com/shkj/wms/enums/TaskStatusEnum.java +++ b/shkj-wms/src/main/java/com/shkj/wms/enums/TaskStatusEnum.java @@ -25,7 +25,7 @@ public enum TaskStatusEnum { */ finished("3", "完成"), - clean("4","已取消"), + clean("6","已取消"), ; private String value; diff --git a/shkj-wms/src/main/java/com/shkj/wms/enums/WmsErrorMessage.java b/shkj-wms/src/main/java/com/shkj/wms/enums/WmsErrorMessage.java new file mode 100644 index 0000000..44a7bc3 --- /dev/null +++ b/shkj-wms/src/main/java/com/shkj/wms/enums/WmsErrorMessage.java @@ -0,0 +1,25 @@ +package com.shkj.wms.enums; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum WmsErrorMessage { + + + /** + * agv任务未下发 + */ + error1("1", "找不到设备任务"), + + /** + * wcs反馈失败 + */ + error2("2", "容器在库或者存在未完成的设备任务") + ; + + private String value; + private String desc; +}