|
@@ -3,6 +3,7 @@ package com.ruoyi.tianao.service.impl;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import cn.hutool.http.HttpRequest;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.github.rholder.retry.*;
|
|
|
import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
|
|
|
import com.ruoyi.ams.agv.ndc.domain.AmsTask;
|
|
|
import com.ruoyi.ams.agv.ndc.entity.CarStatus;
|
|
@@ -14,13 +15,17 @@ import com.ruoyi.ams.task.service.IWcsTaskService;
|
|
|
import com.ruoyi.base.constant.Constant;
|
|
|
import com.ruoyi.base.domain.BaseLocationInfo;
|
|
|
import com.ruoyi.base.domain.CarInfo;
|
|
|
+import com.ruoyi.base.domain.dto.CarInfoBo;
|
|
|
+import com.ruoyi.base.domain.dto.CarInfoDTO;
|
|
|
import com.ruoyi.base.mapper.BaseLocationZoneMapper;
|
|
|
import com.ruoyi.base.service.IBaseLocationInfoService;
|
|
|
import com.ruoyi.base.service.ICarInfoService;
|
|
|
+import com.ruoyi.base.service.impl.CarInfoServiceImpl;
|
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
import com.ruoyi.common.utils.DateUtils;
|
|
|
import com.ruoyi.common.utils.StringUtils;
|
|
|
+import com.ruoyi.system.init.PublishAGVInfo;
|
|
|
import com.ruoyi.system.service.ISysConfigService;
|
|
|
import com.ruoyi.tianao.domian.TianaoTask;
|
|
|
import com.ruoyi.system.init.PlcConnectServiceRunner;
|
|
@@ -30,12 +35,15 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.context.event.EventListener;
|
|
|
import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
+import java.util.concurrent.ExecutionException;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
/**
|
|
@@ -84,24 +92,32 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
private final List<Long> statusLsit = Arrays.asList(2L, 5L, 6L, 7L);
|
|
|
|
|
|
private final List<Long> zoneList = Arrays.asList(10003L, 10005L, 10016L, 10015L);
|
|
|
+
|
|
|
private final List<Long> notInventory = Arrays.asList(10005L, 10016L);
|
|
|
|
|
|
+ private final List<Long> threeAgvTaskZoneList = Arrays.asList(10009L, 10000L);
|
|
|
@Autowired
|
|
|
private RedisCache redisCache;
|
|
|
|
|
|
@Autowired
|
|
|
ICarInfoService iCarInfoService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ PublishAGVInfo publishAGVInfo;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
|
|
|
|
|
@Override
|
|
|
@Transactional
|
|
|
public JSONObject addTask(TianaoTask tianaoTask) {
|
|
|
try {
|
|
|
if (redisCache.checkIsLock(tianaoTask.getLcs_task_id())) {
|
|
|
- List<WcsTask> wcsTaskList = wcsTaskMapper.selectWcsTaskByLcsTaskId(tianaoTask.getLcs_task_id());
|
|
|
- if (ObjectUtil.isNotNull(wcsTaskList) || wcsTaskList.size() > 0) {
|
|
|
- return returnJson("e0001", "任务Id已重复", "fail");
|
|
|
- }
|
|
|
+ return returnJson("e0001", "任务Id已重复", "fail");
|
|
|
+ }
|
|
|
+ List<WcsTask> wcsTaskList = wcsTaskMapper.selectWcsTaskByLcsTaskId(tianaoTask.getLcs_task_id());
|
|
|
+ if (ObjectUtil.isNotNull(wcsTaskList) && wcsTaskList.size() > 0) {
|
|
|
+ return returnJson("e0001", "任务Id已重复", "fail");
|
|
|
}
|
|
|
if (tianaoTask.getFrom_location().equals(tianaoTask.getTo_location())) {
|
|
|
return returnJson("e0001", "起始库位与目标库位不能相同", "fail");
|
|
@@ -122,7 +138,7 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
}
|
|
|
//判断是否需要拆分任务
|
|
|
if (zoneList.contains(formAddress.getZoneId()) || zoneList.contains(toAddress.getZoneId())) {
|
|
|
- WcsTask wcsTask = createWcsTask(tianaoTask, formAddress, toAddress, "0");
|
|
|
+ WcsTask wcsTask = createWcsTask(tianaoTask, formAddress, toAddress, "0", Constant.TASK_TYPE.MOVEFORWARD.getValue());
|
|
|
formAddress.setIsEmpty("N");
|
|
|
iBaseLocationInfoService.updateBaseLocationInfo(formAddress);
|
|
|
if (notInventory.contains(toAddress.getZoneId())) {
|
|
@@ -133,22 +149,45 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
} else {
|
|
|
//拆分任务,获取任务执行的中转区
|
|
|
Long zoneId = null;
|
|
|
+ String oderBy = null;
|
|
|
if (formAddress.getZoneId().equals(10009L) || toAddress.getZoneId().equals(10009L)) {
|
|
|
zoneId = Long.parseLong(iSysConfigService.selectConfigByKey("sys.area.B2"));
|
|
|
- } else {
|
|
|
+ }
|
|
|
+ if (formAddress.getZoneId().equals(10000L) || toAddress.getZoneId().equals(10000L)) {
|
|
|
zoneId = Long.parseLong(iSysConfigService.selectConfigByKey("sys.area.C"));
|
|
|
+ if (toAddress.getColIndex() == 8 || toAddress.getColIndex() == 7) {
|
|
|
+ oderBy = "userdefine3";
|
|
|
+ }
|
|
|
+ if (toAddress.getColIndex() <= 6 && toAddress.getColIndex() >= 3) {
|
|
|
+ oderBy = "userdefine4";
|
|
|
+ }
|
|
|
+ if (toAddress.getColIndex() == 2 || toAddress.getColIndex() == 1) {
|
|
|
+ oderBy = "userdefine5";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (zoneId ==null){
|
|
|
+ return returnJson("e0001", "该任务起始点与目标点不符合出入库任务", "fail");
|
|
|
+ }
|
|
|
+ String taskType1 = null;
|
|
|
+ String taskType2 = null;
|
|
|
+ if (formAddress.getZoneId().equals(10009L) || formAddress.getZoneId().equals(10000L)) {
|
|
|
+ taskType1 = Constant.TASK_TYPE.ThreeWayCar.getValue();
|
|
|
+ taskType2 = Constant.TASK_TYPE.MOVEFORWARD.getValue();
|
|
|
+ } else {
|
|
|
+ taskType1 = Constant.TASK_TYPE.MOVEFORWARD.getValue();
|
|
|
+ taskType2 = Constant.TASK_TYPE.ThreeWayCar.getValue();
|
|
|
}
|
|
|
//选择中转区空库位
|
|
|
BaseLocationInfo baseLocationInfo = new BaseLocationInfo();
|
|
|
baseLocationInfo.setZoneId(zoneId);
|
|
|
baseLocationInfo.setIsEmpty("Y");
|
|
|
- List<BaseLocationInfo> baseLocationInfos = iBaseLocationInfoService.selectSortedLocatinListByZoneIdNoTask(baseLocationInfo);
|
|
|
- if (ObjectUtil.isNull(baseLocationInfos) && baseLocationInfos.size() == 0) {
|
|
|
+ List<BaseLocationInfo> baseLocationInfos = iBaseLocationInfoService.selectSortedLocatinListByZoneIdNoTask(baseLocationInfo, oderBy);
|
|
|
+ if (ObjectUtil.isNull(baseLocationInfos) || baseLocationInfos.size() == 0) {
|
|
|
return returnJson("e0001", "没有合适的中转库位", "fail");
|
|
|
}
|
|
|
- System.out.println(baseLocationInfos.get(0));
|
|
|
- WcsTask wcsTask1 = createWcsTask(tianaoTask, formAddress, baseLocationInfos.get(0), "1");
|
|
|
- WcsTask wcsTask2 = createWcsTask(tianaoTask, baseLocationInfos.get(0), toAddress, "0");
|
|
|
+ WcsTask wcsTask1 = createWcsTask(tianaoTask, formAddress, baseLocationInfos.get(0), "1", taskType1);
|
|
|
+ Thread.sleep(20L);
|
|
|
+ WcsTask wcsTask2 = createWcsTask(tianaoTask, baseLocationInfos.get(0), toAddress, "0", taskType2);
|
|
|
wcsTask2.setParentTask(wcsTask1.getTaskNo());
|
|
|
formAddress.setIsEmpty("N");
|
|
|
iBaseLocationInfoService.updateBaseLocationInfo(formAddress);
|
|
@@ -225,7 +264,7 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
if (ObjectUtil.isNotNull(carNo)) {
|
|
|
//修改AGV任务目标地址
|
|
|
statusUpdateService.confirmAnalysis(wcsTask.getTaskNo(), amsTask.getAciIndex(), carNo
|
|
|
- , "07", baseLocationInfo.getAgvStation().toString());
|
|
|
+ , "09", baseLocationInfo.getAgvStation().toString());
|
|
|
Thread.sleep(1000);
|
|
|
//添加切换导航的对接
|
|
|
// statusUpdateService.changeNavigation(carNo,amsTask.getIkey(),"0001");
|
|
@@ -244,26 +283,59 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
return returnJson("e0001", "任务修改卸货点失败", "fail");
|
|
|
}
|
|
|
|
|
|
-
|
|
|
@EventListener
|
|
|
@Async
|
|
|
- public String getAGVCoordinate(CarStatus car) {
|
|
|
+ public String returnAGVCoordinate(CarInfoDTO car) {
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
JSONObject jsonObject1 = new JSONObject();
|
|
|
- jsonObject1.put("carNo", car.getCarNo());
|
|
|
- jsonObject1.put("y", car.getY());
|
|
|
- jsonObject1.put("x", car.getX());
|
|
|
+ jsonObject1.put("agvNo", car.getUserdefine1());
|
|
|
+ if (!car.getY().equals(0L) || !car.getX().equals(0L)) {
|
|
|
+ jsonObject1.put("x", car.getX());
|
|
|
+ jsonObject1.put("y", car.getY());
|
|
|
+ }
|
|
|
+ jsonObject1.put("status", car.getUserdefine4());
|
|
|
jsonObject1.put("time", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date()));
|
|
|
jsonObject.put("HEADER", jsonObject1);
|
|
|
-// log.info("反馈AGV坐标请求参数:{}", jsonObject);
|
|
|
-// String body = HttpRequest.post(AGVStatusBackUrl)
|
|
|
-// .body(jsonObject.toString())
|
|
|
-// .contentType("application/json").execute().body();
|
|
|
-// log.info("反馈AGV坐标回调结果:{}", body);
|
|
|
-// return body;
|
|
|
- return null;
|
|
|
+ log.info("反馈AGV坐标和状态请求参数:{}", jsonObject);
|
|
|
+ String body = null;
|
|
|
+ try {
|
|
|
+ body = HttpRequest.post(AGVStatusBackUrl)
|
|
|
+ .body(jsonObject.toString())
|
|
|
+ .contentType("application/json").execute().body();
|
|
|
+ }catch (Exception e){
|
|
|
+ log.info("反馈AGV坐标和状态回调失败,msg:{},将进行重试",e);
|
|
|
+ retryCallback(AGVStatusBackUrl,jsonObject);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("反馈AGV坐标和状态回调结果:{}", body);
|
|
|
+ return body;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 异步发送AGV坐标
|
|
|
+ * @param carInfoBo
|
|
|
+ */
|
|
|
+ @EventListener
|
|
|
+ @Async
|
|
|
+ public void returnAGVAddress(CarInfoBo carInfoBo) {
|
|
|
+ if (carInfoBo.getY().equals(0L) || carInfoBo.getX().equals(0L)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ JSONObject jsonObject = new JSONObject();
|
|
|
+ jsonObject.put("agvNo", carInfoBo.getUserdefine1());
|
|
|
+ jsonObject.put("x", carInfoBo.getX());
|
|
|
+ jsonObject.put("y", carInfoBo.getY());
|
|
|
+ jsonObject.put("equType", carInfoBo.getUserdefine3());
|
|
|
+ jsonObject.put("addTime", DateUtils.getTime());
|
|
|
+// log.info("MQTT反馈AGV坐标:{}", jsonObject);
|
|
|
+ publishAGVInfo.publishMessage(jsonObject.toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 异步反馈任务状态
|
|
|
+ * @param wcsTask
|
|
|
+ * @return
|
|
|
+ */
|
|
|
@EventListener
|
|
|
@Async
|
|
|
public String tianaoCallBack(WcsTask wcsTask) {
|
|
@@ -271,6 +343,12 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
if (wcsTask.getState().equals(2L) && "1".equals(wcsTask.getExt5())) {
|
|
|
return null;
|
|
|
}
|
|
|
+ if (StringUtils.isNotEmpty(wcsTask.getParentTask()) && wcsTask.getState().equals(4L)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotEmpty(wcsTask.getParentTask()) && wcsTask.getState().equals(3L)) {
|
|
|
+ wcsTask.setState(4L);
|
|
|
+ }
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
System.out.println(wcsTask.getAgvNo());
|
|
|
if ((ObjectUtil.isNotNull(wcsTask.getAgvNo()) || StringUtils.isNotEmpty(wcsTask.getAgvNo())) && !"null".equals(wcsTask.getAgvNo())) {
|
|
@@ -287,15 +365,28 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
jsonObject.put("task_status", wcsTask.getState());
|
|
|
jsonObject.put("time", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date()));
|
|
|
log.info("反馈任务状态请求参数:{}", jsonObject);
|
|
|
- String body = HttpRequest.post(taskBackUrl)
|
|
|
- .body(jsonObject.toString())
|
|
|
- .contentType("application/json").execute().body();
|
|
|
+ String body = null;
|
|
|
+ try {
|
|
|
+ body = HttpRequest.post(taskBackUrl)
|
|
|
+ .body(jsonObject.toString())
|
|
|
+ .contentType("application/json").execute().body();
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("反馈任务状态失败,msg:{},正进行重试",e);
|
|
|
+ retryCallback(taskBackUrl,jsonObject);
|
|
|
+ }
|
|
|
log.info("反馈任务状态回调结果:{}", body);
|
|
|
return body;
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 反馈格式化
|
|
|
+ * @param code
|
|
|
+ * @param msg
|
|
|
+ * @param state
|
|
|
+ * @return
|
|
|
+ */
|
|
|
@Override
|
|
|
public JSONObject returnJson(String code, String msg, String state) {
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
@@ -305,22 +396,68 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
return jsonObject;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+ /**
|
|
|
+ * 添加普通任务
|
|
|
+ * @param tianaoTask
|
|
|
+ * @return
|
|
|
+ */
|
|
|
@Override
|
|
|
- public String testTask(WcsTask wcsTask) {
|
|
|
- return tianaoCallBack(wcsTask);
|
|
|
+ public JSONObject addOrdinaryTask(TianaoTask tianaoTask) {
|
|
|
+ if (redisCache.checkIsLock(tianaoTask.getLcs_task_id())){
|
|
|
+ return returnJson("e0001", "任务Id已重复", "fail");
|
|
|
+ }
|
|
|
+ List<WcsTask> wcsTaskList = wcsTaskMapper.selectWcsTaskByLcsTaskId(tianaoTask.getLcs_task_id());
|
|
|
+ if (ObjectUtil.isNotNull(wcsTaskList) && wcsTaskList.size() > 0) {
|
|
|
+ return returnJson("e0001", "任务Id已重复", "fail");
|
|
|
+ }
|
|
|
+ if (tianaoTask.getFrom_location().equals(tianaoTask.getTo_location())) {
|
|
|
+ return returnJson("e0001", "起始库位与目标库位不能相同", "fail");
|
|
|
+ }
|
|
|
+ BaseLocationInfo formAddress = iBaseLocationInfoService.selectBaseLocationInfoByIdOrNo(tianaoTask.getFrom_location(), Constant.WAREHOUSE_ID);
|
|
|
+ if (ObjectUtil.isNull(formAddress)) {
|
|
|
+ return returnJson("e0001", "起始位置不存在", "fail");
|
|
|
+ }
|
|
|
+ BaseLocationInfo toAddress = iBaseLocationInfoService.selectBaseLocationInfoByIdOrNo(tianaoTask.getTo_location(), Constant.WAREHOUSE_ID);
|
|
|
+ if (ObjectUtil.isNull(toAddress)) {
|
|
|
+ return returnJson("e0001", "目标位置不存在", "fail");
|
|
|
+ }
|
|
|
+ if (!notInventory.contains(toAddress.getZoneId()) && "N".equals(toAddress.getIsEmpty())) {
|
|
|
+ return returnJson("e0001", "目标位置库存不为空", "fail");
|
|
|
+ }
|
|
|
+ if (formAddress.getZoneId().equals(10004L) || toAddress.getZoneId().equals(10004L)) {
|
|
|
+ return returnJson("e0001", "该库区无法进行任务!", "fail");
|
|
|
+ }
|
|
|
+ WcsTask wcsTask = null;
|
|
|
+ if (threeAgvTaskZoneList.contains(formAddress.getZoneId()) || threeAgvTaskZoneList.contains(toAddress.getZoneId())){
|
|
|
+ wcsTask = createWcsTask(tianaoTask, formAddress, toAddress, "0", Constant.TASK_TYPE.ThreeWayCar.getValue());
|
|
|
+ }else {
|
|
|
+ wcsTask = createWcsTask(tianaoTask, formAddress, toAddress, "0", Constant.TASK_TYPE.MOVEFORWARD.getValue());
|
|
|
+ }
|
|
|
+ if ("Y".equals(formAddress.getIsEmpty())){
|
|
|
+ formAddress.setIsEmpty("N");
|
|
|
+ iBaseLocationInfoService.updateBaseLocationInfo(formAddress);
|
|
|
+ }
|
|
|
+ wcsTaskService.insertWcsTask(wcsTask);
|
|
|
+ redisCache.setCacheObject(tianaoTask.getLcs_task_id(), tianaoTask.getLcs_task_id(), 30, TimeUnit.SECONDS);
|
|
|
+ return returnJson("00000", "任务发起成功", "ok");
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 添加紧急任务
|
|
|
+ * @param tianaoTask
|
|
|
+ * @return
|
|
|
+ */
|
|
|
@Override
|
|
|
- public String testAgvAddress(CarStatus car) {
|
|
|
- return getAGVCoordinate(car);
|
|
|
+ public JSONObject addUrgentTask(TianaoTask tianaoTask) {
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- private WcsTask createWcsTask(TianaoTask tianaoTask, BaseLocationInfo formAddress, BaseLocationInfo toAddress, String frontLoadingOrNot) {
|
|
|
+
|
|
|
+ private WcsTask createWcsTask(TianaoTask tianaoTask, BaseLocationInfo formAddress, BaseLocationInfo toAddress, String frontLoadingOrNot, String taskType) {
|
|
|
WcsTask wcsTask = new WcsTask();
|
|
|
wcsTask.setTaskNo(System.currentTimeMillis() + "");
|
|
|
wcsTask.setState(9L);
|
|
|
- wcsTask.setTaskType(Constant.TASK_TYPE.FORWARD.getValue());
|
|
|
+ wcsTask.setTaskType(taskType);
|
|
|
wcsTask.setBusinessType("01");
|
|
|
wcsTask.setAreaFrom(formAddress.getZoneId().toString());
|
|
|
wcsTask.setLocationFrom(formAddress.getId().toString());
|
|
@@ -336,4 +473,32 @@ public class TianaoServiceImpl implements TianaoService {
|
|
|
wcsTask.setExt6(tianaoTask.getTask_type());
|
|
|
return wcsTask;
|
|
|
}
|
|
|
+
|
|
|
+ private void retryCallback(String url,JSONObject parameter){
|
|
|
+ threadPoolTaskExecutor.execute (() -> {
|
|
|
+ Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
|
|
|
+ .retryIfResult(Boolean.FALSE::equals)
|
|
|
+ .retryIfExceptionOfType(Exception.class)
|
|
|
+ .withStopStrategy(StopStrategies.stopAfterAttempt(5))
|
|
|
+ .withWaitStrategy(WaitStrategies.fixedWait(30, TimeUnit.SECONDS))
|
|
|
+ .build();
|
|
|
+ try {
|
|
|
+ retryer.call(() -> {
|
|
|
+ try {
|
|
|
+ String body = HttpRequest.post(url)
|
|
|
+ .body(parameter.toString())
|
|
|
+ .contentType("application/json").execute().body();
|
|
|
+ log.info("重试回调URL:{},结果:{}",url,body);
|
|
|
+ } catch (Exception e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+ } catch (ExecutionException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ } catch (RetryException e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|