|  |  | 
 |  |  | package com.zy.acs.manager.fake; | 
 |  |  |  | 
 |  |  | import com.zy.acs.common.constant.RedisConstant; | 
 |  |  | import com.zy.acs.common.domain.AgvProtocol; | 
 |  |  | import com.zy.acs.common.domain.protocol.AGV_11_UP; | 
 |  |  | import com.zy.acs.common.enums.AgvCompleteType; | 
 |  |  | import com.zy.acs.common.utils.RedisSupport; | 
 |  |  | import com.zy.acs.manager.core.cache.CoreCache; | 
 |  |  | import com.zy.acs.manager.core.domain.CodeStepDto; | 
 |  |  | import com.zy.acs.manager.core.domain.type.JobType; | 
 |  |  | import com.zy.acs.manager.core.scheduler.MapDataWsScheduler; | 
 |  |  | import com.zy.acs.manager.core.service.MainService; | 
 |  |  | import com.zy.acs.manager.core.service.MapService; | 
 |  |  | import com.zy.acs.manager.manager.entity.Action; | 
 |  |  | import com.zy.acs.manager.manager.entity.Agv; | 
 |  |  | import com.zy.acs.manager.manager.entity.AgvDetail; | 
 |  |  | import com.zy.acs.manager.manager.entity.Code; | 
 |  |  | import com.zy.acs.manager.manager.enums.ActionStsType; | 
 |  |  | import com.zy.acs.manager.manager.enums.ActionTypeType; | 
 |  |  | import com.zy.acs.manager.manager.service.ActionService; | 
 |  |  | import com.zy.acs.manager.manager.service.AgvDetailService; | 
 |  |  | import com.zy.acs.manager.manager.service.CodeService; | 
 |  |  | import com.zy.acs.manager.manager.service.*; | 
 |  |  | import lombok.extern.slf4j.Slf4j; | 
 |  |  |  | 
 |  |  | import java.util.List; | 
 |  |  | 
 |  |  |  | 
 |  |  |     private final Agv agv; | 
 |  |  |     private final AgvDetailService agvDetailService; | 
 |  |  |     private final AgvModelService agvModelService; | 
 |  |  |     private final ActionService actionService; | 
 |  |  |     private final CodeService codeService; | 
 |  |  |     private final MapService mapService; | 
 |  |  |     private final JamService jamService; | 
 |  |  |     private final MainService mainService; | 
 |  |  |     private final List<Action> actionList; | 
 |  |  |  | 
 |  |  |     private final RedisSupport redis; | 
 |  |  | 
 |  |  |             Agv agv | 
 |  |  |             , RedisSupport redis | 
 |  |  |             , AgvDetailService agvDetailService | 
 |  |  |             , AgvModelService agvModelService | 
 |  |  |             , ActionService actionService | 
 |  |  |             , CodeService codeService | 
 |  |  |             , MapService mapService | 
 |  |  |             , JamService jamService | 
 |  |  |             , MainService mainService | 
 |  |  |             , List<Action> actionList | 
 |  |  |     ) { | 
 |  |  |         this.agv = agv; | 
 |  |  |         this.redis = redis; | 
 |  |  |         this.agvDetailService = agvDetailService; | 
 |  |  |         this.agvModelService = agvModelService; | 
 |  |  |         this.actionService = actionService; | 
 |  |  |         this.codeService = codeService; | 
 |  |  |         this.mapService = mapService; | 
 |  |  |         this.jamService = jamService; | 
 |  |  |         this.mainService = mainService; | 
 |  |  |         this.actionList = actionList; | 
 |  |  |  | 
 |  |  |         this.groupId = actionList.get(0).getGroupId(); | 
 |  |  | 
 |  |  |     @Override | 
 |  |  |     public void run() { | 
 |  |  |         try { | 
 |  |  |             FakeProcessor.AGV_PROCESSING_MAP.put(agv.getId(), true); | 
 |  |  |             String qrCode = null; | 
 |  |  |             for (Action action : actionList) { | 
 |  |  |                 processAction(agv, action); | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void processAction(Agv agv, Action action) throws InterruptedException { | 
 |  |  |         AgvDetail agvDetail = agvDetailService.selectByAgvId(agv.getId()); | 
 |  |  |         if (agvDetail == null) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         switch (Objects.requireNonNull(ActionTypeType.get(action.getActionTypeEl()))) { | 
 |  |  |             case TurnCorner: | 
 |  |  |                 simulateRotating(agv, agvDetail, action); | 
 |  |  |                 simulateWalking(agv, action); | 
 |  |  |                 simulateRotating(agv, action); | 
 |  |  |                 break; | 
 |  |  |             case StraightBackUnturnable: | 
 |  |  |             case StraightBackTurnable: | 
 |  |  | 
 |  |  |             case StraightAheadTurnable: | 
 |  |  |             case FinishPath: | 
 |  |  |             case DockingCharge: | 
 |  |  |                 simulateWalking(agv, agvDetail, action); | 
 |  |  |                 simulateWalking(agv, action); | 
 |  |  |                 break; | 
 |  |  |             case ReadyTakeFromShelvesLoc: | 
 |  |  |             case ReadyReleaseToShelvesLoc: | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     private void simulateWalking(Agv agv, AgvDetail agvDetail, Action action) throws InterruptedException { | 
 |  |  |         Code currCode = codeService.getById(agvDetail.getRecentCode()); | 
 |  |  |         Code code = codeService.selectByData(action.getCode()); | 
 |  |  |  | 
 |  |  |         agvDetail.setPos(1); | 
 |  |  |         agvDetail.setCode(code.getId()); | 
 |  |  |  | 
 |  |  |     private void simulateWalking(Agv agv, Action action) throws InterruptedException { | 
 |  |  |         Code code = codeService.getCacheByData(action.getCode()); | 
 |  |  | //        agvDetail.setPos(1); | 
 |  |  | //        agvDetail.setCode(code.getId()); | 
 |  |  |         // 模拟电量消耗 | 
 |  |  | //        agvDetail.setVol(agvDetail.getVol() - 0.1 * distanceToMove); // 根据距离消耗电量 | 
 |  |  |  | 
 |  |  |         agvDetailService.updateById(agvDetail); | 
 |  |  |         Thread.sleep(MapDataWsScheduler.WEBSOCKET_BROADCAST_INTERVAL); | 
 |  |  |  | 
 |  |  |         Thread.sleep(1000); | 
 |  |  |         agvDetailService.updatePosCodeByAgvId(agv.getId(), code.getId()); | 
 |  |  | //        agvDetailService.updateById(agvDetail); | 
 |  |  |  | 
 |  |  |         mapService.unlockPath(agv.getUuid(), code.getData()); | 
 |  |  |         jamService.checkIfFinish(agv.getId(), code.getData()); | 
 |  |  |  | 
 |  |  |         action.setActionSts(ActionStsType.FINISH.val()); | 
 |  |  |         actionService.updateById(action); | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 模拟AGV旋转 | 
 |  |  |      * | 
 |  |  |      * @param agv        当前AGV | 
 |  |  |      * @param agvDetail  AGV详细信息 | 
 |  |  |      * @param action     当前动作 | 
 |  |  |      */ | 
 |  |  |     private void simulateRotating(Agv agv, AgvDetail agvDetail, Action action) throws InterruptedException { | 
 |  |  | //        Double agvAngle = agvDetail.getAgvAngle(); | 
 |  |  | //        double actionAngle = Double.parseDouble(action.getParams()); | 
 |  |  |     private void simulateRotating(Agv agv, Action action) throws InterruptedException { | 
 |  |  |         double actionAngle = Double.parseDouble(action.getParams()); | 
 |  |  | //        agvDetail.setAgvAngle(actionAngle); | 
 |  |  |         // 模拟电量消耗? | 
 |  |  | //        agvDetail.setVol(agvDetail.getVol() - 0.05 * (angleToRotate / 15.0)); // 根据角度消耗电量 | 
 |  |  |  | 
 |  |  |  | 
 |  |  |  | 
 |  |  |         double totalAngle = Double.parseDouble(action.getParams()); // 假设Action有angle属性 | 
 |  |  |         double stepAngle = 45.0; // 每秒旋转15度,具体值根据需求调整 | 
 |  |  |         double actionProgress = 0.0; | 
 |  |  |  | 
 |  |  |         while (actionProgress < totalAngle) { | 
 |  |  |             double angleToRotate = Math.min(stepAngle, totalAngle - actionProgress); | 
 |  |  |             // 更新AGV的角度 | 
 |  |  |             double newAngle = (agvDetail.getAgvAngle() + angleToRotate) % 360; | 
 |  |  |             agvDetail.setAgvAngle(newAngle); | 
 |  |  |  | 
 |  |  |             // 模拟电量消耗 | 
 |  |  | //            agvDetail.setVol(agvDetail.getVol() - 0.05 * (angleToRotate / 15.0)); // 根据角度消耗电量 | 
 |  |  |  | 
 |  |  |             // 更新AGV详细信息 | 
 |  |  |             agvDetailService.updateById(agvDetail); | 
 |  |  |  | 
 |  |  |             // 模拟实际执行时间 | 
 |  |  |             Thread.sleep(1000); // 每秒执行一次 | 
 |  |  |  | 
 |  |  |             actionProgress += angleToRotate; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         // 动作完成,更新状态 | 
 |  |  |         Thread.sleep(MapDataWsScheduler.WEBSOCKET_BROADCAST_INTERVAL); | 
 |  |  |         agvDetailService.updateAngleByAgvId(agv.getId(), actionAngle); | 
 |  |  |         action.setActionSts(ActionStsType.FINISH.val()); | 
 |  |  |         actionService.updateById(action); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     private void finishActionList(String qrCode) { | 
 |  |  |         // 1.complete data | 
 |  |  |         Long agvId = this.agv.getId(); | 
 |  |  |         String agvNo = this.agv.getUuid(); | 
 |  |  |         // 1.show effect | 
 |  |  |         CodeStepDto codeStepDto = CoreCache.AGV_MOCK_STEP_CACHE.get(agvId); | 
 |  |  |         if (null != codeStepDto && qrCode.equals(codeStepDto.getCodeData())) { | 
 |  |  | //            Code currentCode = agvDetailService.getCurrentCode(this.agv.getId()); | 
 |  |  |             try { Thread.sleep(codeStepDto.getJobType().waitTime); } catch (InterruptedException ignore) {} | 
 |  |  |             CoreCache.AGV_MOCK_STEP_CACHE.remove(this.agv.getId()); | 
 |  |  |  | 
 |  |  |             JobType jobType = CoreCache.AGV_MOCK_JOB_CACHE.get(this.agv.getUuid()); | 
 |  |  |             switch (jobType) { | 
 |  |  |                 case LOC_PICK: | 
 |  |  |                     Integer usedSlotsByLocPick = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId); | 
 |  |  |                     usedSlotsByLocPick++; | 
 |  |  |                     CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocPick); | 
 |  |  |  | 
 |  |  |                     if (Objects.equals(agvModelService.getByAgvId(agvId).getBackpack(), usedSlotsByLocPick)) { | 
 |  |  |                         CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.CONVEYOR_DROP); | 
 |  |  |                     } | 
 |  |  |                     break; | 
 |  |  |                 case CONVEYOR_DROP: | 
 |  |  |                     CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, 0); | 
 |  |  |  | 
 |  |  |                     CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.CONVEYOR_PICK); | 
 |  |  |                     break; | 
 |  |  |                 case CONVEYOR_PICK: | 
 |  |  |                     CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, agvModelService.getByAgvId(agvId).getBackpack()); | 
 |  |  |  | 
 |  |  |                     CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOCK_DROP); | 
 |  |  |                     break; | 
 |  |  |                 case LOCK_DROP: | 
 |  |  |                     Integer usedSlotsByLocDrop = CoreCache.AGV_BACKPACK_USED_CACHE.get(agvId); | 
 |  |  |                     usedSlotsByLocDrop--; | 
 |  |  |                     CoreCache.AGV_BACKPACK_USED_CACHE.put(agvId, usedSlotsByLocDrop); | 
 |  |  |  | 
 |  |  |                     if (usedSlotsByLocDrop == 0) { | 
 |  |  |                         CoreCache.AGV_MOCK_JOB_CACHE.put(agvNo, JobType.LOC_PICK); | 
 |  |  |                     } | 
 |  |  |                     break; | 
 |  |  |                 default: | 
 |  |  |                     break; | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         // 2.complete data | 
 |  |  |         AGV_11_UP agv_11_up = new AGV_11_UP(); | 
 |  |  |         agv_11_up.setSerialNo(groupId); | 
 |  |  |         agv_11_up.setCompleteCode(AgvCompleteType.ENTIRE_PATH_COMPLETE.getCode()); | 
 |  |  | 
 |  |  |         agv_11_up.setQrCode(qrCode); | 
 |  |  |  | 
 |  |  |         AgvProtocol agvProtocol = AgvProtocol.build(this.agv.getUuid()).setMessageBody(agv_11_up); | 
 |  |  |         redis.push(RedisConstant.AGV_COMPLETE_FLAG, agvProtocol); | 
 |  |  |         mainService.upDataSubscribe(agvProtocol); | 
 |  |  | //        redis.push(RedisConstant.AGV_COMPLETE_FLAG, agvProtocol); | 
 |  |  |     } | 
 |  |  | } |