From e14f937fac9ba2c9af1fffd4d37f0eba86292575 Mon Sep 17 00:00:00 2001
From: luxiaotao1123 <t1341870251@163.com>
Date: 星期二, 07 一月 2025 13:22:35 +0800
Subject: [PATCH] #

---
 zy-acs-flow/src/map/constants.js                                                       |    2 
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java       |    7 
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java    |  220 +++++++++++++++++++++++++++++++
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java |    2 
 zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java          |   10 +
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java               |   46 ++++++
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java        |   20 ++
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java           |   61 +-------
 8 files changed, 311 insertions(+), 57 deletions(-)

diff --git a/zy-acs-flow/src/map/constants.js b/zy-acs-flow/src/map/constants.js
index d7d46c0..8ab6ce1 100644
--- a/zy-acs-flow/src/map/constants.js
+++ b/zy-acs-flow/src/map/constants.js
@@ -1,5 +1,5 @@
 
-export const ANIMATE_DURING_TIME = 800;
+export const ANIMATE_DURING_TIME = 600;
 
 export const MAP_DEFAULT_ROTATION = 270;
 
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java
index ed02249..d64f963 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/common/config/BeanConfig.java
@@ -1,7 +1,11 @@
 package com.zy.acs.manager.common.config;
 
+import com.zy.acs.manager.core.domain.UnlockPathTask;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.LinkedBlockingQueue;
 
 /**
  * Created by vincent on 12/19/2023
@@ -9,4 +13,10 @@
 @Configuration
 @ComponentScan(value = "com.zy.acs.common.config")
 public class BeanConfig {
+
+    @Bean
+    public LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue() {
+        return new LinkedBlockingQueue<>();
+    }
+
 }
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java
index f525f3f..2369fee 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/DemoController.java
@@ -69,6 +69,52 @@
         return R.ok("RCS-FLOW-1.0.0");
     }
 
+    // {"msg":"Success","code":200,"data":[[38,2],[38,3],[38,4],[38,5],[38,6],[37,6],[36,6],[35,6],[34,6],[33,6],[32,6],[31,6],[30,6],[29,6],[28,6],[27,6],[26,6],[25,6]]}
+    // {"msg":"Success","code":200,"data":[[38,2],[38,3],[38,4],[38,5],[38,6],[37,6],[36,6],[35,6],[34,6],[33,6],[32,6],[31,6],[30,6],[29,6],[28,6],[27,6],[26,6],[25,6]]}
+    @RequestMapping(value = "/system/demo", method = {RequestMethod.GET, RequestMethod.POST})
+    public R demo() {
+        long startTime = System.currentTimeMillis();
+        for (int i = 0; i < 1000; i++) {
+            this.demo1();
+        }
+        System.out.println(System.currentTimeMillis() - startTime);
+        return R.ok();
+    }
+
+    private R demo1() {
+        List<String> path = new ArrayList<>();
+        path.add("00000035");
+        path.add("00000085");
+        path.add("00000135");
+        path.add("00000185");
+        path.add("00000235");
+        path.add("00000234");
+        path.add("00000233");
+        path.add("00000232");
+        path.add("00000231");
+        path.add("00000230");
+        path.add("00000229");
+        path.add("00000228");
+        path.add("00000227");
+        path.add("00000226");
+        path.add("00000225");
+        path.add("00000224");
+        path.add("00000223");
+        path.add("00000222");
+
+//        List<int[]> codeMatrixIdxList = new ArrayList<>();
+//        for (String pathStr : path) {
+//            int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(null, pathStr);
+//            codeMatrixIdxList.add(codeMatrixIdx);
+//        }
+
+        List<int[]> codeMatrixIdxList = mapDataDispatcher.getCodeMatrixIdxList(null, path);
+
+//        System.out.println(codeMatrixIdxList.toString());
+
+        return R.ok().add(codeMatrixIdxList);
+    }
+
 //    @RequestMapping(value = "/system/route/generate", method = {RequestMethod.GET, RequestMethod.POST})
 //    public R generate() {
 //        String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null);
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java
new file mode 100644
index 0000000..229cefe
--- /dev/null
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/domain/UnlockPathTask.java
@@ -0,0 +1,20 @@
+package com.zy.acs.manager.core.domain;
+
+import lombok.Data;
+
+@Data
+public class UnlockPathTask {
+
+    private String agvNo;
+
+    private String codeData;
+
+    public UnlockPathTask() {
+    }
+
+    public UnlockPathTask(String agvNo, String codeData) {
+        this.agvNo = agvNo;
+        this.codeData = codeData;
+    }
+
+}
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java
index c0d5448..5b5f82b 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/scheduler/MapDataWsScheduler.java
@@ -33,7 +33,7 @@
 @Component
 public class MapDataWsScheduler {
 
-    public static final int WEBSOCKET_BROADCAST_INTERVAL = 800;
+    public static final int WEBSOCKET_BROADCAST_INTERVAL = 600;
 
     private ExecutorService singleThreadExecutor;
 
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java
index 4918fd8..452befc 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/AgvDataService.java
@@ -84,9 +84,10 @@
             AGV_12_UP agv_12_up = (AGV_12_UP) msgBody;
 
             // unlock path
-            threadPoolRegulator.getInstance().execute(() -> {
-                mapService.unlockPath(protocol.getAgvNo(), agv_12_up.getQrCode());
-            });
+            mapService.unlockPath(protocol.getAgvNo(), agv_12_up.getQrCode());
+//            threadPoolRegulator.getInstance().execute(() -> {
+//
+//            });
             // finish jam
             threadPoolRegulator.getInstance().execute(() -> jamService.checkIfFinish(agvId, agv_12_up.getQrCode()));
 
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
index 11f942d..976c8e0 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/MapService.java
@@ -5,9 +5,9 @@
 import com.zy.acs.framework.common.Cools;
 import com.zy.acs.manager.common.utils.MapDataUtils;
 import com.zy.acs.manager.core.constant.MapDataConstant;
+import com.zy.acs.manager.core.domain.UnlockPathTask;
 import com.zy.acs.manager.core.service.astart.*;
 import com.zy.acs.manager.core.service.astart.domain.AStarNavigateNode;
-import com.zy.acs.manager.core.service.astart.domain.DynamicNode;
 import com.zy.acs.manager.core.service.floyd.FloydNavigateService;
 import com.zy.acs.manager.manager.entity.Code;
 import com.zy.acs.manager.manager.entity.Loc;
@@ -16,12 +16,13 @@
 import com.zy.acs.manager.manager.service.CodeService;
 import com.zy.acs.manager.system.service.ConfigService;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.time.StopWatch;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
 import java.util.*;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -45,6 +46,8 @@
     private ConfigService configService;
     @Autowired
     private ActionService actionService;
+    @Autowired
+    private LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue;
 
     /**
      * 瀵诲潃 ===>> A Star
@@ -177,58 +180,12 @@
         mapDataDispatcher.modifyDynamicMatrix(lev, codeMatrixIdxList, agvNo);
     }
 
-    public synchronized void unlockPath(String agvNo, String codeData) {
+    public void unlockPath(String agvNo, String codeData) {
         try {
-            StopWatch stopWatch = new StopWatch();
-            stopWatch.start();
-
-            if (Cools.isEmpty(agvNo, codeData)) {
-                return;
-            }
-
-            Integer lev = null;
-
-            String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(null);
-            int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, codeData);
-
-
-            DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev);
-
-            DynamicNode dynamicNode = dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]];
-
-
-            int serial = dynamicNode.getSerial();
-
-            List<int[]> resetCodeIdxList = new ArrayList<>();
-
-            for (int i = 0; i < dynamicMatrix.length; i++) {
-                for (int j = 0; j < dynamicMatrix[i].length; j++) {
-
-//                    if (i == codeMatrixIdx[0] && j == codeMatrixIdx[1]) { continue; }
-
-                    DynamicNode node = dynamicMatrix[i][j];
-                    if (node.getVehicle().equals(agvNo)) {
-                        if (node.getSerial() < serial) {
-                            resetCodeIdxList.add(new int[] {i, j});
-                        }
-                    }
-                }
-            }
-
-            if (!Cools.isEmpty(resetCodeIdxList)) {
-
-                mapDataDispatcher.clearDynamicMatrixByCodeList(lev, resetCodeIdxList);
-            }
-
-            stopWatch.stop();
-            if (stopWatch.getTime() > 50) {
-                log.info("瑙i攣璺緞鍑芥暟鑺辫垂鏃堕棿涓猴細{}姣......", stopWatch.getTime());
-            }
-
-        } catch (Exception e) {
-            log.error("MapService.unlockPath", e);
+            unlockTaskQueue.offer(new UnlockPathTask(agvNo, codeData), 5, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            log.error("unlockTaskQueue", e);
         }
-
     }
 
     public List<String> getWaveScopeByCodeList(Integer lev, List<String> codeList, Double radiusLen) {
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java
new file mode 100644
index 0000000..8d38600
--- /dev/null
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/PathQueueConsumer.java
@@ -0,0 +1,220 @@
+package com.zy.acs.manager.core.service;
+
+import com.zy.acs.framework.common.Cools;
+import com.zy.acs.manager.core.domain.UnlockPathTask;
+import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
+import com.zy.acs.manager.core.service.astart.domain.DynamicNode;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class PathQueueConsumer {
+
+    private ExecutorService consumerExecutor;
+
+    @Autowired
+    private LinkedBlockingQueue<UnlockPathTask> unlockTaskQueue;
+    @Autowired
+    private MapDataDispatcher mapDataDispatcher;
+
+    @PostConstruct
+    public void init() {
+        Integer lev = MapDataDispatcher.MAP_DEFAULT_LEV;
+
+        this.consumerExecutor = Executors.newSingleThreadExecutor();
+        this.consumerExecutor.execute(() -> {
+            while (!Thread.currentThread().isInterrupted()) {
+                try {
+
+                    List<UnlockPathTask> tasks = new ArrayList<>();
+                    // if unlockTaskQueue was empty, then block
+//                    tasks.add(unlockTaskQueue.take());
+                    unlockTaskQueue.drainTo(tasks);
+
+                    if (tasks.isEmpty()) {
+                        Thread.sleep(30);
+                    } else {
+
+                        long startTime = System.currentTimeMillis();
+
+                        List<int[]> resetCodeIdxList = null;
+                        if (tasks.size() == 1) {
+                            resetCodeIdxList = this.getResetCodeList(lev, tasks.get(0));
+                        } else if (tasks.size() > 1) {
+                            log.info("consumer task count:{}", tasks.size());
+                            resetCodeIdxList = this.getResetCodeList(lev,tasks);
+                        }
+
+                        if (!Cools.isEmpty(resetCodeIdxList)) {
+                            this.dealResetCodeList(lev, resetCodeIdxList);
+                        }
+
+                        log.info("consumer unlock path spend time:{}", System.currentTimeMillis() - startTime);
+                    }
+
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    log.error("PathQueueConsumer[Thread.currentThread.interrupt]", e);
+                    break;
+                } catch (Exception e) {
+                    log.error("PathQueueConsumer", e);
+                }
+            }
+        });
+    }
+
+    private List<int[]> getResetCodeList(Integer lev, List<UnlockPathTask> tasks) {
+        if (Cools.isEmpty(tasks)) {
+            return new ArrayList<>();
+        }
+
+        // 1.鏁寸悊棰勫鐞嗘暟鎹�
+        String[][] codeMatrix = mapDataDispatcher.getCodeMatrix(lev);
+        DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev);
+
+//        Set<String> codeDataSet = tasks.stream().map(UnlockPathTask::getCodeData).collect(Collectors.toSet());
+        Set<String> agvNoSet = tasks.stream().map(UnlockPathTask::getAgvNo).collect(Collectors.toSet());
+
+        Map<String, Set<String>> agvNoCodeDataMap = new HashMap<>();
+        tasks.forEach(task -> agvNoCodeDataMap.computeIfAbsent(task.getAgvNo(), k -> new HashSet<>()).add(task.getCodeData()));
+
+
+        // 2.鑾峰彇agv鐨勬墍鏈塪ynamic node锛屽苟涓旇褰昦gv褰撳墠鐨刣ynamic node serial
+
+        // agvNo : List<{code, serial}>
+        Map<String, List<CodeSerial>> codeSerialMap = new HashMap<>();
+        // agvNo : serial
+        Map<String, Integer> agvNoSerialMap = new HashMap<>();
+
+
+        for (int i = 0; i < dynamicMatrix.length; i++) {
+            for (int j = 0; j < dynamicMatrix[i].length; j++) {
+                DynamicNode dynamicNode = dynamicMatrix[i][j];
+
+                if (agvNoSet.contains(dynamicNode.getVehicle())) {
+
+                    String codeData = codeMatrix[i][j];
+                    String vehicle = dynamicNode.getVehicle();
+                    int serial = dynamicNode.getSerial();
+
+                    List<CodeSerial> codeSerials = codeSerialMap.computeIfAbsent(vehicle, k -> new ArrayList<>());
+                    codeSerials.add(new CodeSerial(new int[] {i, j}, serial));
+
+                    if (agvNoCodeDataMap.get(vehicle).contains(codeData)) {
+                        Integer agvNoSerial = agvNoSerialMap.get(vehicle);
+                        if (null == agvNoSerial) {
+                            agvNoSerialMap.put(vehicle, serial);
+                        } else {
+                            if (serial > agvNoSerial) {
+                                agvNoSerialMap.put(vehicle, serial);
+                            }
+                        }
+
+                    }
+
+                }
+
+            }
+        }
+
+        // 3.澶勭悊codeSerialMap锛岃幏鍙栨墍鏈塧gv闇�瑕侀噴鏀剧殑code matrix list
+
+        List<int[]> resetCodeIdxList = new ArrayList<>();
+
+        for (Map.Entry<String, List<CodeSerial>> entry : codeSerialMap.entrySet()) {
+            String agvNo = entry.getKey();
+            List<CodeSerial> codeSerials = entry.getValue();
+
+            Integer maxSerial = agvNoSerialMap.get(agvNo);
+
+            for (CodeSerial codeSerial : codeSerials) {
+                if (codeSerial.getSerial() < maxSerial) {
+                    resetCodeIdxList.add(codeSerial.getCodeMatrixIdx());
+                }
+            }
+
+        }
+
+        return resetCodeIdxList;
+    }
+
+    private List<int[]> getResetCodeList(Integer lev, UnlockPathTask task) {
+        if (null == task) {
+            return new ArrayList<>();
+        }
+        DynamicNode[][] dynamicMatrix = mapDataDispatcher.getDynamicMatrix(lev);
+
+        String agvNo = task.getAgvNo();
+        int[] codeMatrixIdx = mapDataDispatcher.getCodeMatrixIdx(lev, task.getCodeData());
+
+        DynamicNode dynamicNode = dynamicMatrix[codeMatrixIdx[0]][codeMatrixIdx[1]];
+        int serial = dynamicNode.getSerial();
+
+        List<int[]> resetCodeIdxList = new ArrayList<>();
+
+        for (int i = 0; i < dynamicMatrix.length; i++) {
+            for (int j = 0; j < dynamicMatrix[i].length; j++) {
+
+                DynamicNode node = dynamicMatrix[i][j];
+                if (node.getVehicle().equals(agvNo)) {
+                    if (node.getSerial() < serial) {
+                        resetCodeIdxList.add(new int[] {i, j});
+                    }
+                }
+            }
+        }
+
+        return resetCodeIdxList;
+    }
+
+    private void dealResetCodeList(Integer lev, List<int[]> resetCodeIdxList) {
+        if (Cools.isEmpty(resetCodeIdxList)) {
+            return;
+        }
+
+        mapDataDispatcher.clearDynamicMatrixByCodeList(lev, resetCodeIdxList);
+    }
+
+    @Data
+    public static class CodeSerial {
+        private String codeData;
+        private int[] codeMatrixIdx;
+        private int serial;
+
+        public CodeSerial(int[] codeMatrixIdx, int serial) {
+            this.codeMatrixIdx = codeMatrixIdx;
+            this.serial = serial;
+        }
+    }
+
+    @PreDestroy
+    public void destroy() {
+        if (this.consumerExecutor != null) {
+            this.consumerExecutor.shutdown();
+            try {
+                if (!this.consumerExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
+                    this.consumerExecutor.shutdownNow();
+                    if (!this.consumerExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
+                        log.error("this.consumerExecutor failed to shutdown");
+                    }
+                }
+            } catch (InterruptedException ie) {
+                this.consumerExecutor.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+        }
+    }
+
+}

--
Gitblit v1.9.1