Commit 1d753b48c023090430c2931fd8e3a45a382eddf8
Committed by
GitHub
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快速体验) |
pom.xml
| @@ -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<RecordItem>{ | @@ -116,18 +117,17 @@ public class RecordItem implements Comparable<RecordItem>{ | ||
| 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') { |