Commit 1d753b48c023090430c2931fd8e3a45a382eddf8

Authored by hotcoffie
Committed by GitHub
2 parents ec8ab540 bfb3b4ea

Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0

Showing 79 changed files with 1163 additions and 1209 deletions
README.md
@@ -106,7 +106,6 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git @@ -106,7 +106,6 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
106 - [X] 添加RTMP视频 106 - [X] 添加RTMP视频
107 - [X] 云端录像(需要部署单独服务配合使用) 107 - [X] 云端录像(需要部署单独服务配合使用)
108 - [X] 多流媒体节点,自动选择负载最低的节点使用。 108 - [X] 多流媒体节点,自动选择负载最低的节点使用。
109 -- [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。  
110 - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 109 - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
111 110
112 [//]: # (# docker快速体验) 111 [//]: # (# docker快速体验)
@@ -101,13 +101,6 @@ @@ -101,13 +101,6 @@
101 <version>8.0.22</version> 101 <version>8.0.22</version>
102 </dependency> 102 </dependency>
103 103
104 - <!-- 添加sqlite-jdbc数据库驱动 -->  
105 - <dependency>  
106 - <groupId>org.xerial</groupId>  
107 - <artifactId>sqlite-jdbc</artifactId>  
108 - <version>3.32.3.2</version>  
109 - </dependency>  
110 -  
111 <!--Mybatis分页插件 --> 104 <!--Mybatis分页插件 -->
112 <dependency> 105 <dependency>
113 <groupId>com.github.pagehelper</groupId> 106 <groupId>com.github.pagehelper</groupId>
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -47,8 +47,6 @@ public class VideoManagerConstants { @@ -47,8 +47,6 @@ public class VideoManagerConstants {
47 public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_"; 47 public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_";
48 48
49 public static final String EVENT_ONLINE_REGISTER = "1"; 49 public static final String EVENT_ONLINE_REGISTER = "1";
50 -  
51 - public static final String EVENT_ONLINE_KEEPLIVE = "2";  
52 50
53 public static final String EVENT_ONLINE_MESSAGE = "3"; 51 public static final String EVENT_ONLINE_MESSAGE = "3";
54 52
src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
@@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.ApiSaveConstant; @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.ApiSaveConstant;
4 import com.genersoft.iot.vmp.conf.security.SecurityUtils; 4 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
5 import com.genersoft.iot.vmp.service.ILogService; 5 import com.genersoft.iot.vmp.service.ILogService;
6 import com.genersoft.iot.vmp.storager.dao.dto.LogDto; 6 import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
  7 +import com.genersoft.iot.vmp.utils.DateUtil;
7 import org.apache.commons.lang3.StringUtils; 8 import org.apache.commons.lang3.StringUtils;
8 import org.slf4j.Logger; 9 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
@@ -16,7 +17,6 @@ import javax.servlet.annotation.WebFilter; @@ -16,7 +17,6 @@ import javax.servlet.annotation.WebFilter;
16 import javax.servlet.http.HttpServletRequest; 17 import javax.servlet.http.HttpServletRequest;
17 import javax.servlet.http.HttpServletResponse; 18 import javax.servlet.http.HttpServletResponse;
18 import java.io.IOException; 19 import java.io.IOException;
19 -import java.text.SimpleDateFormat;  
20 20
21 /** 21 /**
22 * @author lin 22 * @author lin
@@ -26,7 +26,6 @@ public class ApiAccessFilter extends OncePerRequestFilter { @@ -26,7 +26,6 @@ public class ApiAccessFilter extends OncePerRequestFilter {
26 26
27 private final static Logger logger = LoggerFactory.getLogger(ApiAccessFilter.class); 27 private final static Logger logger = LoggerFactory.getLogger(ApiAccessFilter.class);
28 28
29 - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
30 29
31 @Autowired 30 @Autowired
32 private UserSetting userSetting; 31 private UserSetting userSetting;
@@ -58,7 +57,7 @@ public class ApiAccessFilter extends OncePerRequestFilter { @@ -58,7 +57,7 @@ public class ApiAccessFilter extends OncePerRequestFilter {
58 logDto.setTiming(System.currentTimeMillis() - start); 57 logDto.setTiming(System.currentTimeMillis() - start);
59 logDto.setType(servletRequest.getMethod()); 58 logDto.setType(servletRequest.getMethod());
60 logDto.setUri(servletRequest.getRequestURI()); 59 logDto.setUri(servletRequest.getRequestURI());
61 - logDto.setCreateTime(format.format(System.currentTimeMillis())); 60 + logDto.setCreateTime(DateUtil.getNow());
62 logService.add(logDto); 61 logService.add(logDto);
63 // logger.warn("[Api Access] [{}] [{}] [{}] [{}] [{}] {}ms", 62 // logger.warn("[Api Access] [{}] [{}] [{}] [{}] [{}] {}ms",
64 // uriName, servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getRemoteAddr(), HttpStatus.valueOf(servletResponse.getStatus()), 63 // uriName, servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getRemoteAddr(), HttpStatus.valueOf(servletResponse.getStatus()),
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; 3 import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
4 -import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;  
5 import org.slf4j.Logger; 4 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 5 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.beans.factory.annotation.Autowired;
@@ -9,25 +8,27 @@ import org.springframework.context.annotation.Bean; @@ -9,25 +8,27 @@ import org.springframework.context.annotation.Bean;
9 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 8 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
10 import org.springframework.stereotype.Component; 9 import org.springframework.stereotype.Component;
11 10
12 -import java.util.Date; 11 +import java.time.Instant;
13 import java.util.Map; 12 import java.util.Map;
14 import java.util.Set; 13 import java.util.Set;
15 import java.util.concurrent.ConcurrentHashMap; 14 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.ScheduledFuture; 15 import java.util.concurrent.ScheduledFuture;
  16 +import java.util.concurrent.TimeUnit;
17 17
18 /** 18 /**
19 * 动态定时任务 19 * 动态定时任务
  20 + * @author lin
20 */ 21 */
21 @Component 22 @Component
22 public class DynamicTask { 23 public class DynamicTask {
23 24
24 - private Logger logger = LoggerFactory.getLogger(DynamicTask.class); 25 + private final Logger logger = LoggerFactory.getLogger(DynamicTask.class);
25 26
26 @Autowired 27 @Autowired
27 private ThreadPoolTaskScheduler threadPoolTaskScheduler; 28 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
28 29
29 - private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();  
30 - private Map<String, Runnable> runnableMap = new ConcurrentHashMap<>(); 30 + private final Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
  31 + private final Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
31 32
32 @Bean 33 @Bean
33 public ThreadPoolTaskScheduler threadPoolTaskScheduler() { 34 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
@@ -43,27 +44,27 @@ public class DynamicTask { @@ -43,27 +44,27 @@ public class DynamicTask {
43 * 循环执行的任务 44 * 循环执行的任务
44 * @param key 任务ID 45 * @param key 任务ID
45 * @param task 任务 46 * @param task 任务
46 - * @param cycleForCatalog 间隔 47 + * @param cycleForCatalog 间隔 毫秒
47 * @return 48 * @return
48 */ 49 */
49 public void startCron(String key, Runnable task, int cycleForCatalog) { 50 public void startCron(String key, Runnable task, int cycleForCatalog) {
50 - ScheduledFuture future = futureMap.get(key); 51 + ScheduledFuture<?> future = futureMap.get(key);
51 if (future != null) { 52 if (future != null) {
52 if (future.isCancelled()) { 53 if (future.isCancelled()) {
53 - logger.info("任务【{}】已存在但是关闭状态!!!", key); 54 + logger.debug("任务【{}】已存在但是关闭状态!!!", key);
54 } else { 55 } else {
55 - logger.info("任务【{}】已存在且已启动!!!", key); 56 + logger.debug("任务【{}】已存在且已启动!!!", key);
56 return; 57 return;
57 } 58 }
58 } 59 }
59 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 60 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
60 - future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog * 1000L); 61 + future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog);
61 if (future != null){ 62 if (future != null){
62 futureMap.put(key, future); 63 futureMap.put(key, future);
63 runnableMap.put(key, task); 64 runnableMap.put(key, task);
64 - logger.info("任务【{}】启动成功!!!", key); 65 + logger.debug("任务【{}】启动成功!!!", key);
65 }else { 66 }else {
66 - logger.info("任务【{}】启动失败!!!", key); 67 + logger.debug("任务【{}】启动失败!!!", key);
67 } 68 }
68 } 69 }
69 70
@@ -76,25 +77,27 @@ public class DynamicTask { @@ -76,25 +77,27 @@ public class DynamicTask {
76 */ 77 */
77 public void startDelay(String key, Runnable task, int delay) { 78 public void startDelay(String key, Runnable task, int delay) {
78 stop(key); 79 stop(key);
79 - Date starTime = new Date(System.currentTimeMillis() + delay); 80 +
  81 + // 获取执行的时刻
  82 + Instant startInstant = Instant.now().plusMillis(TimeUnit.MILLISECONDS.toMillis(delay));
80 83
81 ScheduledFuture future = futureMap.get(key); 84 ScheduledFuture future = futureMap.get(key);
82 if (future != null) { 85 if (future != null) {
83 if (future.isCancelled()) { 86 if (future.isCancelled()) {
84 - logger.info("任务【{}】已存在但是关闭状态!!!", key); 87 + logger.debug("任务【{}】已存在但是关闭状态!!!", key);
85 } else { 88 } else {
86 - logger.info("任务【{}】已存在且已启动!!!", key); 89 + logger.debug("任务【{}】已存在且已启动!!!", key);
87 return; 90 return;
88 } 91 }
89 } 92 }
90 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 93 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
91 - future = threadPoolTaskScheduler.schedule(task, starTime); 94 + future = threadPoolTaskScheduler.schedule(task, startInstant);
92 if (future != null){ 95 if (future != null){
93 futureMap.put(key, future); 96 futureMap.put(key, future);
94 runnableMap.put(key, task); 97 runnableMap.put(key, task);
95 - logger.info("任务【{}】启动成功!!!", key); 98 + logger.debug("任务【{}】启动成功!!!", key);
96 }else { 99 }else {
97 - logger.info("任务【{}】启动失败!!!", key); 100 + logger.debug("任务【{}】启动失败!!!", key);
98 } 101 }
99 } 102 }
100 103
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  4 +import com.genersoft.iot.vmp.utils.DateUtil;
4 import org.springframework.beans.factory.annotation.Value; 5 import org.springframework.beans.factory.annotation.Value;
5 import org.springframework.context.annotation.Configuration; 6 import org.springframework.context.annotation.Configuration;
6 import org.springframework.util.StringUtils; 7 import org.springframework.util.StringUtils;
7 8
8 -import java.text.SimpleDateFormat;  
9 -import java.util.Date;  
10 9
11 @Configuration("mediaConfig") 10 @Configuration("mediaConfig")
12 public class MediaConfig{ 11 public class MediaConfig{
@@ -206,9 +205,8 @@ public class MediaConfig{ @@ -206,9 +205,8 @@ public class MediaConfig{
206 mediaServerItem.setRecordAssistPort(recordAssistPort); 205 mediaServerItem.setRecordAssistPort(recordAssistPort);
207 mediaServerItem.setHookAliveInterval(120); 206 mediaServerItem.setHookAliveInterval(120);
208 207
209 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
210 - mediaServerItem.setCreateTime(format.format(System.currentTimeMillis()));  
211 - mediaServerItem.setUpdateTime(format.format(System.currentTimeMillis())); 208 + mediaServerItem.setCreateTime(DateUtil.getNow());
  209 + mediaServerItem.setUpdateTime(DateUtil.getNow());
212 210
213 return mediaServerItem; 211 return mediaServerItem;
214 } 212 }
src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java
@@ -35,10 +35,11 @@ public class ThreadPoolTaskConfig { @@ -35,10 +35,11 @@ public class ThreadPoolTaskConfig {
35 * 允许线程空闲时间(单位:默认为秒) 35 * 允许线程空闲时间(单位:默认为秒)
36 */ 36 */
37 private static final int keepAliveTime = 30; 37 private static final int keepAliveTime = 30;
  38 +
38 /** 39 /**
39 * 缓冲队列大小 40 * 缓冲队列大小
40 */ 41 */
41 - private static final int queueCapacity = 500; 42 + private static final int queueCapacity = 10000;
42 /** 43 /**
43 * 线程池名前缀 44 * 线程池名前缀
44 */ 45 */
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
@@ -48,8 +48,15 @@ public class SipLayer{ @@ -48,8 +48,15 @@ public class SipLayer{
48 Properties properties = new Properties(); 48 Properties properties = new Properties();
49 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); 49 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
50 properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp()); 50 properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp());
  51 + /**
  52 + * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码
  53 + * gov/nist/javax/sip/SipStackImpl.class
  54 + */
51 properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true"); 55 properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
52 properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); // 接收所有notify请求,即使没有订阅 56 properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); // 接收所有notify请求,即使没有订阅
  57 + properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); // 为_NULL _对话框传递_终止的_事件
  58 + properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal"); // 会话清理策略
  59 + properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "10");
53 /** 60 /**
54 * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = 61 * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE =
55 * 0; public static final int TRACE_MESSAGES = 16; public static final int 62 * 0; public static final int TRACE_MESSAGES = 16; public static final int
@@ -74,11 +81,11 @@ public class SipLayer{ @@ -74,11 +81,11 @@ public class SipLayer{
74 tcpSipProvider.setDialogErrorsAutomaticallyHandled(); 81 tcpSipProvider.setDialogErrorsAutomaticallyHandled();
75 tcpSipProvider.addSipListener(sipProcessorObserver); 82 tcpSipProvider.addSipListener(sipProcessorObserver);
76 // tcpSipProvider.setAutomaticDialogSupportEnabled(false); 83 // tcpSipProvider.setAutomaticDialogSupportEnabled(false);
77 - logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}"); 84 + logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort());
78 } catch (TransportNotSupportedException e) { 85 } catch (TransportNotSupportedException e) {
79 e.printStackTrace(); 86 e.printStackTrace();
80 } catch (InvalidArgumentException e) { 87 } catch (InvalidArgumentException e) {
81 - logger.error("无法使用 [ {}:{} ]作为SIP[ TCP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用" 88 + logger.error("[Sip Server] 无法使用 [ {}:{} ]作为SIP[ TCP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用"
82 , sipConfig.getMonitorIp(), sipConfig.getPort()); 89 , sipConfig.getMonitorIp(), sipConfig.getPort());
83 } catch (TooManyListenersException e) { 90 } catch (TooManyListenersException e) {
84 e.printStackTrace(); 91 e.printStackTrace();
@@ -101,14 +108,14 @@ public class SipLayer{ @@ -101,14 +108,14 @@ public class SipLayer{
101 } catch (TransportNotSupportedException e) { 108 } catch (TransportNotSupportedException e) {
102 e.printStackTrace(); 109 e.printStackTrace();
103 } catch (InvalidArgumentException e) { 110 } catch (InvalidArgumentException e) {
104 - logger.error("无法使用 [ {}:{} ]作为SIP[ UDP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用" 111 + logger.error("[Sip Server] 无法使用 [ {}:{} ]作为SIP[ UDP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用"
105 , sipConfig.getMonitorIp(), sipConfig.getPort()); 112 , sipConfig.getMonitorIp(), sipConfig.getPort());
106 } catch (TooManyListenersException e) { 113 } catch (TooManyListenersException e) {
107 e.printStackTrace(); 114 e.printStackTrace();
108 } catch (ObjectInUseException e) { 115 } catch (ObjectInUseException e) {
109 e.printStackTrace(); 116 e.printStackTrace();
110 } 117 }
111 - logger.info("Sip Server UDP 启动成功 port [" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "]"); 118 + logger.info("[Sip Server] UDP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort());
112 return udpSipProvider; 119 return udpSipProvider;
113 } 120 }
114 121
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
@@ -27,8 +27,7 @@ package com.genersoft.iot.vmp.gb28181.auth; @@ -27,8 +27,7 @@ package com.genersoft.iot.vmp.gb28181.auth;
27 27
28 import java.security.MessageDigest; 28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException; 29 import java.security.NoSuchAlgorithmException;
30 -import java.text.DecimalFormat;  
31 -import java.util.Date; 30 +import java.time.Instant;
32 import java.util.Random; 31 import java.util.Random;
33 32
34 import javax.sip.address.URI; 33 import javax.sip.address.URI;
@@ -90,17 +89,12 @@ public class DigestServerAuthenticationHelper { @@ -90,17 +89,12 @@ public class DigestServerAuthenticationHelper {
90 * @return a generated nonce. 89 * @return a generated nonce.
91 */ 90 */
92 private String generateNonce() { 91 private String generateNonce() {
93 - // Get the time of day and run MD5 over it.  
94 - Date date = new Date();  
95 - long time = date.getTime(); 92 + long time = Instant.now().toEpochMilli();
96 Random rand = new Random(); 93 Random rand = new Random();
97 long pad = rand.nextLong(); 94 long pad = rand.nextLong();
98 - // String nonceString = (new Long(time)).toString()  
99 - // + (new Long(pad)).toString();  
100 String nonceString = Long.valueOf(time).toString() 95 String nonceString = Long.valueOf(time).toString()
101 + Long.valueOf(pad).toString(); 96 + Long.valueOf(pad).toString();
102 byte mdbytes[] = messageDigest.digest(nonceString.getBytes()); 97 byte mdbytes[] = messageDigest.digest(nonceString.getBytes());
103 - // Convert the mdbytes array into a hex string.  
104 return toHexString(mdbytes); 98 return toHexString(mdbytes);
105 } 99 }
106 100
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 -import java.util.Date; 3 +import java.time.Instant;
4 import java.util.List; 4 import java.util.List;
5 5
6 public class CatalogData { 6 public class CatalogData {
7 private int sn; // 命令序列号 7 private int sn; // 命令序列号
8 private int total; 8 private int total;
9 private List<DeviceChannel> channelList; 9 private List<DeviceChannel> channelList;
10 - private Date lastTime; 10 + private Instant lastTime;
11 private Device device; 11 private Device device;
12 private String errorMsg; 12 private String errorMsg;
13 13
@@ -41,11 +41,11 @@ public class CatalogData { @@ -41,11 +41,11 @@ public class CatalogData {
41 this.channelList = channelList; 41 this.channelList = channelList;
42 } 42 }
43 43
44 - public Date getLastTime() { 44 + public Instant getLastTime() {
45 return lastTime; 45 return lastTime;
46 } 46 }
47 47
48 - public void setLastTime(Date lastTime) { 48 + public void setLastTime(Instant lastTime) {
49 this.lastTime = lastTime; 49 this.lastTime = lastTime;
50 } 50 }
51 51
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
@@ -100,11 +100,6 @@ public class Device { @@ -100,11 +100,6 @@ public class Device {
100 private String mediaServerId; 100 private String mediaServerId;
101 101
102 /** 102 /**
103 - * 首次注册  
104 - */  
105 - private boolean firsRegister;  
106 -  
107 - /**  
108 * 字符集, 支持 UTF-8 与 GB2312 103 * 字符集, 支持 UTF-8 与 GB2312
109 */ 104 */
110 private String charset ; 105 private String charset ;
@@ -279,14 +274,6 @@ public class Device { @@ -279,14 +274,6 @@ public class Device {
279 this.mediaServerId = mediaServerId; 274 this.mediaServerId = mediaServerId;
280 } 275 }
281 276
282 - public boolean isFirsRegister() {  
283 - return firsRegister;  
284 - }  
285 -  
286 - public void setFirsRegister(boolean firsRegister) {  
287 - this.firsRegister = firsRegister;  
288 - }  
289 -  
290 public String getCharset() { 277 public String getCharset() {
291 return charset; 278 return charset;
292 } 279 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 -  
4 -//import gov.nist.javax.sip.header.SIPDate;  
5 - 3 +import java.time.Instant;
6 import java.util.List; 4 import java.util.List;
7 5
8 /** 6 /**
@@ -21,6 +19,8 @@ public class RecordInfo { @@ -21,6 +19,8 @@ public class RecordInfo {
21 private String name; 19 private String name;
22 20
23 private int sumNum; 21 private int sumNum;
  22 +
  23 + private Instant lastTime;
24 24
25 private List<RecordItem> recordList; 25 private List<RecordItem> recordList;
26 26
@@ -71,4 +71,12 @@ public class RecordInfo { @@ -71,4 +71,12 @@ public class RecordInfo {
71 public void setSn(String sn) { 71 public void setSn(String sn) {
72 this.sn = sn; 72 this.sn = sn;
73 } 73 }
  74 +
  75 + public Instant getLastTime() {
  76 + return lastTime;
  77 + }
  78 +
  79 + public void setLastTime(Instant lastTime) {
  80 + this.lastTime = lastTime;
  81 + }
74 } 82 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 3
  4 +import com.genersoft.iot.vmp.utils.DateUtil;
4 import org.jetbrains.annotations.NotNull; 5 import org.jetbrains.annotations.NotNull;
5 6
6 import java.text.ParseException; 7 import java.text.ParseException;
7 -import java.text.SimpleDateFormat;  
8 -import java.util.Date; 8 +import java.time.Instant;
  9 +import java.time.temporal.TemporalAccessor;
9 10
10 /** 11 /**
11 * @description:设备录像bean 12 * @description:设备录像bean
@@ -116,18 +117,17 @@ public class RecordItem implements Comparable&lt;RecordItem&gt;{ @@ -116,18 +117,17 @@ public class RecordItem implements Comparable&lt;RecordItem&gt;{
116 117
117 @Override 118 @Override
118 public int compareTo(@NotNull RecordItem recordItem) { 119 public int compareTo(@NotNull RecordItem recordItem) {
119 - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
120 - try {  
121 - Date startTime_now = sdf.parse(startTime);  
122 - Date startTime_param = sdf.parse(recordItem.getStartTime());  
123 - if (startTime_param.compareTo(startTime_now) > 0) {  
124 - return -1;  
125 - }else {  
126 - return 1;  
127 - }  
128 - } catch (ParseException e) {  
129 - e.printStackTrace(); 120 + TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime);
  121 + TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime());
  122 + Instant startTimeParamInstant = Instant.from(startTimeParam);
  123 + Instant startTimeNowInstant = Instant.from(startTimeNow);
  124 + if (startTimeNowInstant.equals(startTimeParamInstant)) {
  125 + return 0;
  126 + }else if (Instant.from(startTimeParam).isAfter(Instant.from(startTimeNow)) ) {
  127 + return -1;
  128 + }else {
  129 + return 1;
130 } 130 }
131 - return 0; 131 +
132 } 132 }
133 } 133 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
@@ -77,6 +77,21 @@ public class SendRtpItem { @@ -77,6 +77,21 @@ public class SendRtpItem {
77 private String CallId; 77 private String CallId;
78 78
79 /** 79 /**
  80 + * 发送时,rtp的pt(uint8_t),不传时默认为96
  81 + */
  82 + private int pt = 96;
  83 +
  84 + /**
  85 + * 发送时,rtp的负载类型。为true时,负载为ps;为false时,为es;
  86 + */
  87 + private boolean usePs = true;
  88 +
  89 + /**
  90 + * 当usePs 为false时,有效。为1时,发送音频;为0时,发送视频;不传时默认为0
  91 + */
  92 + private boolean onlyAudio = false;
  93 +
  94 + /**
80 * 播放类型 95 * 播放类型
81 */ 96 */
82 private InviteStreamType playType; 97 private InviteStreamType playType;
@@ -221,5 +236,27 @@ public class SendRtpItem { @@ -221,5 +236,27 @@ public class SendRtpItem {
221 this.dialog = dialog; 236 this.dialog = dialog;
222 } 237 }
223 238
  239 + public int getPt() {
  240 + return pt;
  241 + }
224 242
  243 + public void setPt(int pt) {
  244 + this.pt = pt;
  245 + }
  246 +
  247 + public boolean isUsePs() {
  248 + return usePs;
  249 + }
  250 +
  251 + public void setUsePs(boolean usePs) {
  252 + this.usePs = usePs;
  253 + }
  254 +
  255 + public boolean isOnlyAudio() {
  256 + return onlyAudio;
  257 + }
  258 +
  259 + public void setOnlyAudio(boolean onlyAudio) {
  260 + this.onlyAudio = onlyAudio;
  261 + }
225 } 262 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
@@ -61,12 +61,11 @@ public class SubscribeHolder { @@ -61,12 +61,11 @@ public class SubscribeHolder {
61 // 添加任务处理GPS定时推送 61 // 添加任务处理GPS定时推送
62 dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, 62 dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform,
63 storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask), 63 storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask),
64 - subscribeInfo.getGpsInterval()); 64 + subscribeInfo.getGpsInterval() * 1000);
65 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; 65 String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
66 dynamicTask.stop(taskOverdueKey); 66 dynamicTask.stop(taskOverdueKey);
67 // 添加任务处理订阅过期 67 // 添加任务处理订阅过期
68 dynamicTask.startDelay(taskOverdueKey, () -> { 68 dynamicTask.startDelay(taskOverdueKey, () -> {
69 - System.out.println("订阅过期");  
70 removeMobilePositionSubscribe(subscribeInfo.getId()); 69 removeMobilePositionSubscribe(subscribeInfo.getId());
71 }, 70 },
72 subscribeInfo.getExpires() * 1000); 71 subscribeInfo.getExpires() * 1000);
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
1 package com.genersoft.iot.vmp.gb28181.event; 1 package com.genersoft.iot.vmp.gb28181.event;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.*; 3 import com.genersoft.iot.vmp.gb28181.bean.*;
4 -import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent; 4 +import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent;
5 import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; 5 import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent;
6 import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformCycleRegisterEvent; 6 import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformCycleRegisterEvent;
7 import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; 7 import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent;
@@ -11,12 +11,11 @@ import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; @@ -11,12 +11,11 @@ import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent;
11 import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent; 11 import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent;
12 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
13 import org.springframework.context.ApplicationEventPublisher; 13 import org.springframework.context.ApplicationEventPublisher;
14 -import org.springframework.scheduling.annotation.Async;  
15 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
16 15
17 import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; 16 import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent;
18 -import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent;  
19 17
  18 +import javax.sip.TimeoutEvent;
20 import java.util.ArrayList; 19 import java.util.ArrayList;
21 import java.util.HashSet; 20 import java.util.HashSet;
22 import java.util.List; 21 import java.util.List;
@@ -32,28 +31,6 @@ public class EventPublisher { @@ -32,28 +31,6 @@ public class EventPublisher {
32 31
33 @Autowired 32 @Autowired
34 private ApplicationEventPublisher applicationEventPublisher; 33 private ApplicationEventPublisher applicationEventPublisher;
35 -  
36 - public void onlineEventPublish(Device device, String from, int expires) {  
37 - OnlineEvent onEvent = new OnlineEvent(this);  
38 - onEvent.setDevice(device);  
39 - onEvent.setFrom(from);  
40 - onEvent.setExpires(expires);  
41 - applicationEventPublisher.publishEvent(onEvent);  
42 - }  
43 -  
44 - public void onlineEventPublish(Device device, String from) {  
45 - OnlineEvent onEvent = new OnlineEvent(this);  
46 - onEvent.setDevice(device);  
47 - onEvent.setFrom(from);  
48 - applicationEventPublisher.publishEvent(onEvent);  
49 - }  
50 -  
51 - public void outlineEventPublish(String deviceId, String from){  
52 - OfflineEvent outEvent = new OfflineEvent(this);  
53 - outEvent.setDeviceId(deviceId);  
54 - outEvent.setFrom(from);  
55 - applicationEventPublisher.publishEvent(outEvent);  
56 - }  
57 34
58 /** 35 /**
59 * 平台心跳到期事件 36 * 平台心跳到期事件
@@ -115,6 +92,13 @@ public class EventPublisher { @@ -115,6 +92,13 @@ public class EventPublisher {
115 } 92 }
116 93
117 94
  95 + public void requestTimeOut(TimeoutEvent timeoutEvent) {
  96 + RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this);
  97 + requestTimeoutEvent.setTimeoutEvent(timeoutEvent);
  98 + applicationEventPublisher.publishEvent(requestTimeoutEvent);
  99 + }
  100 +
  101 +
118 /** 102 /**
119 * 103 *
120 * @param platformId 104 * @param platformId
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
@@ -9,11 +9,14 @@ import org.springframework.stereotype.Component; @@ -9,11 +9,14 @@ import org.springframework.stereotype.Component;
9 import javax.sip.*; 9 import javax.sip.*;
10 import javax.sip.header.CallIdHeader; 10 import javax.sip.header.CallIdHeader;
11 import javax.sip.message.Response; 11 import javax.sip.message.Response;
12 -import java.util.Calendar;  
13 -import java.util.Date; 12 +import java.time.Instant;
14 import java.util.Map; 13 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap; 14 import java.util.concurrent.ConcurrentHashMap;
  15 +import java.util.concurrent.TimeUnit;
16 16
  17 +/**
  18 + * @author lin
  19 + */
17 @Component 20 @Component
18 public class SipSubscribe { 21 public class SipSubscribe {
19 22
@@ -23,28 +26,25 @@ public class SipSubscribe { @@ -23,28 +26,25 @@ public class SipSubscribe {
23 26
24 private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>(); 27 private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
25 28
26 - private Map<String, Date> okTimeSubscribes = new ConcurrentHashMap<>();  
27 - private Map<String, Date> errorTimeSubscribes = new ConcurrentHashMap<>(); 29 + private Map<String, Instant> okTimeSubscribes = new ConcurrentHashMap<>();
  30 + private Map<String, Instant> errorTimeSubscribes = new ConcurrentHashMap<>();
28 31
29 // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次 32 // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
30 -// @Scheduled(fixedRate= 100 * 60 * 60 ) 33 + // @Scheduled(fixedRate= 100 * 60 * 60 )
31 @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 34 @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
32 public void execute(){ 35 public void execute(){
33 logger.info("[定时任务] 清理过期的SIP订阅信息"); 36 logger.info("[定时任务] 清理过期的SIP订阅信息");
34 - Calendar calendar = Calendar.getInstance();  
35 - calendar.setTime(new Date());  
36 - calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 5); 37 +
  38 + Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5));
37 39
38 for (String key : okTimeSubscribes.keySet()) { 40 for (String key : okTimeSubscribes.keySet()) {
39 - if (okTimeSubscribes.get(key).before(calendar.getTime())){  
40 -// logger.info("[定时任务] 清理过期的订阅信息: {}", key); 41 + if (okTimeSubscribes.get(key).isBefore(instant)){
41 okSubscribes.remove(key); 42 okSubscribes.remove(key);
42 okTimeSubscribes.remove(key); 43 okTimeSubscribes.remove(key);
43 } 44 }
44 } 45 }
45 for (String key : errorTimeSubscribes.keySet()) { 46 for (String key : errorTimeSubscribes.keySet()) {
46 - if (errorTimeSubscribes.get(key).before(calendar.getTime())){  
47 -// logger.info("[定时任务] 清理过期的订阅信息: {}", key); 47 + if (errorTimeSubscribes.get(key).isBefore(instant)){
48 errorSubscribes.remove(key); 48 errorSubscribes.remove(key);
49 errorTimeSubscribes.remove(key); 49 errorTimeSubscribes.remove(key);
50 } 50 }
@@ -117,12 +117,12 @@ public class SipSubscribe { @@ -117,12 +117,12 @@ public class SipSubscribe {
117 117
118 public void addErrorSubscribe(String key, SipSubscribe.Event event) { 118 public void addErrorSubscribe(String key, SipSubscribe.Event event) {
119 errorSubscribes.put(key, event); 119 errorSubscribes.put(key, event);
120 - errorTimeSubscribes.put(key, new Date()); 120 + errorTimeSubscribes.put(key, Instant.now());
121 } 121 }
122 122
123 public void addOkSubscribe(String key, SipSubscribe.Event event) { 123 public void addOkSubscribe(String key, SipSubscribe.Event event) {
124 okSubscribes.put(key, event); 124 okSubscribes.put(key, event);
125 - okTimeSubscribes.put(key, new Date()); 125 + okTimeSubscribes.put(key, Instant.now());
126 } 126 }
127 127
128 public SipSubscribe.Event getErrorSubscribe(String key) { 128 public SipSubscribe.Event getErrorSubscribe(String key) {
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.event.device;
  2 +
  3 +import org.springframework.context.ApplicationEvent;
  4 +
  5 +import javax.sip.TimeoutEvent;
  6 +
  7 +/**
  8 + * @author lin
  9 + */
  10 +public class RequestTimeoutEvent extends ApplicationEvent {
  11 + public RequestTimeoutEvent(Object source) {
  12 + super(source);
  13 + }
  14 +
  15 +
  16 + private TimeoutEvent timeoutEvent;
  17 +
  18 + public TimeoutEvent getTimeoutEvent() {
  19 + return timeoutEvent;
  20 + }
  21 +
  22 + public void setTimeoutEvent(TimeoutEvent timeoutEvent) {
  23 + this.timeoutEvent = timeoutEvent;
  24 + }
  25 +}
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.event.device;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  4 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
  5 +import com.genersoft.iot.vmp.service.IDeviceService;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.context.ApplicationListener;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +import javax.sip.ClientTransaction;
  11 +import javax.sip.address.SipURI;
  12 +import javax.sip.header.CallIdHeader;
  13 +import javax.sip.header.ToHeader;
  14 +import javax.sip.message.Request;
  15 +
  16 +/**
  17 + * @author lin
  18 + */
  19 +@Component
  20 +public class RequestTimeoutEventImpl implements ApplicationListener<RequestTimeoutEvent> {
  21 +
  22 + @Autowired
  23 + private IDeviceService deviceService;
  24 +
  25 + @Override
  26 + public void onApplicationEvent(RequestTimeoutEvent event) {
  27 + ClientTransaction clientTransaction = event.getTimeoutEvent().getClientTransaction();
  28 + if (clientTransaction != null) {
  29 + Request request = clientTransaction.getRequest();
  30 + if (request != null) {
  31 + String host = ((SipURI) request.getRequestURI()).getHost();
  32 + int port = ((SipURI) request.getRequestURI()).getPort();
  33 + Device device = deviceService.getDeviceByHostAndPort(host, port);
  34 + if (device == null) {
  35 + return;
  36 + }
  37 + deviceService.offline(device.getDeviceId());
  38 + }
  39 + }
  40 + }
  41 +}
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
@@ -17,9 +17,8 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; @@ -17,9 +17,8 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
17 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 17 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
18 18
19 /** 19 /**
20 - * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件  
21 - * @author: swwheihei  
22 - * @date: 2020年5月6日 上午11:35:46 20 + * 设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
  21 + * @author swwheihei
23 */ 22 */
24 @Component 23 @Component
25 public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener { 24 public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener {
@@ -55,25 +54,18 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent @@ -55,25 +54,18 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent
55 // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线 54 // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线
56 String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_"; 55 String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_";
57 String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_"; 56 String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_";
58 - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_";  
59 String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_"; 57 String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_";
60 if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) { 58 if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {
61 - String platformGBId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length(),expiredKey.length());  
62 - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGBId); 59 + String platformGbId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length());
  60 + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId);
63 if (platform != null) { 61 if (platform != null) {
64 - publisher.platformKeepaliveExpireEventPublish(platformGBId); 62 + publisher.platformKeepaliveExpireEventPublish(platformGbId);
65 } 63 }
66 }else if (expiredKey.startsWith(PLATFORM_REGISTER_PREFIX)) { 64 }else if (expiredKey.startsWith(PLATFORM_REGISTER_PREFIX)) {
67 - String platformGBId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length());  
68 - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGBId); 65 + String platformGbId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length());
  66 + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId);
69 if (platform != null) { 67 if (platform != null) {
70 - publisher.platformRegisterCycleEventPublish(platformGBId);  
71 - }  
72 - }else if (expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){  
73 - String deviceId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length());  
74 - Device device = storager.queryVideoDevice(deviceId);  
75 - if (device != null) {  
76 - publisher.outlineEventPublish(deviceId, KEEPLIVEKEY_PREFIX); 68 + publisher.platformRegisterCycleEventPublish(platformGbId);
77 } 69 }
78 }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) { 70 }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) {
79 String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length()); 71 String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length());
@@ -85,6 +77,5 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent @@ -85,6 +77,5 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent
85 sipSubscribe.getErrorSubscribe(callId).response(eventResult); 77 sipSubscribe.getErrorSubscribe(callId).response(eventResult);
86 } 78 }
87 } 79 }
88 -  
89 } 80 }
90 } 81 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.event.offline;  
2 -  
3 -import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;  
4 -import com.genersoft.iot.vmp.conf.UserSetting;  
5 -import org.slf4j.Logger;  
6 -import org.slf4j.LoggerFactory;  
7 -import org.springframework.beans.factory.annotation.Autowired;  
8 -import org.springframework.data.redis.connection.Message;  
9 -import org.springframework.data.redis.listener.RedisMessageListenerContainer;  
10 -import org.springframework.stereotype.Component;  
11 -  
12 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
13 -import com.genersoft.iot.vmp.gb28181.event.EventPublisher;  
14 -  
15 -/**  
16 - * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件  
17 - * @author: swwheihei  
18 - * @date: 2020年5月6日 上午11:35:46  
19 - */  
20 -@Component  
21 -public class KeepliveTimeoutListener extends RedisKeyExpirationEventMessageListener {  
22 -  
23 - private Logger logger = LoggerFactory.getLogger(KeepliveTimeoutListener.class);  
24 -  
25 - @Autowired  
26 - private EventPublisher publisher;  
27 -  
28 - @Autowired  
29 - private UserSetting userSetting;  
30 -  
31 - public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {  
32 - super(listenerContainer, userSetting);  
33 - }  
34 -  
35 - @Override  
36 - public void init() {  
37 - if (!userSetting.getRedisConfig()) {  
38 - // 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用  
39 - setKeyspaceNotificationsConfigParameter("");  
40 - }  
41 - super.init();  
42 - }  
43 -  
44 -  
45 - /**  
46 - * 监听失效的key,key格式为keeplive_deviceId  
47 - * @param message  
48 - * @param pattern  
49 - */  
50 - @Override  
51 - public void onMessage(Message message, byte[] pattern) {  
52 - // 获取失效的key  
53 - String expiredKey = message.toString();  
54 - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_";  
55 - if(!expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){  
56 - logger.debug("收到redis过期监听,但开头不是"+KEEPLIVEKEY_PREFIX+",忽略");  
57 - return;  
58 - }  
59 -  
60 - String deviceId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length());  
61 - publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_TIMEOUT);  
62 - }  
63 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.event.offline;  
2 -  
3 -import org.springframework.context.ApplicationEvent;  
4 -  
5 -/**  
6 - * @description: 离线事件类  
7 - * @author: swwheihei  
8 - * @date: 2020年5月6日 上午11:33:13  
9 - */  
10 -public class OfflineEvent extends ApplicationEvent {  
11 -  
12 - /**  
13 - *  
14 - */  
15 - private static final long serialVersionUID = 1L;  
16 -  
17 - public OfflineEvent(Object source) {  
18 - super(source);  
19 - }  
20 -  
21 - private String deviceId;  
22 -  
23 - private String from;  
24 -  
25 - public String getDeviceId() {  
26 - return deviceId;  
27 - }  
28 -  
29 - public void setDeviceId(String deviceId) {  
30 - this.deviceId = deviceId;  
31 - }  
32 -  
33 - public String getFrom() {  
34 - return from;  
35 - }  
36 -  
37 - public void setFrom(String from) {  
38 - this.from = from;  
39 - }  
40 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.event.offline;  
2 -  
3 -import com.genersoft.iot.vmp.conf.UserSetting;  
4 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
5 -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;  
6 -import com.genersoft.iot.vmp.gb28181.event.EventPublisher;  
7 -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;  
8 -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;  
9 -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;  
10 -import com.genersoft.iot.vmp.service.IMediaServerService;  
11 -import org.slf4j.Logger;  
12 -import org.slf4j.LoggerFactory;  
13 -import org.springframework.beans.factory.annotation.Autowired;  
14 -import org.springframework.context.ApplicationListener;  
15 -import org.springframework.stereotype.Component;  
16 -  
17 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
18 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
19 -import com.genersoft.iot.vmp.utils.redis.RedisUtil;  
20 -  
21 -import java.util.List;  
22 -  
23 -/**  
24 - * @description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源:  
25 - * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor}  
26 - * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener}  
27 - * @author: swwheihei  
28 - * @date: 2020年5月6日 下午1:51:23  
29 - */  
30 -@Component  
31 -public class OfflineEventListener implements ApplicationListener<OfflineEvent> {  
32 -  
33 - private final static Logger logger = LoggerFactory.getLogger(OfflineEventListener.class);  
34 -  
35 - @Autowired  
36 - private IVideoManagerStorage storager;  
37 -  
38 - @Autowired  
39 - private VideoStreamSessionManager streamSession;  
40 -  
41 - @Autowired  
42 - private RedisUtil redis;  
43 -  
44 - @Autowired  
45 - private UserSetting userSetting;  
46 -  
47 - @Autowired  
48 - private EventPublisher eventPublisher;  
49 -  
50 -  
51 - @Autowired  
52 - private IMediaServerService mediaServerService;  
53 -  
54 -  
55 - @Autowired  
56 - private ZLMRTPServerFactory zlmrtpServerFactory;  
57 -  
58 - @Override  
59 - public void onApplicationEvent(OfflineEvent event) {  
60 -  
61 - logger.info("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom());  
62 -  
63 - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + event.getDeviceId();  
64 -  
65 - switch (event.getFrom()) {  
66 - // 心跳超时触发的离线事件,说明redis中已删除,无需处理  
67 - case VideoManagerConstants.EVENT_OUTLINE_TIMEOUT:  
68 - break;  
69 - // 设备主动注销触发的离线事件,需要删除redis中的超时监听  
70 - case VideoManagerConstants.EVENT_OUTLINE_UNREGISTER:  
71 - redis.del(key);  
72 - break;  
73 - default:  
74 - boolean exist = redis.hasKey(key);  
75 - if (exist) {  
76 - redis.del(key);  
77 - }  
78 - }  
79 -  
80 - List<DeviceChannel> deviceChannelList = storager.queryOnlineChannelsByDeviceId(event.getDeviceId());  
81 - eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.OFF);  
82 - // 处理离线监听  
83 - storager.outline(event.getDeviceId());  
84 -  
85 - // TODO 离线取消订阅  
86 -  
87 - // 离线释放所有ssrc  
88 - List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(event.getDeviceId(), null, null, null);  
89 - if (ssrcTransactions != null && ssrcTransactions.size() > 0) {  
90 - for (SsrcTransaction ssrcTransaction : ssrcTransactions) {  
91 - mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());  
92 - mediaServerService.closeRTPServer(event.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());  
93 - streamSession.remove(event.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());  
94 - }  
95 - }  
96 -  
97 - }  
98 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.event.online;  
2 -  
3 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
4 -import org.springframework.context.ApplicationEvent;  
5 -  
6 -/**  
7 - * @description: 在线事件类  
8 - * @author: swwheihei  
9 - * @date: 2020年5月6日 上午11:32:56  
10 - */  
11 -public class OnlineEvent extends ApplicationEvent {  
12 -  
13 - /**  
14 - *  
15 - */  
16 - private static final long serialVersionUID = 1L;  
17 -  
18 - public OnlineEvent(Object source) {  
19 - super(source);  
20 - }  
21 -  
22 - private Device device;  
23 -  
24 - private String from;  
25 -  
26 - private int expires;  
27 -  
28 - public Device getDevice() {  
29 - return device;  
30 - }  
31 -  
32 - public void setDevice(Device device) {  
33 - this.device = device;  
34 - }  
35 -  
36 - public String getFrom() {  
37 - return from;  
38 - }  
39 -  
40 - public void setFrom(String from) {  
41 - this.from = from;  
42 - }  
43 -  
44 - public int getExpires() {  
45 - return expires;  
46 - }  
47 -  
48 - public void setExpires(int expires) {  
49 - this.expires = expires;  
50 - }  
51 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.event.online;  
2 -  
3 -import com.genersoft.iot.vmp.conf.SipConfig;  
4 -import com.genersoft.iot.vmp.conf.UserSetting;  
5 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
6 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
7 -import com.genersoft.iot.vmp.gb28181.event.EventPublisher;  
8 -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;  
9 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;  
10 -import com.genersoft.iot.vmp.service.IDeviceService;  
11 -import org.slf4j.Logger;  
12 -import org.slf4j.LoggerFactory;  
13 -import org.springframework.beans.factory.annotation.Autowired;  
14 -import org.springframework.context.ApplicationListener;  
15 -import org.springframework.stereotype.Component;  
16 -  
17 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
18 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
19 -import com.genersoft.iot.vmp.utils.redis.RedisUtil;  
20 -  
21 -import java.text.SimpleDateFormat;  
22 -import java.util.List;  
23 -  
24 -/**  
25 - * @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源:  
26 - * 1、设备主动注销,发送注销指令  
27 - * 2、设备未知原因离线,心跳超时  
28 - * @author: swwheihei  
29 - * @date: 2020年5月6日 下午1:51:23  
30 - */  
31 -@Component  
32 -public class OnlineEventListener implements ApplicationListener<OnlineEvent> {  
33 -  
34 - private final static Logger logger = LoggerFactory.getLogger(OnlineEventListener.class);  
35 -  
36 - @Autowired  
37 - private IVideoManagerStorage storager;  
38 -  
39 - @Autowired  
40 - private IDeviceService deviceService;  
41 -  
42 - @Autowired  
43 - private RedisUtil redis;  
44 -  
45 - @Autowired  
46 - private SipConfig sipConfig;  
47 -  
48 - @Autowired  
49 - private UserSetting userSetting;  
50 -  
51 - @Autowired  
52 - private EventPublisher eventPublisher;  
53 -  
54 - @Autowired  
55 - private SIPCommander cmder;  
56 -  
57 -  
58 - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
59 -  
60 - @Override  
61 - public void onApplicationEvent(OnlineEvent event) {  
62 -  
63 - logger.info("设备上线事件触发,deviceId:" + event.getDevice().getDeviceId() + ",from:" + event.getFrom());  
64 - Device device = event.getDevice();  
65 - if (device == null) {  
66 - return;  
67 - }  
68 - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + event.getDevice().getDeviceId();  
69 - Device deviceInStore = storager.queryVideoDevice(device.getDeviceId());  
70 - device.setOnline(1);  
71 - switch (event.getFrom()) {  
72 - // 注册时触发的在线事件,先在redis中增加超时超时监听  
73 - case VideoManagerConstants.EVENT_ONLINE_REGISTER:  
74 - // 超时时间  
75 - redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut());  
76 - device.setRegisterTime(format.format(System.currentTimeMillis()));  
77 - if (deviceInStore == null) { //第一次上线  
78 - logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());  
79 - cmder.deviceInfoQuery(device);  
80 - deviceService.sync(device);  
81 - }  
82 - break;  
83 - // 设备主动发送心跳触发的在线事件  
84 - case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE:  
85 - boolean exist = redis.hasKey(key);  
86 - // 先判断是否还存在,当设备先心跳超时后又发送心跳时,redis没有监听,需要增加  
87 - if (!exist) {  
88 - redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut());  
89 - } else {  
90 - redis.expire(key, sipConfig.getKeepaliveTimeOut());  
91 - }  
92 - device.setKeepaliveTime(format.format(System.currentTimeMillis()));  
93 - break;  
94 - // 设备主动发送消息触发的在线事件  
95 - case VideoManagerConstants.EVENT_ONLINE_MESSAGE:  
96 -  
97 - break;  
98 - }  
99 - // 处理上线监听  
100 - storager.updateDevice(device);  
101 - // 上线添加订阅  
102 - if (device.getSubscribeCycleForCatalog() > 0) {  
103 - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅  
104 - deviceService.addCatalogSubscribe(device);  
105 - }  
106 - if (device.getSubscribeCycleForMobilePosition() > 0) {  
107 - deviceService.addMobilePositionSubscribe(device);  
108 - }  
109 - }  
110 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
@@ -4,16 +4,15 @@ import com.genersoft.iot.vmp.gb28181.bean.CatalogData; @@ -4,16 +4,15 @@ import com.genersoft.iot.vmp.gb28181.bean.CatalogData;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
6 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; 6 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
7 -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;  
8 -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;  
9 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 -import com.genersoft.iot.vmp.vmanager.bean.WVPResult;  
11 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.scheduling.annotation.Scheduled; 9 import org.springframework.scheduling.annotation.Scheduled;
13 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
14 11
  12 +import java.time.Instant;
15 import java.util.*; 13 import java.util.*;
16 import java.util.concurrent.ConcurrentHashMap; 14 import java.util.concurrent.ConcurrentHashMap;
  15 +import java.util.concurrent.TimeUnit;
17 16
18 @Component 17 @Component
19 public class CatalogDataCatch { 18 public class CatalogDataCatch {
@@ -21,20 +20,17 @@ public class CatalogDataCatch { @@ -21,20 +20,17 @@ public class CatalogDataCatch {
21 public static Map<String, CatalogData> data = new ConcurrentHashMap<>(); 20 public static Map<String, CatalogData> data = new ConcurrentHashMap<>();
22 21
23 @Autowired 22 @Autowired
24 - private DeferredResultHolder deferredResultHolder;  
25 -  
26 - @Autowired  
27 private IVideoManagerStorage storager; 23 private IVideoManagerStorage storager;
28 24
29 public void addReady(Device device, int sn ) { 25 public void addReady(Device device, int sn ) {
30 CatalogData catalogData = data.get(device.getDeviceId()); 26 CatalogData catalogData = data.get(device.getDeviceId());
31 if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) { 27 if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
32 catalogData = new CatalogData(); 28 catalogData = new CatalogData();
33 - catalogData.setChannelList(new ArrayList<>()); 29 + catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>()));
34 catalogData.setDevice(device); 30 catalogData.setDevice(device);
35 catalogData.setSn(sn); 31 catalogData.setSn(sn);
36 catalogData.setStatus(CatalogData.CatalogDataStatus.ready); 32 catalogData.setStatus(CatalogData.CatalogDataStatus.ready);
37 - catalogData.setLastTime(new Date(System.currentTimeMillis())); 33 + catalogData.setLastTime(Instant.now());
38 data.put(device.getDeviceId(), catalogData); 34 data.put(device.getDeviceId(), catalogData);
39 } 35 }
40 } 36 }
@@ -46,9 +42,9 @@ public class CatalogDataCatch { @@ -46,9 +42,9 @@ public class CatalogDataCatch {
46 catalogData.setSn(sn); 42 catalogData.setSn(sn);
47 catalogData.setTotal(total); 43 catalogData.setTotal(total);
48 catalogData.setDevice(device); 44 catalogData.setDevice(device);
49 - catalogData.setChannelList(new ArrayList<>()); 45 + catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>()));
50 catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); 46 catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
51 - catalogData.setLastTime(new Date(System.currentTimeMillis())); 47 + catalogData.setLastTime(Instant.now());
52 data.put(deviceId, catalogData); 48 data.put(deviceId, catalogData);
53 }else { 49 }else {
54 // 同一个设备的通道同步请求只考虑一个,其他的直接忽略 50 // 同一个设备的通道同步请求只考虑一个,其他的直接忽略
@@ -59,7 +55,7 @@ public class CatalogDataCatch { @@ -59,7 +55,7 @@ public class CatalogDataCatch {
59 catalogData.setDevice(device); 55 catalogData.setDevice(device);
60 catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); 56 catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
61 catalogData.getChannelList().addAll(deviceChannelList); 57 catalogData.getChannelList().addAll(deviceChannelList);
62 - catalogData.setLastTime(new Date(System.currentTimeMillis())); 58 + catalogData.setLastTime(Instant.now());
63 } 59 }
64 } 60 }
65 61
@@ -102,16 +98,13 @@ public class CatalogDataCatch { @@ -102,16 +98,13 @@ public class CatalogDataCatch {
102 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 98 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
103 private void timerTask(){ 99 private void timerTask(){
104 Set<String> keys = data.keySet(); 100 Set<String> keys = data.keySet();
105 - Calendar calendarBefore5S = Calendar.getInstance();  
106 - calendarBefore5S.setTime(new Date());  
107 - calendarBefore5S.set(Calendar.SECOND, calendarBefore5S.get(Calendar.SECOND) - 5);  
108 101
109 - Calendar calendarBefore30S = Calendar.getInstance();  
110 - calendarBefore30S.setTime(new Date());  
111 - calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30); 102 + Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5));
  103 + Instant instantBefore30S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(30));
  104 +
112 for (String deviceId : keys) { 105 for (String deviceId : keys) {
113 CatalogData catalogData = data.get(deviceId); 106 CatalogData catalogData = data.get(deviceId);
114 - if ( catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据 107 + if ( catalogData.getLastTime().isBefore(instantBefore5S)) { // 超过五秒收不到消息任务超时, 只更新这一部分数据
115 if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) { 108 if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) {
116 storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList()); 109 storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
117 if (catalogData.getTotal() != catalogData.getChannelList().size()) { 110 if (catalogData.getTotal() != catalogData.getChannelList().size()) {
@@ -124,7 +117,7 @@ public class CatalogDataCatch { @@ -124,7 +117,7 @@ public class CatalogDataCatch {
124 } 117 }
125 catalogData.setStatus(CatalogData.CatalogDataStatus.end); 118 catalogData.setStatus(CatalogData.CatalogDataStatus.end);
126 } 119 }
127 - if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除 120 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().isBefore(instantBefore30S)) { // 超过三十秒,如果标记为end则删除
128 data.remove(deviceId); 121 data.remove(deviceId);
129 } 122 }
130 } 123 }
src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.session;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.*;
  4 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  5 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  6 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.scheduling.annotation.Scheduled;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +import java.time.Instant;
  12 +import java.util.*;
  13 +import java.util.concurrent.ConcurrentHashMap;
  14 +import java.util.concurrent.TimeUnit;
  15 +
  16 +/**
  17 + * @author lin
  18 + */
  19 +@Component
  20 +public class RecordDataCatch {
  21 +
  22 + public static Map<String, RecordInfo> data = new ConcurrentHashMap<>();
  23 +
  24 + @Autowired
  25 + private DeferredResultHolder deferredResultHolder;
  26 +
  27 +
  28 + public int put(String deviceId, String sn, int sumNum, List<RecordItem> recordItems) {
  29 + String key = deviceId + sn;
  30 + RecordInfo recordInfo = data.get(key);
  31 + if (recordInfo == null) {
  32 + recordInfo = new RecordInfo();
  33 + recordInfo.setDeviceId(deviceId);
  34 + recordInfo.setSn(sn.trim());
  35 + recordInfo.setSumNum(sumNum);
  36 + recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>()));
  37 + recordInfo.setLastTime(Instant.now());
  38 + recordInfo.getRecordList().addAll(recordItems);
  39 + data.put(key, recordInfo);
  40 + }else {
  41 + // 同一个设备的通道同步请求只考虑一个,其他的直接忽略
  42 + if (!Objects.equals(sn.trim(), recordInfo.getSn())) {
  43 + return 0;
  44 + }
  45 + recordInfo.getRecordList().addAll(recordItems);
  46 + recordInfo.setLastTime(Instant.now());
  47 + }
  48 + return recordInfo.getRecordList().size();
  49 + }
  50 +
  51 + @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
  52 + private void timerTask(){
  53 + Set<String> keys = data.keySet();
  54 + // 获取五秒前的时刻
  55 + Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5));
  56 + for (String key : keys) {
  57 + RecordInfo recordInfo = data.get(key);
  58 + // 超过五秒收不到消息任务超时, 只更新这一部分数据
  59 + if ( recordInfo.getLastTime().isBefore(instantBefore5S)) {
  60 + // 处理录像数据, 返回给前端
  61 + String msgKey = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn();
  62 +
  63 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  64 + wvpResult.setCode(0);
  65 + wvpResult.setMsg("success");
  66 + // 对数据进行排序
  67 + Collections.sort(recordInfo.getRecordList());
  68 + wvpResult.setData(recordInfo);
  69 +
  70 + RequestMessage msg = new RequestMessage();
  71 + msg.setKey(msgKey);
  72 + msg.setData(wvpResult);
  73 + deferredResultHolder.invokeAllResult(msg);
  74 + data.remove(key);
  75 + }
  76 + }
  77 + }
  78 +
  79 + public boolean isComplete(String deviceId, String sn) {
  80 + RecordInfo recordInfo = data.get(deviceId + sn);
  81 + return recordInfo != null && recordInfo.getRecordList().size() == recordInfo.getSumNum();
  82 + }
  83 +
  84 + public RecordInfo getRecordInfo(String deviceId, String sn) {
  85 + return data.get(deviceId + sn);
  86 + }
  87 +
  88 + public void remove(String deviceId, String sn) {
  89 + data.remove(deviceId + sn);
  90 + }
  91 +}
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -76,8 +76,8 @@ public class VideoStreamSessionManager { @@ -76,8 +76,8 @@ public class VideoStreamSessionManager {
76 } 76 }
77 77
78 78
79 - public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){  
80 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); 79 + public ClientTransaction getTransaction(String deviceId, String channelId, String stream, String callId){
  80 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, stream);
81 if (ssrcTransaction == null) { 81 if (ssrcTransaction == null) {
82 return null; 82 return null;
83 } 83 }
src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java renamed to src/main/java/com/genersoft/iot/vmp/gb28181/task/SipDeviceRunner.java
1 -package com.genersoft.iot.vmp.conf.runner; 1 +package com.genersoft.iot.vmp.gb28181.task;
2 2
3 import com.genersoft.iot.vmp.conf.UserSetting; 3 import com.genersoft.iot.vmp.conf.UserSetting;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
@@ -10,11 +10,13 @@ import org.springframework.boot.CommandLineRunner; @@ -10,11 +10,13 @@ import org.springframework.boot.CommandLineRunner;
10 import org.springframework.core.annotation.Order; 10 import org.springframework.core.annotation.Order;
11 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
12 12
  13 +import java.util.ArrayList;
13 import java.util.List; 14 import java.util.List;
14 15
15 16
16 /** 17 /**
17 * 系统启动时控制设备 18 * 系统启动时控制设备
  19 + * @author lin
18 */ 20 */
19 @Component 21 @Component
20 @Order(value=4) 22 @Order(value=4)
@@ -34,26 +36,16 @@ public class SipDeviceRunner implements CommandLineRunner { @@ -34,26 +36,16 @@ public class SipDeviceRunner implements CommandLineRunner {
34 36
35 @Override 37 @Override
36 public void run(String... args) throws Exception { 38 public void run(String... args) throws Exception {
37 - // 读取redis没有心跳信息的则设置为离线,等收到下次心跳设置为在线  
38 - // 设置所有设备离线  
39 - storager.outlineForAll();  
40 - List<String> onlineForAll = redisCatchStorage.getOnlineForAll();  
41 - for (String deviceId : onlineForAll) {  
42 - storager.online(deviceId);  
43 - Device device = redisCatchStorage.getDevice(deviceId);  
44 - if (device != null ) {  
45 - if (device.getSubscribeCycleForCatalog() > 0) {  
46 - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅  
47 - deviceService.addCatalogSubscribe(device);  
48 - }  
49 - if (device.getSubscribeCycleForMobilePosition() > 0) {  
50 - deviceService.addMobilePositionSubscribe(device);  
51 - } 39 + List<Device> deviceList = deviceService.getAllOnlineDevice();
  40 +
  41 + for (Device device : deviceList) {
  42 + if (deviceService.expire(device)){
  43 + deviceService.offline(device.getDeviceId());
  44 + }else {
  45 + deviceService.online(device);
52 } 46 }
53 } 47 }
54 // 重置cseq计数 48 // 重置cseq计数
55 redisCatchStorage.resetAllCSEQ(); 49 redisCatchStorage.resetAllCSEQ();
56 -  
57 -  
58 } 50 }
59 } 51 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
1 package com.genersoft.iot.vmp.gb28181.transmit; 1 package com.genersoft.iot.vmp.gb28181.transmit;
2 2
  3 +import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
3 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
4 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; 5 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor;
  7 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.KeepaliveNotifyMessageHandler;
5 import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor; 8 import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
6 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; 9 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
7 import org.slf4j.Logger; 10 import org.slf4j.Logger;
@@ -11,10 +14,13 @@ import org.springframework.scheduling.annotation.Async; @@ -11,10 +14,13 @@ import org.springframework.scheduling.annotation.Async;
11 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
12 15
13 import javax.sip.*; 16 import javax.sip.*;
14 -import javax.sip.header.CSeqHeader;  
15 -import javax.sip.header.CallIdHeader; 17 +import javax.sip.address.SipURI;
  18 +import javax.sip.address.URI;
  19 +import javax.sip.header.*;
  20 +import javax.sip.message.Request;
16 import javax.sip.message.Response; 21 import javax.sip.message.Response;
17 import java.util.Map; 22 import java.util.Map;
  23 +import java.util.Objects;
18 import java.util.concurrent.ConcurrentHashMap; 24 import java.util.concurrent.ConcurrentHashMap;
19 25
20 /** 26 /**
@@ -34,10 +40,11 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @@ -34,10 +40,11 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
34 @Autowired 40 @Autowired
35 private SipSubscribe sipSubscribe; 41 private SipSubscribe sipSubscribe;
36 42
  43 + @Autowired
  44 + private EventPublisher eventPublisher;
  45 +
  46 +
37 47
38 -// @Autowired  
39 -// @Qualifier(value = "taskExecutor")  
40 -// private ThreadPoolTaskExecutor poolTaskExecutor;  
41 48
42 /** 49 /**
43 * 添加 request订阅 50 * 添加 request订阅
@@ -141,9 +148,32 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @@ -141,9 +148,32 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
141 */ 148 */
142 @Override 149 @Override
143 public void processTimeout(TimeoutEvent timeoutEvent) { 150 public void processTimeout(TimeoutEvent timeoutEvent) {
144 - if(timeoutProcessor != null) {  
145 - timeoutProcessor.process(timeoutEvent); 151 + logger.info("[消息发送超时]");
  152 + ClientTransaction clientTransaction = timeoutEvent.getClientTransaction();
  153 + eventPublisher.requestTimeOut(timeoutEvent);
  154 + if (clientTransaction != null) {
  155 + Request request = clientTransaction.getRequest();
  156 + if (request != null) {
  157 + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
  158 + if (callIdHeader != null) {
  159 + SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
  160 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent);
  161 + subscribe.response(eventResult);
  162 + sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
  163 + }
  164 + }
146 } 165 }
  166 +
  167 +// Timeout timeout = timeoutEvent.getTimeout();
  168 +// ServerTransaction serverTransaction = timeoutEvent.getServerTransaction();
  169 +// if (serverTransaction != null) {
  170 +// Request request = serverTransaction.getRequest();
  171 +// URI requestURI = request.getRequestURI();
  172 +// Header header = request.getHeader(FromHeader.NAME);
  173 +// }
  174 +// if(timeoutProcessor != null) {
  175 +// timeoutProcessor.process(timeoutEvent);
  176 +// }
147 } 177 }
148 178
149 @Override 179 @Override
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.transmit.callback;  
2 -  
3 -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;  
4 -import com.genersoft.iot.vmp.gb28181.bean.RecordItem;  
5 -import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.RecordInfoResponseMessageHandler;  
6 -import com.genersoft.iot.vmp.utils.redis.RedisUtil;  
7 -import org.slf4j.Logger;  
8 -  
9 -import java.util.ArrayList;  
10 -import java.util.Comparator;  
11 -import java.util.List;  
12 -import java.util.concurrent.TimeUnit;  
13 -  
14 -@SuppressWarnings("unchecked")  
15 -public class CheckForAllRecordsThread extends Thread {  
16 -  
17 - private String key;  
18 -  
19 - private RecordInfo recordInfo;  
20 -  
21 - private RedisUtil redis;  
22 -  
23 - private Logger logger;  
24 -  
25 - private DeferredResultHolder deferredResultHolder;  
26 -  
27 - public CheckForAllRecordsThread(String key, RecordInfo recordInfo) {  
28 - this.key = key;  
29 - this.recordInfo = recordInfo;  
30 - }  
31 -  
32 - @Override  
33 - public void run() {  
34 -  
35 - String cacheKey = this.key;  
36 -  
37 - for (long stop = System.nanoTime() + TimeUnit.SECONDS.toNanos(10); stop > System.nanoTime();) {  
38 - List<Object> cacheKeys = redis.scan(cacheKey + "_*");  
39 - List<RecordItem> totalRecordList = new ArrayList<RecordItem>();  
40 - for (int i = 0; i < cacheKeys.size(); i++) {  
41 - totalRecordList.addAll((List<RecordItem>) redis.get(cacheKeys.get(i).toString()));  
42 - }  
43 - if (totalRecordList.size() < this.recordInfo.getSumNum()) {  
44 - logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + this.recordInfo.getSumNum() + "项");  
45 - } else {  
46 - logger.info("录像数据已全部获取,共 {} 项", this.recordInfo.getSumNum());  
47 - this.recordInfo.setRecordList(totalRecordList);  
48 - for (int i = 0; i < cacheKeys.size(); i++) {  
49 - redis.del(cacheKeys.get(i).toString());  
50 - }  
51 - break;  
52 - }  
53 - }  
54 - // 自然顺序排序, 元素进行升序排列  
55 - this.recordInfo.getRecordList().sort(Comparator.naturalOrder());  
56 - RequestMessage msg = new RequestMessage();  
57 - msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn());  
58 - msg.setData(recordInfo);  
59 - deferredResultHolder.invokeAllResult(msg);  
60 - logger.info("处理完成,返回结果");  
61 - RecordInfoResponseMessageHandler.threadNameList.remove(cacheKey);  
62 - }  
63 -  
64 - public void setRedis(RedisUtil redis) {  
65 - this.redis = redis;  
66 - }  
67 -  
68 - public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) {  
69 - this.deferredResultHolder = deferredResultHolder;  
70 - }  
71 -  
72 - public void setLogger(Logger logger) {  
73 - this.logger = logger;  
74 - }  
75 -  
76 -}  
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
13 -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; 13 +import com.genersoft.iot.vmp.utils.DateUtil;
14 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 14 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
15 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 15 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
16 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 16 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -27,7 +27,6 @@ import org.slf4j.Logger; @@ -27,7 +27,6 @@ import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory; 27 import org.slf4j.LoggerFactory;
28 import org.springframework.beans.factory.annotation.Autowired; 28 import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.beans.factory.annotation.Qualifier; 29 import org.springframework.beans.factory.annotation.Qualifier;
30 -import org.springframework.boot.SpringBootVersion;  
31 import org.springframework.context.annotation.DependsOn; 30 import org.springframework.context.annotation.DependsOn;
32 import org.springframework.stereotype.Component; 31 import org.springframework.stereotype.Component;
33 import org.springframework.util.StringUtils; 32 import org.springframework.util.StringUtils;
@@ -371,7 +370,7 @@ public class SIPCommander implements ISIPCommander { @@ -371,7 +370,7 @@ public class SIPCommander implements ISIPCommander {
371 // 370 //
372 StringBuffer content = new StringBuffer(200); 371 StringBuffer content = new StringBuffer(200);
373 content.append("v=0\r\n"); 372 content.append("v=0\r\n");
374 - content.append("o="+ sipConfig.getId()+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); 373 + content.append("o="+ channelId+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
375 content.append("s=Play\r\n"); 374 content.append("s=Play\r\n");
376 content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); 375 content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
377 content.append("t=0 0\r\n"); 376 content.append("t=0 0\r\n");
@@ -390,8 +389,7 @@ public class SIPCommander implements ISIPCommander { @@ -390,8 +389,7 @@ public class SIPCommander implements ISIPCommander {
390 content.append("a=rtpmap:126 H264/90000\r\n"); 389 content.append("a=rtpmap:126 H264/90000\r\n");
391 content.append("a=rtpmap:125 H264S/90000\r\n"); 390 content.append("a=rtpmap:125 H264S/90000\r\n");
392 content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); 391 content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
393 - content.append("a=rtpmap:99 MP4V-ES/90000\r\n");  
394 - content.append("a=fmtp:99 profile-level-id=3\r\n"); 392 + content.append("a=rtpmap:99 H265/90000\r\n");
395 content.append("a=rtpmap:98 H264/90000\r\n"); 393 content.append("a=rtpmap:98 H264/90000\r\n");
396 content.append("a=rtpmap:97 MPEG4/90000\r\n"); 394 content.append("a=rtpmap:97 MPEG4/90000\r\n");
397 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 395 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
@@ -403,16 +401,17 @@ public class SIPCommander implements ISIPCommander { @@ -403,16 +401,17 @@ public class SIPCommander implements ISIPCommander {
403 } 401 }
404 }else { 402 }else {
405 if("TCP-PASSIVE".equals(streamMode)) { 403 if("TCP-PASSIVE".equals(streamMode)) {
406 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); 404 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
407 }else if ("TCP-ACTIVE".equals(streamMode)) { 405 }else if ("TCP-ACTIVE".equals(streamMode)) {
408 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); 406 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
409 }else if("UDP".equals(streamMode)) { 407 }else if("UDP".equals(streamMode)) {
410 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n"); 408 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
411 } 409 }
412 content.append("a=recvonly\r\n"); 410 content.append("a=recvonly\r\n");
413 content.append("a=rtpmap:96 PS/90000\r\n"); 411 content.append("a=rtpmap:96 PS/90000\r\n");
414 content.append("a=rtpmap:98 H264/90000\r\n"); 412 content.append("a=rtpmap:98 H264/90000\r\n");
415 content.append("a=rtpmap:97 MPEG4/90000\r\n"); 413 content.append("a=rtpmap:97 MPEG4/90000\r\n");
  414 + content.append("a=rtpmap:99 H265/90000\r\n");
416 if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 415 if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式
417 content.append("a=setup:passive\r\n"); 416 content.append("a=setup:passive\r\n");
418 content.append("a=connection:new\r\n"); 417 content.append("a=connection:new\r\n");
@@ -468,7 +467,7 @@ public class SIPCommander implements ISIPCommander { @@ -468,7 +467,7 @@ public class SIPCommander implements ISIPCommander {
468 467
469 StringBuffer content = new StringBuffer(200); 468 StringBuffer content = new StringBuffer(200);
470 content.append("v=0\r\n"); 469 content.append("v=0\r\n");
471 - content.append("o="+sipConfig.getId()+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); 470 + content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
472 content.append("s=Playback\r\n"); 471 content.append("s=Playback\r\n");
473 content.append("u="+channelId+":0\r\n"); 472 content.append("u="+channelId+":0\r\n");
474 content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); 473 content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
@@ -491,8 +490,7 @@ public class SIPCommander implements ISIPCommander { @@ -491,8 +490,7 @@ public class SIPCommander implements ISIPCommander {
491 content.append("a=rtpmap:126 H264/90000\r\n"); 490 content.append("a=rtpmap:126 H264/90000\r\n");
492 content.append("a=rtpmap:125 H264S/90000\r\n"); 491 content.append("a=rtpmap:125 H264S/90000\r\n");
493 content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); 492 content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
494 - content.append("a=rtpmap:99 MP4V-ES/90000\r\n");  
495 - content.append("a=fmtp:99 profile-level-id=3\r\n"); 493 + content.append("a=rtpmap:99 H265/90000\r\n");
496 content.append("a=rtpmap:98 H264/90000\r\n"); 494 content.append("a=rtpmap:98 H264/90000\r\n");
497 content.append("a=rtpmap:97 MPEG4/90000\r\n"); 495 content.append("a=rtpmap:97 MPEG4/90000\r\n");
498 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 496 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
@@ -504,16 +502,17 @@ public class SIPCommander implements ISIPCommander { @@ -504,16 +502,17 @@ public class SIPCommander implements ISIPCommander {
504 } 502 }
505 }else { 503 }else {
506 if("TCP-PASSIVE".equals(streamMode)) { 504 if("TCP-PASSIVE".equals(streamMode)) {
507 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); 505 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
508 }else if ("TCP-ACTIVE".equals(streamMode)) { 506 }else if ("TCP-ACTIVE".equals(streamMode)) {
509 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); 507 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
510 }else if("UDP".equals(streamMode)) { 508 }else if("UDP".equals(streamMode)) {
511 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n"); 509 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
512 } 510 }
513 content.append("a=recvonly\r\n"); 511 content.append("a=recvonly\r\n");
514 content.append("a=rtpmap:96 PS/90000\r\n"); 512 content.append("a=rtpmap:96 PS/90000\r\n");
515 - content.append("a=rtpmap:98 H264/90000\r\n");  
516 content.append("a=rtpmap:97 MPEG4/90000\r\n"); 513 content.append("a=rtpmap:97 MPEG4/90000\r\n");
  514 + content.append("a=rtpmap:98 H264/90000\r\n");
  515 + content.append("a=rtpmap:99 H265/90000\r\n");
517 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 516 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
518 content.append("a=setup:passive\r\n"); 517 content.append("a=setup:passive\r\n");
519 content.append("a=connection:new\r\n"); 518 content.append("a=connection:new\r\n");
@@ -578,7 +577,7 @@ public class SIPCommander implements ISIPCommander { @@ -578,7 +577,7 @@ public class SIPCommander implements ISIPCommander {
578 577
579 StringBuffer content = new StringBuffer(200); 578 StringBuffer content = new StringBuffer(200);
580 content.append("v=0\r\n"); 579 content.append("v=0\r\n");
581 - content.append("o="+sipConfig.getId()+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); 580 + content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
582 content.append("s=Download\r\n"); 581 content.append("s=Download\r\n");
583 content.append("u="+channelId+":0\r\n"); 582 content.append("u="+channelId+":0\r\n");
584 content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); 583 content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
@@ -614,16 +613,17 @@ public class SIPCommander implements ISIPCommander { @@ -614,16 +613,17 @@ public class SIPCommander implements ISIPCommander {
614 } 613 }
615 }else { 614 }else {
616 if("TCP-PASSIVE".equals(streamMode)) { 615 if("TCP-PASSIVE".equals(streamMode)) {
617 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); 616 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
618 }else if ("TCP-ACTIVE".equals(streamMode)) { 617 }else if ("TCP-ACTIVE".equals(streamMode)) {
619 - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); 618 + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n");
620 }else if("UDP".equals(streamMode)) { 619 }else if("UDP".equals(streamMode)) {
621 - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n"); 620 + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n");
622 } 621 }
623 content.append("a=recvonly\r\n"); 622 content.append("a=recvonly\r\n");
624 content.append("a=rtpmap:96 PS/90000\r\n"); 623 content.append("a=rtpmap:96 PS/90000\r\n");
625 - content.append("a=rtpmap:98 H264/90000\r\n");  
626 content.append("a=rtpmap:97 MPEG4/90000\r\n"); 624 content.append("a=rtpmap:97 MPEG4/90000\r\n");
  625 + content.append("a=rtpmap:98 H264/90000\r\n");
  626 + content.append("a=rtpmap:99 H265/90000\r\n");
627 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 627 if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
628 content.append("a=setup:passive\r\n"); 628 content.append("a=setup:passive\r\n");
629 content.append("a=connection:new\r\n"); 629 content.append("a=connection:new\r\n");
@@ -652,6 +652,17 @@ public class SIPCommander implements ISIPCommander { @@ -652,6 +652,17 @@ public class SIPCommander implements ISIPCommander {
652 (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 652 (MediaServerItem mediaServerItemInUse, JSONObject json)->{
653 hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); 653 hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
654 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); 654 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
  655 + subscribeKey.put("regist", false);
  656 + subscribeKey.put("schema", "rtmp");
  657 + // 添加流注销的订阅,注销了后向设备发送bye
  658 + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
  659 + (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{
  660 + ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
  661 + if (transaction != null) {
  662 + logger.info("[录像]下载结束, 发送BYE");
  663 + streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
  664 + }
  665 + });
655 }); 666 });
656 667
657 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); 668 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
@@ -684,10 +695,10 @@ public class SIPCommander implements ISIPCommander { @@ -684,10 +695,10 @@ public class SIPCommander implements ISIPCommander {
684 @Override 695 @Override
685 public void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent) { 696 public void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent) {
686 try { 697 try {
687 - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, null, stream);  
688 - ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream); 698 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callId, stream);
  699 + ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId, stream, callId);
689 700
690 - if (transaction == null) { 701 + if (transaction == null ) {
691 logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId); 702 logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
692 SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>(); 703 SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
693 if (okEvent != null) { 704 if (okEvent != null) {
@@ -1664,6 +1675,7 @@ public class SIPCommander implements ISIPCommander { @@ -1664,6 +1675,7 @@ public class SIPCommander implements ISIPCommander {
1664 sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> { 1675 sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
1665 errorEvent.response(eventResult); 1676 errorEvent.response(eventResult);
1666 sipSubscribe.removeErrorSubscribe(eventResult.callId); 1677 sipSubscribe.removeErrorSubscribe(eventResult.callId);
  1678 + sipSubscribe.removeOkSubscribe(eventResult.callId);
1667 })); 1679 }));
1668 } 1680 }
1669 // 添加订阅 1681 // 添加订阅
@@ -1671,6 +1683,7 @@ public class SIPCommander implements ISIPCommander { @@ -1671,6 +1683,7 @@ public class SIPCommander implements ISIPCommander {
1671 sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult ->{ 1683 sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult ->{
1672 okEvent.response(eventResult); 1684 okEvent.response(eventResult);
1673 sipSubscribe.removeOkSubscribe(eventResult.callId); 1685 sipSubscribe.removeOkSubscribe(eventResult.callId);
  1686 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
1674 }); 1687 });
1675 } 1688 }
1676 1689
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*; @@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider;
7 -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; 7 +import com.genersoft.iot.vmp.utils.DateUtil;
8 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 8 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 import com.genersoft.iot.vmp.service.IMediaServerService; 10 import com.genersoft.iot.vmp.service.IMediaServerService;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -4,8 +4,12 @@ import com.alibaba.fastjson.JSON; @@ -4,8 +4,12 @@ import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
6 import com.genersoft.iot.vmp.conf.DynamicTask; 6 import com.genersoft.iot.vmp.conf.DynamicTask;
  7 +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
  8 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 9 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
8 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
  11 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  12 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 14 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
11 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 15 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -13,6 +17,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; @@ -13,6 +17,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
13 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
14 import com.genersoft.iot.vmp.service.IMediaServerService; 18 import com.genersoft.iot.vmp.service.IMediaServerService;
15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 19 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  20 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  21 +import org.ehcache.shadow.org.terracotta.offheapstore.storage.IntegerStorageEngine;
16 import org.slf4j.Logger; 22 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory; 23 import org.slf4j.LoggerFactory;
18 import org.springframework.beans.factory.InitializingBean; 24 import org.springframework.beans.factory.InitializingBean;
@@ -51,6 +57,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -51,6 +57,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
51 private IRedisCatchStorage redisCatchStorage; 57 private IRedisCatchStorage redisCatchStorage;
52 58
53 @Autowired 59 @Autowired
  60 + private IVideoManagerStorage storager;
  61 +
  62 + @Autowired
54 private ZLMRTPServerFactory zlmrtpServerFactory; 63 private ZLMRTPServerFactory zlmrtpServerFactory;
55 64
56 @Autowired 65 @Autowired
@@ -62,6 +71,12 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -62,6 +71,12 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
62 @Autowired 71 @Autowired
63 private DynamicTask dynamicTask; 72 private DynamicTask dynamicTask;
64 73
  74 + @Autowired
  75 + private ISIPCommander cmder;
  76 +
  77 + @Autowired
  78 + private ISIPCommanderForPlatform commanderForPlatform;
  79 +
65 80
66 /** 81 /**
67 * 处理 ACK请求 82 * 处理 ACK请求
@@ -78,6 +93,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -78,6 +93,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
78 if (dialog.getState()== DialogState.CONFIRMED) { 93 if (dialog.getState()== DialogState.CONFIRMED) {
79 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); 94 String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
80 logger.info("ACK请求: platformGbId->{}", platformGbId); 95 logger.info("ACK请求: platformGbId->{}", platformGbId);
  96 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId);
81 // 取消设置的超时任务 97 // 取消设置的超时任务
82 dynamicTask.stop(callIdHeader.getCallId()); 98 dynamicTask.stop(callIdHeader.getCallId());
83 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); 99 String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
@@ -94,8 +110,23 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -94,8 +110,23 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
94 param.put("dst_port", sendRtpItem.getPort()); 110 param.put("dst_port", sendRtpItem.getPort());
95 param.put("is_udp", is_Udp); 111 param.put("is_udp", is_Udp);
96 param.put("src_port", sendRtpItem.getLocalPort()); 112 param.put("src_port", sendRtpItem.getLocalPort());
97 - zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);  
98 - 113 + param.put("pt", sendRtpItem.getPt());
  114 + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
  115 + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
  116 + JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
  117 + if (jsonObject == null) {
  118 + logger.error("RTP推流失败: 请检查ZLM服务");
  119 + } else if (jsonObject.getInteger("code") == 0) {
  120 + logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));
  121 + } else {
  122 + logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));
  123 + if (sendRtpItem.isOnlyAudio()) {
  124 + // TODO 可能是语音对讲
  125 + }else {
  126 + // 向上级平台
  127 + commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId());
  128 + }
  129 + }
99 130
100 131
101 // if (streamInfo == null) { // 流还没上来,对方就回复ack 132 // if (streamInfo == null) { // 流还没上来,对方就回复ack
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -23,6 +23,7 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -23,6 +23,7 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
23 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 23 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
24 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 24 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
25 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 25 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  26 +import com.genersoft.iot.vmp.utils.DateUtil;
26 import com.genersoft.iot.vmp.utils.SerializeUtils; 27 import com.genersoft.iot.vmp.utils.SerializeUtils;
27 import gov.nist.javax.sdp.TimeDescriptionImpl; 28 import gov.nist.javax.sdp.TimeDescriptionImpl;
28 import gov.nist.javax.sdp.fields.TimeField; 29 import gov.nist.javax.sdp.fields.TimeField;
@@ -39,8 +40,7 @@ import javax.sip.header.CallIdHeader; @@ -39,8 +40,7 @@ import javax.sip.header.CallIdHeader;
39 import javax.sip.message.Request; 40 import javax.sip.message.Request;
40 import javax.sip.message.Response; 41 import javax.sip.message.Response;
41 import java.text.ParseException; 42 import java.text.ParseException;
42 -import java.text.SimpleDateFormat;  
43 -import java.util.Date; 43 +import java.time.Instant;
44 import java.util.Vector; 44 import java.util.Vector;
45 45
46 /** 46 /**
@@ -180,16 +180,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -180,16 +180,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
180 180
181 Long startTime = null; 181 Long startTime = null;
182 Long stopTime = null; 182 Long stopTime = null;
183 - Date start = null;  
184 - Date end = null; 183 + Instant start = null;
  184 + Instant end = null;
185 if (sdp.getTimeDescriptions(false) != null && sdp.getTimeDescriptions(false).size() > 0) { 185 if (sdp.getTimeDescriptions(false) != null && sdp.getTimeDescriptions(false).size() > 0) {
186 TimeDescriptionImpl timeDescription = (TimeDescriptionImpl)(sdp.getTimeDescriptions(false).get(0)); 186 TimeDescriptionImpl timeDescription = (TimeDescriptionImpl)(sdp.getTimeDescriptions(false).get(0));
187 TimeField startTimeFiled = (TimeField)timeDescription.getTime(); 187 TimeField startTimeFiled = (TimeField)timeDescription.getTime();
188 startTime = startTimeFiled.getStartTime(); 188 startTime = startTimeFiled.getStartTime();
189 stopTime = startTimeFiled.getStopTime(); 189 stopTime = startTimeFiled.getStopTime();
190 190
191 - start = new Date(startTime*1000);  
192 - end = new Date(stopTime*1000); 191 + start = Instant.ofEpochMilli(startTime*1000);
  192 + end = Instant.ofEpochMilli(stopTime*1000);
193 } 193 }
194 // 获取支持的格式 194 // 获取支持的格式
195 Vector mediaDescriptions = sdp.getMediaDescriptions(true); 195 Vector mediaDescriptions = sdp.getMediaDescriptions(true);
@@ -331,13 +331,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -331,13 +331,12 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
331 sendRtpItem.setApp("rtp"); 331 sendRtpItem.setApp("rtp");
332 if ("Playback".equals(sessionName)) { 332 if ("Playback".equals(sessionName)) {
333 sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); 333 sendRtpItem.setPlayType(InviteStreamType.PLAYBACK);
334 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true); 334 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true, true);
335 sendRtpItem.setStreamId(ssrcInfo.getStream()); 335 sendRtpItem.setStreamId(ssrcInfo.getStream());
336 // 写入redis, 超时时回复 336 // 写入redis, 超时时回复
337 redisCatchStorage.updateSendRTPSever(sendRtpItem); 337 redisCatchStorage.updateSendRTPSever(sendRtpItem);
338 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
339 - playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, format.format(start),  
340 - format.format(end), null, result -> { 338 + playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
  339 + DateUtil.formatter.format(end), null, result -> {
341 if (result.getCode() != 0){ 340 if (result.getCode() != 0){
342 logger.warn("录像回放失败"); 341 logger.warn("录像回放失败");
343 if (result.getEvent() != null) { 342 if (result.getEvent() != null) {
@@ -373,7 +372,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -373,7 +372,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
373 if (mediaServerItem.isRtpEnable()) { 372 if (mediaServerItem.isRtpEnable()) {
374 streamId = String.format("%s_%s", device.getDeviceId(), channelId); 373 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
375 } 374 }
376 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, true); 375 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, true, false);
377 sendRtpItem.setStreamId(ssrcInfo.getStream()); 376 sendRtpItem.setStreamId(ssrcInfo.getStream());
378 // 写入redis, 超时时回复 377 // 写入redis, 超时时回复
379 redisCatchStorage.updateSendRTPSever(sendRtpItem); 378 redisCatchStorage.updateSendRTPSever(sendRtpItem);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -252,14 +252,12 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -252,14 +252,12 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
252 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); 252 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
253 String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); 253 String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
254 254
255 - Element rootElement = getRootElement(evt);  
256 Device device = redisCatchStorage.getDevice(deviceId); 255 Device device = redisCatchStorage.getDevice(deviceId);
257 - if (device == null) { 256 + if (device == null || device.getOnline() == 0) {
  257 + logger.warn("[收到 目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" ));
258 return; 258 return;
259 } 259 }
260 - if (device != null ) {  
261 - rootElement = getRootElement(evt, device.getCharset());  
262 - } 260 + Element rootElement = getRootElement(evt, device.getCharset());
263 Element deviceListElement = rootElement.element("DeviceList"); 261 Element deviceListElement = rootElement.element("DeviceList");
264 if (deviceListElement == null) { 262 if (deviceListElement == null) {
265 return; 263 return;
@@ -279,39 +277,46 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -279,39 +277,46 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
279 channel.setDeviceId(device.getDeviceId()); 277 channel.setDeviceId(device.getDeviceId());
280 logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); 278 logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
281 switch (eventElement.getText().toUpperCase()) { 279 switch (eventElement.getText().toUpperCase()) {
282 - case CatalogEvent.ON: // 上线 280 + case CatalogEvent.ON:
  281 + // 上线
283 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); 282 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId());
284 storager.deviceChannelOnline(deviceId, channel.getChannelId()); 283 storager.deviceChannelOnline(deviceId, channel.getChannelId());
285 // 回复200 OK 284 // 回复200 OK
286 responseAck(evt, Response.OK); 285 responseAck(evt, Response.OK);
287 break; 286 break;
288 - case CatalogEvent.OFF : // 离线 287 + case CatalogEvent.OFF :
  288 + // 离线
289 logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId()); 289 logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId());
290 storager.deviceChannelOffline(deviceId, channel.getChannelId()); 290 storager.deviceChannelOffline(deviceId, channel.getChannelId());
291 // 回复200 OK 291 // 回复200 OK
292 responseAck(evt, Response.OK); 292 responseAck(evt, Response.OK);
293 break; 293 break;
294 - case CatalogEvent.VLOST: // 视频丢失 294 + case CatalogEvent.VLOST:
  295 + // 视频丢失
295 logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId()); 296 logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId());
296 storager.deviceChannelOffline(deviceId, channel.getChannelId()); 297 storager.deviceChannelOffline(deviceId, channel.getChannelId());
297 // 回复200 OK 298 // 回复200 OK
298 responseAck(evt, Response.OK); 299 responseAck(evt, Response.OK);
299 break; 300 break;
300 - case CatalogEvent.DEFECT: // 故障 301 + case CatalogEvent.DEFECT:
  302 + // 故障
301 // 回复200 OK 303 // 回复200 OK
302 responseAck(evt, Response.OK); 304 responseAck(evt, Response.OK);
303 break; 305 break;
304 - case CatalogEvent.ADD: // 增加 306 + case CatalogEvent.ADD:
  307 + // 增加
305 logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 308 logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId());
306 storager.updateChannel(deviceId, channel); 309 storager.updateChannel(deviceId, channel);
307 responseAck(evt, Response.OK); 310 responseAck(evt, Response.OK);
308 break; 311 break;
309 - case CatalogEvent.DEL: // 删除 312 + case CatalogEvent.DEL:
  313 + // 删除
310 logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 314 logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId());
311 storager.delChannel(deviceId, channel.getChannelId()); 315 storager.delChannel(deviceId, channel.getChannelId());
312 responseAck(evt, Response.OK); 316 responseAck(evt, Response.OK);
313 break; 317 break;
314 - case CatalogEvent.UPDATE: // 更新 318 + case CatalogEvent.UPDATE:
  319 + // 更新
315 logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 320 logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId());
316 storager.updateChannel(deviceId, channel); 321 storager.updateChannel(deviceId, channel);
317 responseAck(evt, Response.OK); 322 responseAck(evt, Response.OK);
@@ -324,10 +329,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -324,10 +329,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
324 eventPublisher.catalogEventPublish(null, channel, eventElement.getText().toUpperCase()); 329 eventPublisher.catalogEventPublish(null, channel, eventElement.getText().toUpperCase());
325 330
326 } 331 }
327 -  
328 - if (!redisCatchStorage.deviceIsOnline(deviceId)) {  
329 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);  
330 - }  
331 } 332 }
332 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { 333 } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
333 e.printStackTrace(); 334 e.printStackTrace();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -9,8 +9,10 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher; @@ -9,8 +9,10 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; 10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
  12 +import com.genersoft.iot.vmp.service.IDeviceService;
12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  15 +import com.genersoft.iot.vmp.utils.DateUtil;
14 import gov.nist.javax.sip.RequestEventExt; 16 import gov.nist.javax.sip.RequestEventExt;
15 import gov.nist.javax.sip.address.AddressImpl; 17 import gov.nist.javax.sip.address.AddressImpl;
16 import gov.nist.javax.sip.address.SipUri; 18 import gov.nist.javax.sip.address.SipUri;
@@ -60,6 +62,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -60,6 +62,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
60 @Autowired 62 @Autowired
61 private SIPProcessorObserver sipProcessorObserver; 63 private SIPProcessorObserver sipProcessorObserver;
62 64
  65 + @Autowired
  66 + private IDeviceService deviceService;
  67 +
63 @Override 68 @Override
64 public void afterPropertiesSet() throws Exception { 69 public void afterPropertiesSet() throws Exception {
65 // 添加消息处理的订阅 70 // 添加消息处理的订阅
@@ -76,13 +81,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -76,13 +81,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
76 try { 81 try {
77 RequestEventExt evtExt = (RequestEventExt) evt; 82 RequestEventExt evtExt = (RequestEventExt) evt;
78 String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); 83 String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();
79 - logger.info("[{}] 收到注册请求,开始处理", requestAddress); 84 + logger.info("[注册请求] 开始处理: {}", requestAddress);
80 Request request = evt.getRequest(); 85 Request request = evt.getRequest();
81 ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); 86 ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME);
82 Response response = null; 87 Response response = null;
83 boolean passwordCorrect = false; 88 boolean passwordCorrect = false;
84 // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功 89 // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功
85 - int registerFlag = 0; 90 + boolean registerFlag = false;
86 FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); 91 FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME);
87 AddressImpl address = (AddressImpl) fromHeader.getAddress(); 92 AddressImpl address = (AddressImpl) fromHeader.getAddress();
88 SipUri uri = (SipUri) address.getURI(); 93 SipUri uri = (SipUri) address.getURI();
@@ -90,7 +95,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -90,7 +95,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
90 95
91 AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); 96 AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
92 if (authHead == null) { 97 if (authHead == null) {
93 - logger.info("[{}] 未携带授权头 回复401", requestAddress); 98 + logger.info("[注册请求] 未携带授权头 回复401: {}", requestAddress);
94 response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); 99 response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
95 new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); 100 new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
96 sendResponse(evt, response); 101 sendResponse(evt, response);
@@ -106,17 +111,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -106,17 +111,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
106 // 注册失败 111 // 注册失败
107 response = getMessageFactory().createResponse(Response.FORBIDDEN, request); 112 response = getMessageFactory().createResponse(Response.FORBIDDEN, request);
108 response.setReasonPhrase("wrong password"); 113 response.setReasonPhrase("wrong password");
109 - logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress); 114 + logger.info("[注册请求] 密码/SIP服务器ID错误, 回复403: {}", requestAddress);
110 sendResponse(evt, response); 115 sendResponse(evt, response);
111 return; 116 return;
112 } 117 }
113 118
114 - Device deviceInRedis = redisCatchStorage.getDevice(deviceId);  
115 - Device device = storager.queryVideoDevice(deviceId);  
116 - if (deviceInRedis != null && device == null) {  
117 - // redis 存在脏数据  
118 - redisCatchStorage.clearCatchByDeviceId(deviceId);  
119 - } 119 + Device device = deviceService.queryDevice(deviceId);
  120 +
120 // 携带授权头并且密码正确 121 // 携带授权头并且密码正确
121 response = getMessageFactory().createResponse(Response.OK, request); 122 response = getMessageFactory().createResponse(Response.OK, request);
122 // 添加date头 123 // 添加date头
@@ -154,20 +155,17 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -154,20 +155,17 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
154 device.setStreamMode("UDP"); 155 device.setStreamMode("UDP");
155 device.setCharset("GB2312"); 156 device.setCharset("GB2312");
156 device.setDeviceId(deviceId); 157 device.setDeviceId(deviceId);
157 - device.setFirsRegister(true);  
158 - } else {  
159 - device.setFirsRegister(device.getOnline() == 0);  
160 } 158 }
161 device.setIp(received); 159 device.setIp(received);
162 device.setPort(rPort); 160 device.setPort(rPort);
163 device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); 161 device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
164 if (expiresHeader.getExpires() == 0) { 162 if (expiresHeader.getExpires() == 0) {
165 // 注销成功 163 // 注销成功
166 - registerFlag = 2; 164 + registerFlag = false;
167 } else { 165 } else {
168 // 注册成功 166 // 注册成功
169 device.setExpires(expiresHeader.getExpires()); 167 device.setExpires(expiresHeader.getExpires());
170 - registerFlag = 1; 168 + registerFlag = true;
171 // 判断TCP还是UDP 169 // 判断TCP还是UDP
172 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); 170 ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
173 String transport = reqViaHeader.getTransport(); 171 String transport = reqViaHeader.getTransport();
@@ -177,12 +175,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -177,12 +175,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
177 sendResponse(evt, response); 175 sendResponse(evt, response);
178 // 注册成功 176 // 注册成功
179 // 保存到redis 177 // 保存到redis
180 - if (registerFlag == 1) {  
181 - logger.info("[{}] 注册成功! deviceId:" + deviceId, requestAddress);  
182 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER, expiresHeader.getExpires());  
183 - } else if (registerFlag == 2) {  
184 - logger.info("[{}] 注销成功! deviceId:" + deviceId, requestAddress);  
185 - publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); 178 + if (registerFlag) {
  179 + logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);
  180 + device.setRegisterTime(DateUtil.getNow());
  181 + deviceService.online(device);
  182 + } else {
  183 + logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
  184 + deviceService.offline(deviceId);
186 } 185 }
187 } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { 186 } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) {
188 e.printStackTrace(); 187 e.printStackTrace();
@@ -193,7 +192,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -193,7 +192,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
193 private void sendResponse(RequestEvent evt, Response response) throws InvalidArgumentException, SipException { 192 private void sendResponse(RequestEvent evt, Response response) throws InvalidArgumentException, SipException {
194 ServerTransaction serverTransaction = getServerTransaction(evt); 193 ServerTransaction serverTransaction = getServerTransaction(evt);
195 if (serverTransaction == null) { 194 if (serverTransaction == null) {
196 - logger.warn("回复失败:{}", response); 195 + logger.warn("[回复失败]:{}", response);
197 return; 196 return;
198 } 197 }
199 serverTransaction.sendResponse(response); 198 serverTransaction.sendResponse(response);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
2 2
3 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 5 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 6 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; 8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
  9 +import com.genersoft.iot.vmp.service.IDeviceService;
10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  12 +import com.genersoft.iot.vmp.utils.DateUtil;
12 import org.dom4j.Element; 13 import org.dom4j.Element;
13 import org.slf4j.Logger; 14 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
@@ -28,19 +29,13 @@ import java.text.ParseException; @@ -28,19 +29,13 @@ import java.text.ParseException;
28 public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 29 public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
29 30
30 private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class); 31 private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
31 - private final String cmdType = "Keepalive"; 32 + private final static String cmdType = "Keepalive";
32 33
33 @Autowired 34 @Autowired
34 private NotifyMessageHandler notifyMessageHandler; 35 private NotifyMessageHandler notifyMessageHandler;
35 36
36 @Autowired 37 @Autowired
37 - private EventPublisher publisher;  
38 -  
39 - @Autowired  
40 - private IVideoManagerStorage videoManagerStorager;  
41 -  
42 - @Autowired  
43 - private IRedisCatchStorage redisCatchStorage; 38 + private IDeviceService deviceService;
44 39
45 @Override 40 @Override
46 public void afterPropertiesSet() throws Exception { 41 public void afterPropertiesSet() throws Exception {
@@ -49,29 +44,36 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @@ -49,29 +44,36 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
49 44
50 @Override 45 @Override
51 public void handForDevice(RequestEvent evt, Device device, Element element) { 46 public void handForDevice(RequestEvent evt, Device device, Element element) {
52 - // 检查设备是否存在并在线, 不在线则设置为在线 47 + if (device == null) {
  48 + // 未注册的设备不做处理
  49 + return;
  50 + }
53 try { 51 try {
54 - if (device != null ) { 52 + if (device.getOnline() == 1) {
55 // 回复200 OK 53 // 回复200 OK
56 responseAck(evt, Response.OK); 54 responseAck(evt, Response.OK);
57 - // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息  
58 - // 获取到通信地址等信息  
59 - ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME);  
60 - String received = viaHeader.getReceived();  
61 - int rPort = viaHeader.getRPort();  
62 - // 解析本地地址替代  
63 - if (StringUtils.isEmpty(received) || rPort == -1) {  
64 - received = viaHeader.getHost();  
65 - rPort = viaHeader.getPort();  
66 - }  
67 - if (device.getPort() != rPort) {  
68 - device.setPort(rPort);  
69 - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));  
70 - videoManagerStorager.updateDevice(device);  
71 - redisCatchStorage.updateDevice(device);  
72 - }  
73 - if (!redisCatchStorage.deviceIsOnline(device.getDeviceId())) {  
74 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); 55 + }else {
  56 + // 对于已经离线的设备判断他的注册是否已经过期
  57 + if (!deviceService.expire(device)){
  58 + device.setKeepaliveTime(DateUtil.getNow());
  59 + // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息
  60 + // 获取到通信地址等信息
  61 + ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME);
  62 + String received = viaHeader.getReceived();
  63 + int rPort = viaHeader.getRPort();
  64 + // 解析本地地址替代
  65 + if (StringUtils.isEmpty(received) || rPort == -1) {
  66 + received = viaHeader.getHost();
  67 + rPort = viaHeader.getPort();
  68 + }
  69 + if (device.getPort() != rPort) {
  70 + device.setPort(rPort);
  71 + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
  72 + }
  73 + device.setKeepaliveTime(DateUtil.getNow());
  74 + deviceService.online(device);
  75 + // 回复200 OK
  76 + responseAck(evt, Response.OK);
75 } 77 }
76 } 78 }
77 } catch (SipException e) { 79 } catch (SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
@@ -60,10 +60,9 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -60,10 +60,9 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
60 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); 60 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
61 String NotifyType =getText(rootElement, "NotifyType"); 61 String NotifyType =getText(rootElement, "NotifyType");
62 if (NotifyType.equals("121")){ 62 if (NotifyType.equals("121")){
63 - logger.info("媒体播放完毕,通知关流"); 63 + logger.info("[录像流]推送完毕,收到关流通知");
64 String channelId =getText(rootElement, "DeviceID"); 64 String channelId =getText(rootElement, "DeviceID");
65 -// redisCatchStorage.stopPlayback(device.getDeviceId(), channelId, null, callIdHeader.getCallId());  
66 -// redisCatchStorage.stopDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); 65 + // 查询是设备
67 StreamInfo streamInfo = redisCatchStorage.queryDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); 66 StreamInfo streamInfo = redisCatchStorage.queryDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId());
68 // 设置进度100% 67 // 设置进度100%
69 streamInfo.setProgress(1); 68 streamInfo.setProgress(1);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java
@@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler;
12 -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; 12 +import com.genersoft.iot.vmp.utils.DateUtil;
13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; 14 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
15 import org.dom4j.Element; 15 import org.dom4j.Element;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -28,7 +28,6 @@ import javax.sip.RequestEvent; @@ -28,7 +28,6 @@ import javax.sip.RequestEvent;
28 import javax.sip.SipException; 28 import javax.sip.SipException;
29 import javax.sip.message.Response; 29 import javax.sip.message.Response;
30 import java.text.ParseException; 30 import java.text.ParseException;
31 -import java.text.SimpleDateFormat;  
32 import java.util.ArrayList; 31 import java.util.ArrayList;
33 import java.util.Iterator; 32 import java.util.Iterator;
34 import java.util.List; 33 import java.util.List;
@@ -39,8 +38,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -39,8 +38,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
39 private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class); 38 private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class);
40 private final String cmdType = "Catalog"; 39 private final String cmdType = "Catalog";
41 40
42 - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
43 -  
44 @Autowired 41 @Autowired
45 private ResponseMessageHandler responseMessageHandler; 42 private ResponseMessageHandler responseMessageHandler;
46 43
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
@@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; 12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
  13 +import com.genersoft.iot.vmp.service.IDeviceService;
13 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
15 import org.dom4j.DocumentException; 16 import org.dom4j.DocumentException;
@@ -29,6 +30,9 @@ import java.text.ParseException; @@ -29,6 +30,9 @@ import java.text.ParseException;
29 30
30 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; 31 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
31 32
  33 +/**
  34 + * @author lin
  35 + */
32 @Component 36 @Component
33 public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 37 public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
34 38
@@ -53,6 +57,9 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -53,6 +57,9 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
53 @Autowired 57 @Autowired
54 private EventPublisher publisher; 58 private EventPublisher publisher;
55 59
  60 + @Autowired
  61 + private IDeviceService deviceService;
  62 +
56 @Override 63 @Override
57 public void afterPropertiesSet() throws Exception { 64 public void afterPropertiesSet() throws Exception {
58 responseMessageHandler.addHandler(cmdType, this); 65 responseMessageHandler.addHandler(cmdType, this);
@@ -61,6 +68,11 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -61,6 +68,11 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
61 @Override 68 @Override
62 public void handForDevice(RequestEvent evt, Device device, Element rootElement) { 69 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
63 logger.debug("接收到DeviceInfo应答消息"); 70 logger.debug("接收到DeviceInfo应答消息");
  71 + // 检查设备是否存在, 不存在则不回复
  72 + if (device == null || device.getOnline() == 0) {
  73 + logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]:" + (device != null ? device.getDeviceId():"" ));
  74 + return;
  75 + }
64 try { 76 try {
65 rootElement = getRootElement(evt, device.getCharset()); 77 rootElement = getRootElement(evt, device.getCharset());
66 Element deviceIdElement = rootElement.element("DeviceID"); 78 Element deviceIdElement = rootElement.element("DeviceID");
@@ -74,7 +86,8 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -74,7 +86,8 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
74 if (StringUtils.isEmpty(device.getStreamMode())) { 86 if (StringUtils.isEmpty(device.getStreamMode())) {
75 device.setStreamMode("UDP"); 87 device.setStreamMode("UDP");
76 } 88 }
77 - storager.updateDevice(device); 89 + deviceService.updateDevice(device);
  90 +// storager.updateDevice(device);
78 91
79 RequestMessage msg = new RequestMessage(); 92 RequestMessage msg = new RequestMessage();
80 msg.setKey(key); 93 msg.setKey(key);
@@ -82,9 +95,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -82,9 +95,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
82 deferredResultHolder.invokeAllResult(msg); 95 deferredResultHolder.invokeAllResult(msg);
83 // 回复200 OK 96 // 回复200 OK
84 responseAck(evt, Response.OK); 97 responseAck(evt, Response.OK);
85 - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) {  
86 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);  
87 - }  
88 } catch (DocumentException e) { 98 } catch (DocumentException e) {
89 e.printStackTrace(); 99 e.printStackTrace();
90 } catch (InvalidArgumentException e) { 100 } catch (InvalidArgumentException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
@@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; 12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
13 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 13 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  14 +import com.genersoft.iot.vmp.service.IDeviceService;
14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15 import org.dom4j.Element; 16 import org.dom4j.Element;
16 import org.slf4j.Logger; 17 import org.slf4j.Logger;
@@ -24,6 +25,7 @@ import javax.sip.RequestEvent; @@ -24,6 +25,7 @@ import javax.sip.RequestEvent;
24 import javax.sip.SipException; 25 import javax.sip.SipException;
25 import javax.sip.message.Response; 26 import javax.sip.message.Response;
26 import java.text.ParseException; 27 import java.text.ParseException;
  28 +import java.util.Objects;
27 29
28 @Component 30 @Component
29 public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 31 public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@@ -34,12 +36,11 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen @@ -34,12 +36,11 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
34 @Autowired 36 @Autowired
35 private ResponseMessageHandler responseMessageHandler; 37 private ResponseMessageHandler responseMessageHandler;
36 38
37 -  
38 @Autowired 39 @Autowired
39 private DeferredResultHolder deferredResultHolder; 40 private DeferredResultHolder deferredResultHolder;
40 41
41 @Autowired 42 @Autowired
42 - private EventPublisher publisher; 43 + private IDeviceService deviceService;
43 44
44 @Autowired 45 @Autowired
45 private IRedisCatchStorage redisCatchStorage; 46 private IRedisCatchStorage redisCatchStorage;
@@ -53,6 +54,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen @@ -53,6 +54,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
53 public void handForDevice(RequestEvent evt, Device device, Element element) { 54 public void handForDevice(RequestEvent evt, Device device, Element element) {
54 logger.info("接收到DeviceStatus应答消息"); 55 logger.info("接收到DeviceStatus应答消息");
55 // 检查设备是否存在, 不存在则不回复 56 // 检查设备是否存在, 不存在则不回复
  57 + if (device == null) {
  58 + return;
  59 + }
56 // 回复200 OK 60 // 回复200 OK
57 try { 61 try {
58 responseAck(evt, Response.OK); 62 responseAck(evt, Response.OK);
@@ -64,20 +68,23 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen @@ -64,20 +68,23 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
64 e.printStackTrace(); 68 e.printStackTrace();
65 } 69 }
66 Element deviceIdElement = element.element("DeviceID"); 70 Element deviceIdElement = element.element("DeviceID");
  71 + Element onlineElement = element.element("Online");
67 String channelId = deviceIdElement.getText(); 72 String channelId = deviceIdElement.getText();
68 JSONObject json = new JSONObject(); 73 JSONObject json = new JSONObject();
69 XmlUtil.node2Json(element, json); 74 XmlUtil.node2Json(element, json);
70 if (logger.isDebugEnabled()) { 75 if (logger.isDebugEnabled()) {
71 logger.debug(json.toJSONString()); 76 logger.debug(json.toJSONString());
72 } 77 }
  78 + String text = onlineElement.getText();
  79 + if (Objects.equals(text.trim().toUpperCase(), "ONLINE")) {
  80 + deviceService.online(device);
  81 + }else {
  82 + deviceService.offline(device.getDeviceId());
  83 + }
73 RequestMessage msg = new RequestMessage(); 84 RequestMessage msg = new RequestMessage();
74 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId() + channelId); 85 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId() + channelId);
75 msg.setData(json); 86 msg.setData(json);
76 deferredResultHolder.invokeAllResult(msg); 87 deferredResultHolder.invokeAllResult(msg);
77 -  
78 - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) {  
79 - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);  
80 - }  
81 } 88 }
82 89
83 @Override 90 @Override
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
2 2
3 -import com.genersoft.iot.vmp.conf.SipConfig;  
4 -import com.genersoft.iot.vmp.conf.UserSetting;  
5 import com.genersoft.iot.vmp.domain.req.PresetQuerySipReq; 3 import com.genersoft.iot.vmp.domain.req.PresetQuerySipReq;
6 import com.genersoft.iot.vmp.gb28181.bean.*; 4 import com.genersoft.iot.vmp.gb28181.bean.*;
7 -import com.genersoft.iot.vmp.gb28181.event.EventPublisher;  
8 -import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch;  
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 5 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
10 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; 9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
14 -import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;  
15 -import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;  
16 -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;  
17 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
18 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
19 import org.dom4j.DocumentException; 10 import org.dom4j.DocumentException;
20 import org.dom4j.Element; 11 import org.dom4j.Element;
21 import org.slf4j.Logger; 12 import org.slf4j.Logger;
@@ -23,18 +14,15 @@ import org.slf4j.LoggerFactory; @@ -23,18 +14,15 @@ import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.InitializingBean; 14 import org.springframework.beans.factory.InitializingBean;
24 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
26 -import org.springframework.util.StringUtils;  
27 17
28 import javax.sip.InvalidArgumentException; 18 import javax.sip.InvalidArgumentException;
29 import javax.sip.RequestEvent; 19 import javax.sip.RequestEvent;
30 import javax.sip.SipException; 20 import javax.sip.SipException;
31 import javax.sip.message.Response; 21 import javax.sip.message.Response;
32 import java.text.ParseException; 22 import java.text.ParseException;
33 -import java.text.SimpleDateFormat;  
34 import java.util.ArrayList; 23 import java.util.ArrayList;
35 import java.util.Iterator; 24 import java.util.Iterator;
36 import java.util.List; 25 import java.util.List;
37 -import java.util.UUID;  
38 26
39 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; 27 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
40 28
@@ -44,8 +32,6 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent @@ -44,8 +32,6 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
44 private Logger logger = LoggerFactory.getLogger(PresetQueryResponseMessageHandler.class); 32 private Logger logger = LoggerFactory.getLogger(PresetQueryResponseMessageHandler.class);
45 private final String cmdType = "PresetQuery"; 33 private final String cmdType = "PresetQuery";
46 34
47 - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
48 -  
49 @Autowired 35 @Autowired
50 private ResponseMessageHandler responseMessageHandler; 36 private ResponseMessageHandler responseMessageHandler;
51 37
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
@@ -5,14 +5,14 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; @@ -5,14 +5,14 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; 5 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
6 import com.genersoft.iot.vmp.gb28181.bean.RecordItem; 6 import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 -import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread; 8 +import com.genersoft.iot.vmp.gb28181.session.RecordDataCatch;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 9 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
10 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 10 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
14 -import com.genersoft.iot.vmp.gb28181.utils.DateUtil;  
15 -import com.genersoft.iot.vmp.utils.redis.RedisUtil; 14 +import com.genersoft.iot.vmp.utils.DateUtil;
  15 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
16 import org.dom4j.DocumentException; 16 import org.dom4j.DocumentException;
17 import org.dom4j.Element; 17 import org.dom4j.Element;
18 import org.slf4j.Logger; 18 import org.slf4j.Logger;
@@ -20,19 +20,20 @@ import org.slf4j.LoggerFactory; @@ -20,19 +20,20 @@ import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.InitializingBean; 20 import org.springframework.beans.factory.InitializingBean;
21 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
  23 +import org.springframework.util.StringUtils;
23 24
24 import javax.sip.InvalidArgumentException; 25 import javax.sip.InvalidArgumentException;
25 import javax.sip.RequestEvent; 26 import javax.sip.RequestEvent;
26 import javax.sip.SipException; 27 import javax.sip.SipException;
27 import javax.sip.message.Response; 28 import javax.sip.message.Response;
28 import java.text.ParseException; 29 import java.text.ParseException;
29 -import java.util.ArrayList;  
30 -import java.util.Iterator;  
31 -import java.util.List;  
32 -import java.util.UUID; 30 +import java.util.*;
33 31
34 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; 32 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
35 33
  34 +/**
  35 + * @author lin
  36 + */
36 @Component 37 @Component
37 public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 38 public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
38 39
@@ -45,11 +46,13 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -45,11 +46,13 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
45 private ResponseMessageHandler responseMessageHandler; 46 private ResponseMessageHandler responseMessageHandler;
46 47
47 @Autowired 48 @Autowired
48 - private RedisUtil redis; 49 + private RecordDataCatch recordDataCatch;
49 50
50 @Autowired 51 @Autowired
51 private DeferredResultHolder deferredResultHolder; 52 private DeferredResultHolder deferredResultHolder;
52 53
  54 +
  55 +
53 @Autowired 56 @Autowired
54 private EventPublisher eventPublisher; 57 private EventPublisher eventPublisher;
55 58
@@ -66,32 +69,22 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -66,32 +69,22 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
66 responseAck(evt, Response.OK); 69 responseAck(evt, Response.OK);
67 70
68 rootElement = getRootElement(evt, device.getCharset()); 71 rootElement = getRootElement(evt, device.getCharset());
69 - String uuid = UUID.randomUUID().toString().replace("-", "");  
70 - RecordInfo recordInfo = new RecordInfo();  
71 String sn = getText(rootElement, "SN"); 72 String sn = getText(rootElement, "SN");
72 - String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + sn;  
73 - recordInfo.setDeviceId(device.getDeviceId());  
74 - recordInfo.setSn(sn);  
75 - recordInfo.setName(getText(rootElement, "Name"));  
76 - if (getText(rootElement, "SumNum") == null || getText(rootElement, "SumNum") == "") {  
77 - recordInfo.setSumNum(0);  
78 - } else {  
79 - recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum"))); 73 +
  74 + String sumNumStr = getText(rootElement, "SumNum");
  75 + int sumNum = 0;
  76 + if (!StringUtils.isEmpty(sumNumStr)) {
  77 + sumNum = Integer.parseInt(sumNumStr);
80 } 78 }
81 Element recordListElement = rootElement.element("RecordList"); 79 Element recordListElement = rootElement.element("RecordList");
82 - if (recordListElement == null || recordInfo.getSumNum() == 0) { 80 + if (recordListElement == null || sumNum == 0) {
83 logger.info("无录像数据"); 81 logger.info("无录像数据");
84 - eventPublisher.recordEndEventPush(recordInfo);  
85 - RequestMessage msg = new RequestMessage();  
86 - msg.setKey(key);  
87 - msg.setData(recordInfo);  
88 - deferredResultHolder.invokeAllResult(msg); 82 + recordDataCatch.put(device.getDeviceId(), sn, sumNum, new ArrayList<>());
  83 + releaseRequest(device.getDeviceId(), sn);
89 } else { 84 } else {
90 Iterator<Element> recordListIterator = recordListElement.elementIterator(); 85 Iterator<Element> recordListIterator = recordListElement.elementIterator();
91 - List<RecordItem> recordList = new ArrayList<RecordItem>();  
92 if (recordListIterator != null) { 86 if (recordListIterator != null) {
93 - RecordItem record = new RecordItem();  
94 - logger.info("处理录像列表数据..."); 87 + List<RecordItem> recordList = new ArrayList<>();
95 // 遍历DeviceList 88 // 遍历DeviceList
96 while (recordListIterator.hasNext()) { 89 while (recordListIterator.hasNext()) {
97 Element itemRecord = recordListIterator.next(); 90 Element itemRecord = recordListIterator.next();
@@ -100,43 +93,31 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -100,43 +93,31 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
100 logger.info("记录为空,下一个..."); 93 logger.info("记录为空,下一个...");
101 continue; 94 continue;
102 } 95 }
103 - record = new RecordItem(); 96 + RecordItem record = new RecordItem();
104 record.setDeviceId(getText(itemRecord, "DeviceID")); 97 record.setDeviceId(getText(itemRecord, "DeviceID"));
105 record.setName(getText(itemRecord, "Name")); 98 record.setName(getText(itemRecord, "Name"));
106 record.setFilePath(getText(itemRecord, "FilePath")); 99 record.setFilePath(getText(itemRecord, "FilePath"));
107 record.setFileSize(getText(itemRecord, "FileSize")); 100 record.setFileSize(getText(itemRecord, "FileSize"));
108 record.setAddress(getText(itemRecord, "Address")); 101 record.setAddress(getText(itemRecord, "Address"));
109 - record.setStartTime(  
110 - DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "StartTime")));  
111 - record.setEndTime(  
112 - DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "EndTime"))); 102 +
  103 + String startTimeStr = getText(itemRecord, "StartTime");
  104 + record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr));
  105 +
  106 + String endTimeStr = getText(itemRecord, "EndTime");
  107 + record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr));
  108 +
113 record.setSecrecy(itemRecord.element("Secrecy") == null ? 0 109 record.setSecrecy(itemRecord.element("Secrecy") == null ? 0
114 : Integer.parseInt(getText(itemRecord, "Secrecy"))); 110 : Integer.parseInt(getText(itemRecord, "Secrecy")));
115 record.setType(getText(itemRecord, "Type")); 111 record.setType(getText(itemRecord, "Type"));
116 record.setRecorderId(getText(itemRecord, "RecorderID")); 112 record.setRecorderId(getText(itemRecord, "RecorderID"));
117 recordList.add(record); 113 recordList.add(record);
118 } 114 }
119 - recordInfo.setRecordList(recordList); 115 + int count = recordDataCatch.put(device.getDeviceId(), sn, sumNum, recordList);
  116 + logger.info("[国标录像], {}->{}: {}/{}", device.getDeviceId(), sn, count, sumNum);
120 } 117 }
121 - eventPublisher.recordEndEventPush(recordInfo);  
122 - // 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题  
123 - String cacheKey = CACHE_RECORDINFO_KEY + device.getDeviceId() + sn;  
124 - redis.set(cacheKey + "_" + uuid, recordList, 90);  
125 - if (!threadNameList.contains(cacheKey)) {  
126 - threadNameList.add(cacheKey);  
127 - CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo);  
128 - chk.setName(cacheKey);  
129 - chk.setDeferredResultHolder(deferredResultHolder);  
130 - chk.setRedis(redis);  
131 - chk.setLogger(logger);  
132 - chk.start();  
133 - if (logger.isDebugEnabled()) {  
134 - logger.debug("Start Thread " + cacheKey + ".");  
135 - }  
136 - } else {  
137 - if (logger.isDebugEnabled()) {  
138 - logger.debug("Thread " + cacheKey + " already started.");  
139 - } 118 +
  119 + if (recordDataCatch.isComplete(device.getDeviceId(), sn)){
  120 + releaseRequest(device.getDeviceId(), sn);
140 } 121 }
141 } 122 }
142 } catch (SipException e) { 123 } catch (SipException e) {
@@ -154,4 +135,20 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -154,4 +135,20 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
154 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { 135 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) {
155 136
156 } 137 }
  138 +
  139 + public void releaseRequest(String deviceId, String sn){
  140 + String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
  141 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  142 + wvpResult.setCode(0);
  143 + wvpResult.setMsg("success");
  144 + // 对数据进行排序
  145 + Collections.sort(recordDataCatch.getRecordInfo(deviceId, sn).getRecordList());
  146 + wvpResult.setData(recordDataCatch.getRecordInfo(deviceId, sn));
  147 +
  148 + RequestMessage msg = new RequestMessage();
  149 + msg.setKey(key);
  150 + msg.setData(wvpResult);
  151 + deferredResultHolder.invokeAllResult(msg);
  152 + recordDataCatch.remove(deviceId, sn);
  153 + }
157 } 154 }
src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.gb28181.utils;  
2 -  
3 -import java.text.ParseException;  
4 -import java.text.SimpleDateFormat;  
5 -import java.util.Date;  
6 -import java.util.Locale;  
7 -  
8 -/**  
9 - * @description:时间工具类,主要处理ISO 8601格式转换  
10 - * @author: swwheihei  
11 - * @date: 2020年5月8日 下午3:24:42  
12 - */  
13 -public class DateUtil {  
14 -  
15 - //private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";  
16 - private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss";  
17 - private static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";  
18 -  
19 - public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {  
20 -  
21 - SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());  
22 - SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());  
23 - try {  
24 - return newsdf.format(oldsdf.parse(formatTime));  
25 - } catch (ParseException e) {  
26 - e.printStackTrace();  
27 - }  
28 - return "";  
29 - }  
30 -  
31 - public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) {  
32 -  
33 - SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());  
34 - SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());  
35 - try {  
36 - return newsdf.format(oldsdf.parse(formatTime));  
37 - } catch (ParseException e) {  
38 - e.printStackTrace();  
39 - }  
40 - return "";  
41 - }  
42 -  
43 - public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) {  
44 - SimpleDateFormat format=new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss);  
45 - //设置要读取的时间字符串格式  
46 - Date date;  
47 - try {  
48 - date = format.parse(formatTime);  
49 - Long timestamp=date.getTime()/1000;  
50 - //转换为Date类  
51 - return timestamp;  
52 - } catch (ParseException e) {  
53 - e.printStackTrace();  
54 - }  
55 - return 0;  
56 - }  
57 -}  
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -246,17 +246,7 @@ public class ZLMRTPServerFactory { @@ -246,17 +246,7 @@ public class ZLMRTPServerFactory {
246 * 调用zlm RESTFUL API —— startSendRtp 246 * 调用zlm RESTFUL API —— startSendRtp
247 */ 247 */
248 public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) { 248 public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) {
249 - Boolean result = false;  
250 - JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param);  
251 - if (jsonObject == null) {  
252 - logger.error("RTP推流失败: 请检查ZLM服务");  
253 - } else if (jsonObject.getInteger("code") == 0) {  
254 - result= true;  
255 - logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port"));  
256 - } else {  
257 - logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param));  
258 - }  
259 - return jsonObject; 249 + return zlmresTfulUtils.startSendRtp(mediaServerItem, param);
260 } 250 }
261 251
262 /** 252 /**
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -55,9 +55,6 @@ public class ZLMRunner implements CommandLineRunner { @@ -55,9 +55,6 @@ public class ZLMRunner implements CommandLineRunner {
55 @Autowired 55 @Autowired
56 private DynamicTask dynamicTask; 56 private DynamicTask dynamicTask;
57 57
58 - @Qualifier("taskExecutor")  
59 - @Autowired  
60 - private ThreadPoolTaskExecutor taskExecutor;  
61 58
62 @Override 59 @Override
63 public void run(String... strings) throws Exception { 60 public void run(String... strings) throws Exception {
@@ -92,7 +89,7 @@ public class ZLMRunner implements CommandLineRunner { @@ -92,7 +89,7 @@ public class ZLMRunner implements CommandLineRunner {
92 }); 89 });
93 90
94 // 获取zlm信息 91 // 获取zlm信息
95 - logger.info("[zlm接入]等待默认zlm中..."); 92 + logger.info("[zlm] 等待默认zlm中...");
96 93
97 // 获取所有的zlm, 并开启主动连接 94 // 获取所有的zlm, 并开启主动连接
98 List<MediaServerItem> all = mediaServerService.getAllFromDatabase(); 95 List<MediaServerItem> all = mediaServerService.getAllFromDatabase();
@@ -105,9 +102,7 @@ public class ZLMRunner implements CommandLineRunner { @@ -105,9 +102,7 @@ public class ZLMRunner implements CommandLineRunner {
105 startGetMedia = new HashMap<>(); 102 startGetMedia = new HashMap<>();
106 } 103 }
107 startGetMedia.put(mediaServerItem.getId(), true); 104 startGetMedia.put(mediaServerItem.getId(), true);
108 - taskExecutor.execute(()->{  
109 - connectZlmServer(mediaServerItem);  
110 - }); 105 + connectZlmServer(mediaServerItem);
111 } 106 }
112 String taskKey = "zlm-connect-timeout"; 107 String taskKey = "zlm-connect-timeout";
113 dynamicTask.startDelay(taskKey, ()->{ 108 dynamicTask.startDelay(taskKey, ()->{
@@ -119,21 +114,37 @@ public class ZLMRunner implements CommandLineRunner { @@ -119,21 +114,37 @@ public class ZLMRunner implements CommandLineRunner {
119 startGetMedia = null; 114 startGetMedia = null;
120 } 115 }
121 // TODO 清理数据库中与redis不匹配的zlm 116 // TODO 清理数据库中与redis不匹配的zlm
122 - }, 6 * 1000 ); 117 + }, 60 * 1000 );
123 } 118 }
124 119
125 @Async 120 @Async
126 public void connectZlmServer(MediaServerItem mediaServerItem){ 121 public void connectZlmServer(MediaServerItem mediaServerItem){
127 - ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem, 1);  
128 - if (zlmServerConfig != null) {  
129 - zlmServerConfig.setIp(mediaServerItem.getIp());  
130 - zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); 122 + String connectZlmServerTaskKey = "connect-zlm-" + mediaServerItem.getId();
  123 + ZLMServerConfig zlmServerConfigFirst = getMediaServerConfig(mediaServerItem);
  124 + if (zlmServerConfigFirst != null) {
  125 + zlmServerConfigFirst.setIp(mediaServerItem.getIp());
  126 + zlmServerConfigFirst.setHttpPort(mediaServerItem.getHttpPort());
131 startGetMedia.remove(mediaServerItem.getId()); 127 startGetMedia.remove(mediaServerItem.getId());
132 - mediaServerService.zlmServerOnline(zlmServerConfig); 128 + mediaServerService.zlmServerOnline(zlmServerConfigFirst);
  129 + }else {
  130 + logger.info("[ {} ]-[ {}:{} ]主动连接失败, 清理相关资源, 开始尝试重试连接",
  131 + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
  132 + publisher.zlmOfflineEventPublish(mediaServerItem.getId());
133 } 133 }
  134 +
  135 + dynamicTask.startCron(connectZlmServerTaskKey, ()->{
  136 + ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem);
  137 + if (zlmServerConfig != null) {
  138 + dynamicTask.stop(connectZlmServerTaskKey);
  139 + zlmServerConfig.setIp(mediaServerItem.getIp());
  140 + zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
  141 + startGetMedia.remove(mediaServerItem.getId());
  142 + mediaServerService.zlmServerOnline(zlmServerConfig);
  143 + }
  144 + }, 2000);
134 } 145 }
135 146
136 - public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem, int index) { 147 + public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) {
137 if (startGetMedia == null) { return null;} 148 if (startGetMedia == null) { return null;}
138 if (!mediaServerItem.isDefaultServer() && mediaServerService.getOne(mediaServerItem.getId()) == null) { 149 if (!mediaServerItem.isDefaultServer() && mediaServerService.getOne(mediaServerItem.getId()) == null) {
139 return null; 150 return null;
@@ -149,53 +160,10 @@ public class ZLMRunner implements CommandLineRunner { @@ -149,53 +160,10 @@ public class ZLMRunner implements CommandLineRunner {
149 zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); 160 zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
150 } 161 }
151 } else { 162 } else {
152 - logger.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试",  
153 - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index);  
154 - if (index == 1 && !StringUtils.isEmpty(mediaServerItem.getId())) {  
155 - logger.info("[ {} ]-[ {}:{} ]第{}次主动连接失败, 开始清理相关资源",  
156 - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index);  
157 - publisher.zlmOfflineEventPublish(mediaServerItem.getId());  
158 - }  
159 - try {  
160 - Thread.sleep(2000);  
161 - } catch (InterruptedException e) {  
162 - e.printStackTrace();  
163 - }  
164 - zlmServerConfig = getMediaServerConfig(mediaServerItem, index += 1); 163 + logger.error("[ {} ]-[ {}:{} ]主动连接失败, 2s后重试",
  164 + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
165 } 165 }
166 return zlmServerConfig; 166 return zlmServerConfig;
167 167
168 } 168 }
169 -  
170 - /**  
171 - * zlm 连接成功或者zlm重启后  
172 - */  
173 -// private void zLmRunning(ZLMServerConfig zlmServerConfig){  
174 -// logger.info( "[ id: " + zlmServerConfig.getGeneralMediaServerId() + "] zlm接入成功...");  
175 -// // 关闭循环获取zlm配置  
176 -// startGetMedia = false;  
177 -// MediaServerItem mediaServerItem = new MediaServerItem(zlmServerConfig, sipIp);  
178 -// storager.updateMediaServer(mediaServerItem);  
179 -//  
180 -// if (mediaServerItem.isAutoConfig()) setZLMConfig(mediaServerItem);  
181 -// zlmServerManger.updateServerCatchFromHook(zlmServerConfig);  
182 -//  
183 -// // 清空所有session  
184 -//// zlmMediaListManager.clearAllSessions();  
185 -//  
186 -// // 更新流列表  
187 -// zlmMediaListManager.updateMediaList(mediaServerItem);  
188 -// // 恢复流代理, 只查找这个这个流媒体  
189 -// List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer(  
190 -// mediaServerItem.getId(), true);  
191 -// for (StreamProxyItem streamProxyDto : streamProxyListForEnable) {  
192 -// logger.info("恢复流代理," + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());  
193 -// JSONObject jsonObject = streamProxyService.addStreamProxyToZlm(streamProxyDto);  
194 -// if (jsonObject == null) {  
195 -// // 设置为未启用  
196 -// logger.info("恢复流代理失败,请检查流地址后重新启用" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());  
197 -// streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream());  
198 -// }  
199 -// }  
200 -// }  
201 } 169 }
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java
@@ -7,12 +7,10 @@ import com.genersoft.iot.vmp.service.IStreamPushService; @@ -7,12 +7,10 @@ import com.genersoft.iot.vmp.service.IStreamPushService;
7 import org.slf4j.Logger; 7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
9 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
10 -import org.springframework.context.ApplicationListener;  
11 import org.springframework.context.event.EventListener; 10 import org.springframework.context.event.EventListener;
12 import org.springframework.scheduling.annotation.Async; 11 import org.springframework.scheduling.annotation.Async;
13 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
14 13
15 -import java.text.SimpleDateFormat;  
16 14
17 /** 15 /**
18 * @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: 16 * @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源:
@@ -38,13 +36,10 @@ public class ZLMStatusEventListener { @@ -38,13 +36,10 @@ public class ZLMStatusEventListener {
38 @Autowired 36 @Autowired
39 private IPlayService playService; 37 private IPlayService playService;
40 38
41 - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
42 -  
43 @Async 39 @Async
44 @EventListener 40 @EventListener
45 public void onApplicationEvent(ZLMOnlineEvent event) { 41 public void onApplicationEvent(ZLMOnlineEvent event) {
46 -  
47 - logger.info("ZLM上线事件触发,ID:" + event.getMediaServerId()); 42 + logger.info("[ZLM] 上线 ID:" + event.getMediaServerId());
48 streamPushService.zlmServerOnline(event.getMediaServerId()); 43 streamPushService.zlmServerOnline(event.getMediaServerId());
49 streamProxyService.zlmServerOnline(event.getMediaServerId()); 44 streamProxyService.zlmServerOnline(event.getMediaServerId());
50 45
@@ -54,7 +49,7 @@ public class ZLMStatusEventListener { @@ -54,7 +49,7 @@ public class ZLMStatusEventListener {
54 @EventListener 49 @EventListener
55 public void onApplicationEvent(ZLMOfflineEvent event) { 50 public void onApplicationEvent(ZLMOfflineEvent event) {
56 51
57 - logger.info("ZLM离线事件触发,ID:" + event.getMediaServerId()); 52 + logger.info("[ZLM] 离线,ID:" + event.getMediaServerId());
58 // 处理ZLM离线 53 // 处理ZLM离线
59 mediaServerService.zlmServerOffline(event.getMediaServerId()); 54 mediaServerService.zlmServerOffline(event.getMediaServerId());
60 streamProxyService.zlmServerOffline(event.getMediaServerId()); 55 streamProxyService.zlmServerOffline(event.getMediaServerId());
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
@@ -3,56 +3,111 @@ package com.genersoft.iot.vmp.service; @@ -3,56 +3,111 @@ package com.genersoft.iot.vmp.service;
3 import com.genersoft.iot.vmp.gb28181.bean.Device; 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; 4 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
5 5
  6 +import java.util.List;
  7 +
6 /** 8 /**
7 * 设备相关业务处理 9 * 设备相关业务处理
  10 + * @author lin
8 */ 11 */
9 public interface IDeviceService { 12 public interface IDeviceService {
10 13
11 /** 14 /**
  15 + * 设备上线
  16 + * @param device 设备信息
  17 + */
  18 + void online(Device device);
  19 +
  20 + /**
  21 + * 设备下线
  22 + * @param deviceId 设备编号
  23 + */
  24 + void offline(String deviceId);
  25 +
  26 + /**
12 * 添加目录订阅 27 * 添加目录订阅
13 * @param device 设备信息 28 * @param device 设备信息
14 - * @return 29 + * @return 布尔
15 */ 30 */
16 boolean addCatalogSubscribe(Device device); 31 boolean addCatalogSubscribe(Device device);
17 32
18 /** 33 /**
19 * 移除目录订阅 34 * 移除目录订阅
20 * @param device 设备信息 35 * @param device 设备信息
21 - * @return 36 + * @return 布尔
22 */ 37 */
23 boolean removeCatalogSubscribe(Device device); 38 boolean removeCatalogSubscribe(Device device);
24 39
25 /** 40 /**
26 * 添加移动位置订阅 41 * 添加移动位置订阅
27 * @param device 设备信息 42 * @param device 设备信息
28 - * @return 43 + * @return 布尔
29 */ 44 */
30 boolean addMobilePositionSubscribe(Device device); 45 boolean addMobilePositionSubscribe(Device device);
31 46
32 /** 47 /**
33 * 移除移动位置订阅 48 * 移除移动位置订阅
34 * @param device 设备信息 49 * @param device 设备信息
35 - * @return 50 + * @return 布尔
36 */ 51 */
37 boolean removeMobilePositionSubscribe(Device device); 52 boolean removeMobilePositionSubscribe(Device device);
38 53
39 /** 54 /**
40 * 移除移动位置订阅 55 * 移除移动位置订阅
41 * @param deviceId 设备ID 56 * @param deviceId 设备ID
42 - * @return 57 + * @return 同步状态
43 */ 58 */
44 SyncStatus getChannelSyncStatus(String deviceId); 59 SyncStatus getChannelSyncStatus(String deviceId);
45 60
46 /** 61 /**
47 * 查看是否仍在同步 62 * 查看是否仍在同步
48 * @param deviceId 设备ID 63 * @param deviceId 设备ID
49 - * @return 64 + * @return 布尔
50 */ 65 */
51 Boolean isSyncRunning(String deviceId); 66 Boolean isSyncRunning(String deviceId);
52 67
53 /** 68 /**
54 * 通道同步 69 * 通道同步
55 - * @param device 70 + * @param device 设备信息
56 */ 71 */
57 void sync(Device device); 72 void sync(Device device);
  73 +
  74 + /**
  75 + * 查询设备信息
  76 + * @param deviceId 设备编号
  77 + * @return 设备信息
  78 + */
  79 + Device queryDevice(String deviceId);
  80 +
  81 + /**
  82 + * 获取所有在线设备
  83 + * @return 设备列表
  84 + */
  85 + List<Device> getAllOnlineDevice();
  86 +
  87 + /**
  88 + * 判断是否注册已经失效
  89 + * @param device 设备信息
  90 + * @return 布尔
  91 + */
  92 + boolean expire(Device device);
  93 +
  94 + /**
  95 + * 检查设备状态
  96 + * @param device 设备信息
  97 + */
  98 + void checkDeviceStatus(Device device);
  99 +
  100 + /**
  101 + * 根据IP和端口获取设备信息
  102 + * @param host IP
  103 + * @param port 端口
  104 + * @return 设备信息
  105 + */
  106 + Device getDeviceByHostAndPort(String host, int port);
  107 +
  108 + /**
  109 + * 更新设备
  110 + * @param device 设备信息
  111 + */
  112 + void updateDevice(Device device);
58 } 113 }
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -44,7 +44,7 @@ public interface IMediaServerService { @@ -44,7 +44,7 @@ public interface IMediaServerService {
44 44
45 void updateVmServer(List<MediaServerItem> mediaServerItemList); 45 void updateVmServer(List<MediaServerItem> mediaServerItemList);
46 46
47 - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck); 47 + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback);
48 48
49 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback); 49 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
50 50
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -2,21 +2,27 @@ package com.genersoft.iot.vmp.service.impl; @@ -2,21 +2,27 @@ package com.genersoft.iot.vmp.service.impl;
2 2
3 import com.genersoft.iot.vmp.conf.DynamicTask; 3 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
  6 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
6 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; 8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
7 import com.genersoft.iot.vmp.service.IDeviceService; 9 import com.genersoft.iot.vmp.service.IDeviceService;
8 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; 10 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
9 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; 11 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
10 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; 12 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
  13 +import com.genersoft.iot.vmp.service.IMediaServerService;
11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  15 +import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
  16 +import com.genersoft.iot.vmp.utils.DateUtil;
12 import org.slf4j.Logger; 17 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
14 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
15 -import org.springframework.beans.factory.annotation.Qualifier;  
16 -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  
17 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.util.StringUtils;
18 22
19 -import javax.sip.DialogState; 23 +import java.time.Instant;
  24 +import java.util.List;
  25 +import java.util.concurrent.TimeUnit;
20 26
21 /** 27 /**
22 * 设备业务(目录订阅) 28 * 设备业务(目录订阅)
@@ -26,6 +32,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -26,6 +32,8 @@ public class DeviceServiceImpl implements IDeviceService {
26 32
27 private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class); 33 private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);
28 34
  35 + private final String registerExpireTaskKeyPrefix = "device-register-expire-";
  36 +
29 @Autowired 37 @Autowired
30 private DynamicTask dynamicTask; 38 private DynamicTask dynamicTask;
31 39
@@ -38,6 +46,83 @@ public class DeviceServiceImpl implements IDeviceService { @@ -38,6 +46,83 @@ public class DeviceServiceImpl implements IDeviceService {
38 @Autowired 46 @Autowired
39 private IRedisCatchStorage redisCatchStorage; 47 private IRedisCatchStorage redisCatchStorage;
40 48
  49 + @Autowired
  50 + private DeviceMapper deviceMapper;
  51 +
  52 + @Autowired
  53 + private ISIPCommander commander;
  54 +
  55 + @Autowired
  56 + private VideoStreamSessionManager streamSession;
  57 +
  58 + @Autowired
  59 + private IMediaServerService mediaServerService;
  60 +
  61 + @Override
  62 + public void online(Device device) {
  63 + logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort());
  64 + Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId());
  65 + Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId());
  66 +
  67 + String now = DateUtil.getNow();
  68 + if (deviceInRedis != null && deviceInDb == null) {
  69 + // redis 存在脏数据
  70 + redisCatchStorage.clearCatchByDeviceId(device.getDeviceId());
  71 +
  72 + }
  73 + device.setUpdateTime(now);
  74 + device.setOnline(1);
  75 +
  76 + // 第一次上线
  77 + if (device.getCreateTime() == null) {
  78 + device.setCreateTime(now);
  79 + logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
  80 + commander.deviceInfoQuery(device);
  81 + sync(device);
  82 + deviceMapper.add(device);
  83 + }else {
  84 + deviceMapper.update(device);
  85 + }
  86 + redisCatchStorage.updateDevice(device);
  87 + // 上线添加订阅
  88 + if (device.getSubscribeCycleForCatalog() > 0) {
  89 + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
  90 + addCatalogSubscribe(device);
  91 + }
  92 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  93 + addMobilePositionSubscribe(device);
  94 + }
  95 + // 刷新过期任务
  96 + String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId();
  97 + dynamicTask.stop(registerExpireTaskKey);
  98 + dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000);
  99 + }
  100 +
  101 + @Override
  102 + public void offline(String deviceId) {
  103 + Device device = deviceMapper.getDeviceByDeviceId(deviceId);
  104 + if (device == null) {
  105 + return;
  106 + }
  107 + String registerExpireTaskKey = registerExpireTaskKeyPrefix + deviceId;
  108 + dynamicTask.stop(registerExpireTaskKey);
  109 + device.setOnline(0);
  110 + redisCatchStorage.updateDevice(device);
  111 + deviceMapper.update(device);
  112 + // 离线释放所有ssrc
  113 + List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null);
  114 + if (ssrcTransactions != null && ssrcTransactions.size() > 0) {
  115 + for (SsrcTransaction ssrcTransaction : ssrcTransactions) {
  116 + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
  117 + mediaServerService.closeRTPServer(deviceId, ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
  118 + streamSession.remove(deviceId, ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
  119 + }
  120 + }
  121 + // 移除订阅
  122 + removeCatalogSubscribe(device);
  123 + removeMobilePositionSubscribe(device);
  124 + }
  125 +
41 @Override 126 @Override
42 public boolean addCatalogSubscribe(Device device) { 127 public boolean addCatalogSubscribe(Device device) {
43 if (device == null || device.getSubscribeCycleForCatalog() < 0) { 128 if (device == null || device.getSubscribeCycleForCatalog() < 0) {
@@ -49,7 +134,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -49,7 +134,7 @@ public class DeviceServiceImpl implements IDeviceService {
49 // 提前开始刷新订阅 134 // 提前开始刷新订阅
50 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30); 135 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
51 // 设置最小值为30 136 // 设置最小值为30
52 - dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog -1); 137 + dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000);
53 return true; 138 return true;
54 } 139 }
55 140
@@ -74,7 +159,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -74,7 +159,7 @@ public class DeviceServiceImpl implements IDeviceService {
74 // 设置最小值为30 159 // 设置最小值为30
75 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30); 160 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
76 // 提前开始刷新订阅 161 // 提前开始刷新订阅
77 - dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 ); 162 + dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog -1 ) * 1000);
78 return true; 163 return true;
79 } 164 }
80 165
@@ -111,4 +196,92 @@ public class DeviceServiceImpl implements IDeviceService { @@ -111,4 +196,92 @@ public class DeviceServiceImpl implements IDeviceService {
111 catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg); 196 catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
112 }); 197 });
113 } 198 }
  199 +
  200 + @Override
  201 + public Device queryDevice(String deviceId) {
  202 + return deviceMapper.getDeviceByDeviceId(deviceId);
  203 + }
  204 +
  205 + @Override
  206 + public List<Device> getAllOnlineDevice() {
  207 + return deviceMapper.getOnlineDevices();
  208 + }
  209 +
  210 + @Override
  211 + public boolean expire(Device device) {
  212 + Instant registerTimeDate = Instant.from(DateUtil.formatter.parse(device.getRegisterTime()));
  213 + Instant expireInstant = registerTimeDate.plusMillis(TimeUnit.SECONDS.toMillis(device.getExpires()));
  214 + return expireInstant.isBefore(Instant.now());
  215 + }
  216 +
  217 + @Override
  218 + public void checkDeviceStatus(Device device) {
  219 + if (device == null || device.getOnline() == 0) {
  220 + return;
  221 + }
  222 + sipCommander.deviceStatusQuery(device, null);
  223 +
  224 + }
  225 +
  226 + @Override
  227 + public Device getDeviceByHostAndPort(String host, int port) {
  228 + return deviceMapper.getDeviceByHostAndPort(host, port);
  229 + }
  230 +
  231 + @Override
  232 + public void updateDevice(Device device) {
  233 +
  234 + Device deviceInStore = deviceMapper.getDeviceByDeviceId(device.getDeviceId());
  235 + if (deviceInStore == null) {
  236 + logger.warn("更新设备时未找到设备信息");
  237 + return;
  238 + }
  239 + if (!StringUtils.isEmpty(device.getName())) {
  240 + deviceInStore.setName(device.getName());
  241 + }
  242 + if (!StringUtils.isEmpty(device.getCharset())) {
  243 + deviceInStore.setCharset(device.getCharset());
  244 + }
  245 + if (!StringUtils.isEmpty(device.getMediaServerId())) {
  246 + deviceInStore.setMediaServerId(device.getMediaServerId());
  247 + }
  248 +
  249 + // 目录订阅相关的信息
  250 + if (device.getSubscribeCycleForCatalog() > 0) {
  251 + if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
  252 + deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
  253 + // 开启订阅
  254 + addCatalogSubscribe(deviceInStore);
  255 + }
  256 + }else if (device.getSubscribeCycleForCatalog() == 0) {
  257 + if (deviceInStore.getSubscribeCycleForCatalog() != 0) {
  258 + deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
  259 + // 取消订阅
  260 + removeCatalogSubscribe(deviceInStore);
  261 + }
  262 + }
  263 +
  264 + // 移动位置订阅相关的信息
  265 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  266 + if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {
  267 + deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());
  268 + deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());
  269 + // 开启订阅
  270 + addMobilePositionSubscribe(deviceInStore);
  271 + }
  272 + }else if (device.getSubscribeCycleForMobilePosition() == 0) {
  273 + if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {
  274 + // 取消订阅
  275 + removeMobilePositionSubscribe(deviceInStore);
  276 + }
  277 + }
  278 +
  279 + String now = DateUtil.getNow();
  280 + device.setUpdateTime(now);
  281 + device.setCharset(device.getCharset().toUpperCase());
  282 + device.setUpdateTime(DateUtil.getNow());
  283 + if (deviceMapper.update(device) > 0) {
  284 + redisCatchStorage.updateDevice(device);
  285 + }
  286 + }
114 } 287 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -18,6 +18,7 @@ import com.genersoft.iot.vmp.service.IStreamProxyService; @@ -18,6 +18,7 @@ import com.genersoft.iot.vmp.service.IStreamProxyService;
18 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 18 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; 20 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
  21 +import com.genersoft.iot.vmp.utils.DateUtil;
21 import com.genersoft.iot.vmp.utils.redis.JedisUtil; 22 import com.genersoft.iot.vmp.utils.redis.JedisUtil;
22 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 23 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
23 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 24 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
@@ -89,14 +90,12 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -89,14 +90,12 @@ public class MediaServerServiceImpl implements IMediaServerService {
89 @Autowired 90 @Autowired
90 JedisUtil jedisUtil; 91 JedisUtil jedisUtil;
91 92
92 - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
93 -  
94 /** 93 /**
95 * 初始化 94 * 初始化
96 */ 95 */
97 @Override 96 @Override
98 public void updateVmServer(List<MediaServerItem> mediaServerItemList) { 97 public void updateVmServer(List<MediaServerItem> mediaServerItemList) {
99 - logger.info("[缓存初始化] Media Server "); 98 + logger.info("[zlm] 缓存初始化 ");
100 for (MediaServerItem mediaServerItem : mediaServerItemList) { 99 for (MediaServerItem mediaServerItem : mediaServerItemList) {
101 if (StringUtils.isEmpty(mediaServerItem.getId())) { 100 if (StringUtils.isEmpty(mediaServerItem.getId())) {
102 continue; 101 continue;
@@ -117,8 +116,8 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -117,8 +116,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
117 } 116 }
118 117
119 @Override 118 @Override
120 - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck) {  
121 - return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,false); 119 + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) {
  120 + return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,isPlayback);
122 } 121 }
123 122
124 @Override 123 @Override
@@ -231,7 +230,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -231,7 +230,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
231 result.sort((serverItem1, serverItem2)->{ 230 result.sort((serverItem1, serverItem2)->{
232 int sortResult = 0; 231 int sortResult = 0;
233 try { 232 try {
234 - sortResult = format.parse(serverItem1.getCreateTime()).compareTo(format.parse(serverItem2.getCreateTime())); 233 + sortResult = DateUtil.format.parse(serverItem1.getCreateTime()).compareTo(DateUtil.format.parse(serverItem2.getCreateTime()));
235 } catch (ParseException e) { 234 } catch (ParseException e) {
236 e.printStackTrace(); 235 e.printStackTrace();
237 } 236 }
@@ -291,8 +290,8 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -291,8 +290,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
291 @Override 290 @Override
292 public WVPResult<String> add(MediaServerItem mediaServerItem) { 291 public WVPResult<String> add(MediaServerItem mediaServerItem) {
293 WVPResult<String> result = new WVPResult<>(); 292 WVPResult<String> result = new WVPResult<>();
294 - mediaServerItem.setCreateTime(this.format.format(System.currentTimeMillis()));  
295 - mediaServerItem.setUpdateTime(this.format.format(System.currentTimeMillis())); 293 + mediaServerItem.setCreateTime(DateUtil.getNow());
  294 + mediaServerItem.setUpdateTime(DateUtil.getNow());
296 mediaServerItem.setHookAliveInterval(120); 295 mediaServerItem.setHookAliveInterval(120);
297 JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); 296 JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
298 if (responseJSON != null) { 297 if (responseJSON != null) {
@@ -353,7 +352,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -353,7 +352,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
353 */ 352 */
354 @Override 353 @Override
355 public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { 354 public void zlmServerOnline(ZLMServerConfig zlmServerConfig) {
356 - logger.info("[ ZLM:{} ]-[ {}:{} ]正在连接", 355 + logger.info("[ZLM] 正在连接 : {} -> {}:{}",
357 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); 356 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
358 357
359 MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); 358 MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
@@ -406,7 +405,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -406,7 +405,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
406 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); 405 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
407 } 406 }
408 publisher.zlmOnlineEventPublish(serverItem.getId()); 407 publisher.zlmOnlineEventPublish(serverItem.getId());
409 - logger.info("[ ZLM:{} ]-[ {}:{} ]连接成功", 408 + logger.info("[ZLM] 连接成功 {} - {}:{} ",
410 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); 409 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
411 } 410 }
412 411
@@ -484,7 +483,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -484,7 +483,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
484 */ 483 */
485 @Override 484 @Override
486 public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { 485 public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) {
487 - logger.info("[ ZLM:{} ]-[ {}:{} ]正在设置zlm", 486 + logger.info("[ZLM] 正在设置 :{} -> {}:{}",
488 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); 487 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
489 String protocol = sslEnabled ? "https" : "http"; 488 String protocol = sslEnabled ? "https" : "http";
490 String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); 489 String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
@@ -528,17 +527,17 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -528,17 +527,17 @@ public class MediaServerServiceImpl implements IMediaServerService {
528 527
529 if (responseJSON != null && responseJSON.getInteger("code") == 0) { 528 if (responseJSON != null && responseJSON.getInteger("code") == 0) {
530 if (restart) { 529 if (restart) {
531 - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm成功, 开始重启以保证配置生效", 530 + logger.info("[ZLM] 设置成功,开始重启以保证配置生效 {} -> {}:{}",
532 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); 531 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
533 zlmresTfulUtils.restartServer(mediaServerItem); 532 zlmresTfulUtils.restartServer(mediaServerItem);
534 }else { 533 }else {
535 - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm成功", 534 + logger.info("[ZLM] 设置成功 {} -> {}:{}",
536 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); 535 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
537 } 536 }
538 537
539 538
540 }else { 539 }else {
541 - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm失败", 540 + logger.info("[ZLM] 设置zlm失败 {} -> {}:{}",
542 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); 541 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
543 } 542 }
544 543
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
16 -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; 16 +import com.genersoft.iot.vmp.utils.DateUtil;
17 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; 17 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
18 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 18 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
19 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 19 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
@@ -190,7 +190,7 @@ public class PlayServiceImpl implements IPlayService { @@ -190,7 +190,7 @@ public class PlayServiceImpl implements IPlayService {
190 if (mediaServerItem.isRtpEnable()) { 190 if (mediaServerItem.isRtpEnable()) {
191 streamId = String.format("%s_%s", device.getDeviceId(), channelId); 191 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
192 } 192 }
193 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck()); 193 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false);
194 play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{ 194 play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{
195 if (hookEvent != null) { 195 if (hookEvent != null) {
196 hookEvent.response(mediaServerItem, response); 196 hookEvent.response(mediaServerItem, response);
@@ -234,7 +234,7 @@ public class PlayServiceImpl implements IPlayService { @@ -234,7 +234,7 @@ public class PlayServiceImpl implements IPlayService {
234 streamId = String.format("%s_%s", device.getDeviceId(), channelId); 234 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
235 } 235 }
236 if (ssrcInfo == null) { 236 if (ssrcInfo == null) {
237 - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck()); 237 + ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false);
238 } 238 }
239 239
240 // 超时处理 240 // 超时处理
@@ -357,7 +357,7 @@ public class PlayServiceImpl implements IPlayService { @@ -357,7 +357,7 @@ public class PlayServiceImpl implements IPlayService {
357 return null; 357 return null;
358 } 358 }
359 MediaServerItem newMediaServerItem = getNewMediaServerItem(device); 359 MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
360 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); 360 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true, true);
361 361
362 return playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); 362 return playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback);
363 } 363 }
@@ -444,7 +444,7 @@ public class PlayServiceImpl implements IPlayService { @@ -444,7 +444,7 @@ public class PlayServiceImpl implements IPlayService {
444 return null; 444 return null;
445 } 445 }
446 MediaServerItem newMediaServerItem = getNewMediaServerItem(device); 446 MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
447 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); 447 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true, true);
448 448
449 return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed,infoCallBack, hookCallBack); 449 return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed,infoCallBack, hookCallBack);
450 } 450 }
src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java
@@ -4,20 +4,15 @@ import com.alibaba.fastjson.JSON; @@ -4,20 +4,15 @@ import com.alibaba.fastjson.JSON;
4 import com.genersoft.iot.vmp.gb28181.bean.*; 4 import com.genersoft.iot.vmp.gb28181.bean.*;
5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
7 -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;  
8 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
9 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 8 +import com.genersoft.iot.vmp.utils.DateUtil;
11 import org.slf4j.Logger; 9 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
13 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
14 import org.springframework.data.redis.connection.Message; 12 import org.springframework.data.redis.connection.Message;
15 import org.springframework.data.redis.connection.MessageListener; 13 import org.springframework.data.redis.connection.MessageListener;
16 -import org.springframework.http.HttpStatus;  
17 -import org.springframework.http.ResponseEntity;  
18 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
19 15
20 -import java.text.SimpleDateFormat;  
21 16
22 @Component 17 @Component
23 public class RedisAlarmMsgListener implements MessageListener { 18 public class RedisAlarmMsgListener implements MessageListener {
@@ -33,8 +28,6 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -33,8 +28,6 @@ public class RedisAlarmMsgListener implements MessageListener {
33 @Autowired 28 @Autowired
34 private IVideoManagerStorage storage; 29 private IVideoManagerStorage storage;
35 30
36 - private final SimpleDateFormat formatForGB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");  
37 -  
38 @Override 31 @Override
39 public void onMessage(Message message, byte[] bytes) { 32 public void onMessage(Message message, byte[] bytes) {
40 logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); 33 logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody()));
@@ -52,7 +45,7 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -52,7 +45,7 @@ public class RedisAlarmMsgListener implements MessageListener {
52 deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); 45 deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
53 deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); 46 deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
54 deviceAlarm.setAlarmPriority("1"); 47 deviceAlarm.setAlarmPriority("1");
55 - deviceAlarm.setAlarmTime(formatForGB.format(System.currentTimeMillis())); 48 + deviceAlarm.setAlarmTime(DateUtil.getNow());
56 deviceAlarm.setAlarmType("1"); 49 deviceAlarm.setAlarmType("1");
57 deviceAlarm.setLongitude(0); 50 deviceAlarm.setLongitude(0);
58 deviceAlarm.setLatitude(0); 51 deviceAlarm.setLatitude(0);
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -112,23 +112,6 @@ public interface IRedisCatchStorage { @@ -112,23 +112,6 @@ public interface IRedisCatchStorage {
112 void clearCatchByDeviceId(String deviceId); 112 void clearCatchByDeviceId(String deviceId);
113 113
114 /** 114 /**
115 - * 获取mediaServer节点  
116 - * @param mediaServerId  
117 - * @return  
118 - */  
119 -// MediaServerItem getMediaInfo(String mediaServerId);  
120 -  
121 - /**  
122 - * 设置所有设备离线  
123 - */  
124 - void outlineForAll();  
125 -  
126 - /**  
127 - * 获取所有在线的  
128 - */  
129 - List<String> getOnlineForAll();  
130 -  
131 - /**  
132 * 在redis添加wvp的信息 115 * 在redis添加wvp的信息
133 */ 116 */
134 void updateWVPInfo(JSONObject jsonObject, int time); 117 void updateWVPInfo(JSONObject jsonObject, int time);
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
@@ -25,22 +25,6 @@ public interface IVideoManagerStorage { @@ -25,22 +25,6 @@ public interface IVideoManagerStorage {
25 * @return true:存在 false:不存在 25 * @return true:存在 false:不存在
26 */ 26 */
27 public boolean exists(String deviceId); 27 public boolean exists(String deviceId);
28 -  
29 - /**  
30 - * 视频设备创建  
31 - *  
32 - * @param device 设备对象  
33 - * @return true:创建成功 false:创建失败  
34 - */  
35 - public boolean create(Device device);  
36 -  
37 - /**  
38 - * 视频设备更新  
39 - *  
40 - * @param device 设备对象  
41 - * @return true:创建成功 false:创建失败  
42 - */  
43 - public boolean updateDevice(Device device);  
44 28
45 /** 29 /**
46 * 添加设备通道 30 * 添加设备通道
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -257,4 +257,8 @@ public interface DeviceChannelMapper { @@ -257,4 +257,8 @@ public interface DeviceChannelMapper {
257 257
258 @Update(value = {"UPDATE device_channel SET latitude=${latitude}, longitude=${longitude} WHERE deviceId=#{deviceId} AND channelId=#{channelId}"}) 258 @Update(value = {"UPDATE device_channel SET latitude=${latitude}, longitude=${longitude} WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})
259 void updatePotion(String deviceId, String channelId, double longitude, double latitude); 259 void updatePotion(String deviceId, String channelId, double longitude, double latitude);
  260 +
  261 + @Select("SELECT * FROM device_channel WHERE length(trim(streamId)) > 0")
  262 + List<DeviceChannel> getAllChannelInPlay();
  263 +
260 } 264 }
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -99,4 +99,9 @@ public interface DeviceMapper { @@ -99,4 +99,9 @@ public interface DeviceMapper {
99 99
100 @Update("UPDATE device SET online=0") 100 @Update("UPDATE device SET online=0")
101 int outlineForAll(); 101 int outlineForAll();
  102 +
  103 + @Select("SELECT * FROM device WHERE online = 1")
  104 + List<Device> getOnlineDevices();
  105 + @Select("SELECT * FROM device WHERE ip = #{host} AND port=${port}")
  106 + Device getDeviceByHostAndPort(String host, int port);
102 } 107 }
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -14,13 +14,13 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -14,13 +14,13 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
14 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; 14 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; 16 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
  17 +import com.genersoft.iot.vmp.utils.DateUtil;
17 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 18 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
18 import org.slf4j.Logger; 19 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
20 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
21 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
22 23
23 -import java.text.SimpleDateFormat;  
24 import java.util.*; 24 import java.util.*;
25 25
26 @SuppressWarnings("rawtypes") 26 @SuppressWarnings("rawtypes")
@@ -38,8 +38,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -38,8 +38,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
38 @Autowired 38 @Autowired
39 private UserSetting userSetting; 39 private UserSetting userSetting;
40 40
41 - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
42 -  
43 @Override 41 @Override
44 public Long getCSEQ(String method) { 42 public Long getCSEQ(String method) {
45 String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId() + "_" + method; 43 String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId() + "_" + method;
@@ -470,26 +468,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -470,26 +468,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
470 } 468 }
471 469
472 @Override 470 @Override
473 - public void outlineForAll() {  
474 - List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + "*" );  
475 - for (int i = 0; i < onlineDevices.size(); i++) {  
476 - String key = (String) onlineDevices.get(i);  
477 - redis.del(key);  
478 - }  
479 - }  
480 -  
481 - @Override  
482 - public List<String> getOnlineForAll() {  
483 - List<String> result = new ArrayList<>();  
484 - List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + "*" );  
485 - for (int i = 0; i < onlineDevices.size(); i++) {  
486 - String key = (String) onlineDevices.get(i);  
487 - result.add((String) redis.get(key));  
488 - }  
489 - return result;  
490 - }  
491 -  
492 - @Override  
493 public void updateWVPInfo(JSONObject jsonObject, int time) { 471 public void updateWVPInfo(JSONObject jsonObject, int time) {
494 String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId(); 472 String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId();
495 redis.set(key, jsonObject, time); 473 redis.set(key, jsonObject, time);
@@ -638,7 +616,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -638,7 +616,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
638 public void addCpuInfo(double cpuInfo) { 616 public void addCpuInfo(double cpuInfo) {
639 String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId(); 617 String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId();
640 SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>(); 618 SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>();
641 - systemInfoDto.setTime(format.format(System.currentTimeMillis())); 619 + systemInfoDto.setTime(DateUtil.getNow());
642 systemInfoDto.setData(cpuInfo); 620 systemInfoDto.setData(cpuInfo);
643 redis.lSet(key, systemInfoDto); 621 redis.lSet(key, systemInfoDto);
644 // 每秒一个,最多只存30个 622 // 每秒一个,最多只存30个
@@ -653,7 +631,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -653,7 +631,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
653 public void addMemInfo(double memInfo) { 631 public void addMemInfo(double memInfo) {
654 String key = VideoManagerConstants.SYSTEM_INFO_MEM_PREFIX + userSetting.getServerId(); 632 String key = VideoManagerConstants.SYSTEM_INFO_MEM_PREFIX + userSetting.getServerId();
655 SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>(); 633 SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>();
656 - systemInfoDto.setTime(format.format(System.currentTimeMillis())); 634 + systemInfoDto.setTime(DateUtil.getNow());
657 systemInfoDto.setData(memInfo); 635 systemInfoDto.setData(memInfo);
658 redis.lSet(key, systemInfoDto); 636 redis.lSet(key, systemInfoDto);
659 // 每秒一个,最多只存30个 637 // 每秒一个,最多只存30个
@@ -668,7 +646,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -668,7 +646,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
668 public void addNetInfo(Map<String, String> networkInterfaces) { 646 public void addNetInfo(Map<String, String> networkInterfaces) {
669 String key = VideoManagerConstants.SYSTEM_INFO_NET_PREFIX + userSetting.getServerId(); 647 String key = VideoManagerConstants.SYSTEM_INFO_NET_PREFIX + userSetting.getServerId();
670 SystemInfoDto<Map<String, String>> systemInfoDto = new SystemInfoDto<>(); 648 SystemInfoDto<Map<String, String>> systemInfoDto = new SystemInfoDto<>();
671 - systemInfoDto.setTime(format.format(System.currentTimeMillis())); 649 + systemInfoDto.setTime(DateUtil.getNow());
672 systemInfoDto.setData(networkInterfaces); 650 systemInfoDto.setData(networkInterfaces);
673 redis.lSet(key, systemInfoDto); 651 redis.lSet(key, systemInfoDto);
674 // 每秒一个,最多只存30个 652 // 每秒一个,最多只存30个
@@ -702,7 +680,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -702,7 +680,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
702 680
703 @Override 681 @Override
704 public boolean deviceIsOnline(String deviceId) { 682 public boolean deviceIsOnline(String deviceId) {
705 - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + deviceId;  
706 - return redis.hasKey(key); 683 + return getDevice(deviceId).getOnline() == 1;
707 } 684 }
708 } 685 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 import com.genersoft.iot.vmp.storager.dao.*; 14 import com.genersoft.iot.vmp.storager.dao.*;
15 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; 15 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
  16 +import com.genersoft.iot.vmp.utils.DateUtil;
16 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; 17 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
17 import com.github.pagehelper.PageHelper; 18 import com.github.pagehelper.PageHelper;
18 import com.github.pagehelper.PageInfo; 19 import com.github.pagehelper.PageInfo;
@@ -26,8 +27,8 @@ import org.springframework.transaction.TransactionStatus; @@ -26,8 +27,8 @@ import org.springframework.transaction.TransactionStatus;
26 import org.springframework.transaction.annotation.Transactional; 27 import org.springframework.transaction.annotation.Transactional;
27 import org.springframework.util.StringUtils; 28 import org.springframework.util.StringUtils;
28 29
29 -import java.text.SimpleDateFormat;  
30 import java.util.*; 30 import java.util.*;
  31 +import java.util.concurrent.ConcurrentHashMap;
31 32
32 /** 33 /**
33 * 视频设备数据存储-jdbc实现 34 * 视频设备数据存储-jdbc实现
@@ -91,9 +92,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -91,9 +92,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
91 @Autowired 92 @Autowired
92 private ParentPlatformMapper parentPlatformMapper; 93 private ParentPlatformMapper parentPlatformMapper;
93 94
94 - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
95 -  
96 -  
97 /** 95 /**
98 * 根据设备ID判断设备是否存在 96 * 根据设备ID判断设备是否存在
99 * 97 *
@@ -105,45 +103,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -105,45 +103,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
105 return deviceMapper.getDeviceByDeviceId(deviceId) != null; 103 return deviceMapper.getDeviceByDeviceId(deviceId) != null;
106 } 104 }
107 105
108 - /**  
109 - * 视频设备创建  
110 - *  
111 - * @param device 设备对象  
112 - * @return true:创建成功 false:创建失败  
113 - */  
114 - @Override  
115 - public synchronized boolean create(Device device) {  
116 - redisCatchStorage.updateDevice(device);  
117 - return deviceMapper.add(device) > 0;  
118 - }  
119 -  
120 -  
121 -  
122 - /**  
123 - * 视频设备更新  
124 - *  
125 - * @param device 设备对象  
126 - * @return true:更新成功 false:更新失败  
127 - */  
128 - @Override  
129 - public synchronized boolean updateDevice(Device device) {  
130 - String now = this.format.format(System.currentTimeMillis());  
131 - device.setUpdateTime(now);  
132 - Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId());  
133 - device.setCharset(device.getCharset().toUpperCase());  
134 - if (deviceByDeviceId == null) {  
135 - device.setCreateTime(now);  
136 - redisCatchStorage.updateDevice(device);  
137 - return deviceMapper.add(device) > 0;  
138 - }else {  
139 - redisCatchStorage.updateDevice(device);  
140 -  
141 - return deviceMapper.update(device) > 0;  
142 - }  
143 -  
144 -  
145 - }  
146 -  
147 @Override 106 @Override
148 public synchronized void updateChannel(String deviceId, DeviceChannel channel) { 107 public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
149 String channelId = channel.getChannelId(); 108 String channelId = channel.getChannelId();
@@ -152,7 +111,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -152,7 +111,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
152 if (streamInfo != null) { 111 if (streamInfo != null) {
153 channel.setStreamId(streamInfo.getStream()); 112 channel.setStreamId(streamInfo.getStream());
154 } 113 }
155 - String now = this.format.format(System.currentTimeMillis()); 114 + String now = DateUtil.getNow();
156 channel.setUpdateTime(now); 115 channel.setUpdateTime(now);
157 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); 116 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
158 if (deviceChannel == null) { 117 if (deviceChannel == null) {
@@ -178,7 +137,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -178,7 +137,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
178 if (streamInfo != null) { 137 if (streamInfo != null) {
179 channel.setStreamId(streamInfo.getStream()); 138 channel.setStreamId(streamInfo.getStream());
180 } 139 }
181 - String now = this.format.format(System.currentTimeMillis()); 140 + String now = DateUtil.getNow();
182 channel.setUpdateTime(now); 141 channel.setUpdateTime(now);
183 channel.setCreateTime(now); 142 channel.setCreateTime(now);
184 addChannels.add(channel); 143 addChannels.add(channel);
@@ -193,7 +152,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -193,7 +152,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
193 if (streamInfo != null) { 152 if (streamInfo != null) {
194 channel.setStreamId(streamInfo.getStream()); 153 channel.setStreamId(streamInfo.getStream());
195 } 154 }
196 - String now = this.format.format(System.currentTimeMillis()); 155 + String now = DateUtil.getNow();
197 channel.setUpdateTime(now); 156 channel.setUpdateTime(now);
198 if (channelsInStore.get(channel.getChannelId()) != null) { 157 if (channelsInStore.get(channel.getChannelId()) != null) {
199 updateChannels.add(channel); 158 updateChannels.add(channel);
@@ -239,17 +198,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -239,17 +198,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
239 if (deviceChannelList == null) { 198 if (deviceChannelList == null) {
240 return false; 199 return false;
241 } 200 }
  201 + List<DeviceChannel> allChannelInPlay = deviceChannelMapper.getAllChannelInPlay();
  202 + Map<String,DeviceChannel> allChannelMapInPlay = new ConcurrentHashMap<>();
  203 + if (allChannelInPlay.size() > 0) {
  204 + for (DeviceChannel deviceChannel : allChannelInPlay) {
  205 + allChannelMapInPlay.put(deviceChannel.getChannelId(), deviceChannel);
  206 + }
  207 + }
242 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); 208 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
243 // 数据去重 209 // 数据去重
244 List<DeviceChannel> channels = new ArrayList<>(); 210 List<DeviceChannel> channels = new ArrayList<>();
245 StringBuilder stringBuilder = new StringBuilder(); 211 StringBuilder stringBuilder = new StringBuilder();
246 Map<String, Integer> subContMap = new HashMap<>(); 212 Map<String, Integer> subContMap = new HashMap<>();
247 - if (deviceChannelList != null && deviceChannelList.size() > 1) { 213 + if (deviceChannelList.size() > 1) {
248 // 数据去重 214 // 数据去重
249 Set<String> gbIdSet = new HashSet<>(); 215 Set<String> gbIdSet = new HashSet<>();
250 for (DeviceChannel deviceChannel : deviceChannelList) { 216 for (DeviceChannel deviceChannel : deviceChannelList) {
251 if (!gbIdSet.contains(deviceChannel.getChannelId())) { 217 if (!gbIdSet.contains(deviceChannel.getChannelId())) {
252 gbIdSet.add(deviceChannel.getChannelId()); 218 gbIdSet.add(deviceChannel.getChannelId());
  219 + if (allChannelMapInPlay.containsKey(deviceChannel.getChannelId())) {
  220 + deviceChannel.setStreamId(allChannelMapInPlay.get(deviceChannel.getChannelId()).getStreamId());
  221 + }
253 channels.add(deviceChannel); 222 channels.add(deviceChannel);
254 if (!StringUtils.isEmpty(deviceChannel.getParentId())) { 223 if (!StringUtils.isEmpty(deviceChannel.getParentId())) {
255 if (subContMap.get(deviceChannel.getParentId()) == null) { 224 if (subContMap.get(deviceChannel.getParentId()) == null) {
@@ -732,7 +701,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -732,7 +701,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
732 boolean result = false; 701 boolean result = false;
733 streamProxyItem.setStreamType("proxy"); 702 streamProxyItem.setStreamType("proxy");
734 streamProxyItem.setStatus(true); 703 streamProxyItem.setStatus(true);
735 - String now = this.format.format(System.currentTimeMillis()); 704 + String now = DateUtil.getNow();
736 streamProxyItem.setCreateTime(now); 705 streamProxyItem.setCreateTime(now);
737 streamProxyItem.setCreateStamp(System.currentTimeMillis()); 706 streamProxyItem.setCreateStamp(System.currentTimeMillis());
738 try { 707 try {
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils;
  2 +
  3 +
  4 +import java.text.SimpleDateFormat;
  5 +import java.time.Instant;
  6 +import java.time.LocalDate;
  7 +import java.time.LocalDateTime;
  8 +import java.time.ZoneId;
  9 +import java.time.format.DateTimeFormatter;
  10 +import java.time.format.DateTimeParseException;
  11 +import java.time.temporal.TemporalAccessor;
  12 +
  13 +import java.util.Locale;
  14 +
  15 +/**
  16 + * 全局时间工具类
  17 + * @author lin
  18 + */
  19 +public class DateUtil {
  20 +
  21 + private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss";
  22 + public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
  23 +
  24 + public static final SimpleDateFormat formatISO8601 = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault());
  25 + public static final SimpleDateFormat format = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault());
  26 +
  27 + public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()).withZone(ZoneId.systemDefault());
  28 + public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()).withZone(ZoneId.systemDefault());
  29 +
  30 + public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {
  31 + return formatterISO8601.format(formatter.parse(formatTime));
  32 + }
  33 +
  34 + public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) {
  35 + return formatter.format(formatterISO8601.parse(formatTime));
  36 +
  37 + }
  38 +
  39 + public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) {
  40 + TemporalAccessor temporalAccessor = formatter.parse(formatTime);
  41 + Instant instant = Instant.from(temporalAccessor);
  42 + return instant.getEpochSecond();
  43 + }
  44 +
  45 + public static String getNow() {
  46 + LocalDateTime nowDateTime = LocalDateTime.now();
  47 + return formatter.format(nowDateTime);
  48 + }
  49 +
  50 + public static boolean verification(String timeStr, DateTimeFormatter dateTimeFormatter) {
  51 + try {
  52 + LocalDate.parse(timeStr, dateTimeFormatter);
  53 + return true;
  54 + }catch (DateTimeParseException exception) {
  55 + return false;
  56 + }
  57 + }
  58 +}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -169,7 +169,7 @@ public class MobilePositionController { @@ -169,7 +169,7 @@ public class MobilePositionController {
169 Device device = storager.queryVideoDevice(deviceId); 169 Device device = storager.queryVideoDevice(deviceId);
170 device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires)); 170 device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires));
171 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval)); 171 device.setMobilePositionSubmissionInterval(Integer.parseInt(interval));
172 - storager.updateDevice(device); 172 + deviceService.updateDevice(device);
173 String result = msg; 173 String result = msg;
174 if (deviceService.removeMobilePositionSubscribe(device)) { 174 if (deviceService.removeMobilePositionSubscribe(device)) {
175 result += ",成功"; 175 result += ",成功";
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
@@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; @@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 9 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
10 import com.genersoft.iot.vmp.service.IGbStreamService; 10 import com.genersoft.iot.vmp.service.IGbStreamService;
11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  12 +import com.genersoft.iot.vmp.utils.DateUtil;
12 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 13 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
13 import com.github.pagehelper.PageInfo; 14 import com.github.pagehelper.PageInfo;
14 import io.swagger.annotations.Api; 15 import io.swagger.annotations.Api;
@@ -23,9 +24,7 @@ import org.springframework.util.StringUtils; @@ -23,9 +24,7 @@ import org.springframework.util.StringUtils;
23 import org.springframework.web.bind.annotation.*; 24 import org.springframework.web.bind.annotation.*;
24 25
25 import java.text.ParseException; 26 import java.text.ParseException;
26 -import java.text.SimpleDateFormat;  
27 import java.util.Arrays; 27 import java.util.Arrays;
28 -import java.util.Date;  
29 import java.util.List; 28 import java.util.List;
30 29
31 @Api(tags = "报警信息管理") 30 @Api(tags = "报警信息管理")
@@ -46,9 +45,6 @@ public class AlarmController { @@ -46,9 +45,6 @@ public class AlarmController {
46 @Autowired 45 @Autowired
47 private IVideoManagerStorage storage; 46 private IVideoManagerStorage storage;
48 47
49 - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
50 - private SimpleDateFormat formatForGB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");  
51 -  
52 /** 48 /**
53 * 分页查询报警 49 * 分页查询报警
54 * 50 *
@@ -104,10 +100,10 @@ public class AlarmController { @@ -104,10 +100,10 @@ public class AlarmController {
104 100
105 try { 101 try {
106 if (startTime != null) { 102 if (startTime != null) {
107 - format.parse(startTime); 103 + DateUtil.format.parse(startTime);
108 } 104 }
109 if (endTime != null) { 105 if (endTime != null) {
110 - format.parse(endTime); 106 + DateUtil.format.parse(endTime);
111 } 107 }
112 } catch (ParseException e) { 108 } catch (ParseException e) {
113 return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); 109 return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
@@ -150,7 +146,7 @@ public class AlarmController { @@ -150,7 +146,7 @@ public class AlarmController {
150 } 146 }
151 try { 147 try {
152 if (time != null) { 148 if (time != null) {
153 - format.parse(time); 149 + DateUtil.format.parse(time);
154 } 150 }
155 } catch (ParseException e) { 151 } catch (ParseException e) {
156 return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); 152 return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
@@ -193,7 +189,7 @@ public class AlarmController { @@ -193,7 +189,7 @@ public class AlarmController {
193 deviceAlarm.setAlarmDescription("test"); 189 deviceAlarm.setAlarmDescription("test");
194 deviceAlarm.setAlarmMethod("1"); 190 deviceAlarm.setAlarmMethod("1");
195 deviceAlarm.setAlarmPriority("1"); 191 deviceAlarm.setAlarmPriority("1");
196 - deviceAlarm.setAlarmTime(formatForGB.format(System.currentTimeMillis())); 192 + deviceAlarm.setAlarmTime(DateUtil.formatISO8601.format(System.currentTimeMillis()));
197 deviceAlarm.setAlarmType("1"); 193 deviceAlarm.setAlarmType("1");
198 deviceAlarm.setLongitude(115.33333); 194 deviceAlarm.setLongitude(115.33333);
199 deviceAlarm.setLatitude(39.33333); 195 deviceAlarm.setLatitude(39.33333);
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -288,7 +288,8 @@ public class DeviceQuery { @@ -288,7 +288,8 @@ public class DeviceQuery {
288 public ResponseEntity<PageInfo> updateTransport(@PathVariable String deviceId, @PathVariable String streamMode){ 288 public ResponseEntity<PageInfo> updateTransport(@PathVariable String deviceId, @PathVariable String streamMode){
289 Device device = storager.queryVideoDevice(deviceId); 289 Device device = storager.queryVideoDevice(deviceId);
290 device.setStreamMode(streamMode); 290 device.setStreamMode(streamMode);
291 - storager.updateDevice(device); 291 +// storager.updateDevice(device);
  292 + deviceService.updateDevice(device);
292 return new ResponseEntity<>(null,HttpStatus.OK); 293 return new ResponseEntity<>(null,HttpStatus.OK);
293 } 294 }
294 295
@@ -305,51 +306,12 @@ public class DeviceQuery { @@ -305,51 +306,12 @@ public class DeviceQuery {
305 public ResponseEntity<WVPResult<String>> updateDevice(Device device){ 306 public ResponseEntity<WVPResult<String>> updateDevice(Device device){
306 307
307 if (device != null && device.getDeviceId() != null) { 308 if (device != null && device.getDeviceId() != null) {
308 - Device deviceInStore = storager.queryVideoDevice(device.getDeviceId());  
309 - if (!StringUtils.isEmpty(device.getName())) {  
310 - deviceInStore.setName(device.getName());  
311 - }  
312 - if (!StringUtils.isEmpty(device.getCharset())) {  
313 - deviceInStore.setCharset(device.getCharset());  
314 - }  
315 - if (!StringUtils.isEmpty(device.getMediaServerId())) {  
316 - deviceInStore.setMediaServerId(device.getMediaServerId());  
317 - }  
318 -  
319 - // 目录订阅相关的信息  
320 - if (device.getSubscribeCycleForCatalog() > 0) {  
321 - if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {  
322 - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());  
323 - // 开启订阅  
324 - deviceService.addCatalogSubscribe(deviceInStore);  
325 - }  
326 - }else if (device.getSubscribeCycleForCatalog() == 0) {  
327 - if (deviceInStore.getSubscribeCycleForCatalog() != 0) {  
328 - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());  
329 - // 取消订阅  
330 - deviceService.removeCatalogSubscribe(deviceInStore);  
331 - }  
332 - }  
333 309
334 - // 移动位置订阅相关的信息  
335 - if (device.getSubscribeCycleForMobilePosition() > 0) {  
336 - if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) {  
337 - deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval());  
338 - deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition());  
339 - // 开启订阅  
340 - deviceService.addMobilePositionSubscribe(deviceInStore);  
341 - }  
342 - }else if (device.getSubscribeCycleForMobilePosition() == 0) {  
343 - if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) {  
344 - // 取消订阅  
345 - deviceService.removeMobilePositionSubscribe(deviceInStore);  
346 - }  
347 - }  
348 310
349 // TODO 报警订阅相关的信息 311 // TODO 报警订阅相关的信息
350 312
351 - storager.updateDevice(device);  
352 - cmder.deviceInfoQuery(device); 313 + deviceService.updateDevice(device);
  314 +// cmder.deviceInfoQuery(device);
353 } 315 }
354 WVPResult<String> result = new WVPResult<>(); 316 WVPResult<String> result = new WVPResult<>();
355 result.setCode(0); 317 result.setCode(0);
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -5,6 +5,8 @@ import com.genersoft.iot.vmp.common.StreamInfo; @@ -5,6 +5,8 @@ import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 5 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
6 import com.genersoft.iot.vmp.service.IMediaServerService; 6 import com.genersoft.iot.vmp.service.IMediaServerService;
7 import com.genersoft.iot.vmp.service.IPlayService; 7 import com.genersoft.iot.vmp.service.IPlayService;
  8 +import com.genersoft.iot.vmp.utils.DateUtil;
  9 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
8 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
9 import io.swagger.annotations.ApiImplicitParam; 11 import io.swagger.annotations.ApiImplicitParam;
10 import io.swagger.annotations.ApiImplicitParams; 12 import io.swagger.annotations.ApiImplicitParams;
@@ -27,6 +29,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -27,6 +29,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
27 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 29 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
28 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 30 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
29 31
  32 +import java.time.LocalDate;
30 import java.util.UUID; 33 import java.util.UUID;
31 34
32 @Api(tags = "国标录像") 35 @Api(tags = "国标录像")
@@ -60,15 +63,32 @@ public class GBRecordController { @@ -60,15 +63,32 @@ public class GBRecordController {
60 @ApiImplicitParam(name = "endTime", value = "结束时间", dataTypeClass = String.class), 63 @ApiImplicitParam(name = "endTime", value = "结束时间", dataTypeClass = String.class),
61 }) 64 })
62 @GetMapping("/query/{deviceId}/{channelId}") 65 @GetMapping("/query/{deviceId}/{channelId}")
63 - public DeferredResult<ResponseEntity<RecordInfo>> recordinfo(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){ 66 + public DeferredResult<ResponseEntity<WVPResult<RecordInfo>>> recordinfo(@PathVariable String deviceId, @PathVariable String channelId, String startTime, String endTime){
64 67
65 if (logger.isDebugEnabled()) { 68 if (logger.isDebugEnabled()) {
66 logger.debug(String.format("录像信息查询 API调用,deviceId:%s ,startTime:%s, endTime:%s",deviceId, startTime, endTime)); 69 logger.debug(String.format("录像信息查询 API调用,deviceId:%s ,startTime:%s, endTime:%s",deviceId, startTime, endTime));
67 } 70 }
  71 + DeferredResult<ResponseEntity<WVPResult<RecordInfo>>> result = new DeferredResult<>();
  72 + if (!DateUtil.verification(startTime, DateUtil.formatter)){
  73 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  74 + wvpResult.setCode(-1);
  75 + wvpResult.setMsg("startTime error, format is " + DateUtil.yyyy_MM_dd_HH_mm_ss);
  76 +
  77 + ResponseEntity<WVPResult<RecordInfo>> resultResponseEntity = new ResponseEntity<>(wvpResult, HttpStatus.OK);
  78 + result.setResult(resultResponseEntity);
  79 + return result;
  80 + }
  81 + if (!DateUtil.verification(endTime, DateUtil.formatter)){
  82 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  83 + wvpResult.setCode(-1);
  84 + wvpResult.setMsg("endTime error, format is " + DateUtil.yyyy_MM_dd_HH_mm_ss);
  85 + ResponseEntity<WVPResult<RecordInfo>> resultResponseEntity = new ResponseEntity<>(wvpResult, HttpStatus.OK);
  86 + result.setResult(resultResponseEntity);
  87 + return result;
  88 + }
68 89
69 Device device = storager.queryVideoDevice(deviceId); 90 Device device = storager.queryVideoDevice(deviceId);
70 // 指定超时时间 1分钟30秒 91 // 指定超时时间 1分钟30秒
71 - DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<>(90*1000L);  
72 String uuid = UUID.randomUUID().toString(); 92 String uuid = UUID.randomUUID().toString();
73 int sn = (int)((Math.random()*9+1)*100000); 93 int sn = (int)((Math.random()*9+1)*100000);
74 String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; 94 String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
@@ -76,7 +96,10 @@ public class GBRecordController { @@ -76,7 +96,10 @@ public class GBRecordController {
76 msg.setId(uuid); 96 msg.setId(uuid);
77 msg.setKey(key); 97 msg.setKey(key);
78 cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> { 98 cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> {
79 - msg.setData("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg ); 99 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  100 + wvpResult.setCode(-1);
  101 + wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg);
  102 + msg.setData(wvpResult);
80 resultHolder.invokeResult(msg); 103 resultHolder.invokeResult(msg);
81 })); 104 }));
82 105
@@ -84,6 +107,10 @@ public class GBRecordController { @@ -84,6 +107,10 @@ public class GBRecordController {
84 resultHolder.put(key, uuid, result); 107 resultHolder.put(key, uuid, result);
85 result.onTimeout(()->{ 108 result.onTimeout(()->{
86 msg.setData("timeout"); 109 msg.setData("timeout");
  110 + WVPResult<RecordInfo> wvpResult = new WVPResult<>();
  111 + wvpResult.setCode(-1);
  112 + wvpResult.setMsg("timeout");
  113 + msg.setData(wvpResult);
87 resultHolder.invokeResult(msg); 114 resultHolder.invokeResult(msg);
88 }); 115 });
89 return result; 116 return result;
src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java
@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.log; @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.log;
3 import com.genersoft.iot.vmp.conf.UserSetting; 3 import com.genersoft.iot.vmp.conf.UserSetting;
4 import com.genersoft.iot.vmp.service.ILogService; 4 import com.genersoft.iot.vmp.service.ILogService;
5 import com.genersoft.iot.vmp.storager.dao.dto.LogDto; 5 import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
  6 +import com.genersoft.iot.vmp.utils.DateUtil;
6 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 7 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
7 import com.github.pagehelper.PageInfo; 8 import com.github.pagehelper.PageInfo;
8 import io.swagger.annotations.Api; 9 import io.swagger.annotations.Api;
@@ -18,7 +19,6 @@ import org.springframework.util.StringUtils; @@ -18,7 +19,6 @@ import org.springframework.util.StringUtils;
18 import org.springframework.web.bind.annotation.*; 19 import org.springframework.web.bind.annotation.*;
19 20
20 import java.text.ParseException; 21 import java.text.ParseException;
21 -import java.text.SimpleDateFormat;  
22 22
23 @Api(tags = "日志管理") 23 @Api(tags = "日志管理")
24 @CrossOrigin 24 @CrossOrigin
@@ -34,8 +34,6 @@ public class LogController { @@ -34,8 +34,6 @@ public class LogController {
34 @Autowired 34 @Autowired
35 private UserSetting userSetting; 35 private UserSetting userSetting;
36 36
37 - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
38 -  
39 /** 37 /**
40 * 分页查询日志 38 * 分页查询日志
41 * 39 *
@@ -80,10 +78,10 @@ public class LogController { @@ -80,10 +78,10 @@ public class LogController {
80 78
81 try { 79 try {
82 if (startTime != null) { 80 if (startTime != null) {
83 - format.parse(startTime); 81 + DateUtil.format.parse(startTime);
84 } 82 }
85 if (endTime != null) { 83 if (endTime != null) {
86 - format.parse(endTime); 84 + DateUtil.format.parse(endTime);
87 } 85 }
88 } catch (ParseException e) { 86 } catch (ParseException e) {
89 return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); 87 return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
src/main/java/com/genersoft/iot/vmp/vmanager/user/RoleController.java
@@ -2,9 +2,8 @@ package com.genersoft.iot.vmp.vmanager.user; @@ -2,9 +2,8 @@ package com.genersoft.iot.vmp.vmanager.user;
2 2
3 import com.genersoft.iot.vmp.conf.security.SecurityUtils; 3 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
4 import com.genersoft.iot.vmp.service.IRoleService; 4 import com.genersoft.iot.vmp.service.IRoleService;
5 -import com.genersoft.iot.vmp.service.IUserService;  
6 import com.genersoft.iot.vmp.storager.dao.dto.Role; 5 import com.genersoft.iot.vmp.storager.dao.dto.Role;
7 -import com.genersoft.iot.vmp.storager.dao.dto.User; 6 +import com.genersoft.iot.vmp.utils.DateUtil;
8 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 7 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
9 import io.swagger.annotations.Api; 8 import io.swagger.annotations.Api;
10 import io.swagger.annotations.ApiImplicitParam; 9 import io.swagger.annotations.ApiImplicitParam;
@@ -13,12 +12,8 @@ import io.swagger.annotations.ApiOperation; @@ -13,12 +12,8 @@ import io.swagger.annotations.ApiOperation;
13 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
14 import org.springframework.http.HttpStatus; 13 import org.springframework.http.HttpStatus;
15 import org.springframework.http.ResponseEntity; 14 import org.springframework.http.ResponseEntity;
16 -import org.springframework.security.authentication.AuthenticationManager;  
17 -import org.springframework.util.DigestUtils;  
18 -import org.springframework.util.StringUtils;  
19 import org.springframework.web.bind.annotation.*; 15 import org.springframework.web.bind.annotation.*;
20 16
21 -import java.text.SimpleDateFormat;  
22 import java.util.List; 17 import java.util.List;
23 18
24 @Api(tags = "角色管理") 19 @Api(tags = "角色管理")
@@ -30,8 +25,6 @@ public class RoleController { @@ -30,8 +25,6 @@ public class RoleController {
30 @Autowired 25 @Autowired
31 private IRoleService roleService; 26 private IRoleService roleService;
32 27
33 - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
34 -  
35 @ApiOperation("添加角色") 28 @ApiOperation("添加角色")
36 @ApiImplicitParams({ 29 @ApiImplicitParams({
37 @ApiImplicitParam(name = "name", required = true, value = "角色名", dataTypeClass = String.class), 30 @ApiImplicitParam(name = "name", required = true, value = "角色名", dataTypeClass = String.class),
@@ -53,8 +46,8 @@ public class RoleController { @@ -53,8 +46,8 @@ public class RoleController {
53 Role role = new Role(); 46 Role role = new Role();
54 role.setName(name); 47 role.setName(name);
55 role.setAuthority(authority); 48 role.setAuthority(authority);
56 - role.setCreateTime(format.format(System.currentTimeMillis()));  
57 - role.setUpdateTime(format.format(System.currentTimeMillis())); 49 + role.setCreateTime(DateUtil.getNow());
  50 + role.setUpdateTime(DateUtil.getNow());
58 51
59 int addResult = roleService.add(role); 52 int addResult = roleService.add(role);
60 53
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.service.IRoleService; @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.service.IRoleService;
6 import com.genersoft.iot.vmp.service.IUserService; 6 import com.genersoft.iot.vmp.service.IUserService;
7 import com.genersoft.iot.vmp.storager.dao.dto.Role; 7 import com.genersoft.iot.vmp.storager.dao.dto.Role;
8 import com.genersoft.iot.vmp.storager.dao.dto.User; 8 import com.genersoft.iot.vmp.storager.dao.dto.User;
  9 +import com.genersoft.iot.vmp.utils.DateUtil;
9 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 10 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
10 import io.swagger.annotations.Api; 11 import io.swagger.annotations.Api;
11 import io.swagger.annotations.ApiImplicitParam; 12 import io.swagger.annotations.ApiImplicitParam;
@@ -20,7 +21,6 @@ import org.springframework.util.StringUtils; @@ -20,7 +21,6 @@ import org.springframework.util.StringUtils;
20 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
21 22
22 import javax.security.sasl.AuthenticationException; 23 import javax.security.sasl.AuthenticationException;
23 -import java.text.SimpleDateFormat;  
24 import java.util.List; 24 import java.util.List;
25 25
26 @Api(tags = "用户管理") 26 @Api(tags = "用户管理")
@@ -38,8 +38,6 @@ public class UserController { @@ -38,8 +38,6 @@ public class UserController {
38 @Autowired 38 @Autowired
39 private IRoleService roleService; 39 private IRoleService roleService;
40 40
41 - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
42 -  
43 @ApiOperation("登录") 41 @ApiOperation("登录")
44 @ApiImplicitParams({ 42 @ApiImplicitParams({
45 @ApiImplicitParam(name = "username", required = true, value = "用户名", dataTypeClass = String.class), 43 @ApiImplicitParam(name = "username", required = true, value = "用户名", dataTypeClass = String.class),
@@ -135,8 +133,8 @@ public class UserController { @@ -135,8 +133,8 @@ public class UserController {
135 return new ResponseEntity<>(result, HttpStatus.OK); 133 return new ResponseEntity<>(result, HttpStatus.OK);
136 } 134 }
137 user.setRole(role); 135 user.setRole(role);
138 - user.setCreateTime(format.format(System.currentTimeMillis()));  
139 - user.setUpdateTime(format.format(System.currentTimeMillis())); 136 + user.setCreateTime(DateUtil.getNow());
  137 + user.setUpdateTime(DateUtil.getNow());
140 int addResult = userService.addUser(user); 138 int addResult = userService.addUser(user);
141 139
142 result.setCode(addResult > 0 ? 0 : -1); 140 result.setCode(addResult > 0 ? 0 : -1);
src/main/resources/all-application.yml
@@ -28,7 +28,7 @@ spring: @@ -28,7 +28,7 @@ spring:
28 poolMaxIdle: 500 28 poolMaxIdle: 500
29 # [可选] 最大的等待时间(秒) 29 # [可选] 最大的等待时间(秒)
30 poolMaxWait: 5 30 poolMaxWait: 5
31 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 31 + # [必选] jdbc数据库配置
32 datasource: 32 datasource:
33 type: com.alibaba.druid.pool.DruidDataSource 33 type: com.alibaba.druid.pool.DruidDataSource
34 driver-class-name: com.mysql.cj.jdbc.Driver 34 driver-class-name: com.mysql.cj.jdbc.Driver
src/main/resources/application-dev.yml
@@ -16,7 +16,6 @@ spring: @@ -16,7 +16,6 @@ spring:
16 password: face2020 16 password: face2020
17 # [可选] 超时时间 17 # [可选] 超时时间
18 timeout: 10000 18 timeout: 10000
19 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置  
20 # mysql数据源 19 # mysql数据源
21 datasource: 20 datasource:
22 type: com.alibaba.druid.pool.DruidDataSource 21 type: com.alibaba.druid.pool.DruidDataSource
src/main/resources/application-docker.yml
@@ -16,7 +16,7 @@ spring: @@ -16,7 +16,7 @@ spring:
16 password: ${REDIS_PWD:root} 16 password: ${REDIS_PWD:root}
17 # [可选] 超时时间 17 # [可选] 超时时间
18 timeout: 10000 18 timeout: 10000
19 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 19 + # [必选] jdbc数据库配置
20 datasource: 20 datasource:
21 # 使用mysql 打开23-28行注释, 删除29-36行 21 # 使用mysql 打开23-28行注释, 删除29-36行
22 name: wvp 22 name: wvp
src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java
@@ -2,12 +2,12 @@ package com.genersoft.iot.vmp.service.impl; @@ -2,12 +2,12 @@ package com.genersoft.iot.vmp.service.impl;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; 3 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
4 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 4 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
  5 +import com.genersoft.iot.vmp.utils.DateUtil;
5 import org.junit.runner.RunWith; 6 import org.junit.runner.RunWith;
6 import org.springframework.boot.test.context.SpringBootTest; 7 import org.springframework.boot.test.context.SpringBootTest;
7 import org.springframework.test.context.junit4.SpringRunner; 8 import org.springframework.test.context.junit4.SpringRunner;
8 9
9 import javax.annotation.Resource; 10 import javax.annotation.Resource;
10 -import java.text.SimpleDateFormat;  
11 import java.util.Date; 11 import java.util.Date;
12 12
13 13
@@ -18,8 +18,6 @@ class DeviceAlarmServiceImplTest { @@ -18,8 +18,6 @@ class DeviceAlarmServiceImplTest {
18 @Resource 18 @Resource
19 private IDeviceAlarmService deviceAlarmService; 19 private IDeviceAlarmService deviceAlarmService;
20 20
21 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
22 -  
23 @org.junit.jupiter.api.Test 21 @org.junit.jupiter.api.Test
24 void getAllAlarm() { 22 void getAllAlarm() {
25 // deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111",null,null,null, null, null); 23 // deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111",null,null,null, null, null);
@@ -67,7 +65,7 @@ class DeviceAlarmServiceImplTest { @@ -67,7 +65,7 @@ class DeviceAlarmServiceImplTest {
67 */ 65 */
68 deviceAlarm.setAlarmMethod((int)(Math.random()*7 + 1) + ""); 66 deviceAlarm.setAlarmMethod((int)(Math.random()*7 + 1) + "");
69 Date date = randomDate("2021-01-01 00:00:00", "2021-06-01 00:00:00"); 67 Date date = randomDate("2021-01-01 00:00:00", "2021-06-01 00:00:00");
70 - deviceAlarm.setAlarmTime(format.format(date)); 68 + deviceAlarm.setAlarmTime(DateUtil.format.format(date));
71 /** 69 /**
72 * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情- 70 * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情-
73 */ 71 */
@@ -90,8 +88,8 @@ class DeviceAlarmServiceImplTest { @@ -90,8 +88,8 @@ class DeviceAlarmServiceImplTest {
90 private Date randomDate(String beginDate, String endDate) { 88 private Date randomDate(String beginDate, String endDate) {
91 try { 89 try {
92 90
93 - Date start = format.parse(beginDate);//构造开始日期  
94 - Date end = format.parse(endDate);//构造结束日期 91 + Date start = DateUtil.format.parse(beginDate);//构造开始日期
  92 + Date end = DateUtil.format.parse(endDate);//构造结束日期
95 //getTime()表示返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 93 //getTime()表示返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
96 if (start.getTime() >= end.getTime()) { 94 if (start.getTime() >= end.getTime()) {
97 return null; 95 return null;
src/test/java/com/genersoft/iot/vmp/service/impl/RoleServiceImplTest.java
@@ -4,12 +4,12 @@ import com.genersoft.iot.vmp.service.IRoleService; @@ -4,12 +4,12 @@ import com.genersoft.iot.vmp.service.IRoleService;
4 import com.genersoft.iot.vmp.service.IUserService; 4 import com.genersoft.iot.vmp.service.IUserService;
5 import com.genersoft.iot.vmp.storager.dao.dto.Role; 5 import com.genersoft.iot.vmp.storager.dao.dto.Role;
6 import com.genersoft.iot.vmp.storager.dao.dto.User; 6 import com.genersoft.iot.vmp.storager.dao.dto.User;
  7 +import com.genersoft.iot.vmp.utils.DateUtil;
7 import org.junit.runner.RunWith; 8 import org.junit.runner.RunWith;
8 import org.springframework.boot.test.context.SpringBootTest; 9 import org.springframework.boot.test.context.SpringBootTest;
9 import org.springframework.test.context.junit4.SpringRunner; 10 import org.springframework.test.context.junit4.SpringRunner;
10 11
11 import javax.annotation.Resource; 12 import javax.annotation.Resource;
12 -import java.text.SimpleDateFormat;  
13 import java.util.List; 13 import java.util.List;
14 14
15 15
@@ -20,7 +20,6 @@ class RoleServiceImplTest { @@ -20,7 +20,6 @@ class RoleServiceImplTest {
20 @Resource 20 @Resource
21 private IRoleService roleService; 21 private IRoleService roleService;
22 22
23 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
24 @org.junit.jupiter.api.Test 23 @org.junit.jupiter.api.Test
25 void getAllUser() { 24 void getAllUser() {
26 List<Role> all = roleService.getAll(); 25 List<Role> all = roleService.getAll();
@@ -35,8 +34,8 @@ class RoleServiceImplTest { @@ -35,8 +34,8 @@ class RoleServiceImplTest {
35 Role role = new Role(); 34 Role role = new Role();
36 role.setName("test+" + i); 35 role.setName("test+" + i);
37 role.setAuthority("adadadda"); 36 role.setAuthority("adadadda");
38 - role.setCreateTime(format.format(System.currentTimeMillis()));  
39 - role.setUpdateTime(format.format(System.currentTimeMillis())); 37 + role.setCreateTime(DateUtil.getNow());
  38 + role.setUpdateTime(DateUtil.getNow());
40 roleService.add(role); 39 roleService.add(role);
41 } 40 }
42 } 41 }
src/test/java/com/genersoft/iot/vmp/service/impl/UserServiceImplTest.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;  
4 -import com.genersoft.iot.vmp.service.IDeviceAlarmService;  
5 import com.genersoft.iot.vmp.service.IUserService; 3 import com.genersoft.iot.vmp.service.IUserService;
6 import com.genersoft.iot.vmp.storager.dao.dto.Role; 4 import com.genersoft.iot.vmp.storager.dao.dto.Role;
7 import com.genersoft.iot.vmp.storager.dao.dto.User; 5 import com.genersoft.iot.vmp.storager.dao.dto.User;
  6 +import com.genersoft.iot.vmp.utils.DateUtil;
8 import org.junit.runner.RunWith; 7 import org.junit.runner.RunWith;
9 import org.springframework.boot.test.context.SpringBootTest; 8 import org.springframework.boot.test.context.SpringBootTest;
10 import org.springframework.test.context.junit4.SpringRunner; 9 import org.springframework.test.context.junit4.SpringRunner;
11 10
12 import javax.annotation.Resource; 11 import javax.annotation.Resource;
13 -import java.text.SimpleDateFormat;  
14 -import java.util.Date;  
15 import java.util.List; 12 import java.util.List;
16 13
17 14
@@ -22,7 +19,6 @@ class UserServiceImplTest { @@ -22,7 +19,6 @@ class UserServiceImplTest {
22 @Resource 19 @Resource
23 private IUserService userService; 20 private IUserService userService;
24 21
25 - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
26 22
27 @org.junit.jupiter.api.Test 23 @org.junit.jupiter.api.Test
28 void getAllUser() { 24 void getAllUser() {
@@ -42,8 +38,8 @@ class UserServiceImplTest { @@ -42,8 +38,8 @@ class UserServiceImplTest {
42 Role role = new Role(); 38 Role role = new Role();
43 role.setId(1); 39 role.setId(1);
44 user.setRole(role); 40 user.setRole(role);
45 - user.setCreateTime(format.format(System.currentTimeMillis()));  
46 - user.setUpdateTime(format.format(System.currentTimeMillis())); 41 + user.setCreateTime(DateUtil.getNow());
  42 + user.setUpdateTime(DateUtil.getNow());
47 userService.addUser(user); 43 userService.addUser(user);
48 } 44 }
49 } 45 }
@@ -62,7 +58,7 @@ class UserServiceImplTest { @@ -62,7 +58,7 @@ class UserServiceImplTest {
62 Role role = new Role(); 58 Role role = new Role();
63 role.setId(2); 59 role.setId(2);
64 user.setRole(role); 60 user.setRole(role);
65 - user.setUpdateTime(format.format(System.currentTimeMillis())); 61 + user.setUpdateTime(DateUtil.getNow());
66 userService.updateUsers(user); 62 userService.updateUsers(user);
67 } 63 }
68 64
web_src/src/components/channelList.vue
@@ -237,14 +237,16 @@ export default { @@ -237,14 +237,16 @@ export default {
237 that.initData(); 237 that.initData();
238 }, 1000) 238 }, 1000)
239 239
240 - } else { 240 + }else{
241 that.$message.error(res.data.msg); 241 that.$message.error(res.data.msg);
242 } 242 }
243 }).catch(function (e) { 243 }).catch(function (e) {
  244 + that.isLoging = false;
  245 + that.$message.error("请求超时");
244 }); 246 });
245 }, 247 },
246 queryRecords: function (itemData) { 248 queryRecords: function (itemData) {
247 - var format = moment().format("YYYY-M-D"); 249 + var format = moment().format("yyyy-MM-DD");
248 let deviceId = this.deviceId; 250 let deviceId = this.deviceId;
249 let channelId = itemData.channelId; 251 let channelId = itemData.channelId;
250 this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format}) 252 this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})
web_src/src/components/control.vue
@@ -576,7 +576,7 @@ export default { @@ -576,7 +576,7 @@ export default {
576 let that = this; 576 let that = this;
577 this.$axios({ 577 this.$axios({
578 method: 'get', 578 method: 'get',
579 - url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session&id=' + id 579 + url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session?id=' + id
580 }).then(function (res) { 580 }).then(function (res) {
581 that.getAllSession(); 581 that.getAllSession();
582 that.$message({ 582 that.$message({
web_src/src/components/dialog/devicePlayer.vue
@@ -33,10 +33,100 @@ @@ -33,10 +33,100 @@
33 <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> 33 <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
34 <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span> 34 <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span>
35 <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" > 35 <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" >
36 - <template slot="append">  
37 - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>  
38 - </template> 36 + <el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  37 + <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl">
  38 + <el-button >
  39 + 更多地址<i class="el-icon-arrow-down el-icon--right"></i>
  40 + </el-button>
  41 + <el-dropdown-menu slot="dropdown" >
  42 + <el-dropdown-item :command="streamInfo.flv">
  43 + <el-tag >FLV:</el-tag>
  44 + <span>{{ streamInfo.flv }}</span>
  45 + </el-dropdown-item>
  46 + <el-dropdown-item :command="streamInfo.https_flv">
  47 + <el-tag >FLV(https):</el-tag>
  48 + <span>{{ streamInfo.https_flv }}</span>
  49 + </el-dropdown-item>
  50 + <el-dropdown-item :command="streamInfo.ws_flv">
  51 + <el-tag >FLV(ws):</el-tag>
  52 + <span >{{ streamInfo.ws_flv }}</span>
  53 + </el-dropdown-item>
  54 + <el-dropdown-item :command="streamInfo.wss_flv">
  55 + <el-tag >FLV(wss):</el-tag>
  56 + <span>{{ streamInfo.wss_flv }}</span>
  57 + </el-dropdown-item>
  58 + <el-dropdown-item :command="streamInfo.fmp4">
  59 + <el-tag >FMP4:</el-tag>
  60 + <span>{{ streamInfo.fmp4 }}</span>
  61 + </el-dropdown-item>
  62 + <el-dropdown-item :command="streamInfo.https_fmp4">
  63 + <el-tag >FMP4(https):</el-tag>
  64 + <span>{{ streamInfo.https_fmp4 }}</span>
  65 + </el-dropdown-item>
  66 + <el-dropdown-item :command="streamInfo.ws_fmp4">
  67 + <el-tag >FMP4(ws):</el-tag>
  68 + <span>{{ streamInfo.ws_fmp4 }}</span>
  69 + </el-dropdown-item>
  70 + <el-dropdown-item :command="streamInfo.wss_fmp4">
  71 + <el-tag >FMP4(wss):</el-tag>
  72 + <span>{{ streamInfo.wss_fmp4 }}</span>
  73 + </el-dropdown-item>
  74 + <el-dropdown-item :command="streamInfo.hls">
  75 + <el-tag>HLS:</el-tag>
  76 + <span>{{ streamInfo.hls }}</span>
  77 + </el-dropdown-item>
  78 + <el-dropdown-item :command="streamInfo.https_hls">
  79 + <el-tag >HLS(https):</el-tag>
  80 + <span>{{ streamInfo.https_hls }}</span>
  81 + </el-dropdown-item>
  82 + <el-dropdown-item :command="streamInfo.ws_hls">
  83 + <el-tag >HLS(ws):</el-tag>
  84 + <span>{{ streamInfo.ws_hls }}</span>
  85 + </el-dropdown-item>
  86 + <el-dropdown-item :command="streamInfo.wss_hls">
  87 + <el-tag >HLS(wss):</el-tag>
  88 + <span>{{ streamInfo.wss_hls }}</span>
  89 + </el-dropdown-item>
  90 + <el-dropdown-item :command="streamInfo.ts">
  91 + <el-tag>TS:</el-tag>
  92 + <span>{{ streamInfo.ts }}</span>
  93 + </el-dropdown-item>
  94 + <el-dropdown-item :command="streamInfo.https_ts">
  95 + <el-tag>TS(https):</el-tag>
  96 + <span>{{ streamInfo.https_ts }}</span>
  97 + </el-dropdown-item>
  98 + <el-dropdown-item :command="streamInfo.ws_ts">
  99 + <el-tag>TS(ws):</el-tag>
  100 + <span>{{ streamInfo.ws_ts }}</span>
  101 + </el-dropdown-item>
  102 + <el-dropdown-item :command="streamInfo.wss_ts">
  103 + <el-tag>TS(wss):</el-tag>
  104 + <span>{{ streamInfo.wss_ts }}</span>
  105 + </el-dropdown-item>
  106 + <el-dropdown-item :command="streamInfo.rtc">
  107 + <el-tag >RTC:</el-tag>
  108 + <span>{{ streamInfo.rtc }}</span>
  109 + </el-dropdown-item>
  110 + <el-dropdown-item :command="streamInfo.rtmp">
  111 + <el-tag >RTMP:</el-tag>
  112 + <span>{{ streamInfo.rtmp }}</span>
  113 + </el-dropdown-item>
  114 + <el-dropdown-item :command="streamInfo.rtmps">
  115 + <el-tag >RTMPS:</el-tag>
  116 + <span>{{ streamInfo.rtmps }}</span>
  117 + </el-dropdown-item>
  118 + <el-dropdown-item :command="streamInfo.rtsp">
  119 + <el-tag >RTSP:</el-tag>
  120 + <span>{{ streamInfo.rtsp }}</span>
  121 + </el-dropdown-item>
  122 + <el-dropdown-item :command="streamInfo.rtsps">
  123 + <el-tag >RTSPS:</el-tag>
  124 + <span>{{ streamInfo.rtsps }}</span>
  125 + </el-dropdown-item>
  126 + </el-dropdown-menu>
  127 + </el-dropdown>
39 </el-input> 128 </el-input>
  129 +
40 </div> 130 </div>
41 </el-tab-pane> 131 </el-tab-pane>
42 <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> 132 <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
@@ -117,27 +207,27 @@ @@ -117,27 +207,27 @@
117 207
118 <div class="control-panel"> 208 <div class="control-panel">
119 <el-button-group> 209 <el-button-group>
120 - <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium" type="info">预置位编号</el-tag> 210 + <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag>
121 <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number> 211 <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number>
122 <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button> 212 <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button>
123 <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button> 213 <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button>
124 <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button> 214 <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button>
125 - <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium" type="info">巡航速度</el-tag> 215 + <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">巡航速度</el-tag>
126 <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> 216 <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
127 <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button> 217 <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button>
128 - <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium" type="info">停留时间</el-tag> 218 + <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">停留时间</el-tag>
129 <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> 219 <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
130 <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button> 220 <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button>
131 - <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium" type="info">巡航组编号</el-tag> 221 + <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">巡航组编号</el-tag>
132 <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number> 222 <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number>
133 <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button> 223 <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button>
134 <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button> 224 <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button>
135 <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button> 225 <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button>
136 <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button> 226 <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button>
137 - <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium" type="info">扫描速度</el-tag> 227 + <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">扫描速度</el-tag>
138 <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> 228 <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>
139 <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button> 229 <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button>
140 - <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium" type="info">扫描组编号</el-tag> 230 + <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">扫描组编号</el-tag>
141 <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number> 231 <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number>
142 <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button> 232 <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button>
143 <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button> 233 <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button>
@@ -174,6 +264,7 @@ @@ -174,6 +264,7 @@
174 </div> 264 </div>
175 265
176 </el-tab-pane> 266 </el-tab-pane>
  267 +
177 </el-tabs> 268 </el-tabs>
178 </div> 269 </div>
179 </el-dialog> 270 </el-dialog>
@@ -244,6 +335,7 @@ export default { @@ -244,6 +335,7 @@ export default {
244 seekTime: 0, 335 seekTime: 0,
245 recordStartTime: 0, 336 recordStartTime: 0,
246 showTimeText: "00:00:00", 337 showTimeText: "00:00:00",
  338 + streamInfo: null,
247 }; 339 };
248 }, 340 },
249 methods: { 341 methods: {
@@ -306,6 +398,7 @@ export default { @@ -306,6 +398,7 @@ export default {
306 console.log(val) 398 console.log(val)
307 }, 399 },
308 play: function (streamInfo, hasAudio) { 400 play: function (streamInfo, hasAudio) {
  401 + this.streamInfo = streamInfo;
309 this.hasAudio = hasAudio; 402 this.hasAudio = hasAudio;
310 this.isLoging = false; 403 this.isLoging = false;
311 // this.videoUrl = streamInfo.rtc; 404 // this.videoUrl = streamInfo.rtc;
@@ -453,9 +546,19 @@ export default { @@ -453,9 +546,19 @@ export default {
453 method: 'get', 546 method: 'get',
454 url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime 547 url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime
455 }).then(function (res) { 548 }).then(function (res) {
456 - // 处理时间信息  
457 - that.videoHistory.searchHistoryResult = res.data.recordList;  
458 - that.recordsLoading = false; 549 + console.log(res)
  550 + if(res.data.code === 0) {
  551 + // 处理时间信息
  552 + that.videoHistory.searchHistoryResult = res.data.data.recordList;
  553 + that.recordsLoading = false;
  554 + }else {
  555 + this.$message({
  556 + showClose: true,
  557 + message: res.data.msg,
  558 + type: "error",
  559 + });
  560 + }
  561 +
459 }).catch(function (e) { 562 }).catch(function (e) {
460 console.log(e.message); 563 console.log(e.message);
461 // that.videoHistory.searchHistoryResult = falsificationData.recordData; 564 // that.videoHistory.searchHistoryResult = falsificationData.recordData;
@@ -636,6 +739,14 @@ export default { @@ -636,6 +739,14 @@ export default {
636 console.log(resultArray) 739 console.log(resultArray)
637 return resultArray; 740 return resultArray;
638 }, 741 },
  742 + copyUrl: function (dropdownItem){
  743 + console.log(dropdownItem)
  744 + this.$copyText(dropdownItem).then((e)=> {
  745 + this.$message.success("成功拷贝到粘贴板");
  746 + }, (e)=> {
  747 +
  748 + })
  749 + },
639 gbPlay(){ 750 gbPlay(){
640 console.log('前端控制:播放'); 751 console.log('前端控制:播放');
641 this.$axios({ 752 this.$axios({
@@ -671,8 +782,13 @@ export default { @@ -671,8 +782,13 @@ export default {
671 this.$axios({ 782 this.$axios({
672 method: 'get', 783 method: 'get',
673 url: `/api/playback/seek/${this.streamId }/` + Math.floor(this.seekTime * val / 100000) 784 url: `/api/playback/seek/${this.streamId }/` + Math.floor(this.seekTime * val / 100000)
674 - }).then(function (res) {});  
675 - } 785 + }).then( (res)=> {
  786 + setTimeout(()=>{
  787 + this.$refs.videoPlayer.play(this.videoUrl)
  788 + }, 600)
  789 + });
  790 + },
  791 +
676 792
677 } 793 }
678 }; 794 };
web_src/src/components/dialog/recordDownload.vue
@@ -172,6 +172,7 @@ export default { @@ -172,6 +172,7 @@ export default {
172 isEnd: true, 172 isEnd: true,
173 } 173 }
174 }).then((res) => { 174 }).then((res) => {
  175 + console.log(res)
175 if (res.data.code == 0) { 176 if (res.data.code == 0) {
176 this.percentage = parseFloat(res.data.data.percentage)*100 177 this.percentage = parseFloat(res.data.data.percentage)*100
177 if (res.data.data[0].percentage === '1') { 178 if (res.data.data[0].percentage === '1') {