|
|
@@ -0,0 +1,368 @@
|
|
|
+package com.ktg.mes.rms.thread;
|
|
|
+
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.ktg.common.constant.UserConstants;
|
|
|
+import com.ktg.common.utils.StringUtils;
|
|
|
+import com.ktg.common.utils.spring.SpringUtils;
|
|
|
+import com.ktg.mes.rms.domain.*;
|
|
|
+import com.ktg.mes.rms.emcsenum.DeviceTypeEnum;
|
|
|
+import com.ktg.mes.rms.emcsenum.RmsStatusEnum;
|
|
|
+import com.ktg.mes.rms.emcsenum.SiteTypeEnum;
|
|
|
+import com.ktg.mes.rms.emcsenum.TaskTypeEnum;
|
|
|
+import com.ktg.mes.rms.server.RmsWebSocketServer;
|
|
|
+import com.ktg.mes.rms.service.IRmsTaskOutstockLineService;
|
|
|
+import com.ktg.mes.rms.service.impl.RmsTaskOutstockLineServiceImpl;
|
|
|
+import com.ktg.mes.rms.task.ApiStockTask;
|
|
|
+import com.ktg.mes.rms.util.ApiCache;
|
|
|
+import com.ktg.mes.rms.util.RailHelper;
|
|
|
+import com.ktg.mes.wm.domain.WmRmsBox;
|
|
|
+import com.ktg.mes.wm.domain.WmRmsBoxItem;
|
|
|
+import com.ktg.mes.wm.domain.WmStorageArea;
|
|
|
+import com.ktg.mes.wm.domain.WmStorageLocation;
|
|
|
+import com.ktg.mes.wm.service.IWmRmsBoxItemService;
|
|
|
+import com.ktg.mes.wm.service.IWmRmsBoxService;
|
|
|
+import com.ktg.mes.wm.service.IWmStorageAreaService;
|
|
|
+import com.ktg.mes.wm.service.IWmStorageLocationService;
|
|
|
+import com.ktg.mes.wm.service.impl.WmRmsBoxItemServiceImpl;
|
|
|
+import com.ktg.mes.wm.service.impl.WmRmsBoxServiceImpl;
|
|
|
+import com.ktg.mes.wm.utils.MaterialStockTaskHelper;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.transaction.TransactionStatus;
|
|
|
+import org.springframework.transaction.support.DefaultTransactionDefinition;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+public class RailAgvThread extends BaseThread{
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(RailAgvThread.class);
|
|
|
+ private enum AgvStatus {RUN, DONE, CANCEL, ARRIVER}
|
|
|
+
|
|
|
+ private volatile RmsTaskPool rmsTaskPool;
|
|
|
+ private final RailHelper railHelper = RailHelper.getInstance(true);
|
|
|
+ private final IWmRmsBoxService wmRmsBoxService;
|
|
|
+ private final int waitAgvTime = 600;
|
|
|
+
|
|
|
+ private final IRmsTaskOutstockLineService rmsTaskOutstockLineService;
|
|
|
+
|
|
|
+ public RailAgvThread(RmsTaskPool rmsTaskPool){
|
|
|
+ super();
|
|
|
+ this.rmsTaskPool = rmsTaskPool;
|
|
|
+ wmRmsBoxService = SpringUtils.getBean(WmRmsBoxServiceImpl.class);
|
|
|
+ rmsTaskOutstockLineService = SpringUtils.getBean(RmsTaskOutstockLineServiceImpl.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void run(){
|
|
|
+ try{
|
|
|
+ log.info("=========收到轨道AGV任务:"+rmsTaskPool.getTaskId()+"=========");
|
|
|
+ rmsTaskPoolService.startGroupTask(rmsTaskPool);
|
|
|
+ updateRemark(null,1, 1, "开始"+rmsTaskPool.getTaskName());
|
|
|
+ if(rmsTaskPool.getRunDelay()!=null && rmsTaskPool.getRunDelay() > 0){
|
|
|
+ System.out.println("=========延迟"+rmsTaskPool.getRunDelay()+"秒执行=========");
|
|
|
+ Thread.sleep(rmsTaskPool.getRunDelay()*1000);
|
|
|
+ }
|
|
|
+ String robotType = "";
|
|
|
+ Long deviceType = Long.parseLong(rmsTaskPool.getDeviceType());
|
|
|
+ if(deviceType.equals(DeviceTypeEnum.RAILAGV.getValue())){
|
|
|
+ robotType = DeviceTypeEnum.RAILAGV.getKey();
|
|
|
+ }
|
|
|
+ String robotId = "";
|
|
|
+ RmsTaskPool bindPool = getBindTask();
|
|
|
+ if(StringUtils.isNotEmpty(bindPool.getLiftCode())){
|
|
|
+ robotId = bindPool.getLiftCode();
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotEmpty(rmsTaskPool.getLiftCode())){
|
|
|
+ robotId = rmsTaskPool.getLiftCode();
|
|
|
+ }
|
|
|
+ String taskType = rmsTaskPool.getTaskType();
|
|
|
+ String data = railHelper.sendAgvTask(rmsTaskPool.getFromSite(), rmsTaskPool.getToSite()
|
|
|
+ , rmsTaskPool.getPickTime(), rmsTaskPool.getKeyRoute(), taskType
|
|
|
+ , robotType, robotId);
|
|
|
+ JSONObject dataJson = JSONUtil.toBean(data, JSONObject.class);
|
|
|
+ String rmsRemoteTaskId = dataJson.getStr("id");
|
|
|
+ if(StringUtils.isNotEmpty(rmsRemoteTaskId)){
|
|
|
+ if(rmsTaskPool.getIsWait() == 0){
|
|
|
+ updateRemark(rmsRemoteTaskId, 1, 3, rmsTaskPool.getTaskName()+"任务已发送");
|
|
|
+ }else{
|
|
|
+ updateRemark(rmsRemoteTaskId, 1, 3, rmsTaskPool.getTaskName()+"任务已发送,等待中");
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ throw new Exception("AGV任务请求失败");
|
|
|
+ }
|
|
|
+ boolean isRunDone = true;
|
|
|
+ if(TaskTypeEnum.X2B_ROLLER_BACK_UP.getValue().equals(rmsTaskPool.getTaskType())
|
|
|
+ ||TaskTypeEnum.X2B_ROLLER_BACK_DOWN.getValue().equals(rmsTaskPool.getTaskType())){
|
|
|
+ isRunDone = waitAgv(rmsRemoteTaskId);
|
|
|
+ }else{
|
|
|
+ if(rmsTaskPool.getIsWait() != 0){ //不是出入库,不滚动,判断等待用wait
|
|
|
+ log.info("开始AGV等待任务完成");
|
|
|
+ isRunDone = waitAgv(rmsRemoteTaskId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!isRunDone){
|
|
|
+ log.info("任务被取消,结束线程");
|
|
|
+ cancleOrder();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ waitByTask();
|
|
|
+ if(StringUtils.isNotNull(rmsRemoteTaskId)){
|
|
|
+ updateOrder();
|
|
|
+ updateRemark(null,2, 2, "成功");
|
|
|
+ checkNextTask();
|
|
|
+ }
|
|
|
+ rmsTaskPoolService.closeAutoGroupTask(rmsTaskPool);
|
|
|
+ }catch (Exception ex){
|
|
|
+ log.error("AGV异常:" + JSONUtil.toJsonStr(rmsTaskPool), ex);
|
|
|
+ updateLog(rmsTaskPool, ex.getMessage());
|
|
|
+ rmsTaskPoolService.cancelAgvTaskGroup(rmsTaskPool);
|
|
|
+ cancleOrder();
|
|
|
+ }finally {
|
|
|
+ this.rmsTaskPool = null;
|
|
|
+ ApiStockTask.runRailAgvThread.remove(this);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateOrder() throws Exception {
|
|
|
+ DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
|
|
+ definition.setPropagationBehaviorName("PROPAGATION_REQUIRED");
|
|
|
+ TransactionStatus transaction = transactionManager.getTransaction(definition);
|
|
|
+ try {
|
|
|
+ Long deviceType = Long.parseLong(rmsTaskPool.getDeviceType());
|
|
|
+ if(deviceType.equals(DeviceTypeEnum.RAILAGV.getValue())){
|
|
|
+ if(rmsTaskPool.getWaitType() != null && rmsTaskPool.getWaitType() == 2){
|
|
|
+ //清除料框的标注和是否扫码标识
|
|
|
+ String boxCode = rmsTaskPool.getBoxCode();
|
|
|
+ Long lineId = rmsTaskPool.getSourceId();
|
|
|
+ if(StringUtils.isNotEmpty(boxCode)){
|
|
|
+ WmRmsBox wmRmsBox = wmRmsBoxService.selectWmRmsBoxByBoxCode(boxCode);
|
|
|
+ if(wmRmsBox != null && wmRmsBox.getWaitType() != null && wmRmsBox.getWaitType() == 2){
|
|
|
+ //线边库搬运任务。
|
|
|
+ //更新出库明细lineId的状态和库存
|
|
|
+ rmsTaskPoolService.updateXbMoveStock(rmsTaskPool);
|
|
|
+ // 重置isScan和lineIds
|
|
|
+ wmRmsBox.setIsScan("-1");
|
|
|
+ if(StringUtils.isNotEmpty(wmRmsBox.getLineIds())){
|
|
|
+ String lineIds = wmRmsBox.getLineIds();
|
|
|
+ String[] lineIdArray = lineIds.split(",");
|
|
|
+ StringBuilder newLineIds = new StringBuilder();
|
|
|
+ for (String id : lineIdArray) {
|
|
|
+ if (!id.equals(String.valueOf(lineId))) {
|
|
|
+ if (newLineIds.length() > 0) {
|
|
|
+ newLineIds.append(",");
|
|
|
+ }
|
|
|
+ newLineIds.append(id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotEmpty(newLineIds.toString())){
|
|
|
+ wmRmsBox.setLineIds(newLineIds.toString());
|
|
|
+ }else{
|
|
|
+ wmRmsBox.setWaitType(-1);
|
|
|
+ wmRmsBox.setLineIds("-1");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //搬运结束料框加入出库单信息
|
|
|
+ wmRmsBox.setItemOutCode(rmsTaskPool.getSourceType());
|
|
|
+ wmRmsBoxService.updateWmRmsBox2(wmRmsBox);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ transactionManager.commit(transaction);
|
|
|
+ } catch (Exception e) {
|
|
|
+ transactionManager.rollback(transaction);
|
|
|
+ throw e;
|
|
|
+ } finally {
|
|
|
+ if (!transaction.isCompleted()) {
|
|
|
+ transactionManager.commit(transaction);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public RmsTaskPool getBindTask(){
|
|
|
+ RmsTaskPool pool = new RmsTaskPool();
|
|
|
+ pool.setGroupCode(rmsTaskPool.getGroupCode());
|
|
|
+ pool.setFlowLineId(rmsTaskPool.getBindTask());
|
|
|
+ List<RmsTaskPool> poolList = rmsTaskPoolService.selectRmsTaskPoolList(pool);
|
|
|
+ if(poolList.size() > 0){
|
|
|
+ pool = poolList.get(0);
|
|
|
+ }
|
|
|
+ return pool;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void checkNextTask() throws Exception {
|
|
|
+ List<RmsTaskPool> nextTaskPools = rmsTaskPoolService.getTaskPoolByParent(rmsTaskPool.getTaskId());
|
|
|
+ if(nextTaskPools.size() > 0) {
|
|
|
+ log.info("插入新任务:" + nextTaskPools.size());
|
|
|
+ nextTaskPools.forEach(item->{
|
|
|
+ if(item.getTaskType().equals(TaskTypeEnum.PUSH.getValue())){
|
|
|
+ item.setIsSort(1);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ ApiCache.addPriorityList(nextTaskPools);
|
|
|
+ log.info("插入新任务完成");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean waitAgv(String rmsRemoteTaskId) throws Exception {
|
|
|
+ boolean isStop = false;
|
|
|
+ long runTime = new Date().getTime();
|
|
|
+ while (!isStop){
|
|
|
+ AgvStatus agvStatus = checkRmsStock(rmsRemoteTaskId);
|
|
|
+ if(agvStatus.equals(AgvStatus.CANCEL)){
|
|
|
+ throw new Exception("AGV异常,取消任务");
|
|
|
+ }
|
|
|
+ if(agvStatus.equals(AgvStatus.DONE)){
|
|
|
+ isStop = true;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ RmsTaskPool pool = rmsTaskPoolService.selectRmsTaskPoolByTaskId(rmsTaskPool.getTaskId());
|
|
|
+ if ("4".equals(pool.getTaskStatus())) {
|
|
|
+ railHelper.cancelAgvTask(rmsTaskPool.getRmsTaskId());
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }catch (Exception ex){
|
|
|
+ log.error("查工单状态错误:["+rmsTaskPool.getTaskId()+"]" + ex.getMessage());
|
|
|
+ }
|
|
|
+ long longTime = (new Date().getTime() - runTime)/1000;
|
|
|
+ if(longTime > waitAgvTime){
|
|
|
+ throw new Exception("等待AGV任务完成超时");
|
|
|
+ }
|
|
|
+ sleep(1000);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AgvStatus checkRmsStock(String rmsTaskId) throws Exception {
|
|
|
+ if(StringUtils.isEmpty(rmsTaskId)){
|
|
|
+ throw new Exception("没有找到AGV执行的任务ID");
|
|
|
+ }
|
|
|
+ if(StringUtils.isEmpty(railHelper.session)){
|
|
|
+ railHelper.init();
|
|
|
+ }
|
|
|
+// updateLiftCode(robotId, rmsTaskId);
|
|
|
+ return RailAgvThread.AgvStatus.DONE;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateLiftCode(String robotId, String rmsTaskId){
|
|
|
+ if(!StringUtils.isEmpty(robotId)
|
|
|
+ && StringUtils.isEmpty(rmsTaskPool.getLiftCode())){
|
|
|
+ rmsTaskPool.setLiftCode(robotId);
|
|
|
+ RmsTaskPool pool = new RmsTaskPool();
|
|
|
+ pool.setTaskId(rmsTaskPool.getTaskId());
|
|
|
+ pool.setLiftCode(robotId);
|
|
|
+ pool.setRmsTaskId(rmsTaskId);
|
|
|
+ pool.setRemark("获取AGV编号");
|
|
|
+ rmsTaskPoolService.updateRmsTaskPoolMapper(pool);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateRemark(String rmsTaskId, Integer status, int step, String remark) throws Exception {
|
|
|
+ rmsTaskPool.setStep(step);
|
|
|
+ rmsTaskPool.setTaskStatus(status+"");
|
|
|
+ rmsTaskPool.setRmsTaskId(rmsTaskId);
|
|
|
+ rmsTaskPoolService.updateMastPoolRemark(rmsTaskPool, remark);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void waitByTask() throws Exception {
|
|
|
+ Integer isWait = rmsTaskPool.getIsWait();
|
|
|
+ if(isWait==null){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String waitTaskId = rmsTaskPool.getWaitTask();
|
|
|
+ if(StringUtils.isEmpty(rmsTaskPool.getGroupCode())){
|
|
|
+ throw new Exception("任务组编号不存在");
|
|
|
+ }
|
|
|
+ if(isWait == 3 && StringUtils.isNotEmpty(waitTaskId)){
|
|
|
+ String[] taskIds = waitTaskId.split(",");
|
|
|
+ boolean isUpdate = false;
|
|
|
+ for(String taskId:taskIds){
|
|
|
+ boolean isStop = false;
|
|
|
+ while (!isStop){
|
|
|
+ RmsTaskPool p = new RmsTaskPool();
|
|
|
+ p.setGroupCode(rmsTaskPool.getGroupCode());
|
|
|
+ p.setFlowLineId(Long.parseLong(taskId));
|
|
|
+ List<RmsTaskPool> poolList = rmsTaskPoolService.selectRmsTaskPoolList(p);
|
|
|
+ if(poolList.size() > 0){
|
|
|
+ p = poolList.get(0);
|
|
|
+ }else{
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(!("0".equals(p.getTaskStatus()) ||"1".equals(p.getTaskStatus()))){
|
|
|
+ isStop = true;
|
|
|
+ }
|
|
|
+ if(!isUpdate){
|
|
|
+ updateRemark(null,1, 3, "正在等待"+p.getTaskName()+"任务结束");
|
|
|
+ isUpdate = true;
|
|
|
+ }
|
|
|
+ sleep(1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public RmsTaskPool getRmsTaskPool() {
|
|
|
+ return rmsTaskPool;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void cancleOrder(){
|
|
|
+ Long deviceType = Long.parseLong(rmsTaskPool.getDeviceType());
|
|
|
+ if(deviceType.equals(DeviceTypeEnum.ROLLERAGV.getValue())){
|
|
|
+ if(rmsTaskPool.getWaitType() != null && rmsTaskPool.getWaitType() == 2){
|
|
|
+ //清除料框的标注和是否扫码标识
|
|
|
+ String boxCode = rmsTaskPool.getBoxCode();
|
|
|
+ Long lineId = rmsTaskPool.getSourceId();
|
|
|
+ if(StringUtils.isNotEmpty(boxCode)){
|
|
|
+ WmRmsBox wmRmsBox = wmRmsBoxService.selectWmRmsBoxByBoxCode(boxCode);
|
|
|
+ if(wmRmsBox != null && wmRmsBox.getWaitType() != null && wmRmsBox.getWaitType() == 2){
|
|
|
+ //线边库搬运任务。
|
|
|
+ wmRmsBox.setIsScan("-1");
|
|
|
+ if(StringUtils.isNotEmpty(wmRmsBox.getLineIds()) && lineId != null){
|
|
|
+ String lineIds = wmRmsBox.getLineIds();
|
|
|
+ String[] lineIdArray = lineIds.split(",");
|
|
|
+ StringBuilder newLineIds = new StringBuilder();
|
|
|
+ for (String id : lineIdArray) {
|
|
|
+ if (!id.equals(String.valueOf(lineId))) {
|
|
|
+ if (newLineIds.length() > 0) {
|
|
|
+ newLineIds.append(",");
|
|
|
+ }
|
|
|
+ newLineIds.append(id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(StringUtils.isNotEmpty(newLineIds.toString())){
|
|
|
+ wmRmsBox.setLineIds(newLineIds.toString());
|
|
|
+ }else{
|
|
|
+ wmRmsBox.setWaitType(-1);
|
|
|
+ wmRmsBox.setLineIds("-1");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ wmRmsBoxService.updateWmRmsBox2(wmRmsBox);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(lineId != null){
|
|
|
+ RmsTaskOutstockLine rmsTaskOutstockLine = new RmsTaskOutstockLine();
|
|
|
+ rmsTaskOutstockLine.setLineId(lineId);
|
|
|
+ rmsTaskOutstockLine.setBoxCode("-1");
|
|
|
+ rmsTaskOutstockLine.setDeviceCode("-1");
|
|
|
+ rmsTaskOutstockLine.setLiftCode("-1");
|
|
|
+ rmsTaskOutstockLineService.updateRmsTaskOutstockLine(rmsTaskOutstockLine);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean checkDoneOutStockLine(Long inStockId){
|
|
|
+ RmsTaskOutstockLine outStockLine = new RmsTaskOutstockLine();
|
|
|
+ outStockLine.setOutstockId(inStockId);
|
|
|
+ List<RmsTaskOutstockLine> rmsTaskOutStockLines = rmsTaskOutstockLineService.selectRmsTaskOutstockLineList(outStockLine);
|
|
|
+ return rmsTaskOutStockLines.stream().noneMatch(item->item.getStatus()!=2);
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean checkDoneInStockLine(Long inStockId){
|
|
|
+ RmsTaskInstockLine inStockLine = new RmsTaskInstockLine();
|
|
|
+ inStockLine.setInstockId(inStockId);
|
|
|
+ List<RmsTaskInstockLine> rmsTaskInstockLines = rmsTaskInstockLineService.selectRmsTaskInstockLineList(inStockLine);
|
|
|
+ return rmsTaskInstockLines.stream().noneMatch(item->item.getStatus()!=2);
|
|
|
+ }
|
|
|
+}
|