From 80e7cf6660fd0c98350503f3f852fdae088d6d3c Mon Sep 17 00:00:00 2001
From: liejiu946 <liejiu946@163.com>
Date: Fri, 28 Feb 2025 17:35:42 +0800
Subject: [PATCH] =?UTF-8?q?opt:=201.=E6=96=B0=E5=A2=9E=E5=8F=8D=E9=A6=88WC?=
 =?UTF-8?q?S=E4=BB=BB=E5=8A=A1=E7=8A=B6=E6=80=81=E9=87=8D=E5=8F=91?=
 =?UTF-8?q?=E6=9C=BA=E5=88=B6=E3=80=822.=E5=8F=96=E8=B4=A7=E5=AE=8C?=
 =?UTF-8?q?=E6=88=90=E5=90=8ENDC=E8=BF=9B=E8=A1=8C=E5=8F=96=E6=B6=88?=
 =?UTF-8?q?=E4=BB=BB=E5=8A=A1=20=E5=B0=86=E5=8F=8D=E9=A6=88WMS=E4=BB=BB?=
 =?UTF-8?q?=E5=8A=A1=E5=AE=8C=E6=88=90=E3=80=823.=E4=BF=AE=E5=A4=8D?=
 =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BB=BB=E5=8A=A1=E7=8A=B6=E6=80=81=20?=
 =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E5=85=B6=E5=AE=83=E9=97=AE=E9=A2=98?=
 =?UTF-8?q?=E3=80=824.=E8=A7=A3=E5=86=B3hutool=20=E5=AF=BC=E5=87=BAexcel?=
 =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=8A=A5=E9=94=99apache.poi=E7=89=88?=
 =?UTF-8?q?=E6=9C=AC=E8=BF=87=E4=BD=8E=E4=B8=8D=E5=85=BC=E5=AE=B9=E9=97=AE?=
 =?UTF-8?q?=E9=A2=98=20=E5=BC=95=E5=85=A54.0.0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 nlsso-server/pom.xml                          | 17 +++++
 .../service/impl/InstructionServiceImpl.java  | 12 ++++
 .../org/nl/acs/task/service/TaskService.java  |  6 ++
 .../task/service/impl/TaskServiceImpl.java    | 63 +++++++++++++++----
 .../org/nl/quartz/task/ResendRequestWCS.java  | 55 ++++++++++++++++
 .../main/resources/log/ResendRequestWCS.xml   | 32 ++++++++++
 .../src/main/resources/logback-spring.xml     |  1 +
 7 files changed, 175 insertions(+), 11 deletions(-)
 create mode 100644 nlsso-server/src/main/java/org/nl/quartz/task/ResendRequestWCS.java
 create mode 100644 nlsso-server/src/main/resources/log/ResendRequestWCS.xml

diff --git a/nlsso-server/pom.xml b/nlsso-server/pom.xml
index 0c7374e..0bb50eb 100644
--- a/nlsso-server/pom.xml
+++ b/nlsso-server/pom.xml
@@ -115,6 +115,23 @@
             <artifactId>hutool-all</artifactId>
             <version>${hutool.version}</version>
         </dependency>
+
+        <!-- 解决hutool 导出excel数据报错apache.poi版本过低不兼容问题 引入4.0.0 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>4.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml-schemas</artifactId>
+            <version>4.0.0</version>
+        </dependency>
         <!--Spring boot 核心 -->
 
         <dependency>
diff --git a/nlsso-server/src/main/java/org/nl/acs/instruction/service/impl/InstructionServiceImpl.java b/nlsso-server/src/main/java/org/nl/acs/instruction/service/impl/InstructionServiceImpl.java
index 613af1a..2d09a59 100644
--- a/nlsso-server/src/main/java/org/nl/acs/instruction/service/impl/InstructionServiceImpl.java
+++ b/nlsso-server/src/main/java/org/nl/acs/instruction/service/impl/InstructionServiceImpl.java
@@ -29,6 +29,7 @@ import org.nl.acs.device.domain.Device;
 import org.nl.acs.device.service.DeviceService;
 import org.nl.acs.device.service.impl.DeviceServiceImpl;
 import org.nl.acs.device_driver.DeviceDriver;
+import org.nl.acs.device_driver.basedriver.agv.ndcone.AgvNdcOneDeviceDriver;
 import org.nl.acs.device_driver.basedriver.hongxiang_device.HongXiangConveyorDeviceDriver;
 import org.nl.acs.device_driver.basedriver.siemens_conveyor.SiemensConveyorDeviceDriver;
 import org.nl.acs.device_driver.basedriver.standard_conveyor_control_with_scanner.StandardCoveyorControlWithScannerDeviceDriver;
@@ -1382,6 +1383,17 @@ public class InstructionServiceImpl extends CommonServiceImpl<InstructionMapper,
         DeviceAppService appService = SpringContextHolder.getBean(DeviceAppServiceImpl.class);
         DeviceService deviceService = SpringContextHolder.getBean(DeviceServiceImpl.class);
 
+        //判断agv执行状态是否已经完成取货,取货完成后NDC进行取消任务 将反馈WMS任务完成
+        if (StrUtil.isBlank(entity.getCarno())){
+            Device device =  appService.findDeviceByCode(entity.getCarno());
+            if (device !=null && device.getDeviceDriver() instanceof AgvNdcOneDeviceDriver){
+                AgvNdcOneDeviceDriver agvNdcOneDeviceDriver = (AgvNdcOneDeviceDriver) device.getDeviceDriver();
+                if (agvNdcOneDeviceDriver.getAgv_status()>=5){
+                    taskService.ndcCancelSendWmsFinish(entity.getTask_id());
+                }
+            }
+        }
+
         // 如果是无光电的设备 指令完成变更起点、终点状态
         JSONObject jo = new JSONObject();
         jo.put("device_code", entity.getStart_device_code());
diff --git a/nlsso-server/src/main/java/org/nl/acs/task/service/TaskService.java b/nlsso-server/src/main/java/org/nl/acs/task/service/TaskService.java
index 1b51545..e030157 100644
--- a/nlsso-server/src/main/java/org/nl/acs/task/service/TaskService.java
+++ b/nlsso-server/src/main/java/org/nl/acs/task/service/TaskService.java
@@ -218,6 +218,12 @@ public interface TaskService extends CommonService<Task>  {
      */
     void finish(String ids);
 
+    /**
+     * 取货完成后NDC进行取消任务 将反馈WMS任务完成
+     * @param ids
+     */
+    void ndcCancelSendWmsFinish(String ids);
+
     /**
      * 取消任务
      *
diff --git a/nlsso-server/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java b/nlsso-server/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java
index f357ef2..fb47afb 100644
--- a/nlsso-server/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java
+++ b/nlsso-server/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java
@@ -11,6 +11,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
+import jodd.util.StringUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.nl.acs.AcsConfig;
 import org.nl.acs.agv.server.XianGongAgvService;
@@ -50,6 +51,7 @@ import org.nl.acs.utils.PageUtil;
 import org.nl.common.exception.BadRequestException;
 import org.nl.common.utils.CodeUtil;
 import org.nl.common.utils.FileUtil;
+import org.nl.common.utils.RedisUtils;
 import org.nl.common.utils.SecurityUtils;
 import org.nl.config.SpringContextHolder;
 import org.nl.config.thread.ThreadPoolExecutorUtil;
@@ -312,7 +314,7 @@ public class TaskServiceImpl extends CommonServiceImpl<TaskMapper, Task> impleme
             }
         }
         if (StrUtil.isEmpty(is_over) && StrUtil.isEmpty(status)) {
-            wrapper.lt(Task::getTask_status, 2);
+            wrapper.lt(Task::getTask_status, 2).or().eq(Task::getTask_status,4);
         }
         IPage<Task> taskPage = taskMapper.selectPage(queryPage, wrapper);
         final JSONObject json = (JSONObject) JSON.toJSON(ConvertUtil.convertPage(taskPage, TaskDto.class));
@@ -885,17 +887,33 @@ public class TaskServiceImpl extends CommonServiceImpl<TaskMapper, Task> impleme
 
     private void sendTaskStatus(FeedBackTaskStatusRequest request) {
         CompletableFuture<String> future = new CompletableFuture<>();
+        RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
         EXECUTOR.submit(() -> {
+
             try {
-                for (int i = 0; i < 10; i++) {
-                    log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + request.getTask_status());
-                    String resp = acstowmsService.feedTaskStatus(request);
-                    JSONObject result = JSONObject.parseObject(resp);
-                    if ("200".equals("200")) {
-                        log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "成功。");
-                        break;
-                    } else {
-                        log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "失败,服务器响应的失败原因为:" + result.getString("message"));
+                //判断redis里面是否有存储,存在该任务号信息 更新要发送的任务状态。不直接发送 避免网络恢复后同时请求多次。
+                if(redisUtils.hHasKey("ResendRequestWCS",request.getTask_code())){
+                    redisUtils.hset("ResendRequestWCS",request.getTask_code(),request);
+                }else {
+                    //反馈WCS任务状态,如果网络异常连续发送10次
+                    for (int i =0;i<10; i++){
+                        log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + request.getTask_status());
+                        String resp = acstowmsService.feedTaskStatus(request);
+                        JSONObject result = JSONObject.parseObject(resp);
+                        if (StringUtil.isNotBlank(result.getString("status")) && "200".equals(result.getString("status"))) {
+                            log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "成功。");
+                            break;
+                        } else if (StringUtil.isNotBlank(result.getString("status")) && !"200".equals(result.getString("status"))){
+                            log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "失败,服务器响应的失败原因为:" + result.getString("message"));
+                            break;
+                        }else if (StringUtil.isNotBlank(result.getString("code")) && "500".equals(result.getString("code"))){
+                            log.info("任务号" + request.getTask_code() + "请求不通" + "失败,服务器响应的失败原因为:" + result.getString("message"));
+                            //10次还没成功则加入定时任务来执行,直到WCS收到任务反馈。
+                            if (i == 9){
+                                //如果redis也出现断联的话可以考虑存储到内存
+                                redisUtils.hset("ResendRequestWCS",request.getTask_code(),request);
+                            }
+                        }
                     }
                 }
                 future.complete("反馈wcs任务完成状态");
@@ -957,6 +975,29 @@ public class TaskServiceImpl extends CommonServiceImpl<TaskMapper, Task> impleme
         }
     }
 
+    @Override
+    public void ndcCancelSendWmsFinish(String id) {
+        TaskDto entity = this.findById(id);
+        if (entity == null) throw new BadRequestException("被删除或无权限,操作失败!");
+        String currentUsername = SecurityUtils.getCurrentUsername();
+        String now = DateUtil.now();
+        entity.setUpdate_time(now);
+        entity.setUpdate_by(currentUsername);
+        entity.setTask_status("2");
+        // 判断是否为WMS下发的任务,如果是反馈任务状态给WMS
+        String hasWms = paramService.findByCode(AcsConfig.HASWMS).getValue();
+        if (!StrUtil.startWith(entity.getTask_code(), "-") && StrUtil.equals(hasWms, "1")) {
+            FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
+            request.setTask_id(entity.getExt_task_id());
+            request.setTask_code(entity.getTask_code());
+            request.setTask_status(entity.getTask_status());
+            request.setRequest_medthod_code(RequestMethodEnum.feedback_task_status.getCode());
+            request.setRequest_medthod_name(RequestMethodEnum.feedback_task_status.getName());
+            //反馈任务状态
+            sendTaskStatus(request);
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void cancel(String id) throws Exception {
@@ -1187,7 +1228,7 @@ public class TaskServiceImpl extends CommonServiceImpl<TaskMapper, Task> impleme
             throw new BadRequestException("被删除或无权限,操作失败!");
         }
         //只有执行中的任务才能创建指令
-        if (!"1".equals(acsTask.getTask_status())) {
+        if (!"1".equals(acsTask.getTask_status()) && !"4".equals(acsTask.getTask_status())) {
             throw new BadRequestException("任务未执行,不能创建指令!");
         }
         DeviceAppService appService = SpringContextHolder.getBean(DeviceAppServiceImpl.class);
diff --git a/nlsso-server/src/main/java/org/nl/quartz/task/ResendRequestWCS.java b/nlsso-server/src/main/java/org/nl/quartz/task/ResendRequestWCS.java
new file mode 100644
index 0000000..f5bd04f
--- /dev/null
+++ b/nlsso-server/src/main/java/org/nl/quartz/task/ResendRequestWCS.java
@@ -0,0 +1,55 @@
+package org.nl.quartz.task;
+
+import com.alibaba.fastjson.JSONObject;
+import jodd.util.StringUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.nl.acs.ext.wms.data.feedBackTaskStatus.FeedBackTaskStatusRequest;
+import org.nl.acs.ext.wms.service.AcsToWmsService;
+import org.nl.common.utils.RedisUtils;
+import org.nl.config.SpringContextHolder;
+import org.nl.config.thread.ThreadPoolExecutorUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @author liejiu
+ */
+@Slf4j
+@Component
+public class ResendRequestWCS {
+
+    @Resource
+    private RedisUtils redisUtils;
+
+    @Resource
+    AcsToWmsService acstowmsService;
+
+
+    public void run() throws Exception {
+        if (redisUtils.hasKey("ResendRequestWCS")) {
+            Map<Object, Object> resendRequestWCS = redisUtils.hmget("ResendRequestWCS");
+            resendRequestWCS.forEach((k, v) -> {
+
+                FeedBackTaskStatusRequest request = (FeedBackTaskStatusRequest) v;
+                String resp = acstowmsService.feedTaskStatus(request);
+                JSONObject result = JSONObject.parseObject(resp);
+                if (StringUtil.isNotBlank(result.getString("status")) && "200".equals(result.getString("status"))) {
+                    log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "成功。");
+                    redisUtils.hdel("ResendRequestWCS", request.getTask_code());
+                } else if (StringUtil.isNotBlank(result.getString("status")) && !"200".equals(result.getString("status"))) {
+                    log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "失败,服务器响应的失败原因为:" + result.getString("message"));
+                    redisUtils.hdel("ResendRequestWCS", request.getTask_code());
+                } else if (StringUtil.isNotBlank(result.getString("code")) && "500".equals(result.getString("code"))) {
+                    log.info("任务号" + request.getTask_code() + "请求不通" + "失败,服务器响应的失败原因为:" + result.getString("message"));
+                }
+
+            });
+        }
+
+    }
+}
diff --git a/nlsso-server/src/main/resources/log/ResendRequestWCS.xml b/nlsso-server/src/main/resources/log/ResendRequestWCS.xml
new file mode 100644
index 0000000..1916f06
--- /dev/null
+++ b/nlsso-server/src/main/resources/log/ResendRequestWCS.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<included>
+    <springProperty scope="context" name="logPath" source="logging.file.path" defaultValue="logs"/>
+    <property name="LOG_HOME" value="${logPath}"/>
+    <!-- 按照每天生成日志文件 -->
+    <appender name="ResendRequestWCS" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <!--日志文件输出的文件名-->
+            <FileNamePattern>${LOG_HOME}/ACS请求WMS重发/%d{yyyy-MM-dd}.%i.log</FileNamePattern>
+            <!--日志文件保留天数-->
+            <maxHistory>15</maxHistory>
+            <!--单个日志最大容量 至少10MB才能看得出来-->
+            <maxFileSize>100MB</maxFileSize>
+            <!--所有日志最多占多大容量-->
+            <totalSizeCap>2GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>${log.charset}</charset>
+        </encoder>
+    </appender>
+
+    <appender name="asyncFileAppender" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="ResendRequestWCS" />
+        <!-- 设置队列大小,根据您的需求调整 -->
+        <queueSize>512</queueSize>
+    </appender>
+    <logger name="org.nl.quartz.task.ResendRequestWCS" level="info" additivity="true">
+        <appender-ref ref="asyncFileAppender"/>
+    </logger>
+</included>
diff --git a/nlsso-server/src/main/resources/logback-spring.xml b/nlsso-server/src/main/resources/logback-spring.xml
index a9b8bd7..966aa77 100644
--- a/nlsso-server/src/main/resources/logback-spring.xml
+++ b/nlsso-server/src/main/resources/logback-spring.xml
@@ -27,6 +27,7 @@ https://juejin.cn/post/6844903775631572999
     <include resource="log/NDCSocketConnectionAutoRun.xml"/>
     <include resource="log/AgvNdcOneDeviceDriver.xml"/>
     <include resource="log/NDCAgvServiceImpl.xml"/>
+    <include resource="log/ResendRequestWCS.xml"/>
 
     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
         <!--        控制台高亮-->