| package com.zy.acs.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.fake.entity.Action; | 
| import com.zy.acs.fake.entity.Agv; | 
| import com.zy.acs.fake.entity.AgvDetail; | 
| import com.zy.acs.fake.entity.Code; | 
| import com.zy.acs.fake.enums.ActionStsType; | 
| import com.zy.acs.fake.enums.ActionTypeType; | 
| import com.zy.acs.fake.service.*; | 
| import lombok.extern.slf4j.Slf4j; | 
|   | 
| import java.util.List; | 
| import java.util.Objects; | 
|   | 
| /** | 
|  * Created by vincent on 11/11/2024 | 
|  */ | 
| @Slf4j | 
| public class AgvSimulatorTask implements Runnable { | 
|   | 
|     public static final int WEBSOCKET_BROADCAST_INTERVAL = 200; | 
|   | 
|     private final Agv agv; | 
|     private final AgvDetailService agvDetailService; | 
|     private final ActionService actionService; | 
|     private final CodeService codeService; | 
|     private final MapService mapService; | 
|     private final JamService jamService; | 
|     private final List<Action> actionList; | 
|   | 
|     private final RedisSupport redis; | 
|   | 
|     private final String groupId; | 
|   | 
|     public AgvSimulatorTask( | 
|             Agv agv | 
|             , RedisSupport redis | 
|             , AgvDetailService agvDetailService | 
|             , ActionService actionService | 
|             , CodeService codeService | 
|             , MapService mapService | 
|             , JamService jamService | 
|             , List<Action> actionList | 
|     ) { | 
|         this.agv = agv; | 
|         this.redis = redis; | 
|         this.agvDetailService = agvDetailService; | 
|         this.actionService = actionService; | 
|         this.codeService = codeService; | 
|         this.mapService = mapService; | 
|         this.jamService = jamService; | 
|         this.actionList = actionList; | 
|   | 
|         this.groupId = actionList.get(0).getGroupId(); | 
|     } | 
|   | 
|     @Override | 
|     public void run() { | 
|         try { | 
|             String qrCode = null; | 
|             for (Action action : actionList) { | 
|                 processAction(agv, action); | 
|                 qrCode = action.getCode(); | 
|             } | 
|             this.finishActionList(qrCode); | 
|         } catch (Exception e) { | 
|             log.error("AgvSimulatorTask AGV[{}]", agv.getUuid(), e); | 
|         } finally { | 
|             FakeProcessor.AGV_PROCESSING_MAP.put(agv.getId(), false); | 
|         } | 
|     } | 
|   | 
|     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: | 
|                 simulateWalking(agv, agvDetail, action); | 
|                 simulateRotating(agv, agvDetail, action); | 
|                 break; | 
|             case StraightBackUnturnable: | 
|             case StraightBackTurnable: | 
|             case StraightAheadUnturnable: | 
|             case StraightAheadTurnable: | 
|             case FinishPath: | 
|             case DockingCharge: | 
|                 simulateWalking(agv, agvDetail, action); | 
|                 break; | 
|             case ReadyTakeFromShelvesLoc: | 
|             case ReadyReleaseToShelvesLoc: | 
|                 break; | 
|             default: | 
|                 log.warn("Unknown action type {} for AGV ID {}.", action.getActionType(), agv.getId()); | 
|                 break; | 
|         } | 
|     } | 
|   | 
|   | 
|     private void simulateWalking(Agv agv, AgvDetail agvDetail, Action action) throws InterruptedException { | 
|         Code code = codeService.selectByData(action.getCode()); | 
|         agvDetail.setPos(1); | 
|         agvDetail.setCode(code.getId()); | 
|         // 模拟电量消耗 | 
| //        agvDetail.setVol(agvDetail.getVol() - 0.1 * distanceToMove); // 根据距离消耗电量 | 
|   | 
|         Thread.sleep(WEBSOCKET_BROADCAST_INTERVAL); | 
|   | 
|         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 actionAngle = Double.parseDouble(action.getParams()); | 
|         agvDetail.setAgvAngle(actionAngle); | 
|         // 模拟电量消耗? | 
| //        agvDetail.setVol(agvDetail.getVol() - 0.05 * (angleToRotate / 15.0)); // 根据角度消耗电量 | 
|   | 
|         Thread.sleep(WEBSOCKET_BROADCAST_INTERVAL); | 
|         agvDetailService.updateById(agvDetail); | 
|         action.setActionSts(ActionStsType.FINISH.val()); | 
|         actionService.updateById(action); | 
|     } | 
|   | 
|     private void finishActionList(String qrCode) { | 
|         // 1.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.setCompleteType(AgvCompleteType.ENTIRE_PATH_COMPLETE); | 
|         agv_11_up.setQrCode(qrCode); | 
|   | 
|         AgvProtocol agvProtocol = AgvProtocol.build(this.agv.getUuid()).setMessageBody(agv_11_up); | 
|         redis.push(RedisConstant.AGV_COMPLETE_FLAG, agvProtocol); | 
|     } | 
| } |