From bc729b420fc0db8db80fc4d2b8e67f56edada33e Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期一, 13 四月 2026 10:23:35 +0800
Subject: [PATCH] #

---
 version/doc/hua/华睿科技VDA5050协议接入手册-V1.009.pdf                                                         |    0 
 zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java                            |    2 
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/hik/HikInstantActionPublishService.java |   83 ++++++++++++++++++++
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java                          |   14 +++
 version/doc/hua/华睿机器人设备对接协议说明V1.016.pdf                                                              |    0 
 zy-acs-hk/zy-acs-hk-latent/src/main/java/com/zy/acs/hk/latent/listen/MessageListener.java            |   89 +++++++++++++++++----
 zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkInstantActionDown.java                     |   18 ++++
 7 files changed, 188 insertions(+), 18 deletions(-)

diff --git "a/version/doc/hua/\345\215\216\347\235\277\346\234\272\345\231\250\344\272\272\350\256\276\345\244\207\345\257\271\346\216\245\345\215\217\350\256\256\350\257\264\346\230\216V1.016.pdf" "b/version/doc/hua/\345\215\216\347\235\277\346\234\272\345\231\250\344\272\272\350\256\276\345\244\207\345\257\271\346\216\245\345\215\217\350\256\256\350\257\264\346\230\216V1.016.pdf"
new file mode 100644
index 0000000..9507269
--- /dev/null
+++ "b/version/doc/hua/\345\215\216\347\235\277\346\234\272\345\231\250\344\272\272\350\256\276\345\244\207\345\257\271\346\216\245\345\215\217\350\256\256\350\257\264\346\230\216V1.016.pdf"
Binary files differ
diff --git "a/version/doc/hua/\345\215\216\347\235\277\347\247\221\346\212\200VDA5050\345\215\217\350\256\256\346\216\245\345\205\245\346\211\213\345\206\214-V1.009.pdf" "b/version/doc/hua/\345\215\216\347\235\277\347\247\221\346\212\200VDA5050\345\215\217\350\256\256\346\216\245\345\205\245\346\211\213\345\206\214-V1.009.pdf"
new file mode 100644
index 0000000..02560b1
--- /dev/null
+++ "b/version/doc/hua/\345\215\216\347\235\277\347\247\221\346\212\200VDA5050\345\215\217\350\256\256\346\216\245\345\205\245\346\211\213\345\206\214-V1.009.pdf"
Binary files differ
diff --git a/zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java b/zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java
index d2db9d0..d8c8010 100644
--- a/zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java
+++ b/zy-acs-common/src/main/java/com/zy/acs/common/constant/RedisConstant.java
@@ -61,6 +61,8 @@
 
     public static final String HK_AGV_PATH_DOWN_FLAG = "HK_AGV_PATH_DOWN_FLAG";
 
+    public static final String HK_AGV_INSTANT_ACTION_DOWN_FLAG = "HK_AGV_INSTANT_ACTION_DOWN_FLAG";
+
     public static final String HK_AGV_DATA_FLAG = "HK_AGV_DATA_FLAG";
 
 }
diff --git a/zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkInstantActionDown.java b/zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkInstantActionDown.java
new file mode 100644
index 0000000..a345731
--- /dev/null
+++ b/zy-acs-common/src/main/java/com/zy/acs/common/hk/action/HkInstantActionDown.java
@@ -0,0 +1,18 @@
+package com.zy.acs.common.hk.action;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 娴峰悍鍗虫椂鍔ㄤ綔涓嬪彂闃熷垪娑堟伅銆�
+ */
+@Data
+public class HkInstantActionDown implements Serializable {
+
+    private static final long serialVersionUID = 7609495759663594622L;
+
+    private String agvNo;
+
+    private HkInstantActionMessage instantActionMessage;
+}
diff --git a/zy-acs-hk/zy-acs-hk-latent/src/main/java/com/zy/acs/hk/latent/listen/MessageListener.java b/zy-acs-hk/zy-acs-hk-latent/src/main/java/com/zy/acs/hk/latent/listen/MessageListener.java
index afa7433..e1e0473 100644
--- a/zy-acs-hk/zy-acs-hk-latent/src/main/java/com/zy/acs/hk/latent/listen/MessageListener.java
+++ b/zy-acs-hk/zy-acs-hk-latent/src/main/java/com/zy/acs/hk/latent/listen/MessageListener.java
@@ -2,10 +2,13 @@
 
 import com.alibaba.fastjson.JSON;
 import com.zy.acs.common.constant.RedisConstant;
+import com.zy.acs.common.hk.action.HkInstantActionDown;
+import com.zy.acs.common.hk.action.HkInstantActionMessage;
 import com.zy.acs.common.hk.order.HkOrderDown;
 import com.zy.acs.common.hk.order.HkOrderMessage;
 import com.zy.acs.common.utils.RedisSupport;
 import com.zy.acs.framework.common.Cools;
+import com.zy.acs.hk.latent.mqtt.publisher.HkInstantActionPublisher;
 import com.zy.acs.hk.latent.mqtt.publisher.HkOrderPublisher;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -29,6 +32,8 @@
 
     @Autowired
     private HkOrderPublisher hkOrderPublisher;
+    @Autowired
+    private HkInstantActionPublisher hkInstantActionPublisher;
 
     @PostConstruct
     private void start(){
@@ -36,24 +41,12 @@
             while (!Thread.currentThread().isInterrupted()) {
                 HkOrderDown orderDown = redis.pop(RedisConstant.HK_AGV_PATH_DOWN_FLAG);
                 if (orderDown != null) {
-                    try {
-                        log.info("鐩戝惉鍣� >>> {}", JSON.toJSONString(orderDown));
-                        HkOrderMessage orderMessage = normalize(orderDown);
-                        if (orderMessage == null) {
-                            log.error("drop invalid hk order message, payload={}", JSON.toJSONString(orderDown));
-                        } else {
-                            hkOrderPublisher.publish(orderMessage);
-                        }
-                    } catch (IllegalArgumentException e) {
-                        log.error("drop illegal hk order message, payload={}", JSON.toJSONString(orderDown), e);
-                    } catch (Exception e) {
-                        log.error("publish hk order failed, requeue to head payload={}", JSON.toJSONString(orderDown), e);
-                        try {
-                            redis.pushHeadStrict(RedisConstant.HK_AGV_PATH_DOWN_FLAG, orderDown);
-                        } catch (Exception pushEx) {
-                            log.error("requeue hk order failed, payload={}", JSON.toJSONString(orderDown), pushEx);
-                        }
-                    }
+                    handleOrderDown(orderDown);
+                }
+
+                HkInstantActionDown instantActionDown = redis.pop(RedisConstant.HK_AGV_INSTANT_ACTION_DOWN_FLAG);
+                if (instantActionDown != null) {
+                    handleInstantActionDown(instantActionDown);
                 }
                 // 闂撮殧
                 try {
@@ -67,6 +60,48 @@
     @PreDestroy
     public void shutDown(){
         if (thread != null) thread.interrupt();
+    }
+
+    private void handleOrderDown(HkOrderDown orderDown) {
+        try {
+            log.info("鐩戝惉鍣� >>> {}", JSON.toJSONString(orderDown));
+            HkOrderMessage orderMessage = normalize(orderDown);
+            if (orderMessage == null) {
+                log.error("drop invalid hk order message, payload={}", JSON.toJSONString(orderDown));
+            } else {
+                hkOrderPublisher.publish(orderMessage);
+            }
+        } catch (IllegalArgumentException e) {
+            log.error("drop illegal hk order message, payload={}", JSON.toJSONString(orderDown), e);
+        } catch (Exception e) {
+            log.error("publish hk order failed, requeue to head payload={}", JSON.toJSONString(orderDown), e);
+            try {
+                redis.pushHeadStrict(RedisConstant.HK_AGV_PATH_DOWN_FLAG, orderDown);
+            } catch (Exception pushEx) {
+                log.error("requeue hk order failed, payload={}", JSON.toJSONString(orderDown), pushEx);
+            }
+        }
+    }
+
+    private void handleInstantActionDown(HkInstantActionDown instantActionDown) {
+        try {
+            log.info("鐩戝惉鍣� >>> {}", JSON.toJSONString(instantActionDown));
+            HkInstantActionMessage instantActionMessage = normalize(instantActionDown);
+            if (instantActionMessage == null) {
+                log.error("drop invalid hk instant action message, payload={}", JSON.toJSONString(instantActionDown));
+            } else {
+                hkInstantActionPublisher.publish(instantActionMessage);
+            }
+        } catch (IllegalArgumentException e) {
+            log.error("drop illegal hk instant action message, payload={}", JSON.toJSONString(instantActionDown), e);
+        } catch (Exception e) {
+            log.error("publish hk instant action failed, requeue to head payload={}", JSON.toJSONString(instantActionDown), e);
+            try {
+                redis.pushHeadStrict(RedisConstant.HK_AGV_INSTANT_ACTION_DOWN_FLAG, instantActionDown);
+            } catch (Exception pushEx) {
+                log.error("requeue hk instant action failed, payload={}", JSON.toJSONString(instantActionDown), pushEx);
+            }
+        }
     }
 
     private HkOrderMessage normalize(HkOrderDown orderDown) {
@@ -93,4 +128,22 @@
         return orderMessage;
     }
 
+    private HkInstantActionMessage normalize(HkInstantActionDown instantActionDown) {
+        if (instantActionDown == null || instantActionDown.getInstantActionMessage() == null) {
+            return null;
+        }
+
+        HkInstantActionMessage instantActionMessage = instantActionDown.getInstantActionMessage();
+        if (Cools.isEmpty(instantActionMessage.getSerialNumber()) && !Cools.isEmpty(instantActionDown.getAgvNo())) {
+            instantActionMessage.setSerialNumber(instantActionDown.getAgvNo());
+        }
+        if (Cools.isEmpty(instantActionMessage.getSerialNumber())) {
+            return null;
+        }
+        if (instantActionMessage.getInstantActions() == null || instantActionMessage.getInstantActions().isEmpty()) {
+            return null;
+        }
+        return instantActionMessage;
+    }
+
 }
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
index 2e52cda..77fec31 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
@@ -13,6 +13,7 @@
 import com.zy.acs.manager.common.domain.param.HandlerPublishParam;
 import com.zy.acs.manager.common.exception.BusinessException;
 import com.zy.acs.manager.core.service.*;
+import com.zy.acs.manager.core.service.hik.HikInstantActionPublishService;
 import com.zy.acs.manager.core.service.astart.MapDataDispatcher;
 import com.zy.acs.manager.core.service.astart.domain.DynamicNode;
 import com.zy.acs.manager.manager.entity.*;
@@ -81,6 +82,8 @@
     private AgvAreaDispatcher agvAreaDispatcher;
     @Autowired
     private ConfigService configService;
+    @Autowired
+    private HikInstantActionPublishService hikInstantActionPublishService;
 
     @PreAuthorize("hasAuthority('manager:agv:update')")
     @OperationLog("Locate All Agv")
@@ -467,6 +470,7 @@
         }
 
         if (null != agv) {
+            publishRestoreCancelIfNeeded(agv);
             mapDataDispatcher.modifyDynamicMatrix(null, null, agv.getUuid(), true);
             avoidWaveCalculator.calcDynamicNodeByVehicle(agv, null);
 
@@ -477,6 +481,7 @@
         } else {
             List<Agv> agvList = agvService.list(new LambdaQueryWrapper<Agv>());
             for (Agv one : agvList) {
+                publishRestoreCancelIfNeeded(one);
                 mapDataDispatcher.modifyDynamicMatrix(null, null, one.getUuid(), true);
                 avoidWaveCalculator.calcDynamicNodeByVehicle(one, null);
             }
@@ -490,6 +495,15 @@
         return R.ok();
     }
 
+    private void publishRestoreCancelIfNeeded(Agv agv) {
+        if (agv == null) {
+            return;
+        }
+        if (hikInstantActionPublishService.support(agv.getId())) {
+            hikInstantActionPublishService.publishCancelOrder(agv.getUuid());
+        }
+    }
+
     @RequestMapping(value = "/unlock", method = {RequestMethod.GET, RequestMethod.POST})
     public R unlockPath(@RequestHeader String appKey,
                               @RequestBody HandlerPublishParam param) throws ExecutionException, InterruptedException {
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/hik/HikInstantActionPublishService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/hik/HikInstantActionPublishService.java
new file mode 100644
index 0000000..09da197
--- /dev/null
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/service/hik/HikInstantActionPublishService.java
@@ -0,0 +1,83 @@
+package com.zy.acs.manager.core.service.hik;
+
+import com.zy.acs.common.constant.RedisConstant;
+import com.zy.acs.common.hk.action.HkAction;
+import com.zy.acs.common.hk.action.HkActionParameter;
+import com.zy.acs.common.hk.action.HkInstantActionDown;
+import com.zy.acs.common.hk.action.HkInstantActionMessage;
+import com.zy.acs.common.hk.action.type.HkActionType;
+import com.zy.acs.common.utils.Utils;
+import com.zy.acs.framework.common.SnowflakeIdWorker;
+import com.zy.acs.framework.exception.CoolException;
+import com.zy.acs.manager.common.config.HikOrderProperties;
+import com.zy.acs.manager.manager.entity.AgvModel;
+import com.zy.acs.manager.manager.service.AgvModelService;
+import com.zy.acs.common.utils.RedisSupport;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+@Slf4j
+@Service
+public class HikInstantActionPublishService {
+
+    private final RedisSupport redis = RedisSupport.defaultRedisSupport;
+
+    @Autowired
+    private HikOrderProperties hikOrderProperties;
+    @Autowired
+    private SnowflakeIdWorker snowflakeIdWorker;
+    @Autowired
+    private AgvModelService agvModelService;
+
+    public boolean support(Long agvId) {
+        AgvModel agvModel = agvModelService.getByAgvId(agvId);
+        if (agvModel == null || !StringUtils.hasText(agvModel.getProtocol())) {
+            return false;
+        }
+        return agvModel.getProtocol().toLowerCase(Locale.ROOT).contains("hik");
+    }
+
+    public void publishCancelOrder(String agvNo) {
+        if (!StringUtils.hasText(agvNo)) {
+            throw new CoolException("agvNo can not be blank");
+        }
+
+        HkInstantActionMessage message = new HkInstantActionMessage();
+        message.setHeaderId(snowflakeIdWorker.nextId());
+        message.setTimestamp(Instant.now().toString());
+        message.setVersion(hikOrderProperties.getMajorVersion());
+        message.setManufacturer(hikOrderProperties.getManufacturer());
+        message.setSerialNumber(agvNo);
+        message.setInstantActions(Utils.singletonList(buildCancelOrderAction()));
+
+        HkInstantActionDown down = new HkInstantActionDown();
+        down.setAgvNo(agvNo);
+        down.setInstantActionMessage(message);
+        redis.pushStrict(RedisConstant.HK_AGV_INSTANT_ACTION_DOWN_FLAG, down);
+
+        log.info("push hik cancelOrder instant action to redis, agvNo={}, redisKey={}",
+                agvNo, RedisConstant.HK_AGV_INSTANT_ACTION_DOWN_FLAG);
+    }
+
+    private HkAction buildCancelOrderAction() {
+        HkAction action = new HkAction();
+        action.setActionId("cancelOrder-" + snowflakeIdWorker.nextId());
+        action.setActionType(HkActionType.CANCEL_ORDER);
+        action.setActionDescription("restoreAgv cancel current order");
+
+        List<HkActionParameter> parameters = new ArrayList<>();
+        HkActionParameter parameter = new HkActionParameter();
+        parameter.setKey("instantStop");
+        parameter.setValue(Boolean.FALSE);   // true: 绔嬪嵆鍋滆溅锛� false锛氬湪灏辫繎鐐逛綅涓婂仠杞�
+        parameters.add(parameter);
+        action.setActionParameters(parameters);
+        return action;
+    }
+}

--
Gitblit v1.9.1