From 42af11ca3a84e13d1f55207b2770e2454a861983 Mon Sep 17 00:00:00 2001
From: Junjie <540245094@qq.com>
Date: 星期五, 01 八月 2025 17:05:03 +0800
Subject: [PATCH] #

---
 src/main/java/com/zy/core/task/ShuttleExecuteScheduler.java           |   98 ++++-
 src/main/java/com/zy/common/utils/NavigateMapUtils.java               |   38 ++
 src/main/java/com/zy/core/thread/impl/NyShuttleThread.java            |   58 +-
 src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java           |    4 
 src/main/java/com/zy/core/task/TrafficApplyProcess.java               |  104 ++++++
 src/main/java/com/zy/core/thread/TrafficControlThread.java            |    5 
 src/main/java/com/zy/core/ServerBootstrap.java                        |   11 
 src/main/java/com/zy/core/model/param/OperateTrafficControlParam.java |   20 +
 src/main/java/com/zy/core/model/TrafficControlDataModel.java          |   15 
 src/main/java/com/zy/common/utils/RedisUtil.java                      |   18 +
 src/main/webapp/views/trafficControl.html                             |  208 ++++++++++++
 src/main/java/com/zy/asrs/controller/ShuttleController.java           |    4 
 src/main/java/com/zy/core/action/ShuttleAction.java                   |   22 +
 src/main/java/com/zy/core/enums/ShuttleTaskModeType.java              |    1 
 src/main/java/com/zy/asrs/controller/TrafficControlController.java    |   63 +++
 src/main/java/com/zy/core/thread/impl/TrafficControlImplThread.java   |  262 ++++++++++-----
 src/main/java/com/zy/core/enums/RedisKeyType.java                     |    4 
 src/main/java/com/zy/asrs/domain/param/CancelTrafficParam.java        |   12 
 src/main/resources/application.yml                                    |    4 
 src/main/webapp/views/shuttleNew.html                                 |   40 ++
 20 files changed, 841 insertions(+), 150 deletions(-)

diff --git a/src/main/java/com/zy/asrs/controller/ShuttleController.java b/src/main/java/com/zy/asrs/controller/ShuttleController.java
index 94c48cd..a7716ca 100644
--- a/src/main/java/com/zy/asrs/controller/ShuttleController.java
+++ b/src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -368,6 +368,10 @@
             //婕旂ず妯″紡-鍏�
             shuttleThread.enableDemo(false);
             return R.ok();
+        } else if (shuttleTaskModeType == ShuttleTaskModeType.CLEAR_PATH) {
+            //娓呴櫎璺緞
+            shuttleAction.clearPath(shuttleProtocol.getShuttleNo());
+            return R.ok();
         } else {
             throw new CoolException("鏈煡鍛戒护");
         }
diff --git a/src/main/java/com/zy/asrs/controller/TrafficControlController.java b/src/main/java/com/zy/asrs/controller/TrafficControlController.java
new file mode 100644
index 0000000..474c455
--- /dev/null
+++ b/src/main/java/com/zy/asrs/controller/TrafficControlController.java
@@ -0,0 +1,63 @@
+package com.zy.asrs.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.R;
+import com.zy.asrs.domain.param.CancelTrafficParam;
+import com.zy.asrs.entity.WrkMast;
+import com.zy.asrs.service.WrkMastService;
+import com.zy.common.model.NavigateNode;
+import com.zy.common.utils.RedisUtil;
+import com.zy.core.cache.SlaveConnection;
+import com.zy.core.enums.RedisKeyType;
+import com.zy.core.enums.ShuttleCommandModeType;
+import com.zy.core.enums.SlaveType;
+import com.zy.core.model.TrafficControlDataModel;
+import com.zy.core.model.command.ShuttleCommand;
+import com.zy.core.thread.TrafficControlThread;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@Slf4j
+@RestController
+public class TrafficControlController {
+
+    @Autowired
+    private RedisUtil redisUtil;
+    @Autowired
+    private WrkMastService wrkMastService;
+
+    @GetMapping("/trafficControl/getTrafficControlInfos")
+    public R getTrafficControlInfos() {
+        Object object = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_MAP.key);
+        if (object == null) {
+            return R.ok();
+        }
+
+        List<TrafficControlDataModel> trafficControlDataList = (List<TrafficControlDataModel>) object;
+
+        for (TrafficControlDataModel dataModel : trafficControlDataList) {
+            WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>()
+                    .eq("wrk_no", dataModel.getTaskNo()));
+            dataModel.setTaskExist(wrkMast != null);
+        }
+        return R.ok().add(trafficControlDataList);
+    }
+
+    @PostMapping("/trafficControl/cancelTraffic")
+    public R cancelTraffic(CancelTrafficParam param) {
+        TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
+        if (trafficControlThread == null) {
+            return R.error();
+        }
+
+        boolean result = trafficControlThread.cancelTrafficControl(param.getShuttleNo(), param.getTaskNo());
+        return R.ok().add(result);
+    }
+
+}
diff --git a/src/main/java/com/zy/asrs/domain/param/CancelTrafficParam.java b/src/main/java/com/zy/asrs/domain/param/CancelTrafficParam.java
new file mode 100644
index 0000000..3a15076
--- /dev/null
+++ b/src/main/java/com/zy/asrs/domain/param/CancelTrafficParam.java
@@ -0,0 +1,12 @@
+package com.zy.asrs.domain.param;
+
+import lombok.Data;
+
+@Data
+public class CancelTrafficParam {
+
+    private Integer shuttleNo;
+
+    private Integer taskNo;
+
+}
diff --git a/src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java b/src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
index 6843a68..1d08bc7 100644
--- a/src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
+++ b/src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -494,6 +494,10 @@
                 return false;
             }
 
+            if (shuttleProtocol.getCurrentLocNo() == null) {
+                return false;
+            }
+
             if (!shuttleProtocol.getCurrentLocNo().equals(wrkMast.getSourceLocNo())) {
                 News.taskInfo(wrkMast.getWrkNo(), "{}浠诲姟锛屽皬杞︽湭鍒拌揪鍙栬揣浣嶇疆", wrkMast.getWrkNo(), wrkMast.getSourceLocNo());
                 return false;
diff --git a/src/main/java/com/zy/common/utils/NavigateMapUtils.java b/src/main/java/com/zy/common/utils/NavigateMapUtils.java
index ea621f2..49c72a9 100644
--- a/src/main/java/com/zy/common/utils/NavigateMapUtils.java
+++ b/src/main/java/com/zy/common/utils/NavigateMapUtils.java
@@ -2,13 +2,18 @@
 
 import com.zy.asrs.utils.Utils;
 import com.zy.common.model.NavigateNode;
+import com.zy.core.cache.SlaveConnection;
 import com.zy.core.enums.RedisKeyType;
+import com.zy.core.enums.SlaveType;
+import com.zy.core.model.protocol.ShuttleProtocol;
+import com.zy.core.thread.ShuttleThread;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @Component
 public class NavigateMapUtils {
@@ -16,6 +21,39 @@
     @Autowired
     private RedisUtil redisUtil;
 
+    public synchronized boolean clearPath(Integer shuttleNo) {
+        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
+        if (shuttleThread == null) {
+            return false;
+        }
+
+        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
+        if (shuttleProtocol == null) {
+            return false;
+        }
+
+        String currentLocNo = shuttleProtocol.getCurrentLocNo();
+        int lev = Utils.getLev(currentLocNo);
+
+        HashMap<String, Object> lockMap = new HashMap<>();
+        Object o = redisUtil.get(RedisKeyType.LOCK_MAP_NODES.key + lev);
+        if (o != null) {
+            lockMap = (HashMap<String, Object>) o;
+        }
+
+        List<NavigateNode> list = new ArrayList<>();
+        for (Map.Entry<String, Object> entry : lockMap.entrySet()) {
+            String locNo = entry.getKey();
+            Integer value = (Integer) entry.getValue();
+            if (value.equals(shuttleNo)) {
+                NavigateNode navigateNode = NavigatePositionConvert.locNoToNode(locNo);
+                list.add(navigateNode);
+            }
+        }
+
+        return writeNavigateNodeToRedisMap(lev, shuttleNo, list, false);
+    }
+
     /**
      * 鍐欏叆璺緞鑺傜偣鏁版嵁鍒皉edis鍦板浘涓�
      * lock涓簍rue 绂佺敤搴撲綅锛宭ock涓篺alse鎭㈠搴撲綅
diff --git a/src/main/java/com/zy/common/utils/RedisUtil.java b/src/main/java/com/zy/common/utils/RedisUtil.java
index b97506c..80b4f9a 100644
--- a/src/main/java/com/zy/common/utils/RedisUtil.java
+++ b/src/main/java/com/zy/common/utils/RedisUtil.java
@@ -136,6 +136,24 @@
         try {
             redisTemplate.opsForValue().set(key, value);
             redisTemplate.execute((RedisCallback<Void>) connection -> null);
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 鏅�氱紦瀛樻斁鍏�
+     *
+     * @param key   閿�
+     * @param value 鍊�
+     * @return true鎴愬姛 false澶辫触
+     */
+    public boolean setSync(String key, Object value) {
+        try {
+            redisTemplate.opsForValue().set(key, value);
+            redisTemplate.execute((RedisCallback<Void>) connection -> null);
             long start = System.currentTimeMillis();
             while (System.currentTimeMillis() - start < 10000) {//鏈夋晥鏈�10s
                 Object o = redisTemplate.opsForValue().get(key);
diff --git a/src/main/java/com/zy/core/ServerBootstrap.java b/src/main/java/com/zy/core/ServerBootstrap.java
index 6af478e..7f8e82d 100644
--- a/src/main/java/com/zy/core/ServerBootstrap.java
+++ b/src/main/java/com/zy/core/ServerBootstrap.java
@@ -8,9 +8,11 @@
 import com.zy.asrs.service.BasLiftService;
 import com.zy.asrs.service.DeviceConfigService;
 import com.zy.common.utils.RedisUtil;
+import com.zy.core.action.ShuttleAction;
 import com.zy.core.cache.MessageQueue;
 import com.zy.core.cache.SlaveConnection;
 import com.zy.core.enums.SlaveType;
+import com.zy.core.task.ShuttleExecuteScheduler;
 import com.zy.core.thread.TrafficControlThread;
 import com.zy.core.thread.impl.NyShuttleThread;
 import com.zy.core.thread.impl.TrafficControlImplThread;
@@ -18,6 +20,7 @@
 import com.zy.core.utils.DeviceMsgUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 
@@ -33,12 +36,17 @@
 @Component
 public class ServerBootstrap {
 
+    @Value("${deviceExecuteConfig.threadControlCount}")
+    private int threadControlCount;
+
     @Autowired
     private MainProcess mainProcess;
     @Autowired
     private RedisUtil redisUtil;
     @Autowired
     private DeviceConfigService deviceConfigService;
+    @Autowired
+    private ShuttleAction shuttleAction;
     @Autowired
     private DeviceMsgUtils deviceMsgUtils;
     @Autowired
@@ -136,6 +144,9 @@
         TrafficControlThread trafficControlThread = new TrafficControlImplThread(redisUtil);
         new Thread(trafficControlThread).start();
         SlaveConnection.put(SlaveType.TrafficControl, 1, trafficControlThread);
+
+        ShuttleExecuteScheduler shuttleExecuteScheduler = new ShuttleExecuteScheduler(shuttleAction, deviceConfigService, redisUtil, threadControlCount);
+        new Thread(shuttleExecuteScheduler).start();
     }
 
 
diff --git a/src/main/java/com/zy/core/action/ShuttleAction.java b/src/main/java/com/zy/core/action/ShuttleAction.java
index a0a88b1..6a968c0 100644
--- a/src/main/java/com/zy/core/action/ShuttleAction.java
+++ b/src/main/java/com/zy/core/action/ShuttleAction.java
@@ -119,8 +119,10 @@
             return false;
         }
 
+        News.info("execute check command {},{}", shuttleNo, taskNo);
         //妫�娴嬪懡浠�
         int checked = checkCommand(redisCommand, shuttleNo);
+        News.info("execute check command complete {},{}", shuttleNo, taskNo);
         if (checked == 0) {
             return false;
         }
@@ -165,10 +167,20 @@
             }
 
             List<NavigateNode> nodes = JSON.parseArray(JSON.toJSONString(command.getNodes()), NavigateNode.class);
-            //鐢宠绠″埗
-            applyTrafficControl(commands, nodes, shuttleNo, taskNo);
+
+            Object object = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_LOCK_APPLY.key + shuttleNo);
+            if (object == null) {
+                //鐢宠绠″埗
+                News.info("execute apply control {},{}", shuttleNo, taskNo);
+                redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_LOCK_APPLY.key + shuttleNo, "lock", 10);
+                applyTrafficControl(commands, nodes, shuttleNo, taskNo);
+                News.info("execute apply control complete {},{}", shuttleNo, taskNo);
+            }
+
+            News.info("execute query control {},{}", shuttleNo, taskNo);
             //鏌ヨ绠″埗
             boolean apply = queryTrafficControl(shuttleNo, taskNo);
+            News.info("execute query control complete {},{}", shuttleNo, taskNo);
             if(!apply){
                 return false;//鐢宠澶辫触
             }
@@ -415,7 +427,9 @@
                 return false;
             }
             //涓婃姤浜ょ
+            News.info("execute check command report traffic {},{}", shuttleNo, shuttleProtocol.getTaskNo());
             trafficControlThread.trafficReport(command.getNodesDeepCopy(), shuttleNo, shuttleProtocol.getTaskNo());
+            News.info("execute check command report traffic complete {},{}", shuttleNo, shuttleProtocol.getTaskNo());
 
             String currentLocNo = shuttleProtocol.getCurrentLocNo();
             if (currentLocNo == null) {
@@ -768,6 +782,10 @@
         }
     }
 
+    public synchronized boolean clearPath(Integer shuttleNo) {
+        return navigateMapUtils.clearPath(shuttleNo);
+    }
+
 //    //璺戝簱绋嬪簭
 //    public synchronized void moveLoc(Integer shuttleNo) {
 //        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
diff --git a/src/main/java/com/zy/core/enums/RedisKeyType.java b/src/main/java/com/zy/core/enums/RedisKeyType.java
index 002f68b..abb0917 100644
--- a/src/main/java/com/zy/core/enums/RedisKeyType.java
+++ b/src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -19,6 +19,10 @@
 
     //浜ょ淇℃伅
     TRAFFIC_CONTROL_MAP("traffic_control_map"),
+    TRAFFIC_CONTROL_APPLY("traffic_control_apply_"),
+    TRAFFIC_CONTROL_REPORT_LIST("traffic_control_report_list_"),
+    TRAFFIC_CONTROL_LOCK_APPLY("traffic_control_lock_apply_"),
+    TRAFFIC_CONTROL_SHUTTLE_APPLY_COUNT("traffic_control_shuttle_apply_count_"),
 
     //鍦板浘閿佸畾鑺傜偣
     LOCK_MAP_NODES("lock_map_nodes_"),
diff --git a/src/main/java/com/zy/core/enums/ShuttleTaskModeType.java b/src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
index 1475078..1a588bc 100644
--- a/src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
+++ b/src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
@@ -19,6 +19,7 @@
     UPDATE_LOCATION(14, "鏇存柊鍧愭爣"),
     CHARGE_ON(15, "鍏呯數-寮�"),
     CHARGE_OFF(16, "鍏呯數-鍏�"),
+    CLEAR_PATH(17, "娓呴櫎璺緞"),
     ;
 
     public Integer id;
diff --git a/src/main/java/com/zy/core/model/TrafficControlDataModel.java b/src/main/java/com/zy/core/model/TrafficControlDataModel.java
index b73396f..62ccbad 100644
--- a/src/main/java/com/zy/core/model/TrafficControlDataModel.java
+++ b/src/main/java/com/zy/core/model/TrafficControlDataModel.java
@@ -16,4 +16,19 @@
 
     private List<NavigateNode> totalNodeList;
 
+    private Integer applyCount = 0;
+
+    private Boolean taskExist;
+
+    public TrafficControlDataModel() {
+
+    }
+
+    public TrafficControlDataModel(Integer shuttleNo, Integer taskNo, List<NavigateNode> nodeList, List<NavigateNode> totalNodeList) {
+        this.shuttleNo = shuttleNo;
+        this.taskNo = taskNo;
+        this.nodeList = nodeList;
+        this.totalNodeList = totalNodeList;
+    }
+
 }
diff --git a/src/main/java/com/zy/core/model/param/OperateTrafficControlParam.java b/src/main/java/com/zy/core/model/param/OperateTrafficControlParam.java
new file mode 100644
index 0000000..0ac1da1
--- /dev/null
+++ b/src/main/java/com/zy/core/model/param/OperateTrafficControlParam.java
@@ -0,0 +1,20 @@
+package com.zy.core.model.param;
+
+import com.zy.common.model.NavigateNode;
+import com.zy.core.model.TrafficControlDataModel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class OperateTrafficControlParam {
+
+    private TrafficControlDataModel dataModel;
+
+    private String operaType;
+
+    private Boolean forceCancel;
+
+    private List<NavigateNode> reportNodeList;
+
+}
diff --git a/src/main/java/com/zy/core/task/ShuttleExecuteScheduler.java b/src/main/java/com/zy/core/task/ShuttleExecuteScheduler.java
index 9020af6..a3d5036 100644
--- a/src/main/java/com/zy/core/task/ShuttleExecuteScheduler.java
+++ b/src/main/java/com/zy/core/task/ShuttleExecuteScheduler.java
@@ -4,43 +4,81 @@
 import com.zy.asrs.entity.DeviceConfig;
 import com.zy.asrs.service.DeviceConfigService;
 import com.zy.common.utils.RedisUtil;
+import com.zy.core.News;
 import com.zy.core.action.ShuttleAction;
 import com.zy.core.enums.RedisKeyType;
 import com.zy.core.enums.SlaveType;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
 
+import java.util.ArrayList;
 import java.util.List;
 
-@Slf4j
-@Component
-public class ShuttleExecuteScheduler {
+public class ShuttleExecuteScheduler implements Runnable {
 
-//    @Autowired
-//    private ShuttleAction shuttleAction;
-//    @Autowired
-//    private DeviceConfigService deviceConfigService;
-//    @Autowired
-//    private RedisUtil redisUtil;
-//
-//    @Scheduled(cron = "0/1 * * * * ? ")
-//    public void execute() {
-//        List<DeviceConfig> shuttleList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
-//                .eq("device_type", String.valueOf(SlaveType.Shuttle)));
-//        for (DeviceConfig deviceConfig : shuttleList) {
-//            Object object = redisUtil.get(RedisKeyType.SHUTTLE_FLAG.key + deviceConfig.getDeviceNo());
-//            if (object == null) {
-//                continue;
-//            }
-//
-//            int taskNo = Integer.parseInt(String.valueOf(object));
-//            if (taskNo != 0) {
-//                //瀛樺湪浠诲姟闇�瑕佹墽琛�
-//                boolean result = shuttleAction.executeWork(deviceConfig.getDeviceNo(), taskNo);
-//            }
-//        }
-//    }
+    private ShuttleAction shuttleAction;
+    private DeviceConfigService deviceConfigService;
+    private RedisUtil redisUtil;
+    private int threadControlCount;
 
+    @Scheduled(cron = "0/1 * * * * ? ")
+    public void execute() {
+
+    }
+
+    public ShuttleExecuteScheduler(ShuttleAction shuttleAction, DeviceConfigService deviceConfigService, RedisUtil redisUtil, int threadControlCount) {
+        this.shuttleAction = shuttleAction;
+        this.deviceConfigService = deviceConfigService;
+        this.redisUtil = redisUtil;
+        this.threadControlCount = threadControlCount;
+    }
+
+    @Override
+    public void run() {
+        List<DeviceConfig> shuttleList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
+                .eq("device_type", String.valueOf(SlaveType.Shuttle)));
+
+        List<List<DeviceConfig>> lists = new ArrayList<>();
+        List<DeviceConfig> tmp = new ArrayList<>();
+
+        for (int i = 0; i < shuttleList.size(); i++) {
+            DeviceConfig deviceConfig = shuttleList.get(i);
+            if (i != 0 && i % threadControlCount == 0) {
+                lists.add(tmp);
+                tmp = new ArrayList<>();
+            }
+            tmp.add(deviceConfig);
+        }
+        lists.add(tmp);
+
+        for (List<DeviceConfig> list : lists) {
+            if (list.isEmpty()) {
+                continue;
+            }
+
+            new Thread(() -> {
+                while (true) {
+                    try {
+                        for (DeviceConfig deviceConfig : list) {
+                            Object object = redisUtil.get(RedisKeyType.SHUTTLE_FLAG.key + deviceConfig.getDeviceNo());
+                            if (object == null) {
+                                continue;
+                            }
+
+                            int taskNo = Integer.parseInt(String.valueOf(object));
+                            if (taskNo != 0) {
+                                //瀛樺湪浠诲姟闇�瑕佹墽琛�
+                                long startTime = System.currentTimeMillis();
+                                News.info("execute {},{}", deviceConfig.getDeviceNo(), taskNo);
+                                boolean result = shuttleAction.executeWork(deviceConfig.getDeviceNo(), taskNo);
+                                Thread.sleep(100);
+                                News.info("execute end {},{},{}", deviceConfig.getDeviceNo(), taskNo, System.currentTimeMillis() - startTime);
+                            }
+                        }
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }
+                }
+            }).start();
+        }
+    }
 }
diff --git a/src/main/java/com/zy/core/task/TrafficApplyProcess.java b/src/main/java/com/zy/core/task/TrafficApplyProcess.java
new file mode 100644
index 0000000..2935d3e
--- /dev/null
+++ b/src/main/java/com/zy/core/task/TrafficApplyProcess.java
@@ -0,0 +1,104 @@
+package com.zy.core.task;
+
+import com.zy.common.utils.RedisUtil;
+import com.zy.core.cache.SlaveConnection;
+import com.zy.core.enums.RedisKeyType;
+import com.zy.core.enums.SlaveType;
+import com.zy.core.model.TrafficControlDataModel;
+import com.zy.core.model.param.OperateTrafficControlParam;
+import com.zy.core.thread.TrafficControlThread;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+@Slf4j
+@Component
+public class TrafficApplyProcess {
+
+    @Autowired
+    private RedisUtil redisUtil;
+
+    @Scheduled(cron = "0/3 * * * * ? ")
+    public void processApply() {
+        TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
+        if (trafficControlThread == null) {
+            return;
+        }
+        Set<String> keys = redisUtil.searchKeys(RedisKeyType.TRAFFIC_CONTROL_APPLY.key);
+
+        List<ApplyKey> sortList = new ArrayList<>();
+        for (String key : keys) {
+            String[] split = key.split(RedisKeyType.TRAFFIC_CONTROL_APPLY.key);
+            String[] split1 = split[1].split("_");
+            String shuttleNo = split1[0];
+
+            int count = 0;
+            String applyCountKey = RedisKeyType.TRAFFIC_CONTROL_SHUTTLE_APPLY_COUNT.key + shuttleNo;
+            Object object = redisUtil.get(applyCountKey);
+            if(object != null) {
+                count = (Integer) object;
+            }
+
+            sortList.add(new ApplyKey(key, count));
+        }
+
+        sortList.sort(Comparator.comparing(ApplyKey::getCount).reversed());
+
+        for (ApplyKey applyKey : sortList) {
+            String key = applyKey.getKey();
+            TrafficControlDataModel dataModel = (TrafficControlDataModel) redisUtil.get(key);
+            redisUtil.del(key);
+
+            boolean apply = trafficControlThread.processApply(dataModel);
+
+            String applyCountKey = RedisKeyType.TRAFFIC_CONTROL_SHUTTLE_APPLY_COUNT.key + dataModel.getShuttleNo();
+            if (apply) {
+                redisUtil.del(applyCountKey);
+            }else {
+                Object object = redisUtil.get(applyCountKey);
+                if (object == null) {
+                    redisUtil.set(applyCountKey, 0, 60 * 60);
+                }else {
+                    Integer count = (Integer) object;
+                    redisUtil.set(applyCountKey, count + 1, 60 * 60);
+                }
+            }
+        }
+    }
+
+    @Scheduled(cron = "0/3 * * * * ? ")
+    public void processReport() {
+        TrafficControlThread trafficControlThread = (TrafficControlThread) SlaveConnection.get(SlaveType.TrafficControl, 1);
+        if (trafficControlThread == null) {
+            return;
+        }
+        Set<String> keys = redisUtil.searchKeys(RedisKeyType.TRAFFIC_CONTROL_REPORT_LIST.key);
+
+        for (String key : keys) {
+            OperateTrafficControlParam param = (OperateTrafficControlParam) redisUtil.get(key);
+            redisUtil.del(key);
+            boolean apply = trafficControlThread.operateTrafficControl(param);
+        }
+    }
+
+    class ApplyKey{
+        @Getter
+        String key;
+        @Getter
+        Integer count;
+
+        public ApplyKey(String key, Integer count) {
+            this.key = key;
+            this.count = count;
+        }
+
+    }
+
+}
diff --git a/src/main/java/com/zy/core/thread/TrafficControlThread.java b/src/main/java/com/zy/core/thread/TrafficControlThread.java
index a12dd26..1c9cb6e 100644
--- a/src/main/java/com/zy/core/thread/TrafficControlThread.java
+++ b/src/main/java/com/zy/core/thread/TrafficControlThread.java
@@ -4,11 +4,16 @@
 import com.zy.common.model.NavigateNode;
 import com.zy.core.ThreadHandler;
 import com.zy.core.model.TrafficControlDataModel;
+import com.zy.core.model.param.OperateTrafficControlParam;
 
 import java.util.List;
 
 public interface TrafficControlThread extends ThreadHandler {
 
+    boolean processApply(TrafficControlDataModel applyData);
+
+    boolean operateTrafficControl(OperateTrafficControlParam param);
+
     boolean applyTrafficControl(List<NavigateNode> totalNodeList, List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo);
 
     boolean trafficReport(List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo);
diff --git a/src/main/java/com/zy/core/thread/impl/NyShuttleThread.java b/src/main/java/com/zy/core/thread/impl/NyShuttleThread.java
index 312b527..724ba7a 100644
--- a/src/main/java/com/zy/core/thread/impl/NyShuttleThread.java
+++ b/src/main/java/com/zy/core/thread/impl/NyShuttleThread.java
@@ -89,35 +89,35 @@
         });
         readThread.start();
 
-        //璁惧鎵ц
-        Thread executeThread = new Thread(() -> {
-            while (true) {
-                try {
-                    if (shuttleAction == null) {
-                        try {
-                            shuttleAction = SpringUtils.getBean(ShuttleAction.class);
-                        }catch (Exception e){
-                        }
-                        continue;
-                    }
-
-                    Object object = redisUtil.get(RedisKeyType.SHUTTLE_FLAG.key + deviceConfig.getDeviceNo());
-                    if (object == null) {
-                        continue;
-                    }
-
-                    Integer taskNo = Integer.valueOf(String.valueOf(object));
-                    if (taskNo != 0) {
-                        //瀛樺湪浠诲姟闇�瑕佹墽琛�
-                        boolean result = shuttleAction.executeWork(deviceConfig.getDeviceNo(), taskNo);
-                    }
-                    Thread.sleep(100);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        });
-        executeThread.start();
+//        //璁惧鎵ц
+//        Thread executeThread = new Thread(() -> {
+//            while (true) {
+//                try {
+//                    if (shuttleAction == null) {
+//                        try {
+//                            shuttleAction = SpringUtils.getBean(ShuttleAction.class);
+//                        }catch (Exception e){
+//                        }
+//                        continue;
+//                    }
+//
+//                    Object object = redisUtil.get(RedisKeyType.SHUTTLE_FLAG.key + deviceConfig.getDeviceNo());
+//                    if (object == null) {
+//                        continue;
+//                    }
+//
+//                    Integer taskNo = Integer.valueOf(String.valueOf(object));
+//                    if (taskNo != 0) {
+//                        //瀛樺湪浠诲姟闇�瑕佹墽琛�
+//                        boolean result = shuttleAction.executeWork(deviceConfig.getDeviceNo(), taskNo);
+//                    }
+//                    Thread.sleep(100);
+//                } catch (Exception e) {
+//                    e.printStackTrace();
+//                }
+//            }
+//        });
+//        executeThread.start();
     }
 
     private void listenMessageFromRedis() {
diff --git a/src/main/java/com/zy/core/thread/impl/TrafficControlImplThread.java b/src/main/java/com/zy/core/thread/impl/TrafficControlImplThread.java
index 7fccedc..1f3f4f2 100644
--- a/src/main/java/com/zy/core/thread/impl/TrafficControlImplThread.java
+++ b/src/main/java/com/zy/core/thread/impl/TrafficControlImplThread.java
@@ -1,13 +1,8 @@
 package com.zy.core.thread.impl;
 
-import com.alibaba.fastjson.JSON;
 import com.core.common.SpringUtils;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.zy.asrs.utils.Utils;
 import com.zy.common.model.NavigateNode;
-import com.zy.common.model.enums.NavigationMapType;
-import com.zy.common.utils.NavigatePositionConvert;
-import com.zy.common.utils.NavigateUtils;
 import com.zy.common.utils.RedisUtil;
 import com.zy.common.utils.ShuttleOperaUtils;
 import com.zy.core.News;
@@ -15,16 +10,14 @@
 import com.zy.core.enums.RedisKeyType;
 import com.zy.core.enums.SlaveType;
 import com.zy.core.model.TrafficControlDataModel;
-import com.zy.core.model.command.ShuttleAssignCommand;
-import com.zy.core.model.command.ShuttleRedisCommand;
+import com.zy.core.model.param.OperateTrafficControlParam;
 import com.zy.core.model.protocol.ShuttleProtocol;
 import com.zy.core.thread.ShuttleThread;
 import com.zy.core.thread.TrafficControlThread;
-import com.zy.core.utils.TrafficControlUtils;
+import org.springframework.scheduling.annotation.Async;
 
-import java.io.IOException;
 import java.util.*;
-import java.util.function.Function;
+import java.util.stream.Collectors;
 
 public class TrafficControlImplThread implements TrafficControlThread {
 
@@ -36,6 +29,7 @@
     private HashMap<Integer,Long> applyRecordsMap = new HashMap<>();
     private HashMap<String, List<NavigateNode>> taskNodesMap = new HashMap<>();
     private List<TrafficControlDataModel> trafficControlDataList = new ArrayList<>();
+    private List<TrafficControlDataModel> trafficControlDataListRead = new ArrayList<>();
 
     public TrafficControlImplThread(RedisUtil redisUtil) {
         this.redisUtil = redisUtil;
@@ -47,17 +41,22 @@
         Object object = redisUtil.get(RedisKeyType.TRAFFIC_CONTROL_MAP.key);
         if(object != null) {
             trafficControlDataList = (List<TrafficControlDataModel>) object;
+            trafficControlDataListRead = trafficControlDataList.stream()
+                    .map(model -> new TrafficControlDataModel(
+                            model.getShuttleNo(),
+                            model.getTaskNo(),
+                            new ArrayList<>(model.getNodeList()),
+                            new ArrayList<>(model.getTotalNodeList())
+                    ))
+                    .collect(Collectors.toList());
         }
 
         while (true) {
             try {
-                if (applyList.isEmpty()) {
-                    continue;
-                }
-
-                TrafficControlDataModel dataModel = applyList.get(0);
-                processApply(dataModel);
-                applyList.remove(0);
+                List<TrafficControlDataModel> allTrafficControl = getAllTrafficControl();
+                //鏇存柊浜ょ淇℃伅
+                redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_MAP.key, allTrafficControl);
+                Thread.sleep(200);
             }catch (Exception e){
                 e.printStackTrace();
             }
@@ -65,6 +64,7 @@
 
     }
 
+    @Override
     public synchronized boolean processApply(TrafficControlDataModel applyData) {
         ShuttleOperaUtils shuttleOperaUtils = SpringUtils.getBean(ShuttleOperaUtils.class);
         if (shuttleOperaUtils == null) {
@@ -79,13 +79,12 @@
             return false;
         }
 
+        List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
+
         Integer shuttleNo = applyData.getShuttleNo();
         Integer taskNo = applyData.getTaskNo();
         List<NavigateNode> nodeList = applyData.getNodeList();
         List<NavigateNode> totalNodeList = applyData.getTotalNodeList();
-
-        //鏇存柊浜ょ淇℃伅
-        redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_MAP.key, trafficControlDataList);
 
         NavigateNode startNode = totalNodeList.get(0);
         List<int[]> shuttlePoints = Utils.getShuttlePoints(shuttleNo, startNode.getZ());
@@ -103,8 +102,8 @@
         }
 
         //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
-        for (int i = 0; i < trafficControlDataList.size(); i++) {
-            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
+        for (int i = 0; i < allTrafficControlList.size(); i++) {
+            TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
             if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
                 //瀛樺湪绠″埗
                 if(!controlDataModel.getTaskNo().equals(taskNo)) {
@@ -178,7 +177,7 @@
         }
 
         //妫�娴嬭妭鐐规槸鍚﹁浣跨敤
-        for (TrafficControlDataModel controlDataModel : trafficControlDataList) {
+        for (TrafficControlDataModel controlDataModel : allTrafficControlList) {
             List<NavigateNode> list = controlDataModel.getTotalNodeList();
             for (int i = 0; i < list.size(); i++) {
                 NavigateNode node = list.get(i);
@@ -194,7 +193,10 @@
         }
 
         //浜ょ鎺ユ敹
-        trafficControlDataList.add(applyData);
+        OperateTrafficControlParam param = new OperateTrafficControlParam();
+        param.setDataModel(applyData);
+        param.setOperaType("add");
+        operateTrafficControl(param);
 
         applyRecordsMap.remove(shuttleNo);
         News.info("receipt traffic {},{}", shuttleNo, taskNo);
@@ -202,55 +204,34 @@
     }
 
     @Override
-    public synchronized boolean applyTrafficControl(List<NavigateNode> totalNodeList, List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
-        boolean add = true;
-        for (TrafficControlDataModel controlDataModel : applyList) {
-            if(controlDataModel.getShuttleNo().equals(shuttleNo)) {
-                add = false;
-                break;
-            }
-        }
-
-        if (add) {
-            TrafficControlDataModel model = new TrafficControlDataModel();
-            model.setShuttleNo(shuttleNo);
-            model.setTaskNo(taskNo);
-            model.setNodeList(nodeList);
-            model.setTotalNodeList(totalNodeList);
-            applyList.add(model);
-        }else {
+    public boolean applyTrafficControl(List<NavigateNode> totalNodeList, List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
+        Set<String> keys = redisUtil.searchKeys(RedisKeyType.TRAFFIC_CONTROL_APPLY.key + shuttleNo + "_");
+        if (!keys.isEmpty()) {
             return false;
         }
 
+        TrafficControlDataModel model = new TrafficControlDataModel();
+        model.setShuttleNo(shuttleNo);
+        model.setTaskNo(taskNo);
+        model.setNodeList(nodeList);
+        model.setTotalNodeList(totalNodeList);
+        redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_APPLY.key + shuttleNo + "_" + System.currentTimeMillis(), model);
         return true;
     }
 
     @Override
-    public synchronized boolean trafficReport(List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
+    public boolean trafficReport(List<NavigateNode> nodeList, Integer shuttleNo, Integer taskNo) {
         //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
-        for (int i = 0; i < trafficControlDataList.size(); i++) {
-            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
+        List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
+        for (int i = 0; i < allTrafficControlList.size(); i++) {
+            TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
             if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
                 if(controlDataModel.getTaskNo().equals(taskNo)) {
-                    List<NavigateNode> newTotalNodeList = new ArrayList<>();
-                    List<NavigateNode> totalNodeList = controlDataModel.getTotalNodeList();
-
-                    List<String> reportList = new ArrayList<>();
-                    for (NavigateNode node : nodeList) {
-                        reportList.add(Utils.getLocNo(node.getX(), node.getY(), node.getZ()));
-                    }
-
-                    for (NavigateNode node : totalNodeList) {
-                        String locNo = Utils.getLocNo(node.getX(), node.getY(), node.getZ());
-                        if(reportList.contains(locNo)) {
-                            continue;
-                        }
-                        newTotalNodeList.add(node);
-                    }
-
-                    controlDataModel.setTotalNodeList(newTotalNodeList);
-                    trafficControlDataList.set(i, controlDataModel);
-                    shuttleReportErrorMap.remove(shuttleNo);
+                    OperateTrafficControlParam param = new OperateTrafficControlParam();
+                    param.setDataModel(controlDataModel);
+                    param.setOperaType("report");
+                    param.setReportNodeList(nodeList);
+                    redisUtil.set(RedisKeyType.TRAFFIC_CONTROL_REPORT_LIST.key + shuttleNo + "_" + System.currentTimeMillis(), param);
                     return true;
                 }
             }
@@ -259,7 +240,7 @@
     }
 
     @Override
-    public boolean trafficReportError(Integer shuttleNo, Integer taskNo) {
+    public synchronized boolean trafficReportError(Integer shuttleNo, Integer taskNo) {
         ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
         if (shuttleThread == null) {
             return false;
@@ -279,37 +260,38 @@
 
     @Override
     public synchronized boolean cancelTrafficControl(Integer shuttleNo, Integer taskNo) {
-        //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
-        for (int i = 0; i < trafficControlDataList.size(); i++) {
-            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
-            if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
-                if(controlDataModel.getTaskNo().equals(taskNo)) {
-                    trafficControlDataList.remove(i);//鍙栨秷绠″埗
-                    return true;
-                }
-            }
+        TrafficControlDataModel dataModel = queryTrafficControl(shuttleNo, taskNo);
+        if (dataModel == null) {
+            return false;
         }
-        return false;
+
+        OperateTrafficControlParam param = new OperateTrafficControlParam();
+        param.setDataModel(dataModel);
+        param.setOperaType("cancel");
+        param.setForceCancel(false);
+        return operateTrafficControl(param);
     }
 
     @Override
-    public boolean forceCancelTrafficControl(Integer shuttleNo) {
-        //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
-        for (int i = 0; i < trafficControlDataList.size(); i++) {
-            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
-            if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
-                trafficControlDataList.remove(i);//鍙栨秷绠″埗
-                return true;
-            }
+    public synchronized boolean forceCancelTrafficControl(Integer shuttleNo) {
+        TrafficControlDataModel dataModel = queryTrafficControl(shuttleNo);
+        if (dataModel == null) {
+            return false;
         }
-        return false;
+
+        OperateTrafficControlParam param = new OperateTrafficControlParam();
+        param.setDataModel(dataModel);
+        param.setOperaType("cancel");
+        param.setForceCancel(true);
+        return operateTrafficControl(param);
     }
 
     @Override
     public TrafficControlDataModel queryTrafficControl(Integer shuttleNo, Integer taskNo) {
         //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
-        for (int i = 0; i < trafficControlDataList.size(); i++) {
-            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
+        List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
+        for (int i = 0; i < allTrafficControlList.size(); i++) {
+            TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
             if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
                 if(controlDataModel.getTaskNo().equals(taskNo)) {
                     return controlDataModel;
@@ -322,8 +304,9 @@
     @Override
     public TrafficControlDataModel queryTrafficControl(Integer shuttleNo) {
         //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
-        for (int i = 0; i < trafficControlDataList.size(); i++) {
-            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
+        List<TrafficControlDataModel> allTrafficControlList = getAllTrafficControl();
+        for (int i = 0; i < allTrafficControlList.size(); i++) {
+            TrafficControlDataModel controlDataModel = allTrafficControlList.get(i);
             if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
                 return controlDataModel;
             }
@@ -333,7 +316,110 @@
 
     @Override
     public List<TrafficControlDataModel> getAllTrafficControl() {
-        return trafficControlDataList;
+        return trafficControlDataListRead;
+    }
+
+    @Override
+    public synchronized boolean operateTrafficControl(OperateTrafficControlParam param) {
+        long startTime = System.currentTimeMillis();
+        String operaType = param.getOperaType();
+        News.info("Operate Traffic Control is Start " + operaType);
+
+        boolean result = false;
+        if (operaType.equals("add")) {
+            result = addTrafficControlDataList(param);
+        } else if (operaType.equals("cancel")) {
+            result = removeTrafficControlDataList(param);
+        } else if (operaType.equals("report")) {
+            result = reportTrafficControlDataList(param);
+        }
+
+        this.trafficControlDataListRead = trafficControlDataList.stream()
+                .map(model -> new TrafficControlDataModel(
+                        model.getShuttleNo(),
+                        model.getTaskNo(),
+                        new ArrayList<>(model.getNodeList()),
+                        new ArrayList<>(model.getTotalNodeList())
+                ))
+                .collect(Collectors.toList());
+        News.info("Operate Traffic Control is end " + (System.currentTimeMillis() - startTime) + "ms");
+        return result;
+    }
+
+    public synchronized boolean addTrafficControlDataList(OperateTrafficControlParam param) {
+        TrafficControlDataModel dataModel = param.getDataModel();
+        trafficControlDataList.add(dataModel);
+        return true;
+    }
+
+    public synchronized boolean removeTrafficControlDataList(OperateTrafficControlParam param) {
+        //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
+        TrafficControlDataModel dataModel = param.getDataModel();
+        Boolean forceCancel = param.getForceCancel();
+
+        Integer shuttleNo = dataModel.getShuttleNo();
+        Integer taskNo = dataModel.getTaskNo();
+
+        int idx = -1;
+        for (int i = 0; i < trafficControlDataList.size(); i++) {
+            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
+            if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
+                if (forceCancel) {
+                    idx = i;
+                    break;
+                }else {
+                    if(controlDataModel.getTaskNo().equals(taskNo)) {
+                        idx = i;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if(idx == -1) {
+            return false;
+        }
+
+        trafficControlDataList.remove(idx);//鍙栨秷绠″埗
+        return true;
+    }
+
+    public synchronized boolean reportTrafficControlDataList(OperateTrafficControlParam param) {
+        //妫�娴嬭溅瀛愭槸鍚﹀瓨鍦ㄧ鍒�
+        TrafficControlDataModel dataModel = param.getDataModel();
+        List<NavigateNode> reportNodeList = param.getReportNodeList();
+
+        Integer shuttleNo = dataModel.getShuttleNo();
+        Integer taskNo = dataModel.getTaskNo();
+
+        for (int i = 0; i < trafficControlDataList.size(); i++) {
+            TrafficControlDataModel controlDataModel = trafficControlDataList.get(i);
+            if(shuttleNo.equals(controlDataModel.getShuttleNo())) {
+                if(controlDataModel.getTaskNo().equals(taskNo)) {
+                    List<NavigateNode> newTotalNodeList = new ArrayList<>();
+                    List<NavigateNode> totalNodeList = controlDataModel.getTotalNodeList();
+
+                    List<String> reportList = new ArrayList<>();
+                    for (NavigateNode node : reportNodeList) {
+                        reportList.add(Utils.getLocNo(node.getX(), node.getY(), node.getZ()));
+                    }
+
+                    for (NavigateNode node : totalNodeList) {
+                        String locNo = Utils.getLocNo(node.getX(), node.getY(), node.getZ());
+                        if(reportList.contains(locNo)) {
+                            continue;
+                        }
+                        newTotalNodeList.add(node);
+                    }
+
+                    controlDataModel.setTotalNodeList(newTotalNodeList);
+                    trafficControlDataList.set(i, controlDataModel);
+                    shuttleReportErrorMap.remove(shuttleNo);
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     @Override
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index be50803..734f2e1 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -50,6 +50,10 @@
   # 璇诲彇鏁版嵁鍚庤嚜鍔ㄥ垹闄�
   destroyAfterReading: true
 
+deviceExecuteConfig:
+  # 姣忎釜绾跨▼绠℃帶璁惧鎵ц鏁伴噺
+  threadControlCount: 10
+
 ## 涓嬩綅鏈洪厤缃�
 #wcs-slave:
 #  # 鍥涘悜绌挎杞�1
diff --git a/src/main/webapp/views/shuttleNew.html b/src/main/webapp/views/shuttleNew.html
index ef80807..db1afad 100644
--- a/src/main/webapp/views/shuttleNew.html
+++ b/src/main/webapp/views/shuttleNew.html
@@ -183,12 +183,18 @@
                                 <el-input @change="changeControlShuttleNo" v-model="controlData.shuttleNo" style="width: 150px;" placeholder="杞﹁締缂栧彿"></el-input>
                             </div>
                             <div>
+                                <el-input @change="changeControlShuttleNo" v-model="controlData.taskNo" style="width: 150px;" placeholder="宸ヤ綔鍙�"></el-input>
+                            </div>
+                            <div>
                                 <el-input v-model="controlData.sourceLocNo" style="width: 200px;" placeholder="婧愬簱浣�"></el-input>
                             </div>
                             <div>
                                 <el-input v-model="controlData.targetLocNo" style="width: 200px;" placeholder="鐩爣搴撲綅"></el-input>
                             </div>
                             <div>
+                                <button class="btn bg-slate-600 hover:bg-slate-500" @click="shuttleOperator('writeTaskNo')">
+                                    <i class="fas fa-credit-card-alt mr-1"></i>鍐欏叆宸ヤ綔鍙�
+                                </button>
                                 <button class="btn bg-slate-600 hover:bg-slate-500" @click="shuttleOperator('transport')">
                                     <i class="fas fa-truck mr-1"></i>鎼繍璐х墿
                                 </button>
@@ -224,6 +230,9 @@
                             </button>
                             <button class="btn bg-slate-600 hover:bg-slate-500" @click="shuttleOperator('demoOff')">
                                 <i class="fas fa-hourglass-empty mr-1"></i>婕旂ず-鍏�
+                            </button>
+                            <button class="btn bg-slate-600 hover:bg-slate-500" @click="shuttleOperator('clearPath')">
+                                <i class="fas fa-anchor mr-1"></i>娓呴櫎璺緞
                             </button>
                         </div>
                     </div>
@@ -393,6 +402,7 @@
             deviceStatusCountMap: {},
             controlData: {
                 shuttleNo: "",
+                taskNo: "",
                 sourceLocNo: "",
                 targetLocNo: ""
             },
@@ -557,6 +567,34 @@
                     requestParam.shuttleTaskMode = 12;
                 }else if (type == 'demoOff') {
                     requestParam.shuttleTaskMode = 13;
+                }else if (type == 'clearPath') {
+                    requestParam.shuttleTaskMode = 17;
+                }else if (type == 'writeTaskNo') {
+                    requestParam.workNo = this.controlData.taskNo;
+                    requestParam.pakMk = null;
+
+                    $.ajax({
+                        url: baseUrl + "/shuttle/detl/update",
+                        headers: {'token': localStorage.getItem('token')},
+                        method: 'POST',
+                        data: requestParam,
+                        success: function (res) {
+                            if (res.code === 200) {
+                                that.$message({
+                                    message: res.msg,
+                                    type: 'success'
+                                });
+                            } else if (res.code === 403) {
+                                window.location.href = baseUrl + "/login";
+                            } else {
+                                that.$message({
+                                    message: res.msg,
+                                    type: 'warning'
+                                });
+                            }
+                        }
+                    });
+                    return;
                 }
 
                 $.ajax({
@@ -573,7 +611,7 @@
                         } else if (res.code === 403) {
                             window.location.href = baseUrl + "/login";
                         } else {
-                            this.$message({
+                            that.$message({
                                 message: res.msg,
                                 type: 'warning'
                             });
diff --git a/src/main/webapp/views/trafficControl.html b/src/main/webapp/views/trafficControl.html
new file mode 100644
index 0000000..a3721d8
--- /dev/null
+++ b/src/main/webapp/views/trafficControl.html
@@ -0,0 +1,208 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>浜ら�氱鍒剁洃鎺т腑蹇�</title>
+    <link rel="stylesheet" href="../static/vue/element/element.css">
+    <link rel="stylesheet" href="../static/css/shuttle_page.min.css">
+    <script src="../static/js/shuttle_page.js"></script>
+    <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
+    <script type="text/javascript" src="../static/js/common.js"></script>
+    <script type="text/javascript" src="../static/vue/js/vue.min.js"></script>
+    <script type="text/javascript" src="../static/vue/element/element.js"></script>
+    <style>
+        body {
+            font-family: 'Noto Sans SC', sans-serif;
+            background-color: #0f172a;
+            color: #e2e8f0;
+        }
+        .card {
+            background-color: #1e293b;
+            border-radius: 0.75rem;
+            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+            transition: all 0.3s ease;
+        }
+        /*.card:hover {*/
+        /*    transform: translateY(-2px);*/
+        /*    box-shadow: 0 10px 15px rgba(0, 0, 0, 0.2);*/
+        /*}*/
+        .btn {
+            background-color: #3b82f6;
+            color: white;
+            border-radius: 0.5rem;
+            padding: 0.5rem 1rem;
+            transition: all 0.3s ease;
+        }
+        .btn:hover {
+            background-color: #2563eb;
+            transform: translateY(-1px);
+        }
+        .status-active {
+            color: #4ade80;
+        }
+        .status-inactive {
+            color: #f87171;
+        }
+        .progress-bar {
+            height: 0.75rem;
+            border-radius: 0.375rem;
+            background-color: #334155;
+        }
+        .progress-fill {
+            height: 100%;
+            border-radius: 0.375rem;
+            background-color: #4ade80;
+            transition: width 0.5s ease;
+        }
+        .table-striped tbody tr:nth-child(odd) {
+            background-color: #1e293b;
+        }
+        .table-striped tbody tr:nth-child(even) {
+            background-color: #1a2537;
+        }
+    </style>
+</head>
+<body class="min-h-screen">
+    <div id="app">
+        <div class="container mx-auto px-4 py-8">
+            <!-- 椤堕儴鏍囬鍜岀姸鎬佹爮 -->
+            <div class="flex flex-col md:flex-row justify-between items-center mb-8">
+                <h1 class="text-3xl font-bold text-blue-400 mb-4 md:mb-0">
+                    <i class="fas fa-robot mr-2"></i>浜ら�氱鍒剁洃鎺т腑蹇�
+                </h1>
+            </div>
+
+            <!-- 鎿嶄綔鎺у埗鍖哄煙 -->
+            <div class="card p-6 mb-8">
+                <h2 class="text-xl font-semibold text-blue-300 mb-4">
+                    <i class="fas fa-sliders-h mr-2"></i>淇℃伅
+                </h2>
+                <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-2 gap-2">
+                    <div v-for="(item) in controlList" class="bg-slate-700 p-4 rounded-lg">
+                        <div class="gap-2">
+                            <div class="p-2">
+                                <button class="btn bg-slate-600 hover:bg-slate-500" @click="cancelTraffic(item)">
+                                    <i class="fas fa-home mr-1"></i>鐢宠鍙栨秷
+                                </button>
+                            </div>
+                            <div class="p-2">
+                                杞﹁締缂栧彿锛歿{ item.shuttleNo }}
+                            </div>
+                            <div class="p-2">
+                                浠诲姟鍙凤細{{ item.taskNo }} - {{ item.taskExist }}
+                            </div>
+                            <div class="p-2">
+                                褰撳墠琛岄┒鑺傜偣锛歿{ item.nodeList }}
+                            </div>
+                            <div class="p-2">
+                                鎬昏妭鐐癸細{{ item.totalNodeList }}
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</body>
+
+<script>
+    var app = new Vue({
+        el: '#app',
+        data: {
+            ws: null,
+            controlList: []
+        },
+        created() {
+            this.init()
+        },
+        watch: {
+
+        },
+        methods: {
+            init() {
+                this.consoleInterval = setInterval(() => {
+                    this.getTrafficControlInfos()
+                }, 1000)
+            },
+            getTrafficControlInfos() {
+                let that = this;
+                $.ajax({
+                    url: baseUrl + "/trafficControl/getTrafficControlInfos",
+                    headers: {'token': localStorage.getItem('token')},
+                    method: 'GET',
+                    data: {},
+                    success: function (res) {
+                        if (res.code === 200) {
+                            let list = []
+                            res.data.forEach((item) => {
+                                let nodeList = []
+                                item.nodeList.forEach((nodeItem) => {
+                                    let tmp = {
+                                        x: nodeItem.x,
+                                        y: nodeItem.y,
+                                        z: nodeItem.z
+                                    }
+                                    nodeList.push(tmp)
+                                })
+
+                                let totalNodeList = []
+                                item.totalNodeList.forEach((nodeItem) => {
+                                    let tmp = {
+                                        x: nodeItem.x,
+                                        y: nodeItem.y,
+                                        z: nodeItem.z
+                                    }
+                                    totalNodeList.push(tmp)
+                                })
+
+                                item.nodeList = nodeList;
+                                item.totalNodeList = totalNodeList;
+
+                                list.push(item)
+                            })
+
+                            that.controlList = list;
+                        } else if (res.code === 403) {
+                            window.location.href = baseUrl + "/login";
+                        } else {
+                            that.$message({
+                                message: res.msg,
+                                type: 'warning'
+                            });
+                        }
+                    }
+                });
+            },
+            cancelTraffic(item) {
+                let that = this;
+                $.ajax({
+                    url: baseUrl + "/trafficControl/cancelTraffic",
+                    headers: {'token': localStorage.getItem('token')},
+                    method: 'POST',
+                    data: {
+                        shuttleNo: item.shuttleNo,
+                        taskNo: item.taskNo
+                    },
+                    success: function (res) {
+                        if (res.code === 200) {
+                            that.$message({
+                                message: res.msg,
+                                type: 'success'
+                            });
+                        } else if (res.code === 403) {
+                            window.location.href = baseUrl + "/login";
+                        } else {
+                            that.$message({
+                                message: res.msg,
+                                type: 'warning'
+                            });
+                        }
+                    }
+                });
+            }
+        }
+    })
+</script>
+</html>
\ No newline at end of file

--
Gitblit v1.9.1