| package com.zy.acs.manager.fake; | 
|   | 
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
| import com.zy.acs.common.constant.RedisConstant; | 
| import com.zy.acs.common.domain.AgvProtocol; | 
| import com.zy.acs.common.domain.protocol.AGV_01_DOWN; | 
| import com.zy.acs.common.domain.protocol.AGV_01_UP; | 
| import com.zy.acs.common.utils.RedisSupport; | 
| import com.zy.acs.framework.common.Cools; | 
| 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.enums.ActionStsType; | 
| import com.zy.acs.manager.manager.enums.StatusType; | 
| import com.zy.acs.manager.manager.service.*; | 
| import com.zy.acs.manager.system.service.ConfigService; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.stereotype.Component; | 
|   | 
| import javax.annotation.PostConstruct; | 
| import javax.annotation.PreDestroy; | 
| import java.util.ArrayList; | 
| import java.util.List; | 
| import java.util.Map; | 
| import java.util.concurrent.ConcurrentHashMap; | 
| import java.util.concurrent.ExecutorService; | 
| import java.util.concurrent.Executors; | 
| import java.util.concurrent.TimeUnit; | 
|   | 
| /** | 
|  * Created by vincent on 11/9/2024 | 
|  */ | 
| @Slf4j | 
| @Component | 
| public class FakeProcessor { | 
|   | 
|     private final RedisSupport redis = RedisSupport.defaultRedisSupport; | 
|   | 
|     public static final Map<Long, Boolean> AGV_PROCESSING_MAP = new ConcurrentHashMap<>(); | 
|   | 
|     private ExecutorService executorService; | 
|   | 
|     private List<Agv> agvList = new ArrayList<>(); | 
|   | 
|     private Thread heartBeatThread; | 
|   | 
|     private Thread responseThread; | 
|   | 
|     private Thread simulatorTread; | 
|   | 
|     @Autowired | 
|     private AgvService agvService; | 
|     @Autowired | 
|     private AgvDetailService agvDetailService; | 
|     @Autowired | 
|     private AgvModelService agvModelService; | 
|     @Autowired | 
|     private ActionService actionService; | 
|     @Autowired | 
|     private ConfigService configService; | 
|     @Autowired | 
|     private CodeService codeService; | 
|     @Autowired | 
|     private MapService mapService; | 
|     @Autowired | 
|     private JamService jamService; | 
|     @Autowired | 
|     private MainService mainService; | 
|   | 
|     @PostConstruct | 
|     public void init() { | 
|         // heartBeat | 
|         this.heartBeatThread = new Thread(() -> { | 
|             while (!Thread.currentThread().isInterrupted()) { | 
|                 try { | 
|                     Thread.sleep(1000); | 
|   | 
|                     if (configService.getVal("fakeSign", Boolean.class)) { | 
|                         this.processOnline(); | 
|                     } | 
|   | 
|                 } catch (Exception e) { | 
|                     log.error("FakeProcessor.heartBeatThread fail", e); | 
|                 } | 
|             } | 
|         }); | 
|         this.heartBeatThread.start(); | 
|   | 
|         // response the request | 
|         this.responseThread = new Thread(() -> { | 
|             while (!Thread.currentThread().isInterrupted()) { | 
|                 try { | 
|                     Thread.sleep(5); | 
|   | 
|                     if (configService.getVal("fakeSign", Boolean.class)) { | 
|                         this.responseTheRequest(); | 
|                     } | 
|   | 
|                 } catch (Exception e) { | 
|                     log.error("FakeProcessor.responseThread fail", e); | 
|                 } | 
|             } | 
|         }); | 
|         this.responseThread.start(); | 
|   | 
|         /** | 
|          * 1.AgvDataService.dataProcess [ agvDetail: vol, code, agvAngle, agvStatus ] | 
|          * 2.MainService.upDataSubscribe | 
|          * 3.AgvCmdService.executeRequest {@link com.zy.acs.manager.core.service.AgvCmdService#executeAgvActionCmd} | 
|          * 4.AgvServiceImpl.judgeOnline | 
|          */ | 
|         // Simulator | 
|         this.simulatorTread = new Thread(() -> { | 
|             while (!Thread.currentThread().isInterrupted()) { | 
|                 try { | 
|                     Thread.sleep(30); | 
|   | 
|                     if (configService.getVal("fakeSign", Boolean.class)) { | 
|   | 
|                         List<Agv> agvList = this.getAgvList(); | 
|                         if (null == this.executorService) { | 
|                             int count = agvList.size(); | 
|                             this.executorService = Executors.newFixedThreadPool(count); | 
|                         } | 
|   | 
|                         for (Agv agv : agvList) { | 
|   | 
|                             if (!AGV_PROCESSING_MAP.get(agv.getId())) { | 
|                                 AGV_PROCESSING_MAP.put(agv.getId(), true); | 
|                                 List<Action> actionList = actionService.queryLatestGroup(agv.getId(), ActionStsType.ISSUED); | 
|                                 if (!Cools.isEmpty(actionList)) { | 
|                                     executorService.submit(new AgvSimulatorTask( | 
|                                             agv | 
|                                             , redis | 
|                                             , agvDetailService | 
|                                             , agvModelService | 
|                                             , actionService | 
|                                             , codeService | 
|                                             , mapService | 
|                                             , jamService | 
|                                             , mainService | 
|                                             , actionList | 
|                                     )); | 
|                                 } else { | 
|                                     AGV_PROCESSING_MAP.put(agv.getId(), false); | 
|                                 } | 
|                             } | 
|   | 
|                         } | 
|   | 
|                     } else { | 
|                         this.shutdownFakeThreads(); | 
|                     } | 
|   | 
|                 } catch (Exception e) { | 
|                     log.error("FakeProcessor.simulatorTread fail", e); | 
|                 } | 
|             } | 
|         }); | 
|         this.simulatorTread.start(); | 
|     } | 
|   | 
|     private void processOnline() { | 
|         for (Agv agv : this.getAgvList()) { | 
|             redis.setObject(RedisConstant.AGV_ONLINE_FLAG, agv.getUuid(), 1, 30); | 
|         } | 
|     } | 
|   | 
|     private void responseTheRequest() { | 
|         AgvProtocol protocol = redis.pop(RedisConstant.AGV_PATH_DOWN_FLAG); | 
|         if (null != protocol) { | 
|             AGV_01_DOWN agv_01_down = (AGV_01_DOWN) protocol.getMessageBody(); | 
|   | 
|             AGV_01_UP agv_01_up = new AGV_01_UP(); | 
|             agv_01_up.setSerialNo(agv_01_down.getSerialNo()); | 
|   | 
|             redis.setObject(RedisConstant.AGV_PATH_UP_FLAG | 
|                     , protocol.getAgvNo() + "_" + agv_01_up.getSerialNo() | 
|                     , agv_01_up); | 
|         } | 
|     } | 
|   | 
|     public List<Agv> getAgvList() { | 
|         if (Cools.isEmpty(this.agvList)) { | 
|             this.agvList = agvService.list(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, StatusType.ENABLE.val)); | 
|             this.agvList.forEach(agv -> {AGV_PROCESSING_MAP.putIfAbsent(agv.getId(), false);}); | 
|         } | 
|         return this.agvList; | 
|     } | 
|   | 
|     public void shutdownFakeThreads() { | 
|         if (this.executorService != null && !this.executorService.isShutdown()) { | 
|             this.executorService.shutdown(); | 
|             try { | 
|                 if (!this.executorService.awaitTermination(60, TimeUnit.SECONDS)) { | 
|                     this.executorService.shutdownNow(); | 
|                 } | 
|             } catch (InterruptedException e) { | 
|                 this.executorService.shutdownNow(); | 
|                 Thread.currentThread().interrupt(); | 
|             } | 
|             this.executorService = null; // 释放资源 | 
|         } | 
|         if (!Cools.isEmpty(this.agvList)) { | 
|             agvList = new ArrayList<>(); | 
|         } | 
|         if (!AGV_PROCESSING_MAP.isEmpty()) { | 
|             AGV_PROCESSING_MAP.clear(); | 
|         } | 
|     } | 
|   | 
|     @PreDestroy | 
|     public void shutDown(){ | 
|         if (this.heartBeatThread != null) { | 
|             this.heartBeatThread .interrupt(); | 
|         } | 
|         if (this.responseThread != null) { | 
|             this.responseThread .interrupt(); | 
|         } | 
|         if (this.simulatorTread != null) { | 
|             this.simulatorTread.interrupt(); | 
|         } | 
|         this.shutdownFakeThreads(); | 
|     } | 
|   | 
|   | 
| } |