修改提交

main
shensy 5 months ago
parent dc5f716d9b
commit 9765bf5f81
  1. 2
      shkj-admin/src/main/java/com/shkj/ShkjApplication.java
  2. 3
      shkj-admin/src/main/resources/application.yml
  3. 2
      shkj-admin/src/main/resources/logback.xml
  4. 10
      shkj-common/src/main/java/com/shkj/common/core/domain/Result.java
  5. 287
      shkj-wms/src/main/java/com/shkj/wcs/plc/PlcEventTask.java
  6. 44
      shkj-wms/src/main/java/com/shkj/wcs/service/impl/BusinDataTaskServiceImpl.java
  7. 49
      shkj-wms/src/main/java/com/shkj/wcs/third/RetryConfig.java
  8. 87
      shkj-wms/src/main/java/com/shkj/wcs/third/RetryableHttpUtil.java
  9. 42
      shkj-wms/src/main/java/com/shkj/wcs/third/rcs/RCSUtil.java
  10. 67
      shkj-wms/src/main/java/com/shkj/wcs/third/workbinWcs/WCSUtil.java
  11. 8
      shkj-wms/src/main/java/com/shkj/wms/enums/MapEnum.java
  12. 2
      shkj-wms/src/main/java/com/shkj/wms/enums/TaskStatusEnum.java
  13. 25
      shkj-wms/src/main/java/com/shkj/wms/enums/WmsErrorMessage.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");

@ -90,8 +90,7 @@ token:
# 令牌有效期(默认30分钟)-- 修改为720分钟=12个小时
expireTime: 720
## MyBatis配置
#mybatis:
#mybatis:
# # 搜索指定包别名
# typeAliasesPackage: com.shkj.**.domain
# # 配置mapper的扫描,找到所有的mapper.xml映射文件

@ -55,7 +55,7 @@
<maxFileSize>1MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
<maxHistory>40</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">

@ -52,6 +52,12 @@ public class Result<T> 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<T> 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());
}

@ -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<WcsPlcConnectVo> plcList = (List<WcsPlcConnectVo>) 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<String, Object> map1 = new HashMap<>();
// map1.put("areaInLocation", "SC-A2");
// map1.put("status", 0);
//
// Map<String, Object> map2 = new HashMap<>();
// map2.put("areaInLocation", "SC-B2");
// map2.put("status", 1);
//
// Map<String, Object> map3 = new HashMap<>();
// map3.put("areaInLocation", "SC-C2");
// map3.put("status", 1);
//
// Map<String, Object> 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<String, Object> allMap = new HashMap<>(1);
@ -486,7 +480,7 @@ public class PlcEventTask {
List<AGVFeedbackDepBo> 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<String, Object> allMap = new HashMap<>(1);
@ -535,7 +529,7 @@ public class PlcEventTask {
List<AGVFeedbackDepBo> 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<String, Object> 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<String, Integer> reqMap = new HashMap<>(1);
log.info("空托上报完成时,读取的条码内容:" + s);
if(!s.isEmpty()){
LambdaQueryWrapper<BusinDataTask> lqw = new LambdaQueryWrapper<BusinDataTask>().eq(BusinDataTask::getContainerCode,s)
.eq(BusinDataTask::getTaskStatus,TaskStatusEnum.wait_callback.getValue());
if (!s.isEmpty()) {
LambdaQueryWrapper<BusinDataTask> lqw = new LambdaQueryWrapper<BusinDataTask>().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<UploadWCSTaskStatusBody> 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<UploadWCSTaskStatusBody> 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<BusinDataTask>()
.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<String, Integer> reqMap = new HashMap<>(1);
Map<String, Integer> req1Map = new HashMap<>(1);
Map<String, Integer> 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<BusinDataTask> lqwTask = new LambdaQueryWrapper<BusinDataTask>()
.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<String, Object> allMap, String logMsg,PLCReadAndWrite plcReadAndWrite, PlcOperate plcOperate) {
private void sendToPLC(Map<String, Object> 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<String, Object> 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);

@ -123,9 +123,11 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B
log.info("任务储存成功!");
Result result = rcsTaskIssued(businDataTask);
if (!Result.isOk(result)) {
String msg = result.getMsg();
businDataTask.setExceptionMsg(WayEnum.agv_task_put.getValue());
businDataTask.setTaskStatus(TaskStatusEnum.clean.getValue());
iBusinDataTaskService.updateById(businDataTask);
return WcsResponseVo.error(200, "接受成功但给rcs下发任务失败");
return WcsResponseVo.error(500, "KJ-WCS接受成功,AGV:"+msg);
}
businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
businDataTask.setTaskStarttime(DateUtils.getNowDate());
@ -146,15 +148,18 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B
}
//推送给下游
if(one.getTaskStatus().equals(TaskStatusEnum.wait_callback.getValue())){
RcsCancelTaskDto rcsCancelTaskDto = new RcsCancelTaskDto();
rcsCancelTaskDto.setRobotTaskCode(taskId);
rcsCancelTaskDto.setCancelType("cancel");
rcsCancelTaskDto.setReason("上游取消");
Result result = rcsUtil.rcsTaskCancel(rcsCancelTaskDto);
if (!Result.isOk(result)) {
one.setExceptionMsg(WayEnum.agv_task_cancel.getValue());
return WcsResponseVo.error(500, "给rcs取消任务失败");
if(!one.getAgvTaskStatus().equals("end")){
if(one.getTaskStatus().equals(TaskStatusEnum.wait_callback.getValue())){
RcsCancelTaskDto rcsCancelTaskDto = new RcsCancelTaskDto();
rcsCancelTaskDto.setRobotTaskCode(taskId);
rcsCancelTaskDto.setCancelType("cancel");
rcsCancelTaskDto.setReason("上游取消");
Result result = rcsUtil.rcsTaskCancel(rcsCancelTaskDto);
if (!Result.isOk(result)) {
String msg = result.getMsg();
one.setExceptionMsg(WayEnum.agv_task_cancel.getValue());
return WcsResponseVo.error(500, "KJ-WCS取消任务成功,AGV:"+msg);
}
}
}
one.setTaskStatus(TaskStatusEnum.clean.getValue());
@ -176,13 +181,16 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B
ExtraData.Values values = bo.getExtra().getValues();
String carrierCode = values.getCarrierCode();
String method = values.getMethod();
String slotName = values.getSlotName();
if (slotName.equals("0187000XY0234215")) {
slotName = "SC-G2-00-00-43022";
String slotName =null;
if(!method.equals("cancel")){
slotName = values.getSlotName();
if (slotName.equals("0187000XY0234215")) {
slotName = "SC-G2-00-00-43022";
}
}
LambdaQueryWrapper<BusinDataTask> queryWrapper = new LambdaQueryWrapper<BusinDataTask>()
.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<BusinDataTaskMapper, B
break;
case "cancel":
businDataTask.setTaskStatus(TaskStatusEnum.clean.getValue());
businDataTask.setDestination(slotName);
businDataTask.setDestination(businDataTask.getFromSide());
break;
default:
return RcsResponseVo.error("任务状态未知!");
@ -231,8 +239,12 @@ public class BusinDataTaskServiceImpl extends ServiceImpl<BusinDataTaskMapper, B
return RcsResponseVo.error("总任务状态更新失败");
}
log.info("总任务状态更新成功,任务号:{}", robotTaskCode);
if(!method.equals("start")){
if(!method.equals("start") && !businDataTask.getToSide().equals(MapEnum.dpj.getValue())){
RcsResponseVo rcsResponseVo = wcsFeedbackTask(businDataTask);
if(rcsResponseVo.getCode().equals("ERROR")){
businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
iBusinDataTaskService.updateById(businDataTask);
}
return rcsResponseVo;
}
}

@ -0,0 +1,49 @@
package com.shkj.wcs.third;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Collections;
import java.util.concurrent.TimeoutException;
@Configuration
public class RetryConfig {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000); // 连接超时5秒
factory.setReadTimeout(10000); // 读取超时10秒
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setInterceptors(Collections.singletonList(retryInterceptor()));
return restTemplate;
}
@Bean
public ClientHttpRequestInterceptor retryInterceptor() {
return (request, body, execution) -> {
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));
};
}
}

@ -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<String, String> 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<String, String> 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")));
}
}

@ -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<String, String> 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<String, String> headerMap = getHeaderMap();
try {
Map<String, String> 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());
}
}

@ -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());
}
}

@ -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", "二楼连廊入库扫码工作站(面)"),
/**
* 叠盘机工作站
*/

@ -25,7 +25,7 @@ public enum TaskStatusEnum {
*/
finished("3", "完成"),
clean("4","已取消"),
clean("6","已取消"),
;
private String value;

@ -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;
}
Loading…
Cancel
Save