zhang
2025-05-20 1313906bb1eb983d3beece810035e7fc28d6a92f
zy-acs-manager/src/main/java/com/zy/acs/manager/fake/FakeProcessor.java
@@ -7,6 +7,7 @@
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;
@@ -16,14 +17,17 @@
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
@@ -38,10 +42,20 @@
    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
@@ -52,65 +66,111 @@
    private MapService mapService;
    @Autowired
    private JamService jamService;
    @Autowired
    private MainService mainService;
    /**
     * 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
     * 5.
     */
    @Scheduled(cron = "0/1 * * * * ? ")
    public void process() {
        Boolean fakeSign = configService.getVal("fakeSign", Boolean.class);
        if (null == fakeSign || !fakeSign) {
            return;
        }
    @PostConstruct
    public void init() {
        // heartBeat
        this.heartBeatThread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(1000);
        List<Agv> agvList = agvService.list(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, StatusType.ENABLE.val));
        // init executorService
        if (null == this.executorService) {
            int count = agvList.size();
            this.executorService = Executors.newFixedThreadPool(count);
        }
                    if (configService.getVal("fakeSign", Boolean.class)) {
                        this.processOnline();
                    }
        this.responseTheRequest();
        for (Agv agv : agvList) {
            AGV_PROCESSING_MAP.putIfAbsent(agv.getId(), false);
            this.processOnline(agv);
            if (!AGV_PROCESSING_MAP.get(agv.getId())) {
                List<Action> actionList = actionService.queryLatestGroup(agv.getId(), ActionStsType.ISSUED);
                if (!Cools.isEmpty(actionList)) {
                    executorService.submit(new AgvSimulatorTask(
                            agv
                            , redis
                            , agvDetailService
                            , actionService
                            , codeService
                            , mapService
                            , jamService
                            , actionList
                    ));
                } 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(Agv agv) {
        redis.setObject(RedisConstant.AGV_ONLINE_FLAG, agv.getUuid(), 1, 30);
    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) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ignore) {}
            AGV_01_DOWN agv_01_down = (AGV_01_DOWN) protocol.getMessageBody();
            AGV_01_UP agv_01_up = new AGV_01_UP();
@@ -122,4 +182,48 @@
        }
    }
    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();
    }
}