Преглед изворни кода

Merge branch 'master' of http://192.168.1.43:3000/git/sass-lab-distributed-java

zhuchangxue пре 3 година
родитељ
комит
557cd43370

+ 12 - 0
zd-modules/zd-forward/pom.xml

@@ -83,6 +83,18 @@
             <groupId>com.zd</groupId>
             <artifactId>zd-common-mqtt</artifactId>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/org.bytedeco/ffmpeg-platform -->
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>ffmpeg-platform</artifactId>
+            <version>5.0-1.5.7</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv -->
+        <dependency>
+            <groupId>org.bytedeco</groupId>
+            <artifactId>javacv</artifactId>
+            <version>1.5.7</version>
+        </dependency>
 
     </dependencies>
     <build>

+ 2 - 6
zd-modules/zd-forward/src/main/java/com/zd/forward/ForwardApp.java

@@ -2,6 +2,7 @@ package com.zd.forward;
 
 import com.zd.common.security.annotation.EnableCustomConfig;
 import com.zd.common.security.annotation.EnableRyFeignClients;
+import com.zd.forward.properties.FireProperties;
 import com.zd.forward.serivce.LoginService;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -11,15 +12,10 @@ import org.springframework.context.ConfigurableApplicationContext;
 import springfox.documentation.oas.annotations.EnableOpenApi;
 import zd.common.mqtt.config.MqttProperties;
 
-/**
- * @Author: zhoupan
- * @Date: 2021/11/13/11:41
- * @Description:
- */
 @EnableCustomConfig
 @EnableRyFeignClients
 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
-@EnableConfigurationProperties(MqttProperties.class)
+@EnableConfigurationProperties({MqttProperties.class, FireProperties.class})
 @EnableOpenApi
 public class ForwardApp {
 

+ 0 - 6
zd-modules/zd-forward/src/main/java/com/zd/forward/component/AppStartedListener.java

@@ -17,11 +17,6 @@ import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 
-/**
- * @Author: zhoupan
- * @Date: 2021/11/14/11:30
- * @Description:
- */
 @Component
 public class AppStartedListener implements ApplicationListener<ApplicationStartedEvent> {
     Logger logger = LoggerFactory.getLogger(AppStartedListener.class);
@@ -106,6 +101,5 @@ public class AppStartedListener implements ApplicationListener<ApplicationStarte
                 applicationStartedEvent.getApplicationContext().close();
             }
         });
-
     }
 }

+ 8 - 1
zd-modules/zd-forward/src/main/java/com/zd/forward/config/AlgorithmYml.java

@@ -1,6 +1,7 @@
 package com.zd.forward.config;
 
 
+import com.zd.common.core.exception.ServiceException;
 import com.zd.forward.serivce.CheckResultValid;
 import com.zd.forward.serivce.ImageCheckResultValidImpl;
 import com.zd.forward.serivce.VideoCheckResultValid;
@@ -12,6 +13,7 @@ import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.util.Collections;
 import java.util.Map;
+import java.util.Optional;
 
 @ConfigurationProperties("sys.config")
 @RefreshScope
@@ -216,7 +218,7 @@ public class AlgorithmYml {
         @NotNull (message = "算法ID不能为空")
         private Integer algoId;
         //cid
-        @NotNull (message = "=数据ID不能为空")
+        @NotNull (message = "数据ID不能为空")
         private String did;
 
         private String algorithmName;
@@ -283,4 +285,9 @@ public class AlgorithmYml {
     public void setAlgorithmMap(Map<Integer,CheckValid> algorithmMap) {
         this.algorithmMap = algorithmMap;
     }
+
+    public AlgorithmYml.CheckValid getCheckValid(Integer code) {
+        return Optional.ofNullable(getAlgorithmMap().get(code))
+                .orElseThrow(() -> new ServiceException("未配置对应算法code:" + code));
+    }
 }

+ 34 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/listener/StartListener.java

@@ -0,0 +1,34 @@
+package com.zd.forward.listener;
+
+import com.zd.forward.serivce.FireImageService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * 监听Spring容器启动完成,完成后启动Netty服务器
+ *
+ * @author dgs
+ **/
+@Component
+@Slf4j
+public class StartListener implements ApplicationRunner {
+    @Resource
+    private FireImageService fireImageService;
+
+    @Override
+    public void run(ApplicationArguments args) {
+        //未验证部分,待验证后启用
+//        new Thread(new Runnable() {
+//            @Override
+//            public void run() {
+//                synchronized (this){
+//                    fireImageService.catchImage();
+//                }
+//            }
+//        }).start();
+    }
+}

+ 46 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/properties/FireProperties.java

@@ -0,0 +1,46 @@
+package com.zd.forward.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.validation.annotation.Validated;
+
+import javax.validation.constraints.NotNull;
+
+@ConfigurationProperties("fire")
+@RefreshScope
+@Validated
+@Data
+public class FireProperties {
+
+    @NotNull(message = "算法ID不能为空")
+    private Integer algoId;
+    //cid
+    @NotNull (message = "=数据ID不能为空")
+    private String did;
+
+    /**
+     * 实验室ID,和设备编号二选一即可
+     */
+    private Integer labId;
+
+    /**
+     * 设备编号,和实验室ID二选一即可
+     */
+    private String hardwareNum;
+    /**
+     * 算法名称
+     */
+    private String algorithmName;
+
+    /**
+     * 视频流地址
+     */
+    private String streamURL;
+
+    /**
+     * 间隔时间
+     */
+    private Integer waitTime=1;
+
+}

+ 8 - 120
zd-modules/zd-forward/src/main/java/com/zd/forward/serivce/CheckService.java

@@ -20,6 +20,7 @@ import com.zd.forward.domain.VideoRequestData;
 import com.zd.forward.serivce.mqtt.CommonSend;
 import com.zd.forward.util.Base64DecodedMultipartFile;
 import com.zd.forward.util.FileUploadUtils;
+import com.zd.forward.util.HttpUtils;
 import com.zd.system.api.RemoteFileService;
 import com.zd.system.api.alarm.RemoteAlarmService;
 import com.zd.system.api.alarm.domain.AlarmEntrty;
@@ -54,6 +55,8 @@ import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.util.*;
 
+import static com.zd.forward.util.HttpUtils.*;
+
 @Service
 @EnableConfigurationProperties(AlgorithmYml.class)
 @RefreshScope
@@ -125,10 +128,10 @@ public class CheckService {
             String[] checkItem = labCheckIn.split(",");
             for (String code : checkItem) {
                 //========= 获取算法INFO ===========
-                AlgorithmYml.CheckValid checkValid = getCheckValid(Integer.valueOf(code));
+                AlgorithmYml.CheckValid checkValid = algorithmYml.getCheckValid(Integer.valueOf(code));
                 MultiValueMap<String, Object> params = getStringObjectMultiValueMap(checkValid, String.valueOf(id));
                 HttpEntity<MultiValueMap<String, Object>> files=getHttpEntityMap(file,params);
-                ImgPostResponse<DataPostAnalysisRespDto> send = send(files, checkValid, id);
+                ImgPostResponse<DataPostAnalysisRespDto> send = HttpUtils.send(restTemplateLocal,files,algorithmYml);
                 if (send == null || send.getStatus_code() != 1000) {
                     assert send != null;
                     logger.error(send.getMessage());
@@ -175,10 +178,7 @@ public class CheckService {
     }
 
     /**
-     * @param code
-     * @param file
      * @param id   进出记录ID
-     * @return
      */
     public R checkAndCommit(String code, MultipartFile file, Long id) {
         //========= 请求超时验证部分开始 ===========
@@ -187,7 +187,7 @@ public class CheckService {
         if (fail.getCode() != 200) return fail;
         //========= 请求超时验证部分结束 ===========
         //========= 获取算法INFO ===========
-        AlgorithmYml.CheckValid checkValid = getCheckValid(Integer.valueOf(code));
+        AlgorithmYml.CheckValid checkValid = algorithmYml.getCheckValid(Integer.valueOf(code));
         //=========发送验证信息到算法服务开始
         JSONObject send = null;
         try {
@@ -270,7 +270,7 @@ public class CheckService {
         String[] codesArrs = codes.split(",");
         for (int i = 0; i < codesArrs.length; i++) {
             R r = checkAndCommit(codesArrs[i], file[i], ids[i]);
-            AlgorithmYml.CheckValid checkValid = getCheckValid(Integer.valueOf(codesArrs[i]));
+            AlgorithmYml.CheckValid checkValid = algorithmYml.getCheckValid(Integer.valueOf(codesArrs[i]));
             result.put(checkValid.getAlgoId(), r.getMsg() == null ? "通过" : r.getMsg());
 
         }
@@ -407,40 +407,6 @@ public class CheckService {
         sendSginAccessLogService.sendAddLogRest(code, id, f, msg, token, algorithmYml.getLoginUri() + algorithmYml.getCheckLogUrl());
     }
 
-    private AlgorithmYml.CheckValid getCheckValid(Integer code) {
-        return Optional.ofNullable(algorithmYml.getAlgorithmMap().get(code))
-                .orElseThrow(() -> new ServiceException("未配置对应算法code:" + code));
-    }
-
-    /**
-     * 构造算法文件逆流
-     * @param file
-     * @param params
-     * @return
-     */
-    private HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(MultipartFile file, MultiValueMap<String, Object> params){
-        try {
-            //设置请求头
-            HttpHeaders headers = new HttpHeaders();
-            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
-            // 文件本地存储收集
-            //FileUploadUtils.upload(localFilePath, file);
-            //MultipartFile 转为临时文件
-            File uploadFile = multipartFileToFile(file);
-            //文件转为文件系统资源
-            FileSystemResource fileSystemResource = new FileSystemResource(uploadFile);
-            //设置请求体,注意是LinkedMultiValueMap
-            MultiValueMap<String, Object> form = getStringObjectMultiValueMap(fileSystemResource);
-            form.addAll(params);
-            //用HttpEntity封装整个请求报文
-            HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers);
-            return files;
-        }catch (IOException ex){
-            ex.printStackTrace();
-        }
-        return null;
-    }
-
     /**
      * 获取算法请求地址
      * @param checkValid
@@ -460,23 +426,6 @@ public class CheckService {
         return paramUrl;
     }
 
-
-    public ImgPostResponse<DataPostAnalysisRespDto> send(HttpEntity<MultiValueMap<String, Object>> files,AlgorithmYml.CheckValid checkValid, Long id){
-        ParameterizedTypeReference<ImgPostResponse<DataPostAnalysisRespDto>> reference = new ParameterizedTypeReference<ImgPostResponse<DataPostAnalysisRespDto>>() {
-        };
-        ResponseEntity<ImgPostResponse<DataPostAnalysisRespDto>> response = restTemplateLocal.exchange(algorithmYml.getImgPostUrl(), HttpMethod.POST, files, reference);
-        if (response.getStatusCode()!=HttpStatus.OK){
-            logger.error("算法服务请求异常,请查看算服务器");
-            throw new ServiceException("算法服务请求异常,请查看算服务器");
-        }
-        if (response.getBody()==null){
-            logger.error("算法服务接口返回异常");
-            throw new ServiceException("算法服务接口返回异常");
-        }
-        return response.getBody();
-    }
-
-
     /**
      * 图片算法请求参数
      *
@@ -500,13 +449,7 @@ public class CheckService {
             FileSystemResource fileSystemResource = new FileSystemResource(uploadFile);
             //设置请求体,注意是LinkedMultiValueMap
             MultiValueMap<String, Object> params = getStringObjectMultiValueMap(checkValid, String.valueOf(id));
-//            Set<String> keySet = params.keySet();
-//            StringBuilder stb = new StringBuilder();
-//            String paramStr = "";
-//            for (String key : keySet) {
-//                stb.append("&").append(key).append("=").append(params.get(key).get(0).toString());
-//            }
-//            paramStr = String.valueOf(stb).replaceFirst("&", "?");
+
             MultiValueMap<String, Object> form = getStringObjectMultiValueMap(fileSystemResource);
             params.addAll(form);
             //用HttpEntity封装整个请求报文
@@ -524,61 +467,6 @@ public class CheckService {
         }
     }
 
-
-    /**
-     * 构建算法图片post请求 参数:只构建文件
-     *
-     * @param
-     * @param fileSystemResource
-     * @return
-     */
-    private MultiValueMap<String, Object> getStringObjectMultiValueMap(FileSystemResource fileSystemResource) {
-        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
-        form.add("file", fileSystemResource);
-        return form;
-    }
-
-    /**
-     * 构建算法图片post请求 参数
-     *
-     * @param checkValid
-     * @return
-     */
-    private MultiValueMap<String, Object> getStringObjectMultiValueMap(AlgorithmYml.CheckValid checkValid, String extension) {
-        MultiValueMap<String, Object> form = getStringObjectMultiValueMap(extension);
-        form.add("algoId", checkValid.getAlgoId());
-        form.add("did", checkValid.getDid());
-        return form;
-    }
-
-    private MultiValueMap<String, Object> getStringObjectMultiValueMap() {
-
-        return getStringObjectMultiValueMap(true, null);
-    }
-
-    private MultiValueMap<String, Object> getStringObjectMultiValueMap(String extension) {
-
-        return getStringObjectMultiValueMap(true, extension);
-    }
-
-    private MultiValueMap<String, Object> getStringObjectMultiValueMap(boolean sync, String extension) {
-        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
-        //1-同步(默认),0-异步
-        form.add("sync", sync ? 1 : 0);
-        form.add("timestamp", LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000);
-        form.add("extension", extension);
-        return form;
-    }
-
-    public static File multipartFileToFile(MultipartFile file) throws IOException {
-        String originalFilename = file.getOriginalFilename();
-        String[] filename = originalFilename.split("\\.");
-        File toFile = File.createTempFile(filename[0], "." + filename[1]);
-        file.transferTo(toFile);
-        //toFile.deleteOnExit();//在jvm 退出时删除
-        return toFile;
-    }
-
     /**
      * base64转图片/视频
      *

+ 123 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/serivce/FireImageService.java

@@ -0,0 +1,123 @@
+package com.zd.forward.serivce;
+
+import com.zd.common.core.exception.ServiceException;
+import com.zd.common.core.utils.IdGen;
+import com.zd.forward.config.AlgorithmYml;
+import com.zd.forward.domain.DataPostAnalysisRespDto;
+import com.zd.forward.domain.ImgPostResponse;
+import com.zd.forward.properties.FireProperties;
+import com.zd.forward.util.HttpUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+import org.bytedeco.javacv.Frame;
+import org.bytedeco.javacv.FrameGrabber;
+import org.bytedeco.javacv.Java2DFrameConverter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+
+import static com.zd.forward.util.HttpUtils.getHttpEntityMap;
+
+/**
+ * 火焰图片抓拍处理
+ */
+@Service
+@Slf4j
+public class FireImageService {
+
+    @Resource
+    private FireProperties fireProperties;
+    @Resource
+    private AlgorithmYml algorithmYml;
+
+    @Resource(name = "restTemplateLocal")
+    private RestTemplate restTemplateLocal;
+    @Resource
+    private SendSginAccessLogService sendSginAccessLogService;
+
+    /**
+     * 上传文件存储在本地的根路径
+     */
+    @Value("${file.path:/home/AIPIC}")
+    private String imagePath;
+
+    public void catchImage(){
+
+        String streamURL = fireProperties.getStreamURL();
+        if (streamURL==null){
+            throw new ServiceException("未配置流媒体地址");
+        }
+
+        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(streamURL);
+        try {
+            grabber.start();
+            //获取第一帧
+            Frame frame = grabber.grabFrame();
+            if (frame != null) {
+                int flag = 0;
+                while (frame != null) {
+                    //视频快照
+                    frame = grabber.grabImage();
+                    long uuid = IdGen.snowflakeId();
+                    //文件储存对象
+                    String fileName = imagePath+File.pathSeparator + uuid + "_" + flag;
+                    File tempFile = File.createTempFile(fileName, ".jpg");
+                    ImageIO.write(FrameToBufferedImage(frame), "jpg", tempFile);
+                    send(tempFile);
+                }
+                //停止
+                grabber.stop();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                grabber.stop();
+            } catch (FrameGrabber.Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void send(File file){
+        if (fireProperties.getAlgoId()==null){
+            throw new ServiceException("未配置火焰算法ID");
+        }
+        MultiValueMap<String, Object> params = HttpUtils.getMultiValueMap(fireProperties, null);
+        HttpEntity<MultiValueMap<String, Object>> files=getHttpEntityMap(file,params);
+        ImgPostResponse<DataPostAnalysisRespDto> send = HttpUtils.send(restTemplateLocal,files,algorithmYml);
+        if (send == null || send.getStatus_code() != 1000) {
+            assert send != null;
+            log.error(send.getMessage());
+            throw new ServiceException(send.getMessage());
+        }
+        DataPostAnalysisRespDto data = send.getData();
+
+        Map<String,Object> result = (Map<String, Object>) Optional.ofNullable(data.getAnalysisDatas().get(0).getResult()).orElse(Collections.emptyMap());
+        Map<String,Object> algorithmData = (Map<String, Object>)  Optional.ofNullable(result.get("algorithm_data")).orElse(Collections.emptyMap());
+        boolean alert = algorithmData.getOrDefault("is_alert", "").toString().equals("false");
+        if (!alert){
+            sendSginAccessLogService.saveAlarm(fireProperties);
+        }
+    }
+
+    /**
+     * frame 转图片流
+     */
+    public static BufferedImage FrameToBufferedImage(Frame frame) {
+        //创建BufferedImage对象
+        Java2DFrameConverter converter = new Java2DFrameConverter();
+        return converter.getBufferedImage(frame);
+    }
+}

+ 44 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/serivce/SendSginAccessLogService.java

@@ -8,6 +8,7 @@ import com.zd.common.core.utils.StringUtils;
 import com.zd.common.core.web.domain.AjaxResult;
 import com.zd.forward.config.AlgorithmYml;
 import com.zd.forward.domain.VideoRequestData;
+import com.zd.forward.properties.FireProperties;
 import com.zd.system.api.domain.Algorithm;
 import com.zd.system.api.domain.ParamVo;
 import com.zd.system.api.domain.PlayVo;
@@ -97,6 +98,24 @@ public class SendSginAccessLogService {
 
     }
 
+    public void saveAlarm(FireProperties properties) {
+        String hardwareNum = properties.getHardwareNum();
+        if (Boolean.TRUE.equals(redisTemplate.hasKey(hardwareNum))) {
+            Integer count = (Integer) redisTemplate.opsForValue().get(hardwareNum);
+            if (count == null) {
+                count = 0;
+            }
+            redisTemplate.opsForValue().set(hardwareNum, count + 1, 30, TimeUnit.SECONDS);
+            R<Object> r = send(properties);
+            if (r.getCode() != HttpStatus.SUCCESS) {
+                logger.error("火焰警报失败原因:{}", r.getMsg());
+            }
+        } else {
+            redisTemplate.opsForValue().set(hardwareNum, 1, 30, TimeUnit.SECONDS);
+        }
+
+    }
+
     public void playMp3() {
         if (!algorithmYml.isLoudspeakerSwitch()){
             return;
@@ -153,6 +172,31 @@ public class SendSginAccessLogService {
         return R.fail("未找到算法");
     }
 
+    /**
+     * 发送火焰警报
+     */
+    public R<Object> send(FireProperties properties) {
+        Map<String, Object> requestMap = new HashMap<>();
+        List<Map<String, Object>> maps = new ArrayList<>();
+        Integer aid = properties.getAlgoId();
+        Map<Integer, AlgorithmYml.AlarmConfig> alarmConfigMap = algorithmYml.getAlarmConfigMap();
+        if (alarmConfigMap.containsKey(aid)) {
+            AlgorithmYml.AlarmConfig alarmConfig = alarmConfigMap.get(aid);
+            Map<String, Object> params = new HashMap<>();
+            params.put("hardwareNum", properties.getHardwareNum());
+            params.put("subId", properties.getLabId());
+            params.put("val", 1);
+            params.put("funNum", alarmConfig.getFunNum());
+            params.put("describe", alarmConfig.getDescribe());
+            maps.add(params);
+            requestMap.put("functionStatuses", maps);
+            ParameterizedTypeReference<R<Object>> reference = new ParameterizedTypeReference<R<Object>>() {
+            };
+            return send(requestMap, algorithmYml.getTargetUrl() + "laboratory/plan/triggerRiskPlan", HttpMethod.POST, reference);
+        }
+        return R.fail("未找到算法");
+    }
+
     private <T> R<T> send(Map<String, Object> params, String url, HttpMethod method, ParameterizedTypeReference<R<T>> reference) {
         HttpEntity<Map<String, Object>> requestEntity = getMapHttpEntity(params);
         ResponseEntity<R<T>> exchange = restTemplateLocal.exchange(url, method, requestEntity, reference);

+ 126 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/util/HttpUtils.java

@@ -0,0 +1,126 @@
+package com.zd.forward.util;
+
+import com.zd.common.core.exception.ServiceException;
+import com.zd.forward.config.AlgorithmYml;
+import com.zd.forward.domain.DataPostAnalysisRespDto;
+import com.zd.forward.domain.ImgPostResponse;
+import com.zd.forward.properties.FireProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.*;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+@Slf4j
+public class HttpUtils {
+
+    /**
+     * 构造算法文件逆流
+     */
+    public static HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(MultipartFile file, MultiValueMap<String, Object> params){
+        try {
+            //设置请求头
+            HttpHeaders headers = new HttpHeaders();
+            headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+            // 文件本地存储收集
+            //FileUploadUtils.upload(localFilePath, file);
+            //MultipartFile 转为临时文件
+            File uploadFile = multipartFileToFile(file);
+            //文件转为文件系统资源
+            return getHttpEntity(uploadFile, params, headers);
+        }catch (IOException ex){
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 构造算法文件逆流
+     */
+    public static HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(File file, MultiValueMap<String, Object> params){
+        //设置请求头
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
+        return getHttpEntity(file, params, headers);
+    }
+
+    private static HttpEntity<MultiValueMap<String, Object>> getHttpEntity(File file, MultiValueMap<String, Object> params, HttpHeaders headers) {
+        //文件转为文件系统资源
+        FileSystemResource fileSystemResource = new FileSystemResource(file);
+        //设置请求体,注意是LinkedMultiValueMap
+        MultiValueMap<String, Object> form = getStringObjectMultiValueMap(fileSystemResource);
+        form.addAll(params);
+        //用HttpEntity封装整个请求报文
+        return new HttpEntity<>(form, headers);
+    }
+
+    public static File multipartFileToFile(MultipartFile file) throws IOException {
+        String originalFilename = file.getOriginalFilename()==null?"":file.getOriginalFilename();
+        String[] filename = originalFilename.split("\\.");
+        File toFile = File.createTempFile(filename[0], "." + filename[1]);
+        file.transferTo(toFile);
+        //toFile.deleteOnExit();//在jvm 退出时删除
+        return toFile;
+    }
+
+    /**
+     * 构建算法图片post请求 参数:只构建文件
+     */
+    public static MultiValueMap<String, Object> getStringObjectMultiValueMap(FileSystemResource fileSystemResource) {
+        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
+        form.add("file", fileSystemResource);
+        return form;
+    }
+
+    private static MultiValueMap<String, Object> getStringObjectMultiValueMap(String extension) {
+        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
+        //1-同步(默认),0-异步
+        form.add("sync", 1);
+        form.add("timestamp", LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli() / 1000);
+        form.add("extension", extension);
+        return form;
+    }
+
+    /**
+     * 构建算法图片post请求 参数
+     */
+    public static MultiValueMap<String, Object> getStringObjectMultiValueMap(AlgorithmYml.CheckValid checkValid, String extension) {
+        MultiValueMap<String, Object> form = getStringObjectMultiValueMap(extension);
+        form.add("algoId", checkValid.getAlgoId());
+        form.add("did", checkValid.getDid());
+        return form;
+    }
+
+    /**
+     * 构建算法图片post请求 参数
+     */
+    public static MultiValueMap<String, Object> getMultiValueMap(FireProperties properties, String extension) {
+        MultiValueMap<String, Object> form = getStringObjectMultiValueMap(extension);
+        form.add("algoId", properties.getAlgoId());
+        form.add("did", properties.getDid());
+        return form;
+    }
+
+    public static ImgPostResponse<DataPostAnalysisRespDto> send(RestTemplate restTemplate,HttpEntity<MultiValueMap<String, Object>> files, AlgorithmYml algorithmYml){
+        ParameterizedTypeReference<ImgPostResponse<DataPostAnalysisRespDto>> reference = new ParameterizedTypeReference<ImgPostResponse<DataPostAnalysisRespDto>>() {
+        };
+        ResponseEntity<ImgPostResponse<DataPostAnalysisRespDto>> response = restTemplate.exchange(algorithmYml.getImgPostUrl(), HttpMethod.POST, files, reference);
+        if (response.getStatusCode()!=HttpStatus.OK){
+            log.error("算法服务请求异常,请查看算服务器");
+            throw new ServiceException("算法服务请求异常,请查看算服务器");
+        }
+        if (response.getBody()==null){
+            log.error("算法服务接口返回异常");
+            throw new ServiceException("算法服务接口返回异常");
+        }
+        return response.getBody();
+    }
+}

+ 18 - 1
zd-modules/zd-netty/src/main/java/com/zd/netty/enums/ManufacturerTypeEnum.java

@@ -7,16 +7,33 @@ import com.zd.netty.service.IService;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
+/**
+ * @author Administrator
+ */
+
 @Getter
 @AllArgsConstructor
 public enum ManufacturerTypeEnum {
 
+    /**
+     * 枚举常量
+     */
     WU_WEI(1,"无源", WuYuanRFIDService.class),
-    DE_JU(2,"惠州德聚", DeJuRFIDListenerService.class);
+    DE_JU(2,"惠州德聚服务端", DeJuRFIDService.class),
+    DE_JU2(3,"惠州德聚客户端", DeJuRFIDListenerService.class);
 
+    /**
+     * 字典码
+     */
     private final Integer code;
+    /**
+     * 供应厂商名称
+     */
     private final String name;
 
+    /**
+     * 接口实现对象
+     */
     private final Class<? extends IService> service;
 
     /**

+ 24 - 166
zd-modules/zd-netty/src/main/java/com/zd/netty/sdk/DeJuRFIDListenerService.java

@@ -2,57 +2,33 @@ package com.zd.netty.sdk;
 
 import com.gg.reader.api.dal.GClient;
 import com.gg.reader.api.dal.GServer;
-import com.gg.reader.api.protocol.gx.*;
-import com.zd.common.core.utils.SpringUtils;
-import com.zd.netty.service.ISendService;
+import com.gg.reader.api.protocol.gx.MsgBaseStop;
 import com.zd.netty.service.IService;
-import com.zd.system.api.domain.InventoryTag;
 import com.zd.system.api.laboratory.domain.RemoteLabHardware;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
-import javax.annotation.Resource;
-import java.util.Hashtable;
 import java.util.Map;
-import java.util.Objects;
-import java.util.TimerTask;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 
 @Slf4j
 @Service
 public class DeJuRFIDListenerService implements IService {
 
-    @Resource
-    private ISendService sendService;
-
-    private final Map<String, GClient> clientMap = new ConcurrentHashMap<>();
-
-    AtomicBoolean isAlarm = new AtomicBoolean();
-
-    GClient client;
-
-    private final ScheduledExecutorService scheduledExecutorService = SpringUtils.getBean("scheduledExecutorService");
+    private final Map<String, GServer> serverMap = new ConcurrentHashMap<>();
 
     @Override
     public void start(RemoteLabHardware hardware) {
         String ipAddress = hardware.getIpAddress();
-        if (clientMap.containsKey(ipAddress)){
-            return;
+        GServer server;
+        if (serverMap.containsKey(ipAddress)) {
+            server = serverMap.get(ipAddress);
+        } else {
+            server = new GServer();
         }
-        GServer server = new GServer();
-        if (server.open(9190)) {
-            subscribeServerHandler(server);
-            if (client!=null){
-                clientMap.put(ipAddress,client);
-                setPower(hardware);
-                setInventory(hardware);
-                subscribeHandler(client);
-            }
+        if (server.open(DeJuRFIDService.PORT)) {
+            subscribeServerHandler(server, hardware);
             log.info("开始监听");
         } else {
             log.info("监听失败");
@@ -61,31 +37,36 @@ public class DeJuRFIDListenerService implements IService {
 
     @Override
     public void disconnect(RemoteLabHardware hardware) {
-        stop();
-        clientMap.remove(hardware.getIpAddress());
+        String ipAddress = hardware.getIpAddress();
+        if (serverMap.containsKey(ipAddress)) {
+            GServer server = serverMap.get(ipAddress);
+            server.close();
+        }
+        serverMap.remove(hardware.getIpAddress());
     }
 
     //订阅监听上报
-    private void subscribeServerHandler(GServer server) {
-        server.onGClientConnected = (gClient, serialNumber) -> {
-            log.info(gClient.getName() + "---监听成功");
-            client = gClient;//切换连接对象
+    private void subscribeServerHandler(GServer server, RemoteLabHardware hardware) {
+        server.onGClientConnected = (client, serialNumber) -> {
+            log.info(client.getName() + "---监听成功");
             client.setSendHeartBeat(true);//开启心跳检测Tcp连接状态
             client.setPrint(true);
-            subscribeTcpHandler();//订阅Tcp断连上报
-            stop();//测试监听成功的连接是否通信正常
+            subscribeTcpHandler(client);//订阅Tcp断连上报
+            DeJuRFIDService.setPower(hardware, client);
+            DeJuRFIDService.setInventory(hardware, client);
+            DeJuRFIDService.subscribeHandler(client);
         };
     }
 
     //订阅TCP断开连接上报
-    private void subscribeTcpHandler() {
+    private void subscribeTcpHandler(GClient client) {
         client.onDisconnected = s -> {
             log.info("连接" + s + "已断开");
             client.close();//释放当前连接资源
         };
     }
 
-    private void stop() {
+    private void stop(GClient client) {
         MsgBaseStop msg = new MsgBaseStop();
         client.sendSynMsg(msg);
         if (0x00 == msg.getRtCode()) {
@@ -94,127 +75,4 @@ public class DeJuRFIDListenerService implements IService {
             log.info(msg.getRtMsg());
         }
     }
-
-    /**
-     * 订阅6c标签信息上报
-     *
-     * @param client 客户端
-     */
-    private void subscribeHandler(GClient client) {
-        client.onTagEpcLog = (s, logBaseEpcInfo) -> {
-            if (logBaseEpcInfo.getResult() == 0) {
-                log.info("===========》{}", logBaseEpcInfo.getbEpc());
-                //灯带设置
-                if (!isAlarm.get()) {
-                    scheduledExecutorService.execute(() -> {
-                        isAlarm.set(true);
-                        changeGpo(1, client, 10);
-                    });
-                }
-                InventoryTag tag = new InventoryTag();
-                BeanUtils.copyProperties(logBaseEpcInfo, tag);
-                sendService.send(tag);
-            }
-        };
-        client.onTagEpcOver = (s, logBaseEpcOver) -> log.info("HandlerTagEpcOver");
-    }
-
-    private void changeGpo(int state, GClient client, int delayTime) {
-        MsgAppSetGpo msgAppSetGpo = new MsgAppSetGpo();
-        msgAppSetGpo.setGpo1(state);
-        msgAppSetGpo.setGpo2(state);
-
-        client.sendSynMsg(msgAppSetGpo);
-        String status = state == 1 ? "start" : "stop";
-        if (0 == msgAppSetGpo.getRtCode()) {
-            if (state == 1) {
-                stopGpo(client, delayTime);
-            } else {
-                isAlarm.set(false);
-            }
-        } else {
-            log.error("Gpo epc {} error.", status);
-            if (state == 1) {
-                stopGpo(client, delayTime);
-            }
-        }
-    }
-
-    public void stopGpo(GClient client, int delayTime) {
-        scheduledExecutorService.schedule(new TimerTask() {
-            @Override
-            public void run() {
-                changeGpo(0, client, 0);
-            }
-        }, delayTime, TimeUnit.SECONDS);
-    }
-
-    private void setPower(RemoteLabHardware hardware){
-        // 功率配置, 将4个天线功率都设置为30dBm.
-        Integer uniformPower = hardware.getUniformPower();
-        MsgBaseGetPower msgBaseGetPower = new MsgBaseGetPower();
-        client.sendSynMsg(msgBaseGetPower);
-        if (0 == msgBaseGetPower.getRtCode()) {
-            Hashtable<Integer, Integer> dicPower = msgBaseGetPower.getDicPower();
-            Integer integer = dicPower.get(0);
-            if (!Objects.equals(integer, uniformPower)) {
-                MsgBaseSetPower msgBaseSetPower = new MsgBaseSetPower();
-                Hashtable<Integer, Integer> hashtable = new Hashtable<>();
-
-                Integer channels = hardware.getChannels();
-                for (int i = 1; i <= channels; i++) {
-                    hashtable.put(i, uniformPower);
-                }
-                msgBaseSetPower.setDicPower(hashtable);
-                client.sendSynMsg(msgBaseSetPower);
-                if (0 != msgBaseSetPower.getRtCode()) {
-                    log.error("Power configuration error.");
-                    reset(client);
-                    disconnect(hardware);
-                    start(hardware);
-                }
-            }
-        } else {
-            log.error("Power configuration error.");
-            reset(client);
-            disconnect(hardware);
-            start(hardware);
-        }
-    }
-
-    private void setInventory(RemoteLabHardware hardware){
-        //天线读卡, 读取EPC数据区以及TID数据区
-        MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
-        switch (hardware.getChannels()) {
-            case 4:
-                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4);
-                break;
-            case 8:
-                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4 | EnumG.AntennaNo_5 | EnumG.AntennaNo_6 | EnumG.AntennaNo_7 | EnumG.AntennaNo_8);
-                break;
-            case 16:
-                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4 | EnumG.AntennaNo_5 | EnumG.AntennaNo_6 | EnumG.AntennaNo_7 | EnumG.AntennaNo_8 | EnumG.AntennaNo_9 | EnumG.AntennaNo_10 | EnumG.AntennaNo_11 | EnumG.AntennaNo_12 | EnumG.AntennaNo_13 | EnumG.AntennaNo_14 | EnumG.AntennaNo_15 | EnumG.AntennaNo_16);
-                break;
-            case 1:
-            default:
-                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1);
-        }
-        msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);
-
-        client.sendSynMsg(msgBaseInventoryEpc);
-        if (0 != msgBaseInventoryEpc.getRtCode()) {
-            log.error("Inventory epc error.");
-            reset(client);
-            disconnect(hardware);
-            start(hardware);
-        }
-    }
-
-    public void reset(GClient client) {
-        MsgAppReset msgAppReset = new MsgAppReset();
-        client.sendSynMsg(msgAppReset);
-        if (0 != msgAppReset.getRtCode()) {
-            log.error("Reset epc error.");
-        }
-    }
 }

+ 71 - 57
zd-modules/zd-netty/src/main/java/com/zd/netty/sdk/DeJuRFIDService.java

@@ -28,17 +28,22 @@ import java.util.concurrent.atomic.AtomicBoolean;
 @Service
 public class DeJuRFIDService implements IService {
 
-    @Resource
-    private ISendService sendService;
+    private static final ISendService sendService = SpringUtils.getBean("sendService");
 
-    private final Map<String, GClient> clientMap = new ConcurrentHashMap<>();
+    private static final Map<String, GClient> clientMap = new ConcurrentHashMap<>();
 
-    AtomicBoolean isAlarm = new AtomicBoolean();
+    static AtomicBoolean isAlarm = new AtomicBoolean();
 
-    private final ScheduledExecutorService scheduledExecutorService = SpringUtils.getBean("scheduledExecutorService");
+    public static final Integer PORT=8160;
+
+    private static final ScheduledExecutorService scheduledExecutorService = SpringUtils.getBean("scheduledExecutorService");
 
     @Override
     public void start(RemoteLabHardware hardware) {
+        open(hardware);
+    }
+
+    private static void open(RemoteLabHardware hardware) {
         GClient client;
         String ipAddress = hardware.getIpAddress();
         if (clientMap.containsKey(ipAddress)) {
@@ -47,71 +52,76 @@ public class DeJuRFIDService implements IService {
             client = new GClient();
             clientMap.put(ipAddress, client);
         }
-        if (client.openTcp(ipAddress + ":8160", 2000)) {
+        if (client.openTcp(ipAddress + ":"+PORT, 2000)) {
             // 订阅标签上报事件
             subscribeHandler(client);
             // 功率配置, 将4个天线功率都设置为30dBm.
-            Integer uniformPower = hardware.getUniformPower();
-            MsgBaseGetPower msgBaseGetPower = new MsgBaseGetPower();
-            client.sendSynMsg(msgBaseGetPower);
-            if (0 == msgBaseGetPower.getRtCode()) {
-                Hashtable<Integer, Integer> dicPower = msgBaseGetPower.getDicPower();
-                Integer integer = dicPower.get(0);
-                if (!Objects.equals(integer, uniformPower)) {
-                    MsgBaseSetPower msgBaseSetPower = new MsgBaseSetPower();
-                    Hashtable<Integer, Integer> hashtable = new Hashtable<>();
-
-                    Integer channels = hardware.getChannels();
-                    for (int i = 1; i <= channels; i++) {
-                        hashtable.put(i, uniformPower);
-                    }
-                    msgBaseSetPower.setDicPower(hashtable);
-                    client.sendSynMsg(msgBaseSetPower);
-                    if (0 != msgBaseSetPower.getRtCode()) {
-                        log.error("Power configuration error.");
-                        reset(client);
-                        disconnect(hardware);
-                        start(hardware);
-                    }
-                }
-            } else {
+            MsgBaseSetPower msgBaseSetPower = setPower(hardware, client);
+            if (0 != msgBaseSetPower.getRtCode()) {
                 log.error("Power configuration error.");
                 reset(client);
-                disconnect(hardware);
-                start(hardware);
+                close(hardware);
+                open(hardware);
             }
-
             //天线读卡, 读取EPC数据区以及TID数据区
-            MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
-            switch (hardware.getChannels()) {
-                case 4:
-                    msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4);
-                    break;
-                case 8:
-                    msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4 | EnumG.AntennaNo_5 | EnumG.AntennaNo_6 | EnumG.AntennaNo_7 | EnumG.AntennaNo_8);
-                    break;
-                case 16:
-                    msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4 | EnumG.AntennaNo_5 | EnumG.AntennaNo_6 | EnumG.AntennaNo_7 | EnumG.AntennaNo_8 | EnumG.AntennaNo_9 | EnumG.AntennaNo_10 | EnumG.AntennaNo_11 | EnumG.AntennaNo_12 | EnumG.AntennaNo_13 | EnumG.AntennaNo_14 | EnumG.AntennaNo_15 | EnumG.AntennaNo_16);
-                    break;
-                case 1:
-                default:
-                    msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1);
-            }
-            msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);
-
-            client.sendSynMsg(msgBaseInventoryEpc);
+            MsgBaseInventoryEpc msgBaseInventoryEpc = setInventory(hardware, client);
             if (0 != msgBaseInventoryEpc.getRtCode()) {
                 log.error("Inventory epc error.");
                 reset(client);
-                disconnect(hardware);
-                start(hardware);
+                close(hardware);
+                open(hardware);
             }
         } else {
             throw new ServiceException("Connect failure.");
         }
     }
 
-    public void reset(GClient client) {
+    public static MsgBaseInventoryEpc setInventory(RemoteLabHardware hardware, GClient client) {
+        MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
+        switch (hardware.getChannels()) {
+            case 4:
+                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4);
+                break;
+            case 8:
+                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4 | EnumG.AntennaNo_5 | EnumG.AntennaNo_6 | EnumG.AntennaNo_7 | EnumG.AntennaNo_8);
+                break;
+            case 16:
+                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1 | EnumG.AntennaNo_2 | EnumG.AntennaNo_3 | EnumG.AntennaNo_4 | EnumG.AntennaNo_5 | EnumG.AntennaNo_6 | EnumG.AntennaNo_7 | EnumG.AntennaNo_8 | EnumG.AntennaNo_9 | EnumG.AntennaNo_10 | EnumG.AntennaNo_11 | EnumG.AntennaNo_12 | EnumG.AntennaNo_13 | EnumG.AntennaNo_14 | EnumG.AntennaNo_15 | EnumG.AntennaNo_16);
+                break;
+            case 1:
+            default:
+                msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1);
+        }
+        msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);
+
+        client.sendSynMsg(msgBaseInventoryEpc);
+        return msgBaseInventoryEpc;
+    }
+
+    public static MsgBaseSetPower setPower(RemoteLabHardware hardware, GClient client) {
+        Integer uniformPower = hardware.getUniformPower();
+        MsgBaseGetPower msgBaseGetPower = new MsgBaseGetPower();
+        client.sendSynMsg(msgBaseGetPower);
+        MsgBaseSetPower msgBaseSetPower = new MsgBaseSetPower();
+        if (0 == msgBaseGetPower.getRtCode()) {
+            Hashtable<Integer, Integer> dicPower = msgBaseGetPower.getDicPower();
+            Integer integer = dicPower.get(0);
+            if (!Objects.equals(integer, uniformPower)) {
+                Hashtable<Integer, Integer> hashtable = new Hashtable<>();
+                Integer channels = hardware.getChannels();
+                for (int i = 1; i <= channels; i++) {
+                    hashtable.put(i, uniformPower);
+                }
+                msgBaseSetPower.setDicPower(hashtable);
+                client.sendSynMsg(msgBaseSetPower);
+            } else {
+                msgBaseSetPower.setRtCode((byte) 0);
+            }
+        }
+        return msgBaseSetPower;
+    }
+
+    public static void reset(GClient client) {
         MsgAppReset msgAppReset = new MsgAppReset();
         client.sendSynMsg(msgAppReset);
         if (0 != msgAppReset.getRtCode()) {
@@ -121,6 +131,10 @@ public class DeJuRFIDService implements IService {
 
     @Override
     public void disconnect(RemoteLabHardware hardware) {
+        close(hardware);
+    }
+
+    private static void close(RemoteLabHardware hardware) {
         String ipAddress = hardware.getIpAddress();
         if (clientMap.containsKey(ipAddress)) {
             GClient client = clientMap.get(ipAddress);
@@ -133,7 +147,7 @@ public class DeJuRFIDService implements IService {
         }
     }
 
-    private void changeGpo(int state, GClient client, int delayTime) {
+    private static void changeGpo(int state, GClient client, int delayTime) {
         MsgAppSetGpo msgAppSetGpo = new MsgAppSetGpo();
         msgAppSetGpo.setGpo1(state);
         msgAppSetGpo.setGpo2(state);
@@ -154,7 +168,7 @@ public class DeJuRFIDService implements IService {
         }
     }
 
-    public void stopGpo(GClient client, int delayTime) {
+    public static void stopGpo(GClient client, int delayTime) {
         scheduledExecutorService.schedule(new TimerTask() {
             @Override
             public void run() {
@@ -168,7 +182,7 @@ public class DeJuRFIDService implements IService {
      *
      * @param client 客户端
      */
-    private void subscribeHandler(GClient client) {
+    public static void subscribeHandler(GClient client) {
         client.onTagEpcLog = (s, logBaseEpcInfo) -> {
             if (logBaseEpcInfo.getResult() == 0) {
                 log.info("===========》{}", logBaseEpcInfo.getbEpc());

+ 1 - 1
zd-modules/zd-netty/src/main/java/com/zd/netty/service/impl/SendServiceImpl.java

@@ -11,7 +11,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 
 @Slf4j
-@Service
+@Service(value = "sendService")
 public class SendServiceImpl implements ISendService {
 
     @Resource