package com.zy.acs.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.fake.entity.Action; 
 | 
import com.zy.acs.fake.entity.Agv; 
 | 
import com.zy.acs.fake.enums.ActionStsType; 
 | 
import com.zy.acs.fake.service.*; 
 | 
import com.zy.acs.framework.common.Cools; 
 | 
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<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 ActionService actionService; 
 | 
    @Autowired 
 | 
    private ConfigService configService; 
 | 
    @Autowired 
 | 
    private CodeService codeService; 
 | 
    @Autowired 
 | 
    private MapService mapService; 
 | 
    @Autowired 
 | 
    private JamService jamService; 
 | 
  
 | 
    @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<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())) { 
 | 
                                List<Action> 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 
 | 
                                            , 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<Agv> getAgvList() { 
 | 
        if (Cools.isEmpty(this.agvList)) { 
 | 
            this.agvList = agvService.list(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, 1)); 
 | 
            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(); 
 | 
    } 
 | 
  
 | 
} 
 |