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.scheduling.annotation.Scheduled; 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 AGV_PROCESSING_MAP = new ConcurrentHashMap<>(); private ExecutorService executorService; private List agvList = new ArrayList<>(); private Thread heartBeatThread; private Thread responseThread; private Thread simulatorTread; @Autowired private AgvService agvService; @Autowired private AgvDetailService agvDetailService; @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(30); 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 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())) { List actionList = actionService.queryLatestGroup(agv.getId(), ActionStsType.ISSUED); if (!Cools.isEmpty(actionList)) { AGV_PROCESSING_MAP.put(agv.getId(), true); executorService.submit(new AgvSimulatorTask( agv , redis , agvDetailService , actionService , codeService , mapService , jamService , mainService , actionList )); } } } } 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 getAgvList() { if (Cools.isEmpty(this.agvList)) { this.agvList = agvService.list(new LambdaQueryWrapper().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(); } }