소스 검색

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

zhuchangxue 3 년 전
부모
커밋
c6cd296d12

+ 12 - 1
zd-common/zd-common-core/src/main/java/com/zd/common/core/utils/IdGen.java

@@ -1,10 +1,21 @@
 package com.zd.common.core.utils;
 
+import java.util.UUID;
+
 /**
  * id生成工具类
+ * @author Administrator
  */
 public class IdGen {
-
+    private IdGen() {
+        throw new IllegalStateException("IdGen class");
+    }
+    /**
+     * 封装JDK自带的UUID, 中间无-分割.
+     */
+    public static String uuid() {
+        return UUID.randomUUID().toString().replace("-", "");
+    }
     /**
      * 基于snowflake算法生成ID
      * @return String

+ 90 - 7
zd-modules/zd-forward/src/main/java/com/zd/forward/config/WebConfig.java

@@ -1,27 +1,110 @@
 package com.zd.forward.config;
 
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.HttpClientConnectionManager;
+import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 import org.springframework.http.client.SimpleClientHttpRequestFactory;
 import org.springframework.web.client.RestTemplate;
 
+import javax.annotation.Resource;
+import java.util.concurrent.TimeUnit;
+
 /**
- * @Author: zhoupan
- * @Date: 2021/11/13/10:42
- * @Description:
+ * @author Administrator
  */
 @Configuration
 public class WebConfig {
 
-    //自创建RestTemplate
-    // 这里需要重命名, 因为会导致原来的负载均衡冲突失效 导致项目起不来
+    @Resource
+    private RestTemplateBuilder restTemplateBuilder;
+    /**
+     * 自创建RestTemplate
+     * 这里需要重命名, 因为会导致原来的负载均衡冲突失效 导致项目起不来
+     * @return restTemplateLocal
+     */
     @Bean
     public static RestTemplate restTemplateLocal() {
         SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
-        requestFactory.setConnectTimeout(10000);// 设置连接超时,单位毫秒
-        requestFactory.setReadTimeout(10000);  //设置读取超时
+        // 设置连接超时,单位毫秒
+        requestFactory.setConnectTimeout(10000);
+        //设置读取超时
+        requestFactory.setReadTimeout(10000);
         RestTemplate restTemplate = new RestTemplate();
         restTemplate.setRequestFactory(requestFactory);
         return restTemplate;
     }
+
+    /**
+     * 让spring管理RestTemplate,参数相关配置
+     *
+     * @return restTemplate
+     */
+    @Bean
+    public RestTemplate restTemplate() {
+        RestTemplate restTemplate = restTemplateBuilder.build();
+        restTemplate.setRequestFactory(clientHttpRequestFactory());
+        return restTemplate;
+    }
+
+    /**
+     * 客户端请求链接策略
+     *
+     * @return clientHttpRequestFactory
+     */
+    private ClientHttpRequestFactory clientHttpRequestFactory() {
+        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
+        clientHttpRequestFactory.setHttpClient(httpClientBuilder().build());
+        // 连接超时时间/毫秒
+        clientHttpRequestFactory.setConnectTimeout(60000);
+        // 读写超时时间/毫秒
+        clientHttpRequestFactory.setReadTimeout(60000);
+        // 请求超时时间/毫秒
+        clientHttpRequestFactory.setConnectionRequestTimeout(50000);
+        return clientHttpRequestFactory;
+    }
+
+    /**
+     * 设置HTTP连接管理器,连接池相关配置管理
+     *
+     * @return 客户端链接管理器
+     */
+    private HttpClientBuilder httpClientBuilder() {
+        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+        httpClientBuilder.setConnectionManager(poolingConnectionManager());
+        ConnectionKeepAliveStrategy connectionKeepAliveStrategy = (httpResponse, httpContext) -> 20 * 1000;
+        httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy);
+        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler());
+        RequestConfig requestConfig = RequestConfig.custom()
+                .setConnectTimeout(10 * 1000)
+                .setSocketTimeout(10 * 1000)
+                .setConnectionRequestTimeout(10 * 1000)
+                .build();
+        httpClientBuilder.setDefaultRequestConfig(requestConfig);
+        return httpClientBuilder;
+    }
+
+    /**
+     * 链接线程池管理,可以keep-alive不断开链接请求,这样速度会更快 MaxTotal 连接池最大连接数 DefaultMaxPerRoute
+     * 每个主机的并发 ValidateAfterInactivity
+     * 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
+     *
+     * @return poolingConnectionManager
+     */
+    private HttpClientConnectionManager poolingConnectionManager() {
+        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
+        poolingConnectionManager.setMaxTotal(1000);
+        poolingConnectionManager.setDefaultMaxPerRoute(5000);
+        poolingConnectionManager.setValidateAfterInactivity(30000);
+        poolingConnectionManager.closeIdleConnections(30, TimeUnit.SECONDS);
+        poolingConnectionManager.closeExpiredConnections();
+        return poolingConnectionManager;
+    }
 }

+ 29 - 7
zd-modules/zd-forward/src/main/java/com/zd/forward/listener/StartListener.java

@@ -1,14 +1,17 @@
 package com.zd.forward.listener;
 
+import com.zd.common.core.exception.ServiceException;
+import com.zd.forward.properties.FireProperties;
 import com.zd.forward.serivce.FireImageService;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 import org.springframework.boot.CommandLineRunner;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
+import java.io.IOException;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 /**
  * 监听Spring容器启动完成,完成后启动Netty服务器
@@ -20,18 +23,37 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
 public class StartListener implements CommandLineRunner {
     @Resource
     private FireImageService fireImageService;
+    @Resource
+    private FireProperties fireProperties;
+
+    @Resource
+    private ScheduledExecutorService scheduledExecutorService;
+
+    @Resource
+    private ThreadPoolTaskExecutor taskExecutor;
 
     @Override
     public void run(String... args) {
-        //未验证部分,待验证后启用
-        ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new BasicThreadFactory.Builder().namingPattern("fire-pool-%d").daemon(true).build());
-        executorService.execute(new Runnable() {
+        //定时调度,无法使用scheduledExecutorService完成定时调度,scheduledExecutorService默认实现了jdk自动关闭策略,默认会杀死程序,此处手动实现延时调用
+        taskExecutor.execute(new Runnable() {
             @Override
             public void run() {
-                synchronized (this){
-                    fireImageService.catchImage();
+                try {
+                    String streamUrl = fireProperties.getStreamUrl();
+                    if (streamUrl == null) {
+                        throw new ServiceException("未配置流媒体地址");
+                    }
+                    while (true) {
+                        fireImageService.catchImage();
+                        Thread.sleep(fireProperties.getWaitTime() * 15 * 1000L);
+                    }
+                } catch (Exception e) {
+                    //异常回调,防止系统因异常问题被杀死
+                    log.error("=========调用产生异常:{}============", e.getMessage());
+                    run();
                 }
             }
         });
     }
+
 }

+ 4 - 9
zd-modules/zd-forward/src/main/java/com/zd/forward/serivce/CheckService.java

@@ -3,7 +3,6 @@ package com.zd.forward.serivce;
 import cn.hutool.core.text.CharSequenceUtil;
 import cn.hutool.core.util.RandomUtil;
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.zd.common.core.constant.Constants;
 import com.zd.common.core.constant.SecurityConstants;
@@ -18,9 +17,9 @@ import com.zd.forward.domain.DataPostAnalysisRespDto;
 import com.zd.forward.domain.ImgPostResponse;
 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.forward.utils.Base64DecodedMultipartFile;
+import com.zd.forward.utils.FileUploadUtils;
+import com.zd.forward.utils.HttpUtils;
 import com.zd.system.api.RemoteFileService;
 import com.zd.system.api.alarm.RemoteAlarmService;
 import com.zd.system.api.alarm.domain.AlarmEntrty;
@@ -35,11 +34,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.cloud.context.config.annotation.RefreshScope;
-import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.core.io.FileSystemResource;
 import org.springframework.http.*;
 import org.springframework.stereotype.Service;
-import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
@@ -51,11 +48,9 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
 import java.util.*;
 
-import static com.zd.forward.util.HttpUtils.*;
+import static com.zd.forward.utils.HttpUtils.*;
 
 @Service
 @EnableConfigurationProperties(AlgorithmYml.class)

+ 51 - 32
zd-modules/zd-forward/src/main/java/com/zd/forward/serivce/FireImageService.java

@@ -3,14 +3,15 @@ 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.AnalysisData;
 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 com.zd.forward.utils.HttpUtils;
+import com.zd.forward.utils.VideoUtils;
 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;
@@ -23,14 +24,17 @@ import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 
-import static com.zd.forward.util.HttpUtils.getHttpEntityMap;
+import static com.zd.forward.utils.HttpUtils.getHttpEntityMap;
 
 /**
  * 火焰图片抓拍处理
+ *
  * @author Administrator
  */
 @Service
@@ -42,12 +46,20 @@ public class FireImageService {
     @Resource
     private AlgorithmYml algorithmYml;
 
-    @Resource(name = "restTemplateLocal")
-    private RestTemplate restTemplateLocal;
+    @Resource
+    private RestTemplate restTemplate;
     @Resource
     private SendSginAccessLogService sendSginAccessLogService;
 
-    private static final Integer SUCCESS_CODE=1000;
+    /**
+     * 算法接口返回值
+     */
+    private static final Integer SUCCESS_CODE = 1000;
+
+    /**
+     * 生成的图片的类型
+     */
+    private static final String IMAGE_FORMAT = "jpg";
 
     /**
      * 上传文件存储在本地的根路径
@@ -55,58 +67,65 @@ public class FireImageService {
     @Value("${file.path:/home/AIPIC}")
     private String imagePath;
 
-    public void catchImage() {
-
+    public void catchImage() throws Exception {
         String streamUrl = fireProperties.getStreamUrl();
         if (streamUrl == null) {
             throw new ServiceException("未配置流媒体地址");
         }
 
-        try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(streamUrl)) {
+        try (FFmpegFrameGrabber grabber = VideoUtils.createGrabber(streamUrl)) {
             grabber.start();
+            String uuid = IdGen.uuid();
+            //文件储存对象
+            String fileName = imagePath + File.separator + uuid;
+            File tempFile = File.createTempFile(fileName, "." + IMAGE_FORMAT);
             //获取第一帧
             Frame frame = grabber.grabFrame();
             if (frame != null) {
-                int flag = 0;
-                while (frame != null) {
-                    //视频快照
-                    frame = grabber.grabImage();
-                    long uuid = IdGen.snowflakeId();
-                    //文件储存对象
-                    String fileName = imagePath + File.separator + uuid + "_" + flag;
-                    File tempFile = File.createTempFile(fileName, ".jpg");
-                    ImageIO.write(frameToBufferedImage(frame), "jpg", tempFile);
-                    send(tempFile);
+                //视频快照
+                frame = grabber.grabImage();
+                BufferedImage bufferedImage = frameToBufferedImage(frame);
+                if (bufferedImage != null) {
+                    ImageIO.write(bufferedImage, IMAGE_FORMAT, tempFile);
                 }
-                //停止
+                log.info("图片地址为[{}]", tempFile.getAbsoluteFile());
                 grabber.stop();
+                send(tempFile);
             }
-        } catch (IOException e) {
-            e.printStackTrace();
-            throw new ServiceException(e.getMessage());
         }
     }
 
-    private void send(File file) {
+    private void send(File file) throws IOException {
         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);
+        ImgPostResponse<DataPostAnalysisRespDto> send = HttpUtils.send(restTemplate, files, algorithmYml);
         if (send == null || send.getStatus_code() != SUCCESS_CODE) {
             assert send != null;
             log.error(send.getMessage());
-            throw new ServiceException(send.getMessage());
+            return;
         }
         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 = "false".equals(algorithmData.getOrDefault("is_alert", "").toString());
-        if (!alert) {
-            sendSginAccessLogService.saveAlarm(fireProperties);
+        List<AnalysisData> analysisDatas = data.getAnalysisDatas();
+        AnalysisData analysisData = analysisDatas.get(0);
+        int code = analysisData.getCode();
+        if (code==-1){
+            log.error("==============请求失败:{}=================",analysisData.getMsg());
+            throw new ServiceException(analysisData.getMsg());
+        }else {
+            log.info("===============向算法服务发送数据完成====================");
+            Map<String, Object> result = (Map<String, Object>) Optional.ofNullable(analysisData.getResult()).orElse(Collections.emptyMap());
+            Map<String, Object> algorithmData = (Map<String, Object>) Optional.ofNullable(result.get("algorithm_data")).orElse(Collections.emptyMap());
+            boolean alert = "false".equals(algorithmData.getOrDefault("is_alert", "").toString());
+            if (!alert) {
+                log.info("===============返回告警信息====================");
+                sendSginAccessLogService.saveAlarm(fireProperties);
+            }
         }
+        Files.delete(file.getAbsoluteFile().toPath());
     }
 
     /**
@@ -114,7 +133,7 @@ public class FireImageService {
      */
     public static BufferedImage frameToBufferedImage(Frame frame) {
         //创建BufferedImage对象
-        try (Java2DFrameConverter converter = new Java2DFrameConverter()){
+        try (Java2DFrameConverter converter = new Java2DFrameConverter()) {
             return converter.getBufferedImage(frame);
         }
     }

+ 39 - 20
zd-modules/zd-forward/src/main/java/com/zd/forward/serivce/SendSginAccessLogService.java

@@ -10,7 +10,6 @@ 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;
 import com.zd.system.api.speak.RemoteSpeakService;
 import org.slf4j.Logger;
@@ -28,6 +27,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
 import static com.zd.common.core.constant.Constants.MAP_INIT_SIZE;
@@ -44,6 +44,15 @@ public class SendSginAccessLogService {
 
     private final RemoteSpeakService remoteSpeakService;
 
+    /**
+     * 报警次数记录
+     */
+    static Map<String, Integer> alarmMap = new ConcurrentHashMap<>();
+    /**
+     * 超时时间设置MAP
+     */
+    static Map<String, Long> expiryMap = new ConcurrentHashMap<>();
+
     @Autowired
     public SendSginAccessLogService(RestTemplate restTemplateLocal, RedisTemplate<Object, Object> redisTemplate, LoginService loginLab, AlgorithmYml algorithmYml, RemoteSpeakService remoteSpeakService) {
         this.restTemplateLocal = restTemplateLocal;
@@ -102,24 +111,37 @@ 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);
+        long currentTimeMillis = System.currentTimeMillis();
+        if (expiryMap.containsKey(hardwareNum)) {
+            Long expiryTime = expiryMap.get(hardwareNum);
+            if (currentTimeMillis > expiryTime) {
+                expiryMap.remove(hardwareNum);
+                alarmMap.remove(hardwareNum);
+            } else {
+                send(properties, hardwareNum);
+            }
+        } else {
+            alarmMap.put(hardwareNum, 1);
+            expiryMap.put(hardwareNum, currentTimeMillis + 30 * 1000);
+        }
+    }
+
+    private void send(FireProperties properties, String hardwareNum) {
+        if (alarmMap.containsKey(hardwareNum)) {
+            Integer count = alarmMap.get(hardwareNum);
             if (count == null) {
                 count = 0;
             }
-            redisTemplate.opsForValue().set(hardwareNum, count + 1, 30, TimeUnit.SECONDS);
+            alarmMap.put(hardwareNum, count + 1);
             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()){
+        if (!algorithmYml.isLoudspeakerSwitch()) {
             return;
         }
         String loudspeakerIp1 = algorithmYml.getLoudspeakerIp1();
@@ -133,7 +155,7 @@ public class SendSginAccessLogService {
                     playVo.setSn(map.get("deviceSn") + "");
                     playVo.setPort(Integer.parseInt(map.get("port") + ""));
                     sendText(loudspeakerIp1, playVo);
-                    sendText(loudspeakerIp2 , playVo);
+                    sendText(loudspeakerIp2, playVo);
                 }
             }
         }
@@ -142,10 +164,10 @@ public class SendSginAccessLogService {
     private void sendText(String ip, PlayVo playVo) {
         String url = algorithmYml.getTargetUrl() + "/zd-speaker/speaker/textPlayMusic?ip={ip}&texts={texts}";
         HttpEntity<PlayVo> requestEntity = getMapHttpEntity(playVo);
-        if (StringUtils.isNotEmpty(ip)){
+        if (StringUtils.isNotEmpty(ip)) {
             List<String> texts = new ArrayList<>();
             texts.add("当前环境监测到无人值守");
-            ResponseEntity<AjaxResult> response = restTemplateLocal.postForEntity(url, requestEntity, AjaxResult.class, ip,texts);
+            ResponseEntity<AjaxResult> response = restTemplateLocal.postForEntity(url, requestEntity, AjaxResult.class, ip, texts);
             logger.info("响应码:{},响应结果:{}", response.getStatusCode(), response.getBody());
         }
     }
@@ -176,15 +198,12 @@ public class SendSginAccessLogService {
         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<>(MAP_INIT_SIZE);
-            params.put("hardwareNum", properties.getHardwareNum());
-            params.put("subId", properties.getLabId());
-            params.put("val", 1);
-            return getParams(requestMap, maps, alarmConfig, params);
-        }
-        return R.fail("未找到算法");
+        AlgorithmYml.AlarmConfig alarmConfig = alarmConfigMap.get(aid);
+        Map<String, Object> params = new HashMap<>(MAP_INIT_SIZE);
+        params.put("hardwareNum", properties.getHardwareNum());
+        params.put("subId", properties.getLabId());
+        params.put("val", 1);
+        return getParams(requestMap, maps, alarmConfig, params);
     }
 
     private R<Object> getParams(Map<String, Object> requestMap, List<Map<String, Object>> maps, AlgorithmYml.AlarmConfig alarmConfig, Map<String, Object> params) {

+ 78 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/thread/ThreadPoolTaskConfig.java

@@ -0,0 +1,78 @@
+package com.zd.forward.thread;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.*;
+
+/**
+ * @author Administrator
+ */
+@Configuration
+@Slf4j
+public class ThreadPoolTaskConfig {
+
+    private static final int CORE_POOL_SIZE = 10;
+    private static final int MAX_POOL_SIZE = 100;
+    private static final int KEEP_ALIVE_TIME = 10;
+    private static final int QUEUE_CAPACITY = 200;
+    private static final String THREAD_NAME_PREFIX = "Async-Service-";
+
+    @Bean("taskExecutor")
+    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(CORE_POOL_SIZE);
+        executor.setMaxPoolSize(MAX_POOL_SIZE);
+        executor.setQueueCapacity(QUEUE_CAPACITY);
+        executor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
+        executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
+
+        // 线程池对拒绝任务的处理策略
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 初始化
+        executor.initialize();
+        return executor;
+    }
+
+    /**
+     * 执行定时任务
+     */
+    @Bean(name = "scheduledExecutorService")
+    public ScheduledExecutorService scheduledExecutorService() {
+        return new ScheduledThreadPoolExecutor(CORE_POOL_SIZE,
+                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build()) {
+            @Override
+            protected void afterExecute(Runnable r, Throwable t) {
+                super.afterExecute(r, t);
+                printException(r, t);
+            }
+        };
+    }
+
+
+    /**
+     * 打印线程异常信息
+     */
+    public static void printException(Runnable r, Throwable t) {
+        if (t == null && r instanceof Future<?>) {
+            try {
+                Future<?> future = (Future<?>) r;
+                if (future.isDone()) {
+                    future.get();
+                }
+            } catch (CancellationException ce) {
+                t = ce;
+            } catch (ExecutionException ee) {
+                t = ee.getCause();
+            } catch (InterruptedException ie) {
+                Thread.currentThread().interrupt();
+            }
+        }
+        if (t != null) {
+            log.error(t.getMessage(), t);
+        }
+    }
+}

+ 1 - 1
zd-modules/zd-forward/src/main/java/com/zd/forward/util/Base64DecodedMultipartFile.java

@@ -1,4 +1,4 @@
-package com.zd.forward.util;
+package com.zd.forward.utils;
 
 import org.springframework.web.multipart.MultipartFile;
 import sun.misc.BASE64Decoder;

+ 1 - 1
zd-modules/zd-forward/src/main/java/com/zd/forward/util/Base64ToMultipartFile.java

@@ -1,4 +1,4 @@
-package com.zd.forward.util;
+package com.zd.forward.utils;
 
 import org.springframework.web.multipart.MultipartFile;
 

+ 1 - 1
zd-modules/zd-forward/src/main/java/com/zd/forward/util/FileUploadUtils.java

@@ -1,4 +1,4 @@
-package com.zd.forward.util;
+package com.zd.forward.utils;
 
 import com.zd.common.core.exception.ServiceException;
 import com.zd.common.core.exception.file.FileNameLengthLimitExceededException;

+ 9 - 8
zd-modules/zd-forward/src/main/java/com/zd/forward/util/HttpUtils.java

@@ -1,4 +1,4 @@
-package com.zd.forward.util;
+package com.zd.forward.utils;
 
 import com.zd.common.core.exception.ServiceException;
 import com.zd.forward.config.AlgorithmYml;
@@ -11,6 +11,7 @@ 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.RestClientException;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -25,7 +26,7 @@ public class HttpUtils {
     /**
      * 构造算法文件逆流
      */
-    public static HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(MultipartFile file, MultiValueMap<String, Object> params){
+    public static HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(MultipartFile file, MultiValueMap<String, Object> params) {
         try {
             //设置请求头
             HttpHeaders headers = new HttpHeaders();
@@ -36,7 +37,7 @@ public class HttpUtils {
             File uploadFile = multipartFileToFile(file);
             //文件转为文件系统资源
             return getHttpEntity(uploadFile, params, headers);
-        }catch (IOException ex){
+        } catch (IOException ex) {
             ex.printStackTrace();
         }
         return null;
@@ -45,7 +46,7 @@ public class HttpUtils {
     /**
      * 构造算法文件逆流
      */
-    public static HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(File file, MultiValueMap<String, Object> params){
+    public static HttpEntity<MultiValueMap<String, Object>> getHttpEntityMap(File file, MultiValueMap<String, Object> params) {
         //设置请求头
         HttpHeaders headers = new HttpHeaders();
         headers.setContentType(MediaType.MULTIPART_FORM_DATA);
@@ -63,7 +64,7 @@ public class HttpUtils {
     }
 
     public static File multipartFileToFile(MultipartFile file) throws IOException {
-        String originalFilename = file.getOriginalFilename()==null?"":file.getOriginalFilename();
+        String originalFilename = file.getOriginalFilename() == null ? "" : file.getOriginalFilename();
         String[] filename = originalFilename.split("\\.");
         File toFile = File.createTempFile(filename[0], "." + filename[1]);
         file.transferTo(toFile);
@@ -109,15 +110,15 @@ public class HttpUtils {
         return form;
     }
 
-    public static ImgPostResponse<DataPostAnalysisRespDto> send(RestTemplate restTemplate,HttpEntity<MultiValueMap<String, Object>> files, AlgorithmYml algorithmYml){
+    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){
+        if (response.getStatusCode() != HttpStatus.OK) {
             log.error("算法服务请求异常,请查看算服务器");
             throw new ServiceException("算法服务请求异常,请查看算服务器");
         }
-        if (response.getBody()==null){
+        if (response.getBody() == null) {
             log.error("算法服务接口返回异常");
             throw new ServiceException("算法服务接口返回异常");
         }

+ 37 - 0
zd-modules/zd-forward/src/main/java/com/zd/forward/utils/VideoUtils.java

@@ -0,0 +1,37 @@
+package com.zd.forward.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.bytedeco.javacv.FFmpegFrameGrabber;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+public class VideoUtils {
+
+    private VideoUtils() {
+        throw new IllegalStateException("VideoUtils class");
+    }
+    /**
+     * 帧率
+     */
+    private static final int FRAME_RATE = 25;
+
+    /**
+     * 视频宽度
+     */
+    private static final int FRAME_WIDTH = 1920;
+    /**
+     * 视频高度
+     */
+    private static final int FRAME_HEIGHT = 1080;
+
+    public static FFmpegFrameGrabber createGrabber(String rtsp) throws FFmpegFrameGrabber.Exception {
+        FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(rtsp);
+        grabber.setOption("rtsp_transport", "tcp");
+        grabber.setImageHeight(FRAME_HEIGHT);
+        grabber.setImageWidth(FRAME_WIDTH);
+        grabber.setFrameRate(FRAME_RATE);
+        return grabber;
+    }
+}

+ 0 - 1
zd-modules/zd-netty/src/main/java/com/zd/netty/sdk/DeJuRFIDListenerServiceImpl.java

@@ -83,7 +83,6 @@ public class DeJuRFIDListenerServiceImpl implements IService {
             client.setSendHeartBeat(true);//开启心跳检测Tcp连接状态
             client.setPrint(true);
             subscribeTcpHandler(client, hardware);//订阅Tcp断连上报
-
             reSet(hardware, client);
             DeJuRFIDServiceImpl.subscribeHandler(client, hardware);
             remoteLaboratoryService.update(HardwareOperate.OPEN, hardware.getIpAddress());