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