Merge remote-tracking branch 'origin/master' into wvp-28181-2.0
# Conflicts: # README.md # src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java # src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java # src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java # src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java # src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java # src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java # src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java # src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java # src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java # src/main/resources/application-dev.yml # web_src/src/components/gb28181/devicePlayer.vue
This commit is contained in:
commit
34135cce5d
88
pom.xml
88
pom.xml
@ -13,13 +13,38 @@
|
|||||||
<artifactId>wvp</artifactId>
|
<artifactId>wvp</artifactId>
|
||||||
<name>web video platform</name>
|
<name>web video platform</name>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>nexus-aliyun</id>
|
||||||
|
<name>Nexus aliyun</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>nexus-aliyun</id>
|
||||||
|
<name>Nexus aliyun</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
<!-- 依赖版本 -->
|
<!-- 依赖版本 -->
|
||||||
<mapper.version>4.1.5</mapper.version>
|
|
||||||
<mybatis.version>3.5.5</mybatis.version>
|
|
||||||
<mybatis.spring.version>2.0.5</mybatis.spring.version>
|
|
||||||
<pagehelper.version>5.2.0</pagehelper.version>
|
<pagehelper.version>5.2.0</pagehelper.version>
|
||||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||||
<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
|
<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
|
||||||
@ -31,30 +56,16 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.mybatis.spring.boot</groupId>
|
||||||
<artifactId>spring-context</artifactId>
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
<version>2.1.4</version>
|
||||||
|
|
||||||
<!-- redis -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.data</groupId>
|
|
||||||
<artifactId>spring-data-redis</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>redis.clients</groupId>
|
|
||||||
<artifactId>jedis</artifactId>
|
|
||||||
<version>3.3.0</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- druid数据库连接池 -->
|
<!-- druid数据库连接池 -->
|
||||||
@ -71,36 +82,25 @@
|
|||||||
<version>8.0.22</version>
|
<version>8.0.22</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--Mybatis -->
|
<!-- 添加sqlite-jdbc数据库驱动 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mybatis</groupId>
|
<groupId>org.xerial</groupId>
|
||||||
<artifactId>mybatis</artifactId>
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
<version>${mybatis.version}</version>
|
<version>3.32.3.2</version>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mybatis</groupId>
|
|
||||||
<artifactId>mybatis-spring</artifactId>
|
|
||||||
<version>${mybatis.spring.version}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--分页插件 -->
|
<!--Mybatis分页插件 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.pagehelper</groupId>
|
<groupId>com.github.pagehelper</groupId>
|
||||||
<artifactId>pagehelper</artifactId>
|
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||||
<version>${pagehelper.version}</version>
|
<version>1.2.10</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--通用Mapper -->
|
<!-- <dependency>-->
|
||||||
<dependency>
|
<!-- <groupId>org.apache.commons</groupId>-->
|
||||||
<groupId>tk.mybatis</groupId>
|
<!-- <artifactId>commons-lang3</artifactId>-->
|
||||||
<artifactId>mapper</artifactId>
|
<!-- <version>3.11</version>-->
|
||||||
<version>${mapper.version}</version>
|
<!-- </dependency>-->
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-lang3</artifactId>
|
|
||||||
<version>3.11</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!--Swagger2 -->
|
<!--Swagger2 -->
|
||||||
<!--在线文档 -->
|
<!--在线文档 -->
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.common;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PageResult<T> {
|
|
||||||
|
|
||||||
private int page;
|
|
||||||
private int count;
|
|
||||||
private int total;
|
|
||||||
|
|
||||||
private List<T> data;
|
|
||||||
|
|
||||||
public List<T> getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPage() {
|
|
||||||
return page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPage(int page) {
|
|
||||||
this.page = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCount() {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCount(int count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTotal() {
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTotal(int total) {
|
|
||||||
this.total = total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setData(List<T> data) {
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
}
|
|
@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONArray;
|
|||||||
|
|
||||||
public class StreamInfo {
|
public class StreamInfo {
|
||||||
|
|
||||||
private String ssrc;
|
|
||||||
private String streamId;
|
private String streamId;
|
||||||
private String deviceID;
|
private String deviceID;
|
||||||
private String cahnnelId;
|
private String cahnnelId;
|
||||||
@ -20,14 +19,6 @@ public class StreamInfo {
|
|||||||
private String rtsp;
|
private String rtsp;
|
||||||
private JSONArray tracks;
|
private JSONArray tracks;
|
||||||
|
|
||||||
public String getSsrc() {
|
|
||||||
return ssrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSsrc(String ssrc) {
|
|
||||||
this.ssrc = ssrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceID() {
|
public String getDeviceID() {
|
||||||
return deviceID;
|
return deviceID;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.genersoft.iot.vmp.conf;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对配置文件进行校验
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Order(value=2)
|
||||||
|
public class ApplicationCheckRunner implements CommandLineRunner {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger("ApplicationCheckRunner");
|
||||||
|
|
||||||
|
@Value("${sip.ip}")
|
||||||
|
private String sipIp;
|
||||||
|
|
||||||
|
@Value("${media.ip}")
|
||||||
|
private String mediaIp;
|
||||||
|
|
||||||
|
@Value("${media.wanIp}")
|
||||||
|
private String mediaWanIp;
|
||||||
|
|
||||||
|
@Value("${media.hookIp}")
|
||||||
|
private String mediaHookIp;
|
||||||
|
|
||||||
|
@Value("${media.port}")
|
||||||
|
private int mediaPort;
|
||||||
|
|
||||||
|
@Value("${media.secret}")
|
||||||
|
private String mediaSecret;
|
||||||
|
|
||||||
|
@Value("${media.streamNoneReaderDelayMS}")
|
||||||
|
private String streamNoneReaderDelayMS;
|
||||||
|
|
||||||
|
@Value("${sip.ip}")
|
||||||
|
private String sipIP;
|
||||||
|
|
||||||
|
@Value("${server.port}")
|
||||||
|
private String serverPort;
|
||||||
|
|
||||||
|
@Value("${media.autoConfig}")
|
||||||
|
private boolean autoConfig;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
if (sipIP.equals("localhost") || sipIP.equals("127.0.0.1")) {
|
||||||
|
logger.error("sip.ip不能使用 {} ,请使用类似192.168.1.44这样的来自网卡的IP!!!", sipIP );
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaIp.equals("localhost") || mediaIp.equals("127.0.0.1")) {
|
||||||
|
logger.warn("mediaIp.ip使用 {} ,将无法收到网络内其他设备的推流!!!", mediaIp );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -8,8 +8,10 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.sip.*;
|
import javax.sip.*;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
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;
|
||||||
@ -34,6 +36,9 @@ public class SipLayer implements SipListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SIPProcessorFactory processorFactory;
|
private SIPProcessorFactory processorFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
private SipStack sipStack;
|
private SipStack sipStack;
|
||||||
|
|
||||||
private SipFactory sipFactory;
|
private SipFactory sipFactory;
|
||||||
@ -133,17 +138,34 @@ public class SipLayer implements SipListener {
|
|||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
if (evt.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {
|
||||||
|
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
||||||
|
if (callIdHeader != null) {
|
||||||
|
SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
|
||||||
|
if (subscribe != null) {
|
||||||
|
subscribe.response(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// } else if (status == Response.TRYING) {
|
// } else if (status == Response.TRYING) {
|
||||||
// trying不会回复
|
// trying不会回复
|
||||||
} else if ((status >= 100) && (status < 200)) {
|
} else if ((status >= 100) && (status < 200)) {
|
||||||
// 增加其它无需回复的响应,如101、180等
|
// 增加其它无需回复的响应,如101、180等
|
||||||
} else {
|
} else {
|
||||||
logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
|
logger.warn("接收到失败的response响应!status:" + status + ",message:" + response.getReasonPhrase()/* .getContent().toString()*/);
|
||||||
|
if (evt.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {
|
||||||
|
CallIdHeader callIdHeader = (CallIdHeader)evt.getResponse().getHeader(CallIdHeader.NAME);
|
||||||
|
if (callIdHeader != null) {
|
||||||
|
SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
|
||||||
|
if (subscribe != null) {
|
||||||
|
subscribe.response(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// trying不会回复
|
|
||||||
// if (status == Response.TRYING) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,6 +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.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -103,9 +104,12 @@ public class DigestServerAuthenticationHelper {
|
|||||||
.createWWWAuthenticateHeader(DEFAULT_SCHEME);
|
.createWWWAuthenticateHeader(DEFAULT_SCHEME);
|
||||||
proxyAuthenticate.setParameter("realm", realm);
|
proxyAuthenticate.setParameter("realm", realm);
|
||||||
proxyAuthenticate.setParameter("nonce", generateNonce());
|
proxyAuthenticate.setParameter("nonce", generateNonce());
|
||||||
|
|
||||||
proxyAuthenticate.setParameter("opaque", "");
|
proxyAuthenticate.setParameter("opaque", "");
|
||||||
proxyAuthenticate.setParameter("stale", "FALSE");
|
proxyAuthenticate.setParameter("stale", "FALSE");
|
||||||
proxyAuthenticate.setParameter("algorithm", DEFAULT_ALGORITHM);
|
proxyAuthenticate.setParameter("algorithm", DEFAULT_ALGORITHM);
|
||||||
|
|
||||||
|
// proxyAuthenticate.setParameter("qop", "auth");
|
||||||
response.setHeader(proxyAuthenticate);
|
response.setHeader(proxyAuthenticate);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
InternalErrorHandler.handleException(ex);
|
InternalErrorHandler.handleException(ex);
|
||||||
@ -170,42 +174,116 @@ public class DigestServerAuthenticationHelper {
|
|||||||
public boolean doAuthenticatePlainTextPassword(Request request, String pass) {
|
public boolean doAuthenticatePlainTextPassword(Request request, String pass) {
|
||||||
AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
|
||||||
if ( authHeader == null ) return false;
|
if ( authHeader == null ) return false;
|
||||||
String realm = authHeader.getRealm();
|
String realm = authHeader.getRealm().trim();
|
||||||
String username = authHeader.getUsername();
|
String username = authHeader.getUsername().trim();
|
||||||
|
|
||||||
|
|
||||||
if ( username == null || realm == null ) {
|
if ( username == null || realm == null ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String nonce = authHeader.getNonce();
|
String nonce = authHeader.getNonce();
|
||||||
URI uri = authHeader.getURI();
|
URI uri = authHeader.getURI();
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略
|
||||||
|
String qop = authHeader.getQop();
|
||||||
|
|
||||||
|
// 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。
|
||||||
|
// 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护
|
||||||
|
String cNonce = authHeader.getCNonce();
|
||||||
|
|
||||||
|
// nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
|
||||||
|
int nc = authHeader.getNonceCount();
|
||||||
|
String ncStr = new DecimalFormat("00000000").format(nc);
|
||||||
|
// String ncStr = new DecimalFormat("00000000").format(Integer.parseInt(nc + "", 16));
|
||||||
|
|
||||||
String A1 = username + ":" + realm + ":" + pass;
|
String A1 = username + ":" + realm + ":" + pass;
|
||||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||||
byte mdbytes[] = messageDigest.digest(A1.getBytes());
|
byte mdbytes[] = messageDigest.digest(A1.getBytes());
|
||||||
String HA1 = toHexString(mdbytes);
|
String HA1 = toHexString(mdbytes);
|
||||||
|
System.out.println("A1: " + A1);
|
||||||
|
System.out.println("A2: " + A2);
|
||||||
|
|
||||||
|
|
||||||
mdbytes = messageDigest.digest(A2.getBytes());
|
mdbytes = messageDigest.digest(A2.getBytes());
|
||||||
String HA2 = toHexString(mdbytes);
|
String HA2 = toHexString(mdbytes);
|
||||||
|
System.out.println("HA1: " + HA1);
|
||||||
|
System.out.println("HA2: " + HA2);
|
||||||
String cnonce = authHeader.getCNonce();
|
String cnonce = authHeader.getCNonce();
|
||||||
|
System.out.println("nonce: " + nonce);
|
||||||
|
System.out.println("nc: " + ncStr);
|
||||||
|
System.out.println("cnonce: " + cnonce);
|
||||||
|
System.out.println("qop: " + qop);
|
||||||
String KD = HA1 + ":" + nonce;
|
String KD = HA1 + ":" + nonce;
|
||||||
if (cnonce != null) {
|
|
||||||
KD += ":" + cnonce;
|
if (qop != null && qop.equals("auth") ) {
|
||||||
|
if (nc != -1) {
|
||||||
|
KD += ":" + ncStr;
|
||||||
|
}
|
||||||
|
if (cnonce != null) {
|
||||||
|
KD += ":" + cnonce;
|
||||||
|
}
|
||||||
|
KD += ":" + qop;
|
||||||
}
|
}
|
||||||
KD += ":" + HA2;
|
KD += ":" + HA2;
|
||||||
|
System.out.println("KD: " + KD);
|
||||||
mdbytes = messageDigest.digest(KD.getBytes());
|
mdbytes = messageDigest.digest(KD.getBytes());
|
||||||
String mdString = toHexString(mdbytes);
|
String mdString = toHexString(mdbytes);
|
||||||
|
System.out.println("mdString: " + mdString);
|
||||||
String response = authHeader.getResponse();
|
String response = authHeader.getResponse();
|
||||||
|
System.out.println("response: " + response);
|
||||||
return mdString.equals(response);
|
return mdString.equals(response);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws NoSuchAlgorithmException {
|
||||||
|
MessageDigest messageDigest2 = MessageDigest.getInstance(DEFAULT_ALGORITHM);
|
||||||
|
String realm = "DS-2CD2520F";
|
||||||
|
String username = "admin";
|
||||||
|
String passwd = "12345";
|
||||||
|
|
||||||
|
String nonce = "4d6a553452444d30525441364e6d4d304e6a68684e47553d";
|
||||||
|
|
||||||
|
String uri = "/ISAPI/Streaming/channels/101/picture";
|
||||||
|
// qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略
|
||||||
|
String qop = "auth";
|
||||||
|
|
||||||
|
// 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。
|
||||||
|
// 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护
|
||||||
|
String cNonce = "C1A5298F939E87E8F962A5EDFC206918";
|
||||||
|
|
||||||
|
// nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
|
||||||
|
int nc = 1;
|
||||||
|
|
||||||
|
String A1 = username + ":" + realm + ":" + passwd;
|
||||||
|
System.out.println("A1: " + A1);
|
||||||
|
String A2 = "GET" + ":" + uri.toString();
|
||||||
|
System.out.println("A2: " + A2);
|
||||||
|
byte mdbytes[] = messageDigest2.digest(A1.getBytes());
|
||||||
|
String HA1 = toHexString(mdbytes);
|
||||||
|
System.out.println("HA1: " + HA1);
|
||||||
|
|
||||||
|
mdbytes = messageDigest2.digest(A2.getBytes());
|
||||||
|
String HA2 = toHexString(mdbytes);
|
||||||
|
System.out.println("HA2: " + HA2);
|
||||||
|
String cnonce = "93d4d37df32e1a85";
|
||||||
|
String KD = HA1 + ":" + nonce;
|
||||||
|
|
||||||
|
if (nc != -1) {
|
||||||
|
KD += ":" + "00000001";
|
||||||
|
}
|
||||||
|
if (cnonce != null) {
|
||||||
|
KD += ":" + cnonce;
|
||||||
|
}
|
||||||
|
if (qop != null) {
|
||||||
|
KD += ":" + qop;
|
||||||
|
}
|
||||||
|
KD += ":" + HA2;
|
||||||
|
System.out.println("KD: " + KD);
|
||||||
|
mdbytes = messageDigest2.digest(KD.getBytes());
|
||||||
|
String mdString = toHexString(mdbytes);
|
||||||
|
String response = "3993a815e5cdaf4470e9b4f9bd41cf4a";
|
||||||
|
System.out.println(mdString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,6 @@ public class RegisterLogicHandler {
|
|||||||
// TODO 后续处理,只有第一次注册时调用查询设备信息,如需更新调用更新API接口
|
// TODO 后续处理,只有第一次注册时调用查询设备信息,如需更新调用更新API接口
|
||||||
cmder.deviceInfoQuery(device);
|
cmder.deviceInfoQuery(device);
|
||||||
|
|
||||||
cmder.catalogQuery(device);
|
cmder.catalogQuery(device, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.bean;
|
package com.genersoft.iot.vmp.gb28181.bean;
|
||||||
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Device {
|
public class Device {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,25 +42,37 @@ public class Device {
|
|||||||
*/
|
*/
|
||||||
private String streamMode;
|
private String streamMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wan地址_ip
|
||||||
|
*/
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wan地址_port
|
||||||
|
*/
|
||||||
|
private int port;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wan地址
|
* wan地址
|
||||||
*/
|
*/
|
||||||
private Host host;
|
private String hostAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在线
|
* 在线
|
||||||
*/
|
*/
|
||||||
private int online;
|
private int online;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通道列表
|
* 注册时间
|
||||||
*/
|
*/
|
||||||
// private Map<String,DeviceChannel> channelMap;
|
private Long registerTimeMillis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通道个数
|
||||||
|
*/
|
||||||
private int channelCount;
|
private int channelCount;
|
||||||
|
|
||||||
private List<String> channelList;
|
|
||||||
|
|
||||||
public String getDeviceId() {
|
public String getDeviceId() {
|
||||||
return deviceId;
|
return deviceId;
|
||||||
}
|
}
|
||||||
@ -120,12 +129,28 @@ public class Device {
|
|||||||
this.streamMode = streamMode;
|
this.streamMode = streamMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Host getHost() {
|
public String getIp() {
|
||||||
return host;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHost(Host host) {
|
public void setIp(String ip) {
|
||||||
this.host = host;
|
this.ip = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostAddress() {
|
||||||
|
return hostAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostAddress(String hostAddress) {
|
||||||
|
this.hostAddress = hostAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOnline() {
|
public int getOnline() {
|
||||||
@ -144,11 +169,11 @@ public class Device {
|
|||||||
this.channelCount = channelCount;
|
this.channelCount = channelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getChannelList() {
|
public Long getRegisterTimeMillis() {
|
||||||
return channelList;
|
return registerTimeMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChannelList(List<String> channelList) {
|
public void setRegisterTimeMillis(Long registerTimeMillis) {
|
||||||
this.channelList = channelList;
|
this.registerTimeMillis = registerTimeMillis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,17 @@ package com.genersoft.iot.vmp.gb28181.bean;
|
|||||||
|
|
||||||
public class DeviceChannel {
|
public class DeviceChannel {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通道id
|
* 通道id
|
||||||
*/
|
*/
|
||||||
private String channelId;
|
private String channelId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备id
|
||||||
|
*/
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通道名
|
* 通道名
|
||||||
@ -141,18 +148,20 @@ public class DeviceChannel {
|
|||||||
/**
|
/**
|
||||||
* 流唯一编号,存在表示正在直播
|
* 流唯一编号,存在表示正在直播
|
||||||
*/
|
*/
|
||||||
private String ssrc;
|
private String streamId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否含有音频
|
* 是否含有音频
|
||||||
*/
|
*/
|
||||||
private boolean hasAudio;
|
private boolean hasAudio;
|
||||||
|
|
||||||
/**
|
public String getDeviceId() {
|
||||||
* 是否正在播放
|
return deviceId;
|
||||||
*/
|
}
|
||||||
private boolean play;
|
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPTZType(int PTZType) {
|
public void setPTZType(int PTZType) {
|
||||||
this.PTZType = PTZType;
|
this.PTZType = PTZType;
|
||||||
@ -379,14 +388,6 @@ public class DeviceChannel {
|
|||||||
this.subCount = subCount;
|
this.subCount = subCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSsrc() {
|
|
||||||
return ssrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSsrc(String ssrc) {
|
|
||||||
this.ssrc = ssrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHasAudio() {
|
public boolean isHasAudio() {
|
||||||
return hasAudio;
|
return hasAudio;
|
||||||
}
|
}
|
||||||
@ -395,11 +396,11 @@ public class DeviceChannel {
|
|||||||
this.hasAudio = hasAudio;
|
this.hasAudio = hasAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPlay() {
|
public String getStreamId() {
|
||||||
return play;
|
return streamId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlay(boolean play) {
|
public void setStreamId(String streamId) {
|
||||||
this.play = play;
|
this.streamId = streamId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.event;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.sip.ResponseEvent;
|
||||||
|
import javax.sip.message.Request;
|
||||||
|
import java.util.EventObject;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SipSubscribe {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(SipSubscribe.class);
|
||||||
|
|
||||||
|
private Map<String, SipSubscribe.Event> errorSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public interface Event {
|
||||||
|
void response(ResponseEvent event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addErrorSubscribe(String key, SipSubscribe.Event event) {
|
||||||
|
errorSubscribes.put(key, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOkSubscribe(String key, SipSubscribe.Event event) {
|
||||||
|
okSubscribes.put(key, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SipSubscribe.Event getErrorSubscribe(String key) {
|
||||||
|
return errorSubscribes.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SipSubscribe.Event getOkSubscribe(String key) {
|
||||||
|
return okSubscribes.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getErrorSubscribesSize(){
|
||||||
|
return errorSubscribes.size();
|
||||||
|
}
|
||||||
|
public int getOkSubscribesSize(){
|
||||||
|
return okSubscribes.size();
|
||||||
|
}
|
||||||
|
}
|
@ -7,8 +7,10 @@ import javax.sip.header.CSeqHeader;
|
|||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*;
|
||||||
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;
|
||||||
@ -54,7 +56,10 @@ public class SIPProcessorFactory {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private EventPublisher publisher;
|
private EventPublisher publisher;
|
||||||
|
|
||||||
@ -82,10 +87,11 @@ public class SIPProcessorFactory {
|
|||||||
@Autowired
|
@Autowired
|
||||||
@Lazy
|
@Lazy
|
||||||
private RegisterResponseProcessor registerResponseProcessor;
|
private RegisterResponseProcessor registerResponseProcessor;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private OtherResponseProcessor otherResponseProcessor;
|
private OtherResponseProcessor otherResponseProcessor;
|
||||||
|
|
||||||
|
|
||||||
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
// 注:这里使用注解会导致循环依赖注入,暂用springBean
|
||||||
private SipProvider tcpSipProvider;
|
private SipProvider tcpSipProvider;
|
||||||
|
|
||||||
@ -140,6 +146,7 @@ public class SIPProcessorFactory {
|
|||||||
processor.setOffLineDetector(offLineDetector);
|
processor.setOffLineDetector(offLineDetector);
|
||||||
processor.setCmder(cmder);
|
processor.setCmder(cmder);
|
||||||
processor.setStorager(storager);
|
processor.setStorager(storager);
|
||||||
|
processor.setRedisCatchStorage(redisCatchStorage);
|
||||||
return processor;
|
return processor;
|
||||||
} else {
|
} else {
|
||||||
return new OtherRequestProcessor();
|
return new OtherRequestProcessor();
|
||||||
@ -147,6 +154,7 @@ public class SIPProcessorFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) {
|
public ISIPResponseProcessor createResponseProcessor(ResponseEvent evt) {
|
||||||
|
|
||||||
Response response = evt.getResponse();
|
Response response = evt.getResponse();
|
||||||
CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||||
String method = cseqHeader.getMethod();
|
String method = cseqHeader.getMethod();
|
||||||
|
@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.callback;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@ -24,8 +25,10 @@ public class DeferredResultHolder {
|
|||||||
|
|
||||||
public static final String CALLBACK_CMD_PlAY = "CALLBACK_PLAY";
|
public static final String CALLBACK_CMD_PlAY = "CALLBACK_PLAY";
|
||||||
|
|
||||||
private Map<String, DeferredResult> map = new HashMap<String, DeferredResult>();
|
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
|
||||||
|
|
||||||
|
private Map<String, DeferredResult> map = new ConcurrentHashMap<String, DeferredResult>();
|
||||||
|
|
||||||
public void put(String key, DeferredResult result) {
|
public void put(String key, DeferredResult result) {
|
||||||
map.put(key, result);
|
map.put(key, result);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
|
|||||||
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
* @Description:设备能力接口,用于定义设备的控制、查询能力
|
||||||
@ -84,7 +84,7 @@ public interface ISIPCommander {
|
|||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
*/
|
*/
|
||||||
void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event);
|
void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求回放视频流
|
* 请求回放视频流
|
||||||
@ -94,15 +94,16 @@ public interface ISIPCommander {
|
|||||||
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
*/
|
*/
|
||||||
void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event);
|
void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频流停止
|
* 视频流停止
|
||||||
*
|
*
|
||||||
* @param ssrc ssrc
|
* @param ssrc ssrc
|
||||||
*/
|
*/
|
||||||
|
void streamByeCmd(String ssrc, SipSubscribe.Event okEvent);
|
||||||
void streamByeCmd(String ssrc);
|
void streamByeCmd(String ssrc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 语音广播
|
* 语音广播
|
||||||
*
|
*
|
||||||
@ -176,7 +177,7 @@ public interface ISIPCommander {
|
|||||||
*
|
*
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
boolean catalogQuery(Device device);
|
boolean catalogQuery(Device device, SipSubscribe.Event errorEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询录像信息
|
* 查询录像信息
|
||||||
@ -214,4 +215,11 @@ public interface ISIPCommander {
|
|||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
boolean mobilePostitionQuery(Device device);
|
boolean mobilePostitionQuery(Device device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放rtpserver
|
||||||
|
* @param device
|
||||||
|
* @param channelId
|
||||||
|
*/
|
||||||
|
void closeRTPServer(Device device, String channelId);
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,8 @@ public class SIPRequestHeaderProvider {
|
|||||||
|
|
||||||
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createMessageRequest(Device device, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
Host host = device.getHost();
|
|
||||||
// sipuri
|
// sipuri
|
||||||
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
|
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||||
// via
|
// via
|
||||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
|
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(),
|
||||||
@ -75,22 +74,21 @@ public class SIPRequestHeaderProvider {
|
|||||||
|
|
||||||
request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
|
request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
|
||||||
toHeader, viaHeaders, maxForwards);
|
toHeader, viaHeaders, maxForwards);
|
||||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
|
||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag, String ssrc) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
Host host = device.getHost();
|
|
||||||
//请求行
|
//请求行
|
||||||
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, host.getAddress());
|
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(channelId, device.getHostAddress());
|
||||||
//via
|
//via
|
||||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
// ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
|
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag);
|
||||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getHost().getIp(), device.getHost().getPort(), device.getTransport(), viaTag);
|
|
||||||
viaHeader.setRPort();
|
viaHeader.setRPort();
|
||||||
viaHeaders.add(viaHeader);
|
viaHeaders.add(viaHeader);
|
||||||
|
|
||||||
//from
|
//from
|
||||||
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain());
|
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(),sipConfig.getSipDomain());
|
||||||
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
|
||||||
@ -122,20 +120,18 @@ public class SIPRequestHeaderProvider {
|
|||||||
// Subject
|
// Subject
|
||||||
SubjectHeader subjectHeader = sipFactory.createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getSipId(), 0));
|
SubjectHeader subjectHeader = sipFactory.createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", channelId, ssrc, sipConfig.getSipId(), 0));
|
||||||
request.addHeader(subjectHeader);
|
request.addHeader(subjectHeader);
|
||||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "SDP");
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
public Request createPlaybackInviteRequest(Device device, String channelId, String content, String viaTag, String fromTag, String toTag) throws ParseException, InvalidArgumentException, PeerUnavailableException {
|
||||||
Request request = null;
|
Request request = null;
|
||||||
Host host = device.getHost();
|
|
||||||
//请求行
|
//请求行
|
||||||
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), host.getAddress());
|
SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
|
||||||
//via
|
// via
|
||||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
|
||||||
// ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(sipConfig.getSipIp(), sipConfig.getSipPort(), device.getTransport(), viaTag);
|
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getIp(), device.getPort(), device.getTransport(), viaTag);
|
||||||
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(device.getHost().getIp(), device.getHost().getPort(), device.getTransport(), viaTag);
|
|
||||||
viaHeader.setRPort();
|
viaHeader.setRPort();
|
||||||
viaHeaders.add(viaHeader);
|
viaHeaders.add(viaHeader);
|
||||||
//from
|
//from
|
||||||
@ -167,7 +163,7 @@ public class SIPRequestHeaderProvider {
|
|||||||
// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory().createSipURI(sipConfig.getSipId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||||
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
|
||||||
|
|
||||||
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "SDP");
|
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
|
||||||
request.setContent(content, contentTypeHeader);
|
request.setContent(content, contentTypeHeader);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,14 @@
|
|||||||
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.sip.ClientTransaction;
|
import javax.sip.*;
|
||||||
import javax.sip.Dialog;
|
|
||||||
import javax.sip.InvalidArgumentException;
|
|
||||||
import javax.sip.SipException;
|
|
||||||
import javax.sip.SipFactory;
|
|
||||||
import javax.sip.SipProvider;
|
|
||||||
import javax.sip.TransactionDoesNotExistException;
|
|
||||||
import javax.sip.address.SipURI;
|
import javax.sip.address.SipURI;
|
||||||
|
import javax.sip.header.CallIdHeader;
|
||||||
|
import javax.sip.header.Header;
|
||||||
import javax.sip.header.ViaHeader;
|
import javax.sip.header.ViaHeader;
|
||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
|
|
||||||
@ -19,9 +16,13 @@ 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.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
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.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@ -41,6 +42,8 @@ import com.genersoft.iot.vmp.gb28181.utils.DateUtil;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class SIPCommander implements ISIPCommander {
|
public class SIPCommander implements ISIPCommander {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SIPCommander.class);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SipConfig sipConfig;
|
private SipConfig sipConfig;
|
||||||
@ -53,6 +56,9 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@Qualifier(value="tcpSipProvider")
|
@Qualifier(value="tcpSipProvider")
|
||||||
@ -63,14 +69,20 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
private SipProvider udpSipProvider;
|
private SipProvider udpSipProvider;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMUtils zlmUtils;
|
private ZLMRTPServerFactory zlmrtpServerFactory;
|
||||||
|
|
||||||
@Value("${media.rtp.enable}")
|
@Value("${media.rtp.enable}")
|
||||||
private boolean rtpEnable;
|
private boolean rtpEnable;
|
||||||
|
|
||||||
|
@Value("${media.seniorSdp}")
|
||||||
|
private boolean seniorSdp;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMHttpHookSubscribe subscribe;
|
private ZLMHttpHookSubscribe subscribe;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SipSubscribe sipSubscribe;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -176,19 +188,29 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
|
* @param moveSpeed 镜头移动速度 默认 0XFF (0-255)
|
||||||
* @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
|
* @param zoomSpeed 镜头缩放速度 默认 0X1 (0-255)
|
||||||
*/
|
*/
|
||||||
public static String frontEndCmdString(int cmdCode, int parameter1, int parameter2, int combineCode2) {
|
|
||||||
|
/**
|
||||||
|
* 云台指令码计算
|
||||||
|
*
|
||||||
|
* @param cmdCode 指令码
|
||||||
|
* @param horizonSpeed 水平移动速度
|
||||||
|
* @param verticalSpeed 垂直移动速度
|
||||||
|
* @param zoomSpeed 缩放速度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String frontEndCmdString(int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed) {
|
||||||
StringBuilder builder = new StringBuilder("A50F01");
|
StringBuilder builder = new StringBuilder("A50F01");
|
||||||
String strTmp;
|
String strTmp;
|
||||||
strTmp = String.format("%02X", cmdCode);
|
strTmp = String.format("%02X", cmdCode);
|
||||||
builder.append(strTmp, 0, 2);
|
builder.append(strTmp, 0, 2);
|
||||||
strTmp = String.format("%02X", parameter1);
|
strTmp = String.format("%02X", horizonSpeed);
|
||||||
builder.append(strTmp, 0, 2);
|
builder.append(strTmp, 0, 2);
|
||||||
strTmp = String.format("%02X", parameter2);
|
strTmp = String.format("%02X", verticalSpeed);
|
||||||
builder.append(strTmp, 0, 2);
|
builder.append(strTmp, 0, 2);
|
||||||
strTmp = String.format("%X", combineCode2);
|
strTmp = String.format("%X", zoomSpeed);
|
||||||
builder.append(strTmp, 0, 1).append("0");
|
builder.append(strTmp, 0, 1).append("0");
|
||||||
//计算校验码
|
//计算校验码
|
||||||
int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
|
int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + horizonSpeed + verticalSpeed + (zoomSpeed & 0XF0)) % 0X100;
|
||||||
strTmp = String.format("%02X", checkCode);
|
strTmp = String.format("%02X", checkCode);
|
||||||
builder.append(strTmp, 0, 2);
|
builder.append(strTmp, 0, 2);
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
@ -237,14 +259,14 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param device 控制设备
|
* @param device 控制设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
* @param cmdCode 指令码
|
* @param cmdCode 指令码
|
||||||
* @param parameter1 数据1
|
* @param horizonSpeed 水平移动速度
|
||||||
* @param parameter2 数据2
|
* @param verticalSpeed 垂直移动速度
|
||||||
* @param combineCode2 组合码2
|
* @param zoomSpeed 缩放速度
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) {
|
public boolean frontEndCmd(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed) {
|
||||||
try {
|
try {
|
||||||
String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
|
String cmdStr= frontEndCmdString(cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||||
System.out.println("控制字符串:" + cmdStr);
|
System.out.println("控制字符串:" + cmdStr);
|
||||||
StringBuffer ptzXml = new StringBuffer(200);
|
StringBuffer ptzXml = new StringBuffer(200);
|
||||||
ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
|
ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
|
||||||
@ -258,7 +280,6 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
ptzXml.append("</Control>\r\n");
|
ptzXml.append("</Control>\r\n");
|
||||||
|
|
||||||
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
|
Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "ViaPtzBranch", "FromPtzTag", "ToPtzTag");
|
||||||
|
|
||||||
transmitRequest(device, request);
|
transmitRequest(device, request);
|
||||||
return true;
|
return true;
|
||||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
@ -266,28 +287,39 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求预览视频流
|
* 请求预览视频流
|
||||||
*
|
|
||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
* @param channelId 预览通道
|
* @param channelId 预览通道
|
||||||
|
* @param event hook订阅
|
||||||
|
* @param errorEvent sip错误订阅
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event) {
|
public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String ssrc = streamSession.createPlaySsrc();
|
String ssrc = streamSession.createPlaySsrc();
|
||||||
|
String streamId = null;
|
||||||
|
if (rtpEnable) {
|
||||||
|
streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||||
|
}else {
|
||||||
|
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||||
|
}
|
||||||
String streamMode = device.getStreamMode().toUpperCase();
|
String streamMode = device.getStreamMode().toUpperCase();
|
||||||
MediaServerConfig mediaInfo = storager.getMediaInfo();
|
MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||||
|
if (mediaInfo == null) {
|
||||||
|
logger.warn("点播时发现ZLM尚未连接...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
String mediaPort = null;
|
String mediaPort = null;
|
||||||
// 使用动态udp端口
|
// 使用动态udp端口
|
||||||
if (rtpEnable) {
|
if (rtpEnable) {
|
||||||
mediaPort = zlmUtils.getNewRTPPort(ssrc) + "";
|
mediaPort = zlmrtpServerFactory.createRTPServer(streamId) + "";
|
||||||
}else {
|
}else {
|
||||||
mediaPort = mediaInfo.getRtpProxyPort();
|
mediaPort = mediaInfo.getRtpProxyPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
|
||||||
// 添加订阅
|
// 添加订阅
|
||||||
JSONObject subscribeKey = new JSONObject();
|
JSONObject subscribeKey = new JSONObject();
|
||||||
subscribeKey.put("app", "rtp");
|
subscribeKey.put("app", "rtp");
|
||||||
@ -297,7 +329,8 @@ 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="+channelId+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
// content.append("o="+channelId+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
||||||
|
content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
||||||
content.append("s=Play\r\n");
|
content.append("s=Play\r\n");
|
||||||
content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
|
||||||
content.append("t=0 0\r\n");
|
content.append("t=0 0\r\n");
|
||||||
@ -327,17 +360,14 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
}
|
}
|
||||||
content.append("y="+ssrc+"\r\n");//ssrc
|
content.append("y="+ssrc+"\r\n");//ssrc
|
||||||
|
|
||||||
|
// String fromTag = UUID.randomUUID().toString();
|
||||||
|
// Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, fromTag, null, ssrc);
|
||||||
|
|
||||||
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "live", null, ssrc);
|
Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "live", null, ssrc);
|
||||||
|
|
||||||
ClientTransaction transaction = transmitRequest(device, request);
|
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
||||||
streamSession.put(ssrc, transaction);
|
streamSession.put(streamId, transaction);
|
||||||
DeviceChannel deviceChannel = storager.queryChannel(device.getDeviceId(), channelId);
|
|
||||||
if (deviceChannel != null) {
|
|
||||||
deviceChannel.setSsrc(ssrc);
|
|
||||||
storager.updateChannel(device.getDeviceId(), deviceChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO 订阅SIP response,处理对方的错误返回
|
|
||||||
|
|
||||||
|
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
@ -354,9 +384,10 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
* @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event) {
|
public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event
|
||||||
|
, SipSubscribe.Event errorEvent) {
|
||||||
try {
|
try {
|
||||||
MediaServerConfig mediaInfo = storager.getMediaInfo();
|
MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||||
String ssrc = streamSession.createPlayBackSsrc();
|
String ssrc = streamSession.createPlayBackSsrc();
|
||||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
||||||
// 添加订阅
|
// 添加订阅
|
||||||
@ -378,57 +409,91 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
String mediaPort = null;
|
String mediaPort = null;
|
||||||
// 使用动态udp端口
|
// 使用动态udp端口
|
||||||
if (rtpEnable) {
|
if (rtpEnable) {
|
||||||
mediaPort = zlmUtils.getNewRTPPort(ssrc) + "";
|
mediaPort = zlmrtpServerFactory.createRTPServer(streamId) + "";
|
||||||
}else {
|
}else {
|
||||||
mediaPort = mediaInfo.getRtpProxyPort();
|
mediaPort = mediaInfo.getRtpProxyPort();
|
||||||
}
|
}
|
||||||
String streamMode = device.getStreamMode().toUpperCase();
|
String streamMode = device.getStreamMode().toUpperCase();
|
||||||
if("TCP-PASSIVE".equals(streamMode)) {
|
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 126 125 99 34 98 97 96\r\n");
|
if (seniorSdp) {
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 126 125 99 34 98 97 96\r\n");
|
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 126 125 99 34 98 97 96\r\n");
|
||||||
}else if("UDP".equals(streamMode)) {
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
content.append("m=video "+ mediaPort +" RTP/AVP 126 125 99 34 98 97 96\r\n");
|
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 126 125 99 34 98 97 96\r\n");
|
||||||
}
|
}else if("UDP".equals(streamMode)) {
|
||||||
content.append("a=recvonly\r\n");
|
content.append("m=video "+ mediaPort +" RTP/AVP 126 125 99 34 98 97 96\r\n");
|
||||||
content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
|
}
|
||||||
content.append("a=rtpmap:126 H264/90000\r\n");
|
content.append("a=recvonly\r\n");
|
||||||
content.append("a=rtpmap:125 H264S/90000\r\n");
|
content.append("a=fmtp:126 profile-level-id=42e01e\r\n");
|
||||||
content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
|
content.append("a=rtpmap:126 H264/90000\r\n");
|
||||||
content.append("a=rtpmap:99 MP4V-ES/90000\r\n");
|
content.append("a=rtpmap:125 H264S/90000\r\n");
|
||||||
content.append("a=fmtp:99 profile-level-id=3\r\n");
|
content.append("a=fmtp:125 profile-level-id=42e01e\r\n");
|
||||||
content.append("a=rtpmap:98 H264/90000\r\n");
|
content.append("a=rtpmap:99 MP4V-ES/90000\r\n");
|
||||||
content.append("a=rtpmap:97 MPEG4/90000\r\n");
|
content.append("a=fmtp:99 profile-level-id=3\r\n");
|
||||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
content.append("a=rtpmap:98 H264/90000\r\n");
|
||||||
if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
|
content.append("a=rtpmap:97 MPEG4/90000\r\n");
|
||||||
content.append("a=setup:passive\r\n");
|
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||||
content.append("a=connection:new\r\n");
|
if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
|
||||||
}else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
|
content.append("a=setup:passive\r\n");
|
||||||
content.append("a=setup:active\r\n");
|
content.append("a=connection:new\r\n");
|
||||||
content.append("a=connection:new\r\n");
|
}else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
|
||||||
|
content.append("a=setup:active\r\n");
|
||||||
|
content.append("a=connection:new\r\n");
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
if("TCP-PASSIVE".equals(streamMode)) {
|
||||||
|
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
|
}else if ("TCP-ACTIVE".equals(streamMode)) {
|
||||||
|
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 98 97\r\n");
|
||||||
|
}else if("UDP".equals(streamMode)) {
|
||||||
|
content.append("m=video "+ mediaPort +" RTP/AVP 96 98 97\r\n");
|
||||||
|
}
|
||||||
|
content.append("a=recvonly\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");
|
||||||
|
if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式
|
||||||
|
content.append("a=setup:passive\r\n");
|
||||||
|
content.append("a=connection:new\r\n");
|
||||||
|
}else if ("TCP-ACTIVE".equals(streamMode)) { // tcp主动模式
|
||||||
|
content.append("a=setup:active\r\n");
|
||||||
|
content.append("a=connection:new\r\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content.append("y="+ssrc+"\r\n");//ssrc
|
content.append("y="+ssrc+"\r\n");//ssrc
|
||||||
|
|
||||||
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "playback", null);
|
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "playback", null);
|
||||||
|
|
||||||
ClientTransaction transaction = transmitRequest(device, request);
|
ClientTransaction transaction = transmitRequest(device, request, errorEvent);
|
||||||
streamSession.put(ssrc, transaction);
|
streamSession.put(streamId, transaction);
|
||||||
|
|
||||||
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
} catch ( SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 视频流停止
|
* 视频流停止
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void streamByeCmd(String ssrc) {
|
public void streamByeCmd(String ssrc) {
|
||||||
|
streamByeCmd(ssrc, null);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void streamByeCmd(String streamId, SipSubscribe.Event okEvent) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ClientTransaction transaction = streamSession.get(ssrc);
|
ClientTransaction transaction = streamSession.get(streamId);
|
||||||
|
// 服务重启后
|
||||||
if (transaction == null) {
|
if (transaction == null) {
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
|
if (streamInfo != null) {
|
||||||
|
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,6 +501,9 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
if (dialog == null) {
|
if (dialog == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Request byeRequest = dialog.createRequest(Request.BYE);
|
Request byeRequest = dialog.createRequest(Request.BYE);
|
||||||
SipURI byeURI = (SipURI) byeRequest.getRequestURI();
|
SipURI byeURI = (SipURI) byeRequest.getRequestURI();
|
||||||
String vh = transaction.getRequest().getHeader(ViaHeader.NAME).toString();
|
String vh = transaction.getRequest().getHeader(ViaHeader.NAME).toString();
|
||||||
@ -452,8 +520,16 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
} else if("UDP".equals(protocol)) {
|
} else if("UDP".equals(protocol)) {
|
||||||
clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
|
clientTransaction = udpSipProvider.getNewClientTransaction(byeRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallIdHeader callIdHeader = (CallIdHeader) byeRequest.getHeader(CallIdHeader.NAME);
|
||||||
|
if (okEvent != null) {
|
||||||
|
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);
|
||||||
|
}
|
||||||
|
|
||||||
dialog.sendRequest(clientTransaction);
|
dialog.sendRequest(clientTransaction);
|
||||||
streamSession.remove(ssrc);
|
|
||||||
|
streamSession.remove(streamId);
|
||||||
|
zlmrtpServerFactory.closeRTPServer(streamId);
|
||||||
} catch (TransactionDoesNotExistException e) {
|
} catch (TransactionDoesNotExistException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
@ -571,6 +647,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
catalogXml.append("</Query>\r\n");
|
catalogXml.append("</Query>\r\n");
|
||||||
|
|
||||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag");
|
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaDeviceInfoBranch", "FromDeviceInfoTag", "ToDeviceInfoTag");
|
||||||
|
|
||||||
transmitRequest(device, request);
|
transmitRequest(device, request);
|
||||||
|
|
||||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
@ -586,7 +663,7 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
* @param device 视频设备
|
* @param device 视频设备
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean catalogQuery(Device device) {
|
public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) {
|
||||||
// 清空通道
|
// 清空通道
|
||||||
storager.cleanChannelsForDevice(device.getDeviceId());
|
storager.cleanChannelsForDevice(device.getDeviceId());
|
||||||
try {
|
try {
|
||||||
@ -598,8 +675,9 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
|
||||||
catalogXml.append("</Query>\r\n");
|
catalogXml.append("</Query>\r\n");
|
||||||
|
|
||||||
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", "ToCatalogTag");
|
Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), "ViaCatalogBranch", "FromCatalogTag", null);
|
||||||
transmitRequest(device, request);
|
|
||||||
|
transmitRequest(device, request, errorEvent);
|
||||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
@ -631,7 +709,8 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
recordInfoXml.append("<Type>all</Type>\r\n");
|
recordInfoXml.append("<Type>all</Type>\r\n");
|
||||||
recordInfoXml.append("</Query>\r\n");
|
recordInfoXml.append("</Query>\r\n");
|
||||||
|
|
||||||
Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", "ToRecordInfoTag");
|
Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), "ViaRecordInfoBranch", "FromRecordInfoTag", null);
|
||||||
|
|
||||||
transmitRequest(device, request);
|
transmitRequest(device, request);
|
||||||
} catch (SipException | ParseException | InvalidArgumentException e) {
|
} catch (SipException | ParseException | InvalidArgumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -683,17 +762,45 @@ public class SIPCommander implements ISIPCommander {
|
|||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
private ClientTransaction transmitRequest(Device device, Request request) throws SipException {
|
||||||
|
return transmitRequest(device, request, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent) throws SipException {
|
||||||
|
return transmitRequest(device, request, errorEvent, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientTransaction transmitRequest(Device device, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException {
|
||||||
ClientTransaction clientTransaction = null;
|
ClientTransaction clientTransaction = null;
|
||||||
if("TCP".equals(device.getTransport())) {
|
if("TCP".equals(device.getTransport())) {
|
||||||
clientTransaction = tcpSipProvider.getNewClientTransaction(request);
|
clientTransaction = tcpSipProvider.getNewClientTransaction(request);
|
||||||
} else if("UDP".equals(device.getTransport())) {
|
} else if("UDP".equals(device.getTransport())) {
|
||||||
clientTransaction = udpSipProvider.getNewClientTransaction(request);
|
clientTransaction = udpSipProvider.getNewClientTransaction(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
|
||||||
|
// 添加错误订阅
|
||||||
|
if (errorEvent != null) {
|
||||||
|
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), errorEvent);
|
||||||
|
}
|
||||||
|
// 添加订阅
|
||||||
|
if (okEvent != null) {
|
||||||
|
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), okEvent);
|
||||||
|
}
|
||||||
|
|
||||||
clientTransaction.sendRequest();
|
clientTransaction.sendRequest();
|
||||||
return clientTransaction;
|
return clientTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeRTPServer(Device device, String channelId) {
|
||||||
|
if (rtpEnable) {
|
||||||
|
String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
|
||||||
|
zlmrtpServerFactory.closeRTPServer(streamId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import javax.sip.SipException;
|
|||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import org.dom4j.Document;
|
import org.dom4j.Document;
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
@ -48,6 +49,8 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
|
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
private EventPublisher publisher;
|
private EventPublisher publisher;
|
||||||
|
|
||||||
private RedisUtil redis;
|
private RedisUtil redis;
|
||||||
@ -294,7 +297,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
device.setStreamMode("UDP");
|
device.setStreamMode("UDP");
|
||||||
}
|
}
|
||||||
storager.updateDevice(device);
|
storager.updateDevice(device);
|
||||||
cmder.catalogQuery(device);
|
cmder.catalogQuery(device, null);
|
||||||
// 回复200 OK
|
// 回复200 OK
|
||||||
responseAck(evt);
|
responseAck(evt);
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
@ -315,12 +318,16 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
try {
|
try {
|
||||||
Element rootElement = getRootElement(evt);
|
Element rootElement = getRootElement(evt);
|
||||||
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
String deviceId = XmlUtil.getText(rootElement, "DeviceID");
|
||||||
// 回复200 OK
|
// 检查设备是否存在, 不存在则不回复
|
||||||
responseAck(evt);
|
if (storager.exists(deviceId)) {
|
||||||
if (offLineDetector.isOnline(deviceId)) {
|
// 回复200 OK
|
||||||
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
responseAck(evt);
|
||||||
} else {
|
if (offLineDetector.isOnline(deviceId)) {
|
||||||
|
publisher.onlineEventPublish(deviceId, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -447,10 +454,10 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
String NotifyType =XmlUtil.getText(rootElement, "NotifyType");
|
String NotifyType =XmlUtil.getText(rootElement, "NotifyType");
|
||||||
if (NotifyType.equals("121")){
|
if (NotifyType.equals("121")){
|
||||||
logger.info("媒体播放完毕,通知关流");
|
logger.info("媒体播放完毕,通知关流");
|
||||||
StreamInfo streamInfo = storager.queryPlaybackByDevice(deviceId, "*");
|
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, "*");
|
||||||
if (streamInfo != null) {
|
if (streamInfo != null) {
|
||||||
storager.stopPlayback(streamInfo);
|
redisCatchStorage.stopPlayback(streamInfo);
|
||||||
cmder.streamByeCmd(streamInfo.getSsrc());
|
cmder.streamByeCmd(streamInfo.getStreamId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
} catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
|
||||||
@ -503,4 +510,11 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
this.offLineDetector = offLineDetector;
|
this.offLineDetector = offLineDetector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IRedisCatchStorage getRedisCatchStorage() {
|
||||||
|
return redisCatchStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) {
|
||||||
|
this.redisCatchStorage = redisCatchStorage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,17 +107,15 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
rPort = viaHeader.getPort();
|
rPort = viaHeader.getPort();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
Host host = new Host();
|
|
||||||
host.setIp(received);
|
|
||||||
host.setPort(rPort);
|
|
||||||
host.setAddress(received.concat(":").concat(String.valueOf(rPort)));
|
|
||||||
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
AddressImpl address = (AddressImpl) fromHeader.getAddress();
|
||||||
SipUri uri = (SipUri) address.getURI();
|
SipUri uri = (SipUri) address.getURI();
|
||||||
String deviceId = uri.getUser();
|
String deviceId = uri.getUser();
|
||||||
device = new Device();
|
device = new Device();
|
||||||
device.setStreamMode("UDP");
|
device.setStreamMode("UDP");
|
||||||
device.setDeviceId(deviceId);
|
device.setDeviceId(deviceId);
|
||||||
device.setHost(host);
|
device.setIp(received);
|
||||||
|
device.setPort(rPort);
|
||||||
|
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
|
||||||
// 注销成功
|
// 注销成功
|
||||||
if (expiresHeader != null && expiresHeader.getExpires() == 0) {
|
if (expiresHeader != null && expiresHeader.getExpires() == 0) {
|
||||||
registerFlag = 2;
|
registerFlag = 2;
|
||||||
@ -141,9 +139,15 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor {
|
|||||||
// 下发catelog查询目录
|
// 下发catelog查询目录
|
||||||
if (registerFlag == 1 && device != null) {
|
if (registerFlag == 1 && device != null) {
|
||||||
logger.info("注册成功! deviceId:" + device.getDeviceId());
|
logger.info("注册成功! deviceId:" + device.getDeviceId());
|
||||||
|
boolean exists = storager.exists(device.getDeviceId());
|
||||||
|
device.setRegisterTimeMillis(System.currentTimeMillis());
|
||||||
storager.updateDevice(device);
|
storager.updateDevice(device);
|
||||||
publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
|
publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER);
|
||||||
handler.onRegister(device);
|
|
||||||
|
// 只有第一次注册才更新通道
|
||||||
|
if (!exists) {
|
||||||
|
handler.onRegister(device);
|
||||||
|
}
|
||||||
} else if (registerFlag == 2) {
|
} else if (registerFlag == 2) {
|
||||||
logger.info("注销成功! deviceId:" + device.getDeviceId());
|
logger.info("注销成功! deviceId:" + device.getDeviceId());
|
||||||
publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
|
publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER);
|
||||||
|
@ -12,6 +12,7 @@ import javax.sip.header.ViaHeader;
|
|||||||
import javax.sip.message.Request;
|
import javax.sip.message.Request;
|
||||||
import javax.sip.message.Response;
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
|
import gov.nist.javax.sip.header.CSeq;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -23,14 +24,14 @@ import com.genersoft.iot.vmp.gb28181.transmit.response.ISIPResponseProcessor;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:处理INVITE响应
|
* @Description:处理INVITE响应
|
||||||
* @author: swwheihei
|
* @author: swwheihei
|
||||||
* @date: 2020年5月3日 下午4:43:52
|
* @date: 2020年5月3日 下午4:43:52
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class InviteResponseProcessor implements ISIPResponseProcessor {
|
public class InviteResponseProcessor implements ISIPResponseProcessor {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(SIPProcessorFactory.class);
|
private final static Logger logger = LoggerFactory.getLogger(InviteResponseProcessor.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理invite响应
|
* 处理invite响应
|
||||||
@ -49,48 +50,16 @@ public class InviteResponseProcessor implements ISIPResponseProcessor {
|
|||||||
// 成功响应
|
// 成功响应
|
||||||
// 下发ack
|
// 下发ack
|
||||||
if (statusCode == Response.OK) {
|
if (statusCode == Response.OK) {
|
||||||
// ClientTransaction clientTransaction = evt.getClientTransaction();
|
|
||||||
// if(clientTransaction == null){
|
|
||||||
// logger.error("回复ACK时,clientTransaction为null >>> {}",response);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// Dialog clientDialog = clientTransaction.getDialog();
|
|
||||||
|
|
||||||
// CSeqHeader clientCSeqHeader = (CSeqHeader)
|
|
||||||
// response.getHeader(CSeqHeader.NAME);
|
|
||||||
// long cseqId = clientCSeqHeader.getSeqNumber();
|
|
||||||
// /*
|
|
||||||
// createAck函数,创建的ackRequest,会采用Invite响应的200OK,中的contact字段中的地址,作为目标地址。
|
|
||||||
// 有的终端传上来的可能还是内网地址,会造成ack发送不出去。接受不到音视频流
|
|
||||||
// 所以在此处统一替换地址。和响应消息的Via头中的地址保持一致。
|
|
||||||
// */
|
|
||||||
// Request ackRequest = clientDialog.createAck(cseqId);
|
|
||||||
// SipURI requestURI = (SipURI) ackRequest.getRequestURI();
|
|
||||||
// ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
|
|
||||||
// try {
|
|
||||||
// requestURI.setHost(viaHeader.getHost());
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// requestURI.setPort(viaHeader.getPort());
|
|
||||||
// clientDialog.sendAck(ackRequest);
|
|
||||||
|
|
||||||
Dialog dialog = evt.getDialog();
|
Dialog dialog = evt.getDialog();
|
||||||
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
CSeqHeader cseq = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
|
||||||
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
Request reqAck = dialog.createAck(cseq.getSeqNumber());
|
||||||
|
|
||||||
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
SipURI requestURI = (SipURI) reqAck.getRequestURI();
|
||||||
ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
|
ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
|
||||||
// String viaHost =viaHeader.getHost();
|
|
||||||
//getHost()函数取回的IP地址是“[xxx.xxx.xxx.xxx:yyyy]”的格式,需用正则表达式截取为“xxx.xxx.xxx.xxx"格式
|
|
||||||
// Pattern p = Pattern.compile("(?<=//|)((\\w)+\\.)+\\w+");
|
|
||||||
// Matcher matcher = p.matcher(viaHeader.getHost());
|
|
||||||
// if (matcher.find()) {
|
|
||||||
// requestURI.setHost(matcher.group());
|
|
||||||
// }
|
|
||||||
requestURI.setHost(viaHeader.getHost());
|
requestURI.setHost(viaHeader.getHost());
|
||||||
requestURI.setPort(viaHeader.getPort());
|
requestURI.setPort(viaHeader.getPort());
|
||||||
reqAck.setRequestURI(requestURI);
|
reqAck.setRequestURI(requestURI);
|
||||||
|
|
||||||
dialog.sendAck(reqAck);
|
dialog.sendAck(reqAck);
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException | SipException e) {
|
} catch (InvalidArgumentException | SipException e) {
|
||||||
|
@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.media.zlm;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -29,6 +30,9 @@ public class ZLMHTTPProxyController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Value("${media.port}")
|
@Value("${media.port}")
|
||||||
private int mediaHttpPort;
|
private int mediaHttpPort;
|
||||||
|
|
||||||
@ -36,10 +40,10 @@ public class ZLMHTTPProxyController {
|
|||||||
@RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
|
@RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
|
||||||
public Object proxy(HttpServletRequest request, HttpServletResponse response){
|
public Object proxy(HttpServletRequest request, HttpServletResponse response){
|
||||||
|
|
||||||
if (storager.getMediaInfo() == null) {
|
if (redisCatchStorage.getMediaInfo() == null) {
|
||||||
return "未接入流媒体";
|
return "未接入流媒体";
|
||||||
}
|
}
|
||||||
MediaServerConfig mediaInfo = storager.getMediaInfo();
|
MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||||
String requestURI = String.format("http://%s:%s%s?%s&%s",
|
String requestURI = String.format("http://%s:%s%s?%s&%s",
|
||||||
mediaInfo.getLocalIP(),
|
mediaInfo.getLocalIP(),
|
||||||
mediaHttpPort,
|
mediaHttpPort,
|
||||||
|
@ -4,13 +4,17 @@ import java.math.BigInteger;
|
|||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.utils.IpUtil;
|
import com.genersoft.iot.vmp.utils.IpUtil;
|
||||||
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
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;
|
||||||
@ -43,15 +47,24 @@ public class ZLMHttpHookListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SIPCommander cmder;
|
private SIPCommander cmder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPlayService playService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMHttpHookSubscribe subscribe;
|
private ZLMHttpHookSubscribe subscribe;
|
||||||
|
|
||||||
|
@Value("${media.autoApplyPlay}")
|
||||||
|
private boolean autoApplyPlay;
|
||||||
|
|
||||||
@Value("${media.ip}")
|
@Value("${media.ip}")
|
||||||
private String mediaIp;
|
private String mediaIp;
|
||||||
|
|
||||||
@ -135,34 +148,6 @@ public class ZLMHttpHookListener {
|
|||||||
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
|
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
|
||||||
if (subscribe != null) subscribe.response(json);
|
if (subscribe != null) subscribe.response(json);
|
||||||
|
|
||||||
// if ("rtp".equals(app)) {
|
|
||||||
// String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
|
|
||||||
// StreamInfo streamInfoForPlay = storager.queryPlayBySSRC(ssrc);
|
|
||||||
// if ("rtp".equals(app) && streamInfoForPlay != null ) {
|
|
||||||
// MediaServerConfig mediaInfo = storager.getMediaInfo();
|
|
||||||
// streamInfoForPlay.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlay.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlay.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlay.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlay.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), streamId));
|
|
||||||
// streamInfoForPlay.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlay.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId));
|
|
||||||
// storager.startPlay(streamInfoForPlay);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// StreamInfo streamInfoForPlayBack = storager.queryPlaybackBySSRC(ssrc);
|
|
||||||
// if ("rtp".equals(app) && streamInfoForPlayBack != null ) {
|
|
||||||
// MediaServerConfig mediaInfo = storager.getMediaInfo();
|
|
||||||
// streamInfoForPlayBack.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlayBack.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlayBack.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlayBack.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlayBack.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), streamId));
|
|
||||||
// streamInfoForPlayBack.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
|
|
||||||
// streamInfoForPlayBack.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId));
|
|
||||||
// storager.startPlayback(streamInfoForPlayBack);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
@ -268,15 +253,13 @@ public class ZLMHttpHookListener {
|
|||||||
String app = json.getString("app");
|
String app = json.getString("app");
|
||||||
String streamId = json.getString("stream");
|
String streamId = json.getString("stream");
|
||||||
boolean regist = json.getBoolean("regist");
|
boolean regist = json.getBoolean("regist");
|
||||||
// String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 要求大写且首位补零
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
|
|
||||||
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
|
|
||||||
if ("rtp".equals(app) && !regist ) {
|
if ("rtp".equals(app) && !regist ) {
|
||||||
if (streamInfo!=null){
|
if (streamInfo!=null){
|
||||||
storager.stopPlay(streamInfo);
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
}else{
|
}else{
|
||||||
streamInfo = storager.queryPlaybackBySSRC(ssrc);
|
streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
|
||||||
storager.stopPlayback(streamInfo);
|
redisCatchStorage.stopPlayback(streamInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,17 +282,15 @@ public class ZLMHttpHookListener {
|
|||||||
logger.debug("ZLM HOOK on_stream_none_reader API调用,参数:" + json.toString());
|
logger.debug("ZLM HOOK on_stream_none_reader API调用,参数:" + json.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
BigInteger bigint=new BigInteger(json.getString("stream"), 16);
|
String streamId = json.getString("stream");
|
||||||
int numb=bigint.intValue();
|
|
||||||
String ssrc = String.format("%010d", numb);
|
cmder.streamByeCmd(streamId);
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
cmder.streamByeCmd(ssrc);
|
|
||||||
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
|
|
||||||
if (streamInfo!=null){
|
if (streamInfo!=null){
|
||||||
storager.stopPlay(streamInfo);
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
}else{
|
}else{
|
||||||
streamInfo = storager.queryPlaybackBySSRC(ssrc);
|
streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
|
||||||
storager.stopPlayback(streamInfo);
|
redisCatchStorage.stopPlayback(streamInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject ret = new JSONObject();
|
JSONObject ret = new JSONObject();
|
||||||
@ -330,7 +311,31 @@ public class ZLMHttpHookListener {
|
|||||||
logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
|
logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
|
||||||
}
|
}
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
if (autoApplyPlay) {
|
||||||
|
String app = json.getString("app");
|
||||||
|
String streamId = json.getString("stream");
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
|
if ("rtp".equals(app) && streamId.indexOf("gb_play") > -1 && streamInfo == null) {
|
||||||
|
String[] s = streamId.split("_");
|
||||||
|
if (s.length == 4) {
|
||||||
|
String deviceId = s[2];
|
||||||
|
String channelId = s[3];
|
||||||
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
|
if (device != null) {
|
||||||
|
UUID uuid = UUID.randomUUID();
|
||||||
|
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
||||||
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
|
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
JSONObject ret = new JSONObject();
|
JSONObject ret = new JSONObject();
|
||||||
ret.put("code", 0);
|
ret.put("code", 0);
|
||||||
ret.put("msg", "success");
|
ret.put("msg", "success");
|
||||||
@ -354,7 +359,7 @@ public class ZLMHttpHookListener {
|
|||||||
// MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0);
|
// MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0);
|
||||||
MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class);
|
MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class);
|
||||||
mediaServerConfig.setLocalIP(mediaIp);
|
mediaServerConfig.setLocalIP(mediaIp);
|
||||||
storager.updateMediaInfo(mediaServerConfig);
|
redisCatchStorage.updateMediaInfo(mediaServerConfig);
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
JSONObject ret = new JSONObject();
|
JSONObject ret = new JSONObject();
|
||||||
|
@ -116,4 +116,8 @@ public class ZLMRESTfulUtils {
|
|||||||
public JSONObject openRtpServer(Map<String, Object> param){
|
public JSONObject openRtpServer(Map<String, Object> param){
|
||||||
return sendPost("openRtpServer",param);
|
return sendPost("openRtpServer",param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONObject closeRtpServer(Map<String, Object> param) {
|
||||||
|
return sendPost("closeRtpServer",param);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.genersoft.iot.vmp.media.zlm;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ZLMRTPServerFactory {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory");
|
||||||
|
|
||||||
|
@Value("${media.rtp.udpPortRange}")
|
||||||
|
private String udpPortRange;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
|
private int[] udpPortRangeArray = new int[2];
|
||||||
|
|
||||||
|
private int currentPort = 0;
|
||||||
|
|
||||||
|
public int createRTPServer(String streamId) {
|
||||||
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
int result = -1;
|
||||||
|
int newPort = getPortFromUdpPortRange();
|
||||||
|
param.put("port", newPort);
|
||||||
|
param.put("enable_tcp", 1);
|
||||||
|
param.put("stream_id", streamId);
|
||||||
|
JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param);
|
||||||
|
System.out.println(jsonObject);
|
||||||
|
|
||||||
|
if (jsonObject != null) {
|
||||||
|
switch (jsonObject.getInteger("code")){
|
||||||
|
case 0:
|
||||||
|
result= newPort;
|
||||||
|
break;
|
||||||
|
case -300: // id已经存在
|
||||||
|
result = newPort;
|
||||||
|
break;
|
||||||
|
case -400: // 端口占用
|
||||||
|
result= createRTPServer(streamId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.error("创建RTP Server 失败: " + jsonObject.getString("msg"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
// 检查ZLM状态
|
||||||
|
logger.error("创建RTP Server 失败: 请检查ZLM服务");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean closeRTPServer(String streamId) {
|
||||||
|
boolean result = false;
|
||||||
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
param.put("stream_id", streamId);
|
||||||
|
JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(param);
|
||||||
|
if (jsonObject != null ) {
|
||||||
|
if (jsonObject.getInteger("code") == 0) {
|
||||||
|
result = jsonObject.getInteger("hit") == 1;
|
||||||
|
}else {
|
||||||
|
logger.error("关闭RTP Server 失败: " + jsonObject.getString("msg"));
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
// 检查ZLM状态
|
||||||
|
logger.error("关闭RTP Server 失败: 请检查ZLM服务");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPortFromUdpPortRange() {
|
||||||
|
if (currentPort == 0) {
|
||||||
|
String[] udpPortRangeStrArray = udpPortRange.split(",");
|
||||||
|
udpPortRangeArray[0] = Integer.parseInt(udpPortRangeStrArray[0]);
|
||||||
|
udpPortRangeArray[1] = Integer.parseInt(udpPortRangeStrArray[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPort == 0 || currentPort++ > udpPortRangeArray[1]) {
|
||||||
|
currentPort = udpPortRangeArray[0];
|
||||||
|
return udpPortRangeArray[0];
|
||||||
|
} else {
|
||||||
|
if (currentPort % 2 == 1) {
|
||||||
|
currentPort++;
|
||||||
|
}
|
||||||
|
return currentPort++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import okhttp3.*;
|
import okhttp3.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -30,6 +31,9 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Value("${media.ip}")
|
@Value("${media.ip}")
|
||||||
private String mediaIp;
|
private String mediaIp;
|
||||||
|
|
||||||
@ -69,7 +73,7 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
logger.info("zlm接入成功...");
|
logger.info("zlm接入成功...");
|
||||||
if (autoConfig) saveZLMConfig();
|
if (autoConfig) saveZLMConfig();
|
||||||
mediaServerConfig = getMediaServerConfig();
|
mediaServerConfig = getMediaServerConfig();
|
||||||
storager.updateMediaInfo(mediaServerConfig);
|
redisCatchStorage.updateMediaInfo(mediaServerConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.media.zlm;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class ZLMUtils {
|
|
||||||
|
|
||||||
@Value("${media.rtp.udpPortRange}")
|
|
||||||
private String udpPortRange;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
|
||||||
|
|
||||||
private int[] udpPortRangeArray = new int[2];
|
|
||||||
|
|
||||||
private int currentPort = 0;
|
|
||||||
|
|
||||||
public int getNewRTPPort(String ssrc) {
|
|
||||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
|
||||||
Map<String, Object> param = new HashMap<>();
|
|
||||||
int newPort = getPortFromUdpPortRange();
|
|
||||||
param.put("port", newPort);
|
|
||||||
param.put("enable_tcp", 1);
|
|
||||||
param.put("stream_id", streamId);
|
|
||||||
JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param);
|
|
||||||
if (jsonObject != null && jsonObject.getInteger("code") == 0) {
|
|
||||||
return newPort;
|
|
||||||
} else {
|
|
||||||
return getNewRTPPort(ssrc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getPortFromUdpPortRange() {
|
|
||||||
if (currentPort == 0) {
|
|
||||||
String[] udpPortRangeStrArray = udpPortRange.split(",");
|
|
||||||
udpPortRangeArray[0] = Integer.parseInt(udpPortRangeStrArray[0]);
|
|
||||||
udpPortRangeArray[1] = Integer.parseInt(udpPortRangeStrArray[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPort == 0 || currentPort++ > udpPortRangeArray[1]) {
|
|
||||||
currentPort = udpPortRangeArray[0];
|
|
||||||
return udpPortRangeArray[0];
|
|
||||||
} else {
|
|
||||||
if (currentPort % 2 == 1) {
|
|
||||||
currentPort++;
|
|
||||||
}
|
|
||||||
return currentPort++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.genersoft.iot.vmp.storager;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface IRedisCatchStorage {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始播放时将流存入
|
||||||
|
*
|
||||||
|
* @param stream 流信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean startPlay(StreamInfo stream);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止播放时删除
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean stopPlay(StreamInfo streamInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询播放列表
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
StreamInfo queryPlay(StreamInfo streamInfo);
|
||||||
|
|
||||||
|
StreamInfo queryPlayByStreamId(String steamId);
|
||||||
|
|
||||||
|
StreamInfo queryPlaybackByStreamId(String steamId);
|
||||||
|
|
||||||
|
StreamInfo queryPlayByDevice(String deviceId, String code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新流媒体信息
|
||||||
|
* @param mediaServerConfig
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
boolean updateMediaInfo(MediaServerConfig mediaServerConfig);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流媒体信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
MediaServerConfig getMediaInfo();
|
||||||
|
|
||||||
|
Map<String, StreamInfo> queryPlayByDeviceId(String deviceId);
|
||||||
|
|
||||||
|
boolean startPlayback(StreamInfo stream);
|
||||||
|
|
||||||
|
boolean stopPlayback(StreamInfo streamInfo);
|
||||||
|
|
||||||
|
StreamInfo queryPlaybackByDevice(String deviceId, String code);
|
||||||
|
}
|
@ -1,15 +1,10 @@
|
|||||||
package com.genersoft.iot.vmp.storager;
|
package com.genersoft.iot.vmp.storager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.genersoft.iot.vmp.common.PageResult;
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
|
||||||
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.ParentPlatform;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description:视频设备数据存储接口
|
* @Description:视频设备数据存储接口
|
||||||
@ -18,19 +13,6 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
|||||||
*/
|
*/
|
||||||
public interface IVideoManagerStorager {
|
public interface IVideoManagerStorager {
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新流媒体信息
|
|
||||||
* @param mediaServerConfig
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean updateMediaInfo(MediaServerConfig mediaServerConfig);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取流媒体信息
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public MediaServerConfig getMediaInfo();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据设备ID判断设备是否存在
|
* 根据设备ID判断设备是否存在
|
||||||
*
|
*
|
||||||
@ -79,7 +61,7 @@ public interface IVideoManagerStorager {
|
|||||||
* @param count 每页数量
|
* @param count 每页数量
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public PageResult queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, String online, int page, int count);
|
public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, int page, int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取某个设备的通道列表
|
* 获取某个设备的通道列表
|
||||||
@ -88,6 +70,7 @@ public interface IVideoManagerStorager {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId);
|
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取某个设备的通道
|
* 获取某个设备的通道
|
||||||
* @param deviceId 设备ID
|
* @param deviceId 设备ID
|
||||||
@ -95,21 +78,20 @@ public interface IVideoManagerStorager {
|
|||||||
*/
|
*/
|
||||||
public DeviceChannel queryChannel(String deviceId, String channelId);
|
public DeviceChannel queryChannel(String deviceId, String channelId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取多个设备
|
* 获取多个设备
|
||||||
*
|
* @param page 当前页数
|
||||||
* @param deviceIds 设备ID数组
|
* @param count 每页数量
|
||||||
* @return List<Device> 设备对象数组
|
* @return List<Device> 设备对象数组
|
||||||
*/
|
*/
|
||||||
public PageResult<Device> queryVideoDeviceList(String[] deviceIds, int page, int count);
|
public PageInfo<Device> queryVideoDeviceList(int page, int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取多个设备
|
* 获取多个设备
|
||||||
*
|
*
|
||||||
* @param deviceIds 设备ID数组
|
|
||||||
* @return List<Device> 设备对象数组
|
* @return List<Device> 设备对象数组
|
||||||
*/
|
*/
|
||||||
public List<Device> queryVideoDeviceList(String[] deviceIds);
|
public List<Device> queryVideoDeviceList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除设备
|
* 删除设备
|
||||||
@ -135,27 +117,6 @@ public interface IVideoManagerStorager {
|
|||||||
*/
|
*/
|
||||||
public boolean outline(String deviceId);
|
public boolean outline(String deviceId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始播放时将流存入
|
|
||||||
*
|
|
||||||
* @param stream 流信息
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean startPlay(StreamInfo stream);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 停止播放时删除
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public boolean stopPlay(StreamInfo streamInfo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找视频流
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public StreamInfo queryPlay(StreamInfo streamInfo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询子设备
|
* 查询子设备
|
||||||
@ -166,12 +127,8 @@ public interface IVideoManagerStorager {
|
|||||||
* @param count
|
* @param count
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
PageResult querySubChannels(String deviceId, String channelId, String query, Boolean hasSubChannel, String online, int page, int count);
|
PageInfo querySubChannels(String deviceId, String channelId, String query, Boolean hasSubChannel, String online, int page, int count);
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新缓存
|
|
||||||
*/
|
|
||||||
public void updateCatch();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空通道
|
* 清空通道
|
||||||
@ -179,45 +136,4 @@ public interface IVideoManagerStorager {
|
|||||||
*/
|
*/
|
||||||
void cleanChannelsForDevice(String deviceId);
|
void cleanChannelsForDevice(String deviceId);
|
||||||
|
|
||||||
StreamInfo queryPlayBySSRC(String ssrc);
|
|
||||||
|
|
||||||
StreamInfo queryPlayByDevice(String deviceId, String code);
|
|
||||||
|
|
||||||
Map<String, StreamInfo> queryPlayByDeviceId(String deviceId);
|
|
||||||
|
|
||||||
boolean startPlayback(StreamInfo streamInfo);
|
|
||||||
|
|
||||||
boolean stopPlayback(StreamInfo streamInfo);
|
|
||||||
|
|
||||||
StreamInfo queryPlaybackByDevice(String deviceId, String channelId);
|
|
||||||
|
|
||||||
StreamInfo queryPlaybackBySSRC(String ssrc);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新或添加上级平台
|
|
||||||
* @param parentPlatform
|
|
||||||
*/
|
|
||||||
boolean updateParentPlatform(ParentPlatform parentPlatform);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除上级平台
|
|
||||||
* @param parentPlatform
|
|
||||||
*/
|
|
||||||
boolean deleteParentPlatform(ParentPlatform parentPlatform);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页获取上级平台
|
|
||||||
* @param page
|
|
||||||
* @param count
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public PageResult<ParentPlatform> queryParentPlatformList(int page, int count);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取上级平台
|
|
||||||
* @param platformGbId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public ParentPlatform queryParentPlatById(String platformGbId);
|
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.storager;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.conf.VManagerConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:视频设备数据存储工厂,根据存储策略,返回对应的存储器
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月6日 下午2:15:16
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class VideoManagerStoragerFactory {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private VManagerConfig vmConfig;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager jdbcStorager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager redisStorager;
|
|
||||||
|
|
||||||
@Bean("storager")
|
|
||||||
public IVideoManagerStorager getStorager() {
|
|
||||||
if ("redis".equals(vmConfig.getDatabase().toLowerCase())) {
|
|
||||||
return redisStorager;
|
|
||||||
} else if ("jdbc".equals(vmConfig.getDatabase().toLowerCase())) {
|
|
||||||
return jdbcStorager;
|
|
||||||
}
|
|
||||||
return redisStorager;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.storager;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.CommandLineRunner;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class VodeoMannagerTask implements CommandLineRunner {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IVideoManagerStorager storager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run(String... strings) throws Exception {
|
|
||||||
storager.updateCatch();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.genersoft.iot.vmp.storager.dao;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import org.apache.ibatis.annotations.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于存储设备通道信息
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface DeviceChannelMapper {
|
||||||
|
|
||||||
|
@Insert("INSERT INTO device_channel (channelId, deviceId, name, manufacture, model, owner, civilCode, block, " +
|
||||||
|
"address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
|
||||||
|
"ipAddress, port, password, PTZType, status) " +
|
||||||
|
"VALUES ('${channelId}', '${deviceId}', '${name}', '${manufacture}', '${model}', '${owner}', '${civilCode}', '${block}'," +
|
||||||
|
"'${address}', ${parental}, '${parentId}', ${safetyWay}, ${registerWay}, '${certNum}', ${certifiable}, ${errCode}, '${secrecy}', " +
|
||||||
|
"'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status})")
|
||||||
|
int add(DeviceChannel channel);
|
||||||
|
|
||||||
|
@Update("UPDATE device_channel " +
|
||||||
|
"SET name=#{name}, manufacture=#{manufacture}, model=#{model}, owner=#{owner}, civilCode=#{civilCode}, " +
|
||||||
|
"block=#{block}, address=#{address}, parental=#{parental}, parentId=#{parentId}, safetyWay=#{safetyWay}, " +
|
||||||
|
"registerWay=#{registerWay}, certNum=#{certNum}, certifiable=#{certifiable}, errCode=#{errCode}, secrecy=#{secrecy}, " +
|
||||||
|
"ipAddress=#{ipAddress}, port=#{port}, password=#{password}, PTZType=#{PTZType}, status=#{status}, streamId=#{streamId}, " +
|
||||||
|
"hasAudio=#{hasAudio}" +
|
||||||
|
"WHERE deviceId=#{deviceId} AND channelId=#{channelId}")
|
||||||
|
int update(DeviceChannel channel);
|
||||||
|
|
||||||
|
@Select(value = {" <script>" +
|
||||||
|
"SELECT * FROM ( "+
|
||||||
|
" SELECT * , (SELECT count(0) FROM device_channel WHERE parentId=dc.channelId) as subCount FROM device_channel dc " +
|
||||||
|
" WHERE dc.deviceId=#{deviceId} " +
|
||||||
|
" <if test=\"query != null\"> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " +
|
||||||
|
" <if test=\"parentChannelId != null\"> AND dc.parentId=#{parentChannelId} </if> " +
|
||||||
|
" <if test=\"online == true\" > AND dc.status=1</if>" +
|
||||||
|
" <if test=\"online == false\" > AND dc.status=0</if>) dcr" +
|
||||||
|
" WHERE 1=1 " +
|
||||||
|
" <if test=\"hasSubChannel == true\" > AND subCount >0</if>" +
|
||||||
|
" <if test=\"hasSubChannel == false\" > AND subCount=0</if>" +
|
||||||
|
" </script>"})
|
||||||
|
List<DeviceChannel> queryChannelsByDeviceId(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online);
|
||||||
|
|
||||||
|
@Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}")
|
||||||
|
DeviceChannel queryChannel(String deviceId, String channelId);
|
||||||
|
|
||||||
|
@Delete("DELETE FROM device_channel WHERE deviceId=#{deviceId}")
|
||||||
|
int cleanChannelsByDeviceId(String deviceId);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.genersoft.iot.vmp.storager.dao;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import org.apache.ibatis.annotations.*;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于存储设备信息
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@Repository
|
||||||
|
public interface DeviceMapper {
|
||||||
|
|
||||||
|
@Select("SELECT * FROM device WHERE deviceId = #{deviceId}")
|
||||||
|
Device getDeviceByDeviceId(String deviceId);
|
||||||
|
|
||||||
|
@Insert("INSERT INTO device (" +
|
||||||
|
"deviceId, " +
|
||||||
|
"name, " +
|
||||||
|
"manufacturer, " +
|
||||||
|
"model, " +
|
||||||
|
"firmware, " +
|
||||||
|
"transport," +
|
||||||
|
"streamMode," +
|
||||||
|
"ip," +
|
||||||
|
"port," +
|
||||||
|
"hostAddress," +
|
||||||
|
"online" +
|
||||||
|
") VALUES (" +
|
||||||
|
"#{deviceId}," +
|
||||||
|
"#{name}," +
|
||||||
|
"#{manufacturer}," +
|
||||||
|
"#{model}," +
|
||||||
|
"#{firmware}," +
|
||||||
|
"#{transport}," +
|
||||||
|
"#{streamMode}," +
|
||||||
|
"#{ip}," +
|
||||||
|
"#{port}," +
|
||||||
|
"#{hostAddress}," +
|
||||||
|
"#{online}" +
|
||||||
|
")")
|
||||||
|
int add(Device device);
|
||||||
|
|
||||||
|
|
||||||
|
@Update("UPDATE device " +
|
||||||
|
"SET name=#{name}, " +
|
||||||
|
"manufacturer=#{manufacturer}," +
|
||||||
|
"model=#{model}," +
|
||||||
|
"firmware=#{firmware}, " +
|
||||||
|
"transport=#{transport}," +
|
||||||
|
"streamMode=#{streamMode}, " +
|
||||||
|
"ip=#{ip}, " +
|
||||||
|
"port=#{port}, " +
|
||||||
|
"hostAddress=#{hostAddress}, " +
|
||||||
|
"online=#{online} " +
|
||||||
|
"WHERE deviceId=#{deviceId}")
|
||||||
|
int update(Device device);
|
||||||
|
|
||||||
|
@Select("SELECT *, (SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de")
|
||||||
|
List<Device> getDevices();
|
||||||
|
|
||||||
|
@Delete("DELETE FROM device WHERE deviceId=#{deviceId}")
|
||||||
|
int del(String deviceId);
|
||||||
|
}
|
@ -0,0 +1,166 @@
|
|||||||
|
package com.genersoft.iot.vmp.storager.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
|
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||||
|
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RedisCatchStorageImpl implements IRedisCatchStorage {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisUtil redis;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceChannelMapper deviceChannelMapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始播放时将流存入redis
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean startPlay(StreamInfo stream) {
|
||||||
|
return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, stream.getStreamId(),stream.getDeviceID(), stream.getCahnnelId()),
|
||||||
|
stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止播放时从redis删除
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean stopPlay(StreamInfo streamInfo) {
|
||||||
|
if (streamInfo == null) return false;
|
||||||
|
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId());
|
||||||
|
if (deviceChannel != null) {
|
||||||
|
deviceChannel.setStreamId(null);
|
||||||
|
deviceChannel.setDeviceId(streamInfo.getDeviceID());
|
||||||
|
deviceChannelMapper.update(deviceChannel);
|
||||||
|
}
|
||||||
|
return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
||||||
|
streamInfo.getStreamId(),
|
||||||
|
streamInfo.getDeviceID(),
|
||||||
|
streamInfo.getCahnnelId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询播放列表
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public StreamInfo queryPlay(StreamInfo streamInfo) {
|
||||||
|
return (StreamInfo)redis.get(String.format("%S_%s_%s_%s",
|
||||||
|
VideoManagerConstants.PLAYER_PREFIX,
|
||||||
|
streamInfo.getStreamId(),
|
||||||
|
streamInfo.getDeviceID(),
|
||||||
|
streamInfo.getCahnnelId()));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public StreamInfo queryPlayByStreamId(String steamId) {
|
||||||
|
List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, steamId));
|
||||||
|
if (playLeys == null || playLeys.size() == 0) return null;
|
||||||
|
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamInfo queryPlaybackByStreamId(String steamId) {
|
||||||
|
List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, steamId));
|
||||||
|
if (playLeys == null || playLeys.size() == 0) return null;
|
||||||
|
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamInfo queryPlayByDevice(String deviceId, String code) {
|
||||||
|
// List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
||||||
|
List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
||||||
|
deviceId,
|
||||||
|
code));
|
||||||
|
if (playLeys == null || playLeys.size() == 0) return null;
|
||||||
|
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新流媒体信息
|
||||||
|
* @param mediaServerConfig
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
|
||||||
|
return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取流媒体信息
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MediaServerConfig getMediaInfo() {
|
||||||
|
return (MediaServerConfig)redis.get(VideoManagerConstants.MEDIA_SERVER_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
|
||||||
|
Map<String, StreamInfo> streamInfos = new HashMap<>();
|
||||||
|
// List<Object> playLeys = redis.keys(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
|
||||||
|
List<Object> players = redis.scan(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
|
||||||
|
if (players.size() == 0) return streamInfos;
|
||||||
|
for (int i = 0; i < players.size(); i++) {
|
||||||
|
String key = (String) players.get(i);
|
||||||
|
StreamInfo streamInfo = (StreamInfo)redis.get(key);
|
||||||
|
streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getCahnnelId(), streamInfo);
|
||||||
|
}
|
||||||
|
return streamInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startPlayback(StreamInfo stream) {
|
||||||
|
return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getStreamId(),stream.getDeviceID(), stream.getCahnnelId()),
|
||||||
|
stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stopPlayback(StreamInfo streamInfo) {
|
||||||
|
if (streamInfo == null) return false;
|
||||||
|
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId());
|
||||||
|
if (deviceChannel != null) {
|
||||||
|
deviceChannel.setStreamId(null);
|
||||||
|
deviceChannel.setDeviceId(streamInfo.getDeviceID());
|
||||||
|
deviceChannelMapper.update(deviceChannel);
|
||||||
|
}
|
||||||
|
return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
||||||
|
streamInfo.getStreamId(),
|
||||||
|
streamInfo.getDeviceID(),
|
||||||
|
streamInfo.getCahnnelId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamInfo queryPlaybackByDevice(String deviceId, String code) {
|
||||||
|
String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
||||||
|
deviceId,
|
||||||
|
code);
|
||||||
|
List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
||||||
|
deviceId,
|
||||||
|
code));
|
||||||
|
if (playLeys == null || playLeys.size() == 0) {
|
||||||
|
playLeys = redis.scan(String.format("%S_*_*_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
||||||
|
deviceId));
|
||||||
|
}
|
||||||
|
if (playLeys == null || playLeys.size() == 0) return null;
|
||||||
|
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
package com.genersoft.iot.vmp.storager.impl;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
||||||
|
import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import io.swagger.models.auth.In;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description:视频设备数据存储-jdbc实现
|
||||||
|
* @author: swwheihei
|
||||||
|
* @date: 2020年5月6日 下午2:31:42
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceMapper deviceMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceChannelMapper deviceChannelMapper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据设备ID判断设备是否存在
|
||||||
|
*
|
||||||
|
* @param deviceId 设备ID
|
||||||
|
* @return true:存在 false:不存在
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean exists(String deviceId) {
|
||||||
|
return deviceMapper.getDeviceByDeviceId(deviceId) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频设备创建
|
||||||
|
*
|
||||||
|
* @param device 设备对象
|
||||||
|
* @return true:创建成功 false:创建失败
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized boolean create(Device device) {
|
||||||
|
return deviceMapper.add(device) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频设备更新
|
||||||
|
*
|
||||||
|
* @param device 设备对象
|
||||||
|
* @return true:更新成功 false:更新失败
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized boolean updateDevice(Device device) {
|
||||||
|
Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId());
|
||||||
|
if (deviceByDeviceId == null) {
|
||||||
|
return deviceMapper.add(device) > 0;
|
||||||
|
}else {
|
||||||
|
return deviceMapper.update(device) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
|
||||||
|
String channelId = channel.getChannelId();
|
||||||
|
channel.setDeviceId(deviceId);
|
||||||
|
DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
|
||||||
|
if (deviceChannel == null) {
|
||||||
|
deviceChannelMapper.add(channel);
|
||||||
|
}else {
|
||||||
|
deviceChannelMapper.update(channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备
|
||||||
|
*
|
||||||
|
* @param deviceId 设备ID
|
||||||
|
* @return Device 设备对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Device queryVideoDevice(String deviceId) {
|
||||||
|
return deviceMapper.getDeviceByDeviceId(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, int page, int count) {
|
||||||
|
// 获取到所有正在播放的流
|
||||||
|
PageHelper.startPage(page, count);
|
||||||
|
List<DeviceChannel> all = deviceChannelMapper.queryChannelsByDeviceId(deviceId, null, query, hasSubChannel, online);
|
||||||
|
return new PageInfo<>(all);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) {
|
||||||
|
return deviceChannelMapper.queryChannelsByDeviceId(deviceId, null,null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, String online, int page, int count) {
|
||||||
|
PageHelper.startPage(page, count);
|
||||||
|
List<DeviceChannel> all = deviceChannelMapper.queryChannelsByDeviceId(deviceId, parentChannelId, null, null, null);
|
||||||
|
return new PageInfo<>(all);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceChannel queryChannel(String deviceId, String channelId) {
|
||||||
|
return deviceChannelMapper.queryChannel(deviceId, channelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多个设备
|
||||||
|
*
|
||||||
|
* @param page 当前页数
|
||||||
|
* @param count 每页数量
|
||||||
|
* @return PageInfo<Device> 分页设备对象数组
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PageInfo<Device> queryVideoDeviceList(int page, int count) {
|
||||||
|
PageHelper.startPage(page, count);
|
||||||
|
List<Device> all = deviceMapper.getDevices();
|
||||||
|
return new PageInfo<>(all);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多个设备
|
||||||
|
*
|
||||||
|
* @return List<Device> 设备对象数组
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<Device> queryVideoDeviceList() {
|
||||||
|
|
||||||
|
List<Device> deviceList = deviceMapper.getDevices();
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除设备
|
||||||
|
*
|
||||||
|
* @param deviceId 设备ID
|
||||||
|
* @return true:删除成功 false:删除失败
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean delete(String deviceId) {
|
||||||
|
int result = deviceMapper.del(deviceId);
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新设备在线
|
||||||
|
*
|
||||||
|
* @param deviceId 设备ID
|
||||||
|
* @return true:更新成功 false:更新失败
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized boolean online(String deviceId) {
|
||||||
|
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
|
||||||
|
device.setOnline(1);
|
||||||
|
System.out.println("更新设备在线");
|
||||||
|
if (device == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return deviceMapper.update(device) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新设备离线
|
||||||
|
*
|
||||||
|
* @param deviceId 设备ID
|
||||||
|
* @return true:更新成功 false:更新失败
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized boolean outline(String deviceId) {
|
||||||
|
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
|
||||||
|
device.setOnline(0);
|
||||||
|
System.out.println("更新设备离线");
|
||||||
|
return deviceMapper.update(device) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanChannelsForDevice(String deviceId) {
|
||||||
|
int result = deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -1,237 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.storager.jdbc;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.PageResult;
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:视频设备数据存储-jdbc实现
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月6日 下午2:28:12
|
|
||||||
*/
|
|
||||||
@Component("jdbcStorager")
|
|
||||||
public class VideoManagerJdbcStoragerImpl implements IVideoManagerStorager {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MediaServerConfig getMediaInfo() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID判断设备是否存在
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:存在 false:不存在
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean exists(String deviceId) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频设备创建
|
|
||||||
*
|
|
||||||
* @param device 设备对象
|
|
||||||
* @return true:创建成功 false:创建失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean create(Device device) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateDevice(Device device) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateChannel(String deviceId, DeviceChannel channel) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return Device 设备对象
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Device queryVideoDevice(String deviceId) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, String online, int page, int count) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeviceChannel queryChannel(String deviceId, String channelId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<Device> queryVideoDeviceList(String[] deviceIds, int page, int count) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取多个设备
|
|
||||||
*
|
|
||||||
* @param deviceIds 设备ID数组
|
|
||||||
* @return List<Device> 设备对象数组
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<Device> queryVideoDeviceList(String[] deviceIds) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:删除成功 false:删除失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean delete(String deviceId) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新设备在线
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:更新成功 false:更新失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean online(String deviceId) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新设备离线
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:更新成功 false:更新失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean outline(String deviceId) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stopPlay(StreamInfo streamInfo) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlay(StreamInfo streamInfo) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult querySubChannels(String deviceId, String channelId, String query, Boolean hasSubChannel, String online, int page, int count) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateCatch() {
|
|
||||||
System.out.println("##################");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cleanChannelsForDevice(String deviceId) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean startPlay(StreamInfo stream) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlayBySSRC(String ssrc) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlayByDevice(String deviceId, String code) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean startPlayback(StreamInfo streamInfo) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stopPlayback(StreamInfo streamInfo) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlaybackByDevice(String deviceId, String channelId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlaybackBySSRC(String ssrc) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateParentPlatform(ParentPlatform parentPlatform) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteParentPlatform(ParentPlatform parentPlatform) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<ParentPlatform> queryParentPlatformList(int page, int count) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParentPlatform queryParentPlatById(String platformGbId) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,600 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.storager.redis;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.genersoft.iot.vmp.common.PageResult;
|
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
|
||||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:视频设备数据存储-redis实现
|
|
||||||
* @author: swwheihei
|
|
||||||
* @date: 2020年5月6日 下午2:31:42
|
|
||||||
*/
|
|
||||||
@Component("redisStorager")
|
|
||||||
public class VideoManagerRedisStoragerImpl implements IVideoManagerStorager {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RedisUtil redis;
|
|
||||||
|
|
||||||
private HashMap<String, HashMap<String, HashSet<String>>> deviceMap = new HashMap<>();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据设备ID判断设备是否存在
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:存在 false:不存在
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean exists(String deviceId) {
|
|
||||||
return redis.hasKey(VideoManagerConstants.DEVICE_PREFIX+deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频设备创建
|
|
||||||
*
|
|
||||||
* @param device 设备对象
|
|
||||||
* @return true:创建成功 false:创建失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean create(Device device) {
|
|
||||||
return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频设备更新
|
|
||||||
*
|
|
||||||
* @param device 设备对象
|
|
||||||
* @return true:更新成功 false:更新失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean updateDevice(Device device) {
|
|
||||||
if (deviceMap.get(device.getDeviceId()) == null) {
|
|
||||||
deviceMap.put(device.getDeviceId(), new HashMap<String, HashSet<String>>());
|
|
||||||
}
|
|
||||||
// 更新device中的通道数量
|
|
||||||
device.setChannelCount(deviceMap.get(device.getDeviceId()).size());
|
|
||||||
// 存储device
|
|
||||||
return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateChannel(String deviceId, DeviceChannel channel) {
|
|
||||||
String channelId = channel.getChannelId();
|
|
||||||
HashMap<String, HashSet<String>> channelMap = deviceMap.get(deviceId);
|
|
||||||
if (channelMap == null) return;
|
|
||||||
// 作为父设备, 确定自己的子节点数
|
|
||||||
if (channelMap.get(channelId) == null) {
|
|
||||||
channelMap.put(channelId, new HashSet<String>());
|
|
||||||
}else if (channelMap.get(channelId).size() > 0) {
|
|
||||||
channel.setSubCount(channelMap.get(channelId).size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 存储通道
|
|
||||||
redis.set(VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
|
||||||
"_" + channel.getChannelId() +
|
|
||||||
"_" + (channel.getStatus() == 1 ? "on":"off") +
|
|
||||||
"_" + (channelMap.get(channelId).size() > 0)+
|
|
||||||
"_" + (StringUtils.isEmpty(channel.getParentId())?null:channel.getParentId()),
|
|
||||||
channel);
|
|
||||||
// 更新device中的通道数量
|
|
||||||
Device device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
|
|
||||||
device.setChannelCount(deviceMap.get(deviceId).size());
|
|
||||||
redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
|
|
||||||
|
|
||||||
|
|
||||||
// 如果有父设备,更新父设备内子节点数
|
|
||||||
String parentId = channel.getParentId();
|
|
||||||
if (!StringUtils.isEmpty(parentId) && !parentId.equals(deviceId)) {
|
|
||||||
|
|
||||||
if (channelMap.get(parentId) == null) {
|
|
||||||
channelMap.put(parentId, new HashSet<String>());
|
|
||||||
}
|
|
||||||
channelMap.get(parentId).add(channelId);
|
|
||||||
|
|
||||||
DeviceChannel deviceChannel = queryChannel(deviceId, parentId);
|
|
||||||
if (deviceChannel != null) {
|
|
||||||
deviceChannel.setSubCount(channelMap.get(parentId).size());
|
|
||||||
redis.set(VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
|
||||||
"_" + deviceChannel.getChannelId() +
|
|
||||||
"_" + (deviceChannel.getStatus() == 1 ? "on":"off") +
|
|
||||||
"_" + (channelMap.get(deviceChannel.getChannelId()).size() > 0)+
|
|
||||||
"_" + (StringUtils.isEmpty(deviceChannel.getParentId())?null:deviceChannel.getParentId()),
|
|
||||||
deviceChannel);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return Device 设备对象
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Device queryVideoDevice(String deviceId) {
|
|
||||||
return (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, String online, int page, int count) {
|
|
||||||
// 获取到所有正在播放的流
|
|
||||||
Map<String, StreamInfo> stringStreamInfoMap = queryPlayByDeviceId(deviceId);
|
|
||||||
List<DeviceChannel> result = new ArrayList<>();
|
|
||||||
PageResult pageResult = new PageResult<DeviceChannel>();
|
|
||||||
String queryContent = "*";
|
|
||||||
if (!StringUtils.isEmpty(query)) queryContent = String.format("*%S*",query);
|
|
||||||
String queryHasSubChannel = "*";
|
|
||||||
if (hasSubChannel != null) queryHasSubChannel = hasSubChannel?"true":"false";
|
|
||||||
String queryOnline = "*";
|
|
||||||
if (!StringUtils.isEmpty(online)) queryOnline = online;
|
|
||||||
String queryStr = VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
|
||||||
"_" + queryContent + // 搜索编号和名称
|
|
||||||
"_" + queryOnline + // 搜索是否在线
|
|
||||||
"_" + queryHasSubChannel + // 搜索是否含有子节点
|
|
||||||
"_" + "*";
|
|
||||||
// List<Object> deviceChannelList = redis.keys(queryStr);
|
|
||||||
List<Object> deviceChannelList = redis.scan(queryStr);
|
|
||||||
//对查询结果排序,避免出现通道排列顺序乱序的情况
|
|
||||||
Collections.sort(deviceChannelList,new Comparator<Object>(){
|
|
||||||
@Override
|
|
||||||
public int compare(Object o1, Object o2) {
|
|
||||||
return o1.toString().compareToIgnoreCase(o2.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pageResult.setPage(page);
|
|
||||||
pageResult.setCount(count);
|
|
||||||
pageResult.setTotal(deviceChannelList.size());
|
|
||||||
int maxCount = (page + 1 ) * count;
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
for (int i = page * count; i < (pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal() ); i++) {
|
|
||||||
DeviceChannel deviceChannel = (DeviceChannel)redis.get((String)deviceChannelList.get(i));
|
|
||||||
StreamInfo streamInfo = stringStreamInfoMap.get(deviceId + "_" + deviceChannel.getChannelId());
|
|
||||||
deviceChannel.setPlay(streamInfo != null);
|
|
||||||
if (streamInfo != null) deviceChannel.setSsrc(streamInfo.getSsrc());
|
|
||||||
result.add(deviceChannel);
|
|
||||||
}
|
|
||||||
pageResult.setData(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pageResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) {
|
|
||||||
List<DeviceChannel> result = new ArrayList<>();
|
|
||||||
// List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
|
|
||||||
List<Object> deviceChannelList = redis.scan(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
|
|
||||||
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
for (int i = 0; i < deviceChannelList.size(); i++) {
|
|
||||||
result.add((DeviceChannel)redis.get((String) deviceChannelList.get(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, String online, int page, int count) {
|
|
||||||
List<DeviceChannel> allDeviceChannels = new ArrayList<>();
|
|
||||||
String queryContent = "*";
|
|
||||||
if (!StringUtils.isEmpty(query)) queryContent = String.format("*%S*",query);
|
|
||||||
String queryHasSubChannel = "*";
|
|
||||||
if (hasSubChannel != null) queryHasSubChannel = hasSubChannel?"true":"false";
|
|
||||||
String queryOnline = "*";
|
|
||||||
if (!StringUtils.isEmpty(online)) queryOnline = online;
|
|
||||||
String queryStr = VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
|
||||||
"_" + queryContent + // 搜索编号和名称
|
|
||||||
"_" + queryOnline + // 搜索是否在线
|
|
||||||
"_" + queryHasSubChannel + // 搜索是否含有子节点
|
|
||||||
"_" + parentChannelId;
|
|
||||||
|
|
||||||
// List<Object> deviceChannelList = redis.keys(queryStr);
|
|
||||||
List<Object> deviceChannelList = redis.scan(queryStr);
|
|
||||||
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
for (int i = 0; i < deviceChannelList.size(); i++) {
|
|
||||||
DeviceChannel deviceChannel = (DeviceChannel)redis.get((String)deviceChannelList.get(i));
|
|
||||||
if (deviceChannel.getParentId() != null && deviceChannel.getParentId().equals(parentChannelId)) {
|
|
||||||
allDeviceChannels.add(deviceChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int maxCount = (page + 1 ) * count;
|
|
||||||
PageResult pageResult = new PageResult<DeviceChannel>();
|
|
||||||
pageResult.setPage(page);
|
|
||||||
pageResult.setCount(count);
|
|
||||||
pageResult.setTotal(allDeviceChannels.size());
|
|
||||||
|
|
||||||
if (allDeviceChannels.size() > 0) {
|
|
||||||
pageResult.setData(allDeviceChannels.subList(
|
|
||||||
page * count, pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return pageResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DeviceChannel> querySubChannels(String deviceId, String parentChannelId) {
|
|
||||||
List<DeviceChannel> allDeviceChannels = new ArrayList<>();
|
|
||||||
// List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
|
|
||||||
List<Object> deviceChannelList = redis.scan(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
|
|
||||||
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
for (int i = 0; i < deviceChannelList.size(); i++) {
|
|
||||||
DeviceChannel deviceChannel = (DeviceChannel)redis.get((String)deviceChannelList.get(i));
|
|
||||||
if (deviceChannel.getParentId() != null && deviceChannel.getParentId().equals(parentChannelId)) {
|
|
||||||
allDeviceChannels.add(deviceChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allDeviceChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DeviceChannel queryChannel(String deviceId, String channelId) {
|
|
||||||
DeviceChannel deviceChannel = null;
|
|
||||||
// List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
|
||||||
List<Object> deviceChannelList = redis.scan(VideoManagerConstants.CACHEKEY_PREFIX + deviceId +
|
|
||||||
"_" + channelId + "*");
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
deviceChannel = (DeviceChannel)redis.get((String)deviceChannelList.get(0));
|
|
||||||
}
|
|
||||||
return deviceChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取多个设备
|
|
||||||
*
|
|
||||||
* @param deviceIds 设备ID数组
|
|
||||||
* @return List<Device> 设备对象数组
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public PageResult<Device> queryVideoDeviceList(String[] deviceIds, int page, int count) {
|
|
||||||
List<Device> devices = new ArrayList<>();
|
|
||||||
PageResult pageResult = new PageResult<Device>();
|
|
||||||
pageResult.setPage(page);
|
|
||||||
pageResult.setCount(count);
|
|
||||||
Device device = null;
|
|
||||||
|
|
||||||
if (deviceIds == null || deviceIds.length == 0) {
|
|
||||||
|
|
||||||
// List<Object> deviceIdList = redis.keys(VideoManagerConstants.DEVICE_PREFIX+"*");
|
|
||||||
List<Object> deviceIdList = redis.scan(VideoManagerConstants.DEVICE_PREFIX+"*");
|
|
||||||
pageResult.setTotal(deviceIdList.size());
|
|
||||||
int maxCount = (page + 1)* count;
|
|
||||||
for (int i = page * count; i < (pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal() ); i++) {
|
|
||||||
// devices.add((Device)redis.get((String)deviceIdList.get(i)));
|
|
||||||
device =(Device)redis.get((String)deviceIdList.get(i));
|
|
||||||
if (redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX+device.getDeviceId()).size() == 0){
|
|
||||||
// outline(device.getDeviceId());
|
|
||||||
}
|
|
||||||
devices.add(device);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < deviceIds.length; i++) {
|
|
||||||
// devices.add((Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceIds[i]));
|
|
||||||
device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceIds[i]);
|
|
||||||
if (redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX+device.getDeviceId()).size() == 0){
|
|
||||||
// outline(device.getDeviceId());
|
|
||||||
}
|
|
||||||
devices.add(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pageResult.setData(devices);
|
|
||||||
return pageResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取多个设备
|
|
||||||
*
|
|
||||||
* @param deviceIds 设备ID数组
|
|
||||||
* @return List<Device> 设备对象数组
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<Device> queryVideoDeviceList(String[] deviceIds) {
|
|
||||||
List<Device> devices = new ArrayList<>();
|
|
||||||
Device device = null;
|
|
||||||
|
|
||||||
if (deviceIds == null || deviceIds.length == 0) {
|
|
||||||
// List<Object> deviceIdList = redis.keys(VideoManagerConstants.DEVICE_PREFIX+"*");
|
|
||||||
List<Object> deviceIdList = redis.scan(VideoManagerConstants.DEVICE_PREFIX+"*");
|
|
||||||
for (int i = 0; i < deviceIdList.size(); i++) {
|
|
||||||
device =(Device)redis.get((String)deviceIdList.get(i));
|
|
||||||
if (redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX+device.getDeviceId()).size() == 0){
|
|
||||||
outline(device.getDeviceId());
|
|
||||||
}
|
|
||||||
devices.add(device);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < deviceIds.length; i++) {
|
|
||||||
device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceIds[i]);
|
|
||||||
if (redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX+device.getDeviceId()).size() == 0){
|
|
||||||
outline(device.getDeviceId());
|
|
||||||
}
|
|
||||||
devices.add(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:删除成功 false:删除失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean delete(String deviceId) {
|
|
||||||
return redis.del(VideoManagerConstants.DEVICE_PREFIX+deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新设备在线
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:更新成功 false:更新失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean online(String deviceId) {
|
|
||||||
Device device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
|
|
||||||
device.setOnline(1);
|
|
||||||
return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新设备离线
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
* @return true:更新成功 false:更新失败
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean outline(String deviceId) {
|
|
||||||
Device device = (Device)redis.get(VideoManagerConstants.DEVICE_PREFIX+deviceId);
|
|
||||||
if (device == null) return false;
|
|
||||||
device.setOnline(0);
|
|
||||||
return redis.set(VideoManagerConstants.DEVICE_PREFIX+device.getDeviceId(), device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开始播放时将流存入redis
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean startPlay(StreamInfo stream) {
|
|
||||||
return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()),
|
|
||||||
stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 停止播放时从redis删除
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean stopPlay(StreamInfo streamInfo) {
|
|
||||||
if (streamInfo == null) return false;
|
|
||||||
DeviceChannel deviceChannel = queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId());
|
|
||||||
if (deviceChannel != null) {
|
|
||||||
deviceChannel.setSsrc(null);
|
|
||||||
deviceChannel.setPlay(false);
|
|
||||||
updateChannel(streamInfo.getDeviceID(), deviceChannel);
|
|
||||||
}
|
|
||||||
return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
|
||||||
streamInfo.getSsrc(),
|
|
||||||
streamInfo.getDeviceID(),
|
|
||||||
streamInfo.getCahnnelId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询播放列表
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlay(StreamInfo streamInfo) {
|
|
||||||
return (StreamInfo)redis.get(String.format("%S_%s_%s_%s",
|
|
||||||
VideoManagerConstants.PLAYER_PREFIX,
|
|
||||||
streamInfo.getSsrc(),
|
|
||||||
streamInfo.getDeviceID(),
|
|
||||||
streamInfo.getCahnnelId()));
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlayBySSRC(String ssrc) {
|
|
||||||
// List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc));
|
|
||||||
List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc));
|
|
||||||
if (playLeys == null || playLeys.size() == 0) return null;
|
|
||||||
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlaybackBySSRC(String ssrc) {
|
|
||||||
// List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc));
|
|
||||||
List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, ssrc));
|
|
||||||
if (playLeys == null || playLeys.size() == 0) return null;
|
|
||||||
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlayByDevice(String deviceId, String code) {
|
|
||||||
// List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
|
||||||
List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
|
|
||||||
deviceId,
|
|
||||||
code));
|
|
||||||
if (playLeys == null || playLeys.size() == 0) return null;
|
|
||||||
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新流媒体信息
|
|
||||||
* @param mediaServerConfig
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
|
|
||||||
return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取流媒体信息
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public MediaServerConfig getMediaInfo() {
|
|
||||||
return (MediaServerConfig)redis.get(VideoManagerConstants.MEDIA_SERVER_PREFIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateCatch() {
|
|
||||||
deviceMap = new HashMap<>();
|
|
||||||
// 更新设备
|
|
||||||
List<Device> devices = queryVideoDeviceList(null);
|
|
||||||
if (devices == null && devices.size() == 0) return;
|
|
||||||
for (Device device : devices) {
|
|
||||||
// 更新设备下的通道
|
|
||||||
HashMap<String, HashSet<String>> channelMap = new HashMap<String, HashSet<String>>();
|
|
||||||
List<Object> deviceChannelList = redis.scan(VideoManagerConstants.CACHEKEY_PREFIX +
|
|
||||||
device.getDeviceId() + "_" + "*");
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
for (int i = 0; i < deviceChannelList.size(); i++) {
|
|
||||||
String key = (String)deviceChannelList.get(i);
|
|
||||||
String[] s = key.split("_");
|
|
||||||
String channelId = s[3];
|
|
||||||
HashSet<String> subChannel = channelMap.get(channelId);
|
|
||||||
if (subChannel == null) {
|
|
||||||
subChannel = new HashSet<>();
|
|
||||||
}
|
|
||||||
System.out.println(key);
|
|
||||||
if (s.length == 6 && !"null".equals(s[5])) {
|
|
||||||
subChannel.add(s[5]);
|
|
||||||
}
|
|
||||||
channelMap.put(channelId, subChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deviceMap.put(device.getDeviceId(),channelMap);
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cleanChannelsForDevice(String deviceId) {
|
|
||||||
List<DeviceChannel> result = new ArrayList<>();
|
|
||||||
// List<Object> deviceChannelList = redis.keys(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
|
|
||||||
List<Object> deviceChannelList = redis.scan(VideoManagerConstants.CACHEKEY_PREFIX + deviceId + "_" + "*");
|
|
||||||
if (deviceChannelList != null && deviceChannelList.size() > 0 ) {
|
|
||||||
for (int i = 0; i < deviceChannelList.size(); i++) {
|
|
||||||
redis.del((String)deviceChannelList.get(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
|
|
||||||
Map<String, StreamInfo> streamInfos = new HashMap<>();
|
|
||||||
// List<Object> playLeys = redis.keys(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
|
|
||||||
List<Object> playLeys = redis.scan(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
|
|
||||||
if (playLeys.size() == 0) return streamInfos;
|
|
||||||
for (int i = 0; i < playLeys.size(); i++) {
|
|
||||||
String key = (String) playLeys.get(i);
|
|
||||||
StreamInfo streamInfo = (StreamInfo)redis.get(key);
|
|
||||||
streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getCahnnelId(), streamInfo);
|
|
||||||
}
|
|
||||||
return streamInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean startPlayback(StreamInfo stream) {
|
|
||||||
return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()),
|
|
||||||
stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stopPlayback(StreamInfo streamInfo) {
|
|
||||||
if (streamInfo == null) return false;
|
|
||||||
DeviceChannel deviceChannel = queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId());
|
|
||||||
if (deviceChannel != null) {
|
|
||||||
deviceChannel.setSsrc(null);
|
|
||||||
deviceChannel.setPlay(false);
|
|
||||||
updateChannel(streamInfo.getDeviceID(), deviceChannel);
|
|
||||||
}
|
|
||||||
return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
|
||||||
streamInfo.getSsrc(),
|
|
||||||
streamInfo.getDeviceID(),
|
|
||||||
streamInfo.getCahnnelId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public StreamInfo queryPlaybackByDevice(String deviceId, String code) {
|
|
||||||
String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
|
||||||
deviceId,
|
|
||||||
code);
|
|
||||||
List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
|
||||||
deviceId,
|
|
||||||
code));
|
|
||||||
if (playLeys == null || playLeys.size() == 0) {
|
|
||||||
playLeys = redis.scan(String.format("%S_*_*_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
|
|
||||||
deviceId));
|
|
||||||
}
|
|
||||||
if (playLeys == null || playLeys.size() == 0) return null;
|
|
||||||
return (StreamInfo)redis.get(playLeys.get(0).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean updateParentPlatform(ParentPlatform parentPlatform) {
|
|
||||||
|
|
||||||
// 存储device
|
|
||||||
return redis.set(VideoManagerConstants.PLATFORM_PREFIX + parentPlatform.getDeviceGBId(), parentPlatform);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteParentPlatform(ParentPlatform parentPlatform) {
|
|
||||||
return redis.del(VideoManagerConstants.PLATFORM_PREFIX + parentPlatform.getDeviceGBId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageResult<ParentPlatform> queryParentPlatformList(int page, int count) {
|
|
||||||
PageResult pageResult = new PageResult<Device>();
|
|
||||||
pageResult.setPage(page);
|
|
||||||
pageResult.setCount(count);
|
|
||||||
List<ParentPlatform> resultData = new ArrayList<>();
|
|
||||||
List<Object> parentPlatformList = redis.scan(VideoManagerConstants.PLATFORM_PREFIX + "*");
|
|
||||||
pageResult.setTotal(parentPlatformList.size());
|
|
||||||
int maxCount = (page + 1)* count;
|
|
||||||
for (int i = page * count; i < (pageResult.getTotal() > maxCount ? maxCount : pageResult.getTotal() ); i++) {
|
|
||||||
ParentPlatform parentPlatform =(ParentPlatform)redis.get((String)parentPlatformList.get(i));
|
|
||||||
resultData.add(parentPlatform);
|
|
||||||
|
|
||||||
}
|
|
||||||
pageResult.setData(resultData);
|
|
||||||
return pageResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ParentPlatform queryParentPlatById(String platformGbId) {
|
|
||||||
return (ParentPlatform)redis.get(VideoManagerConstants.PLATFORM_PREFIX + platformGbId);
|
|
||||||
}
|
|
||||||
}
|
|
@ -34,6 +34,7 @@ public class SpringBeanFactory implements ApplicationContextAware {
|
|||||||
* 获取对象 这里重写了bean方法,起主要作用
|
* 获取对象 这里重写了bean方法,起主要作用
|
||||||
*/
|
*/
|
||||||
public static Object getBean(String beanId) throws BeansException {
|
public static Object getBean(String beanId) throws BeansException {
|
||||||
|
if (applicationContext == null) return null;
|
||||||
return applicationContext.getBean(beanId);
|
return applicationContext.getBean(beanId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.device;
|
package com.genersoft.iot.vmp.vmanager.device;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.genersoft.iot.vmp.common.PageResult;
|
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
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.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
@ -19,6 +19,8 @@ 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.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
|
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api")
|
@RequestMapping("/api")
|
||||||
@ -50,13 +52,13 @@ public class DeviceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/devices")
|
@GetMapping("/devices")
|
||||||
public PageResult<Device> devices(int page, int count){
|
public PageInfo<Device> devices(int page, int count){
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("查询所有视频设备API调用");
|
logger.debug("查询所有视频设备API调用");
|
||||||
}
|
}
|
||||||
|
|
||||||
return storager.queryVideoDeviceList(null, page, count);
|
return storager.queryVideoDeviceList(page, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,18 +68,33 @@ public class DeviceController {
|
|||||||
* @param count 每页条数
|
* @param count 每页条数
|
||||||
* @return 通道列表
|
* @return 通道列表
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* 分页查询通道数
|
||||||
|
*
|
||||||
|
* @param deviceId 设备id
|
||||||
|
* @param page 当前页
|
||||||
|
* @param count 每页条数
|
||||||
|
* @param query 查询内容
|
||||||
|
* @param online 是否在线 在线 true / 离线 false
|
||||||
|
* @param channelType 设备 false/子目录 true
|
||||||
|
* @return 通道列表
|
||||||
|
*/
|
||||||
@GetMapping("/devices/{deviceId}/channels")
|
@GetMapping("/devices/{deviceId}/channels")
|
||||||
public ResponseEntity<PageResult> channels(@PathVariable String deviceId,
|
public ResponseEntity<PageInfo> channels(@PathVariable String deviceId,
|
||||||
int page, int count,
|
int page, int count,
|
||||||
@RequestParam(required = false) String query,
|
@RequestParam(required = false) String query,
|
||||||
@RequestParam(required = false) String online,
|
@RequestParam(required = false) Boolean online,
|
||||||
@RequestParam(required = false) Boolean channelType
|
@RequestParam(required = false) Boolean channelType
|
||||||
){
|
){
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("查询所有视频设备API调用");
|
logger.debug("查询所有视频设备API调用");
|
||||||
}
|
}
|
||||||
PageResult pageResult = storager.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count);
|
if (StringUtils.isEmpty(query)) {
|
||||||
|
query = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageInfo pageResult = storager.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count);
|
||||||
return new ResponseEntity<>(pageResult,HttpStatus.OK);
|
return new ResponseEntity<>(pageResult,HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,11 +103,25 @@ public class DeviceController {
|
|||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
}
|
}
|
||||||
logger.debug("设备信息同步API调用,deviceId:" + deviceId);
|
logger.debug("设备通道信息同步API调用,deviceId:" + deviceId);
|
||||||
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
cmder.catalogQuery(device);
|
cmder.catalogQuery(device, event -> {
|
||||||
DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>();
|
Response response = event.getResponse();
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
|
||||||
|
msg.setData(String.format("同步通道失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
|
DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(2*1000L);
|
||||||
|
result.onTimeout(()->{
|
||||||
|
logger.warn(String.format("设备通道信息同步超时"));
|
||||||
|
// 释放rtpserver
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
|
||||||
|
msg.setData("Timeout");
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -124,7 +155,7 @@ public class DeviceController {
|
|||||||
* @return 子通道列表
|
* @return 子通道列表
|
||||||
*/
|
*/
|
||||||
@GetMapping("/subChannels/{deviceId}/{channelId}/channels")
|
@GetMapping("/subChannels/{deviceId}/{channelId}/channels")
|
||||||
public ResponseEntity<PageResult> subChannels(@PathVariable String deviceId,
|
public ResponseEntity<PageInfo> subChannels(@PathVariable String deviceId,
|
||||||
@PathVariable String channelId,
|
@PathVariable String channelId,
|
||||||
int page,
|
int page,
|
||||||
int count,
|
int count,
|
||||||
@ -137,23 +168,23 @@ public class DeviceController {
|
|||||||
}
|
}
|
||||||
DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId);
|
DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId);
|
||||||
if (deviceChannel == null) {
|
if (deviceChannel == null) {
|
||||||
PageResult<DeviceChannel> deviceChannelPageResult = new PageResult<>();
|
PageInfo<DeviceChannel> deviceChannelPageResult = new PageInfo<>();
|
||||||
return new ResponseEntity<>(deviceChannelPageResult,HttpStatus.OK);
|
return new ResponseEntity<>(deviceChannelPageResult,HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
PageResult pageResult = storager.querySubChannels(deviceId, channelId, query, channelType, online, page, count);
|
PageInfo pageResult = storager.querySubChannels(deviceId, channelId, query, channelType, online, page, count);
|
||||||
return new ResponseEntity<>(pageResult,HttpStatus.OK);
|
return new ResponseEntity<>(pageResult,HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/channel/update/{deviceId}")
|
@PostMapping("/channel/update/{deviceId}")
|
||||||
public ResponseEntity<PageResult> updateChannel(@PathVariable String deviceId,DeviceChannel channel){
|
public ResponseEntity<PageInfo> updateChannel(@PathVariable String deviceId,DeviceChannel channel){
|
||||||
storager.updateChannel(deviceId, channel);
|
storager.updateChannel(deviceId, channel);
|
||||||
return new ResponseEntity<>(null,HttpStatus.OK);
|
return new ResponseEntity<>(null,HttpStatus.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/devices/{deviceId}/transport/{streamMode}")
|
@GetMapping("/devices/{deviceId}/transport/{streamMode}")
|
||||||
@PostMapping("/devices/{deviceId}/transport/{streamMode}")
|
@PostMapping("/devices/{deviceId}/transport/{streamMode}")
|
||||||
public ResponseEntity<PageResult> 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);
|
||||||
|
@ -1,401 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.device.entity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
import javax.persistence.Transient;
|
|
||||||
import javax.validation.constraints.Max;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import javax.validation.constraints.Size;
|
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:视频设备信息
|
|
||||||
* @author: songww
|
|
||||||
* @date: 2020年5月8日 下午2:05:56
|
|
||||||
*/
|
|
||||||
@ApiModel(value = "视频设备信息", description = "视频设备信息")
|
|
||||||
@Table(name="VMP_VIDEODEVICES")
|
|
||||||
public class Device {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备Id
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("设备编号")
|
|
||||||
@Id
|
|
||||||
@Column(name="DEVICE_ID")
|
|
||||||
@NotNull(message = "deviceId 不能为 null")
|
|
||||||
@Size(min = 4, max = 32, message = "deviceId 必须大于 4 位并且小于 32 位")
|
|
||||||
private String deviceId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备名称
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("设备名称")
|
|
||||||
@Column(name="DEVICE_NAME")
|
|
||||||
@Size(max = 32, message = "deviceName 必须小于 32 位")
|
|
||||||
private String deviceName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产厂商
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("生产厂商")
|
|
||||||
@Column(name="MANUFACTURER")
|
|
||||||
@Size(max = 64, message = "manufacturer 必须小于 64 位")
|
|
||||||
private String manufacturer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 型号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("型号")
|
|
||||||
@Column(name="MODEL")
|
|
||||||
@Size(max = 64, message = "manufacturer 必须小于 64 位")
|
|
||||||
private String model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件版本
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("固件版本")
|
|
||||||
@Column(name="FIRMWARE")
|
|
||||||
@Size(max = 64, message = "firmware 必须小于 64 位")
|
|
||||||
private String firmware;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通信协议
|
|
||||||
* GB28181 ONVIF
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("通信协议")
|
|
||||||
@Column(name="PROTOCOL")
|
|
||||||
@NotNull(message = "protocol 不能为 null")
|
|
||||||
@Size(max = 16, message = "protocol 必须小于 16 位")
|
|
||||||
private String protocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SIP 传输协议
|
|
||||||
* UDP/TCP
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("SIP 传输协议")
|
|
||||||
@Column(name="TRANSPORT")
|
|
||||||
@Size(min = 3,max = 3 ,message = "transport 必须为 3 位")
|
|
||||||
private String transport;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据流传输模式
|
|
||||||
* UDP:udp传输
|
|
||||||
* TCP-ACTIVE:tcp主动模式
|
|
||||||
* TCP-PASSIVE:tcp被动模式
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("数据流传输模式")
|
|
||||||
@Column(name="STREAM_MODE")
|
|
||||||
@Size(max = 64, message = "streamMode 必须小于 16 位")
|
|
||||||
private String streamMode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IP地址
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("IP地址")
|
|
||||||
@Column(name="IP")
|
|
||||||
@Size(max = 15, message = "streamMode 必须小于 15 位")
|
|
||||||
private String ip;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 端口号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("端口号")
|
|
||||||
@Column(name="PORT")
|
|
||||||
@Max(value = 65535,message = "port 最大值为 65535")
|
|
||||||
private Integer port;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在线状态 1在线, 0离线
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("在线状态")
|
|
||||||
@Size(min = 1,max = 1 ,message = "online 必须为 1 位")
|
|
||||||
@Column(name="ONLINE")
|
|
||||||
private String online;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通道数量
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("通道数量")
|
|
||||||
@Column(name="CHANNEL_SUM")
|
|
||||||
@Max(value = 1000000000,message = "channelSum 最大值为 1000000000")
|
|
||||||
private Integer channelSum;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Device{" +
|
|
||||||
"deviceId='" + deviceId + '\'' +
|
|
||||||
", deviceName='" + deviceName + '\'' +
|
|
||||||
", manufacturer='" + manufacturer + '\'' +
|
|
||||||
", model='" + model + '\'' +
|
|
||||||
", firmware='" + firmware + '\'' +
|
|
||||||
", protocol='" + protocol + '\'' +
|
|
||||||
", transport='" + transport + '\'' +
|
|
||||||
", streamMode='" + streamMode + '\'' +
|
|
||||||
", ip='" + ip + '\'' +
|
|
||||||
", port=" + port +
|
|
||||||
", online='" + online + '\'' +
|
|
||||||
", channelSum=" + channelSum +
|
|
||||||
", createTime='" + createTime + '\'' +
|
|
||||||
", registerTime='" + registerTime + '\'' +
|
|
||||||
", heartbeatTime='" + heartbeatTime + '\'' +
|
|
||||||
", updateTime='" + updateTime + '\'' +
|
|
||||||
", updatePerson='" + updatePerson + '\'' +
|
|
||||||
", syncTime='" + syncTime + '\'' +
|
|
||||||
", syncPerson='" + syncPerson + '\'' +
|
|
||||||
", username='" + username + '\'' +
|
|
||||||
", password='" + password + '\'' +
|
|
||||||
", channelList=" + channelList +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("创建时间")
|
|
||||||
@Column(name="CREATE_TIME")
|
|
||||||
private String createTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册时间
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("注册时间")
|
|
||||||
@Column(name="REGISTER_TIME")
|
|
||||||
private String registerTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 心跳时间
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("心跳时间")
|
|
||||||
@Column(name="HEARTBEAT_TIME")
|
|
||||||
private String heartbeatTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改时间
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("更新时间")
|
|
||||||
@Column(name="UPDATE_TIME")
|
|
||||||
private String updateTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改人
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("修改人")
|
|
||||||
@Column(name="UPDATE_PERSON")
|
|
||||||
private String updatePerson;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步时间
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("同步时间")
|
|
||||||
@Column(name="SYNC_TIME")
|
|
||||||
private String syncTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步人
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("同步人")
|
|
||||||
@Column(name="SYNC_PERSON")
|
|
||||||
private String syncPerson;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ONVIF协议-用户名
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("用户名")
|
|
||||||
@Column(name="USERNAME")
|
|
||||||
@Size(max = 32, message = "username 必须小于 32 位")
|
|
||||||
private String username;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ONVIF协议-密码
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("密码")
|
|
||||||
@Size(max = 32, message = "password 必须小于 32 位")
|
|
||||||
@Column(name="PASSWORD")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
@Transient
|
|
||||||
private List<DeviceChannel> channelList;
|
|
||||||
|
|
||||||
|
|
||||||
public String getDeviceId() {
|
|
||||||
return deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceId(String deviceId) {
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceName() {
|
|
||||||
return deviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceName(String deviceName) {
|
|
||||||
this.deviceName = deviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getManufacturer() {
|
|
||||||
return manufacturer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setManufacturer(String manufacturer) {
|
|
||||||
this.manufacturer = manufacturer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModel() {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModel(String model) {
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFirmware() {
|
|
||||||
return firmware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFirmware(String firmware) {
|
|
||||||
this.firmware = firmware;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getProtocol() {
|
|
||||||
return protocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProtocol(String protocol) {
|
|
||||||
this.protocol = protocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTransport() {
|
|
||||||
return transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTransport(String transport) {
|
|
||||||
this.transport = transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStreamMode() {
|
|
||||||
return streamMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStreamMode(String streamMode) {
|
|
||||||
this.streamMode = streamMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIp() {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIp(String ip) {
|
|
||||||
this.ip = ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(Integer port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOnline() {
|
|
||||||
return online;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnline(String online) {
|
|
||||||
this.online = online;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getChannelSum() {
|
|
||||||
return channelSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChannelSum(Integer channelSum) {
|
|
||||||
this.channelSum = channelSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCreateTime() {
|
|
||||||
return createTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCreateTime(String createTime) {
|
|
||||||
this.createTime = createTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRegisterTime() {
|
|
||||||
return registerTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegisterTime(String registerTime) {
|
|
||||||
this.registerTime = registerTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHeartbeatTime() {
|
|
||||||
return heartbeatTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeartbeatTime(String heartbeatTime) {
|
|
||||||
this.heartbeatTime = heartbeatTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUpdateTime() {
|
|
||||||
return updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdateTime(String updateTime) {
|
|
||||||
this.updateTime = updateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUpdatePerson() {
|
|
||||||
return updatePerson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUpdatePerson(String updatePerson) {
|
|
||||||
this.updatePerson = updatePerson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSyncTime() {
|
|
||||||
return syncTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSyncTime(String syncTime) {
|
|
||||||
this.syncTime = syncTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSyncPerson() {
|
|
||||||
return syncPerson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSyncPerson(String syncPerson) {
|
|
||||||
this.syncPerson = syncPerson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUsername(String username) {
|
|
||||||
this.username = username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DeviceChannel> getChannelList() {
|
|
||||||
return channelList;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChannelList(List<DeviceChannel> channelList) {
|
|
||||||
this.channelList = channelList;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,385 +0,0 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.device.entity;
|
|
||||||
|
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Description:设备通道信息
|
|
||||||
* @author: songww
|
|
||||||
* @date: 2020年5月20日 下午9:00:46
|
|
||||||
*/
|
|
||||||
@ApiModel(value = "设备通道信息", description = "设备通道信息")
|
|
||||||
@Table(name="VMP_VIDEOCHANNELS")
|
|
||||||
public class DeviceChannel {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通道编号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("通道编号")
|
|
||||||
@Id
|
|
||||||
@Column(name="CHANNEL_ID")
|
|
||||||
private String channelId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备编号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("设备编号")
|
|
||||||
@Column(name="DEVICE_ID")
|
|
||||||
private String deviceId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通道名
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("通道名")
|
|
||||||
@Column(name="CHANNEL_NAME")
|
|
||||||
private String channelName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生产厂商
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("生产厂商")
|
|
||||||
@Column(name="MANUFACTURER")
|
|
||||||
private String manufacture;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 型号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("型号")
|
|
||||||
@Column(name="MODEL")
|
|
||||||
private String model;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备归属
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("设备归属")
|
|
||||||
@Column(name="OWNER")
|
|
||||||
private String owner;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 行政区域
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("行政区域")
|
|
||||||
@Column(name="CIVIL_CODE")
|
|
||||||
private String civilCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 警区
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("警区")
|
|
||||||
@Column(name="BLOCK")
|
|
||||||
private String block;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 安装地址
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("安装地址")
|
|
||||||
@Column(name="ADDRESS")
|
|
||||||
private String address;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否有子设备 1有, 0没有
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("是否有子设备")
|
|
||||||
@Column(name="PARENTAL")
|
|
||||||
private String parental;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 父级id
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("父级编码")
|
|
||||||
@Column(name="PARENT_ID")
|
|
||||||
private String parentId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 信令安全模式 缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("信令安全模式")
|
|
||||||
@Column(name="SAFETY_WAY")
|
|
||||||
private String safetyWay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("注册方式")
|
|
||||||
@Column(name="REGISTER_WAY")
|
|
||||||
private String registerWay;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 证书序列号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("证书序列号")
|
|
||||||
@Column(name="CERT_NUM")
|
|
||||||
private String certNum;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 证书有效标识 缺省为0;证书有效标识:0:无效1: 有效
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("证书有效标识")
|
|
||||||
@Column(name="CERT_VALID")
|
|
||||||
private String certValid;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 证书无效原因码
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("证书无效原因码")
|
|
||||||
@Column(name="CERT_ERRCODE")
|
|
||||||
private String certErrCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 证书终止有效期
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("证书终止有效期")
|
|
||||||
@Column(name="CERT_ENDTIME")
|
|
||||||
private String certEndTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 保密属性 缺省为0; 0:不涉密, 1:涉密
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("保密属性")
|
|
||||||
@Column(name="SECRECY")
|
|
||||||
private String secrecy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* IP地址
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("IP地址")
|
|
||||||
@Column(name="IP")
|
|
||||||
private String ip;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 端口号
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("端口号")
|
|
||||||
@Column(name="PORT")
|
|
||||||
private Integer port;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("密码")
|
|
||||||
@Column(name="PASSWORD")
|
|
||||||
private String password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在线/离线
|
|
||||||
* 1在线,0离线
|
|
||||||
* 默认在线
|
|
||||||
* 信令:
|
|
||||||
* <Status>ON</Status>
|
|
||||||
* <Status>OFF</Status>
|
|
||||||
* 遇到过NVR下的IPC下发信令可以推流, 但是 Status 响应 OFF
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("状态")
|
|
||||||
@Column(name="ONLINE")
|
|
||||||
private String online;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 经度
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("经度")
|
|
||||||
@Column(name="LONGITUDE")
|
|
||||||
private double longitude;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 纬度
|
|
||||||
*/
|
|
||||||
@ApiModelProperty("纬度")
|
|
||||||
@Column(name="LATITUDE")
|
|
||||||
private double latitude;
|
|
||||||
|
|
||||||
public String getChannelId() {
|
|
||||||
return channelId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChannelId(String channelId) {
|
|
||||||
this.channelId = channelId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceId() {
|
|
||||||
return deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceId(String deviceId) {
|
|
||||||
this.deviceId = deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getChannelName() {
|
|
||||||
return channelName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChannelName(String channelName) {
|
|
||||||
this.channelName = channelName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getManufacture() {
|
|
||||||
return manufacture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setManufacture(String manufacture) {
|
|
||||||
this.manufacture = manufacture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModel() {
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModel(String model) {
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwner() {
|
|
||||||
return owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(String owner) {
|
|
||||||
this.owner = owner;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCivilCode() {
|
|
||||||
return civilCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCivilCode(String civilCode) {
|
|
||||||
this.civilCode = civilCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBlock() {
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(String block) {
|
|
||||||
this.block = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAddress() {
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAddress(String address) {
|
|
||||||
this.address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getParental() {
|
|
||||||
return parental;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParental(String parental) {
|
|
||||||
this.parental = parental;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getParentId() {
|
|
||||||
return parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setParentId(String parentId) {
|
|
||||||
this.parentId = parentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSafetyWay() {
|
|
||||||
return safetyWay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSafetyWay(String safetyWay) {
|
|
||||||
this.safetyWay = safetyWay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRegisterWay() {
|
|
||||||
return registerWay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRegisterWay(String registerWay) {
|
|
||||||
this.registerWay = registerWay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertNum() {
|
|
||||||
return certNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCertNum(String certNum) {
|
|
||||||
this.certNum = certNum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertValid() {
|
|
||||||
return certValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCertValid(String certValid) {
|
|
||||||
this.certValid = certValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertErrCode() {
|
|
||||||
return certErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCertErrCode(String certErrCode) {
|
|
||||||
this.certErrCode = certErrCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertEndTime() {
|
|
||||||
return certEndTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCertEndTime(String certEndTime) {
|
|
||||||
this.certEndTime = certEndTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSecrecy() {
|
|
||||||
return secrecy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSecrecy(String secrecy) {
|
|
||||||
this.secrecy = secrecy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIp() {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIp(String ip) {
|
|
||||||
this.ip = ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPort(Integer port) {
|
|
||||||
this.port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOnline() {
|
|
||||||
return online;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOnline(String online) {
|
|
||||||
this.online = online;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLongitude() {
|
|
||||||
return longitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLongitude(double longitude) {
|
|
||||||
this.longitude = longitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getLatitude() {
|
|
||||||
return latitude;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLatitude(double latitude) {
|
|
||||||
this.latitude = latitude;
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,6 +7,8 @@ import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
|||||||
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.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -27,6 +29,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
|
import javax.sip.message.Response;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -43,6 +46,9 @@ public class PlayController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
@ -58,18 +64,11 @@ public class PlayController {
|
|||||||
|
|
||||||
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
StreamInfo streamInfo = storager.queryPlayByDevice(deviceId, channelId);
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
|
||||||
|
|
||||||
UUID uuid = UUID.randomUUID();
|
UUID uuid = UUID.randomUUID();
|
||||||
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
|
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
|
||||||
// 超时处理
|
|
||||||
result.onTimeout(()->{
|
|
||||||
logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
|
||||||
RequestMessage msg = new RequestMessage();
|
|
||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
|
||||||
msg.setData("Timeout");
|
|
||||||
resultHolder.invokeResult(msg);
|
|
||||||
});
|
|
||||||
// 录像查询以channelId作为deviceId查询
|
// 录像查询以channelId作为deviceId查询
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
||||||
|
|
||||||
@ -78,9 +77,15 @@ public class PlayController {
|
|||||||
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
||||||
|
}, event -> {
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
Response response = event.getResponse();
|
||||||
|
msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
|
String streamId = streamInfo.getStreamId();
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
||||||
if (rtpInfo.getBoolean("exist")) {
|
if (rtpInfo.getBoolean("exist")) {
|
||||||
RequestMessage msg = new RequestMessage();
|
RequestMessage msg = new RequestMessage();
|
||||||
@ -88,58 +93,107 @@ public class PlayController {
|
|||||||
msg.setData(JSON.toJSONString(streamInfo));
|
msg.setData(JSON.toJSONString(streamInfo));
|
||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
} else {
|
} else {
|
||||||
storager.stopPlay(streamInfo);
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
// TODO playStreamCmd 超时处理
|
|
||||||
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
|
||||||
|
}, event -> {
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
Response response = event.getResponse();
|
||||||
|
msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 超时处理
|
||||||
|
result.onTimeout(()->{
|
||||||
|
logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
|
||||||
|
// 释放rtpserver
|
||||||
|
cmder.closeRTPServer(device, channelId);
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
msg.setData("Timeout");
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/play/{ssrc}/stop")
|
@PostMapping("/play/{streamId}/stop")
|
||||||
public ResponseEntity<String> playStop(@PathVariable String ssrc) {
|
public DeferredResult<ResponseEntity<String>> playStop(@PathVariable String streamId) {
|
||||||
|
|
||||||
cmder.streamByeCmd(ssrc);
|
logger.debug(String.format("设备预览/回放停止API调用,streamId:%s", streamId));
|
||||||
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
|
|
||||||
if (streamInfo == null)
|
|
||||||
return new ResponseEntity<String>("ssrc not found", HttpStatus.OK);
|
|
||||||
storager.stopPlay(streamInfo);
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("设备预览停止API调用,ssrc:%s", ssrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ssrc != null) {
|
UUID uuid = UUID.randomUUID();
|
||||||
|
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
|
||||||
|
|
||||||
|
// 录像查询以channelId作为deviceId查询
|
||||||
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result);
|
||||||
|
|
||||||
|
cmder.streamByeCmd(streamId, event -> {
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
|
if (streamInfo == null) {
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
msg.setData("streamId not found");
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
|
||||||
|
Response response = event.getResponse();
|
||||||
|
msg.setData(String.format("success"));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (streamId != null) {
|
||||||
JSONObject json = new JSONObject();
|
JSONObject json = new JSONObject();
|
||||||
json.put("ssrc", ssrc);
|
json.put("streamId", streamId);
|
||||||
return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
msg.setData(json.toString());
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("设备预览停止API调用失败!");
|
logger.warn("设备预览/回放停止API调用失败!");
|
||||||
return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
msg.setData("streamId null");
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 超时处理
|
||||||
|
result.onTimeout(()->{
|
||||||
|
logger.warn(String.format("设备预览/回放停止超时,streamId:%s ", streamId));
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
|
||||||
|
msg.setData("Timeout");
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将不是h264的视频通过ffmpeg 转码为h264 + aac
|
* 将不是h264的视频通过ffmpeg 转码为h264 + aac
|
||||||
* @param ssrc
|
* @param streamId 流ID
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PostMapping("/play/{ssrc}/convert")
|
@PostMapping("/play/{streamId}/convert")
|
||||||
public ResponseEntity<String> playConvert(@PathVariable String ssrc) {
|
public ResponseEntity<String> playConvert(@PathVariable String streamId) {
|
||||||
StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc);
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
if (streamInfo == null) {
|
if (streamInfo == null) {
|
||||||
logger.warn("视频转码API调用失败!, 视频流已经停止!");
|
logger.warn("视频转码API调用失败!, 视频流已经停止!");
|
||||||
return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
|
return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
|
||||||
}
|
}
|
||||||
String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
|
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
||||||
if (!rtpInfo.getBoolean("exist")) {
|
if (!rtpInfo.getBoolean("exist")) {
|
||||||
logger.warn("视频转码API调用失败!, 视频流已停止推流!");
|
logger.warn("视频转码API调用失败!, 视频流已停止推流!");
|
||||||
return new ResponseEntity<String>("推流信息在流媒体中不存在, 视频流可能已停止推流", HttpStatus.OK);
|
return new ResponseEntity<String>("推流信息在流媒体中不存在, 视频流可能已停止推流", HttpStatus.OK);
|
||||||
} else {
|
} else {
|
||||||
MediaServerConfig mediaInfo = storager.getMediaInfo();
|
MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
|
||||||
String dstUrl = String.format("rtmp://%s:%s/convert/%s", "127.0.0.1", mediaInfo.getRtmpPort(),
|
String dstUrl = String.format("rtmp://%s:%s/convert/%s", "127.0.0.1", mediaInfo.getRtmpPort(),
|
||||||
streamId );
|
streamId );
|
||||||
String srcUrl = String.format("rtsp://%s:%s/rtp/%s", "127.0.0.1", mediaInfo.getRtspPort(), streamId);
|
String srcUrl = String.format("rtsp://%s:%s/rtp/%s", "127.0.0.1", mediaInfo.getRtspPort(), streamId);
|
||||||
|
@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.StreamInfo;
|
|||||||
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.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -27,6 +28,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
|||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
|
import javax.sip.message.Response;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
@ -42,6 +44,9 @@ public class PlaybackController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
@ -69,15 +74,21 @@ public class PlaybackController {
|
|||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
StreamInfo streamInfo = storager.queryPlaybackByDevice(deviceId, channelId);
|
StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
|
||||||
if (streamInfo != null) {
|
if (streamInfo != null) {
|
||||||
// 停止之前的回放
|
// 停止之前的回放
|
||||||
cmder.streamByeCmd(streamInfo.getSsrc());
|
cmder.streamByeCmd(streamInfo.getStreamId());
|
||||||
}
|
}
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
|
||||||
cmder.playbackStreamCmd(device, channelId, startTime, endTime, (JSONObject response) -> {
|
cmder.playbackStreamCmd(device, channelId, startTime, endTime, (JSONObject response) -> {
|
||||||
logger.info("收到订阅消息: " + response.toJSONString());
|
logger.info("收到订阅消息: " + response.toJSONString());
|
||||||
playService.onPublishHandlerForPlayBack(response, deviceId, channelId, uuid.toString());
|
playService.onPublishHandlerForPlayBack(response, deviceId, channelId, uuid.toString());
|
||||||
|
}, event -> {
|
||||||
|
Response response = event.getResponse();
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
|
msg.setData(String.format("回放失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -29,15 +29,14 @@ public class PtzController {
|
|||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* http://localhost:8080/api/ptz/34020000001320000002_34020000001320000008?leftRight=1&upDown=0&inOut=0&moveSpeed=50&zoomSpeed=0
|
* 云台控制
|
||||||
* @param deviceId
|
* @param deviceId 设备id
|
||||||
* @param channelId
|
* @param channelId 通道id
|
||||||
* @param leftRight
|
* @param cmdCode 指令码
|
||||||
* @param upDown
|
* @param horizonSpeed 水平移动速度
|
||||||
* @param inOut
|
* @param verticalSpeed 垂直移动速度
|
||||||
* @param moveSpeed
|
* @param zoomSpeed 缩放速度
|
||||||
* @param zoomSpeed
|
* @return String 控制结果
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
@PostMapping("/ptz/{deviceId}/{channelId}")
|
@PostMapping("/ptz/{deviceId}/{channelId}")
|
||||||
public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed){
|
public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed){
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.vmanager.record;
|
package com.genersoft.iot.vmp.vmanager.record;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||||
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;
|
||||||
@ -32,7 +33,7 @@ public class RecordController {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
@GetMapping("/record/{deviceId}/{channelId}")
|
@GetMapping("/record/{deviceId}/{channelId}")
|
||||||
public DeferredResult<ResponseEntity<RecordInfo>> recordinfo(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){
|
public DeferredResult<ResponseEntity<RecordInfo>> recordinfo(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){
|
||||||
|
|
||||||
@ -42,9 +43,17 @@ public class RecordController {
|
|||||||
|
|
||||||
Device device = storager.queryVideoDevice(deviceId);
|
Device device = storager.queryVideoDevice(deviceId);
|
||||||
cmder.recordInfoQuery(device, channelId, startTime, endTime);
|
cmder.recordInfoQuery(device, channelId, startTime, endTime);
|
||||||
DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<ResponseEntity<RecordInfo>>();
|
// 指定超时时间 1分钟30秒
|
||||||
|
DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<ResponseEntity<RecordInfo>>(90*1000L);
|
||||||
// 录像查询以channelId作为deviceId查询
|
// 录像查询以channelId作为deviceId查询
|
||||||
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_RECORDINFO+channelId, result);
|
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_RECORDINFO+channelId, result);
|
||||||
|
result.onTimeout(()->{
|
||||||
|
RequestMessage msg = new RequestMessage();
|
||||||
|
msg.setDeviceId(deviceId);
|
||||||
|
msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
|
||||||
|
msg.setData("timeout");
|
||||||
|
resultHolder.invokeResult(msg);
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ 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.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
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.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
||||||
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
import com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
@ -24,6 +26,9 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeferredResultHolder resultHolder;
|
private DeferredResultHolder resultHolder;
|
||||||
|
|
||||||
@ -33,7 +38,13 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid);
|
StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid);
|
||||||
if (streamInfo != null) {
|
if (streamInfo != null) {
|
||||||
storager.startPlay(streamInfo);
|
DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
|
||||||
|
if (deviceChannel != null) {
|
||||||
|
deviceChannel.setStreamId(streamInfo.getStreamId());
|
||||||
|
storager.updateChannel(deviceId, deviceChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
redisCatchStorage.startPlay(streamInfo);
|
||||||
msg.setData(JSON.toJSONString(streamInfo));
|
msg.setData(JSON.toJSONString(streamInfo));
|
||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
} else {
|
} else {
|
||||||
@ -49,7 +60,7 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
|
||||||
StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid);
|
StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid);
|
||||||
if (streamInfo != null) {
|
if (streamInfo != null) {
|
||||||
storager.startPlayback(streamInfo);
|
redisCatchStorage.startPlayback(streamInfo);
|
||||||
msg.setData(JSON.toJSONString(streamInfo));
|
msg.setData(JSON.toJSONString(streamInfo));
|
||||||
resultHolder.invokeResult(msg);
|
resultHolder.invokeResult(msg);
|
||||||
} else {
|
} else {
|
||||||
@ -61,13 +72,11 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
|
|
||||||
public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
|
public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
|
||||||
String streamId = resonse.getString("id");
|
String streamId = resonse.getString("id");
|
||||||
String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16));
|
|
||||||
StreamInfo streamInfo = new StreamInfo();
|
StreamInfo streamInfo = new StreamInfo();
|
||||||
streamInfo.setSsrc(ssrc);
|
|
||||||
streamInfo.setStreamId(streamId);
|
streamInfo.setStreamId(streamId);
|
||||||
streamInfo.setDeviceID(deviceId);
|
streamInfo.setDeviceID(deviceId);
|
||||||
streamInfo.setCahnnelId(channelId);
|
streamInfo.setCahnnelId(channelId);
|
||||||
MediaServerConfig mediaServerConfig = storager.getMediaInfo();
|
MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo();
|
||||||
|
|
||||||
streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
|
streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
|
||||||
streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
|
streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
|
||||||
|
@ -1,22 +1,17 @@
|
|||||||
package com.genersoft.iot.vmp.web;
|
package com.genersoft.iot.vmp.web;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.PageResult;
|
|
||||||
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.event.DeviceOffLineDetector;
|
import com.genersoft.iot.vmp.gb28181.event.DeviceOffLineDetector;
|
||||||
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.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.device.DeviceController;
|
import com.github.pagehelper.PageInfo;
|
||||||
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.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -65,12 +60,12 @@ public class ApiDeviceController {
|
|||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
List<Device> devices;
|
List<Device> devices;
|
||||||
if (start == null || limit ==null) {
|
if (start == null || limit ==null) {
|
||||||
devices = storager.queryVideoDeviceList(null);
|
devices = storager.queryVideoDeviceList();
|
||||||
result.put("DeviceCount", devices.size());
|
result.put("DeviceCount", devices.size());
|
||||||
}else {
|
}else {
|
||||||
PageResult<Device> deviceList = storager.queryVideoDeviceList(null, start/limit, limit);
|
PageInfo<Device> deviceList = storager.queryVideoDeviceList(start/limit, limit);
|
||||||
result.put("DeviceCount", deviceList.getTotal());
|
result.put("DeviceCount", deviceList.getTotal());
|
||||||
devices = deviceList.getData();
|
devices = deviceList.getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONArray deviceJSONList = new JSONArray();
|
JSONArray deviceJSONList = new JSONArray();
|
||||||
@ -86,8 +81,8 @@ public class ApiDeviceController {
|
|||||||
deviceJsonObject.put("Online", device.getOnline() == 1);
|
deviceJsonObject.put("Online", device.getOnline() == 1);
|
||||||
deviceJsonObject.put("Password", "");
|
deviceJsonObject.put("Password", "");
|
||||||
deviceJsonObject.put("MediaTransport", device.getTransport());
|
deviceJsonObject.put("MediaTransport", device.getTransport());
|
||||||
deviceJsonObject.put("RemoteIP", device.getHost().getIp());
|
deviceJsonObject.put("RemoteIP", device.getIp());
|
||||||
deviceJsonObject.put("RemotePort", device.getHost().getPort());
|
deviceJsonObject.put("RemotePort", device.getPort());
|
||||||
deviceJsonObject.put("LastRegisterAt", "");
|
deviceJsonObject.put("LastRegisterAt", "");
|
||||||
deviceJsonObject.put("LastKeepaliveAt", "");
|
deviceJsonObject.put("LastKeepaliveAt", "");
|
||||||
deviceJsonObject.put("UpdatedAt", "");
|
deviceJsonObject.put("UpdatedAt", "");
|
||||||
@ -123,9 +118,9 @@ public class ApiDeviceController {
|
|||||||
deviceChannels = storager.queryChannelsByDeviceId(serial);
|
deviceChannels = storager.queryChannelsByDeviceId(serial);
|
||||||
result.put("ChannelCount", deviceChannels.size());
|
result.put("ChannelCount", deviceChannels.size());
|
||||||
}else {
|
}else {
|
||||||
PageResult<DeviceChannel> pageResult = storager.queryChannelsByDeviceId(serial, null, null, null,start/limit, limit);
|
PageInfo<DeviceChannel> pageResult = storager.queryChannelsByDeviceId(serial, null, null, null,start/limit, limit);
|
||||||
result.put("ChannelCount", pageResult.getTotal());
|
result.put("ChannelCount", pageResult.getTotal());
|
||||||
deviceChannels = pageResult.getData();
|
deviceChannels = pageResult.getList();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONArray channleJSONList = new JSONArray();
|
JSONArray channleJSONList = new JSONArray();
|
||||||
@ -159,7 +154,7 @@ public class ApiDeviceController {
|
|||||||
deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球,
|
deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球,
|
||||||
// 3 - 固定枪机, 4 - 遥控枪机
|
// 3 - 固定枪机, 4 - 遥控枪机
|
||||||
deviceJOSNChannel.put("CustomPTZType", "");
|
deviceJOSNChannel.put("CustomPTZType", "");
|
||||||
deviceJOSNChannel.put("StreamID", deviceChannel.getSsrc()); // StreamID 直播流ID, 有值表示正在直播
|
deviceJOSNChannel.put("StreamID", deviceChannel.getStreamId()); // StreamID 直播流ID, 有值表示正在直播
|
||||||
deviceJOSNChannel.put("NumOutputs ", -1); // 直播在线人数
|
deviceJOSNChannel.put("NumOutputs ", -1); // 直播在线人数
|
||||||
channleJSONList.add(deviceJOSNChannel);
|
channleJSONList.add(deviceJOSNChannel);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ 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.transmit.cmd.impl.SIPCommander;
|
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||||
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
import com.genersoft.iot.vmp.vmanager.play.PlayController;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -17,6 +18,7 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 兼容LiveGBS的API:实时直播
|
* 兼容LiveGBS的API:实时直播
|
||||||
@ -34,12 +36,17 @@ public class ApiStreamController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
private boolean closeWaitRTPInfo = false;
|
@Autowired
|
||||||
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlayController playController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 实时直播 - 开始直播
|
* 实时直播 - 开始直播
|
||||||
* @param serial 设备编号
|
* @param serial 设备编号
|
||||||
@ -54,126 +61,54 @@ public class ApiStreamController {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@RequestMapping(value = "/start")
|
@RequestMapping(value = "/start")
|
||||||
private JSONObject start(String serial ,
|
private DeferredResult<JSONObject> start(String serial ,
|
||||||
@RequestParam(required = false)Integer channel ,
|
@RequestParam(required = false)Integer channel ,
|
||||||
@RequestParam(required = false)String code,
|
@RequestParam(required = false)String code,
|
||||||
@RequestParam(required = false)String cdn,
|
@RequestParam(required = false)String cdn,
|
||||||
@RequestParam(required = false)String audio,
|
@RequestParam(required = false)String audio,
|
||||||
@RequestParam(required = false)String transport,
|
@RequestParam(required = false)String transport,
|
||||||
@RequestParam(required = false)String checkchannelstatus ,
|
@RequestParam(required = false)String checkchannelstatus ,
|
||||||
@RequestParam(required = false)String transportmode,
|
@RequestParam(required = false)String transportmode,
|
||||||
@RequestParam(required = false)String timeout
|
@RequestParam(required = false)String timeout
|
||||||
|
|
||||||
){
|
){
|
||||||
int getEncoding = closeWaitRTPInfo? 1: 0;
|
DeferredResult<JSONObject> resultDeferredResult = new DeferredResult<JSONObject>();
|
||||||
Device device = storager.queryVideoDevice(serial);
|
Device device = storager.queryVideoDevice(serial);
|
||||||
|
|
||||||
if (device == null ) {
|
if (device == null ) {
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("error","device[ " + serial + " ]未找到");
|
result.put("error","device[ " + serial + " ]未找到");
|
||||||
return result;
|
resultDeferredResult.setResult(result);
|
||||||
}else if (device.getOnline() == 0) {
|
}else if (device.getOnline() == 0) {
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("error","device[ " + code + " ]offline");
|
result.put("error","device[ " + code + " ]offline");
|
||||||
return result;
|
resultDeferredResult.setResult(result);
|
||||||
}
|
}
|
||||||
|
resultDeferredResult.onTimeout(()->{
|
||||||
|
logger.info("播放等待超时");
|
||||||
|
JSONObject result = new JSONObject();
|
||||||
|
result.put("error","timeout");
|
||||||
|
resultDeferredResult.setResult(result);
|
||||||
|
|
||||||
|
// 清理RTP server
|
||||||
|
});
|
||||||
|
|
||||||
DeviceChannel deviceChannel = storager.queryChannel(serial, code);
|
DeviceChannel deviceChannel = storager.queryChannel(serial, code);
|
||||||
if (deviceChannel == null) {
|
if (deviceChannel == null) {
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("error","channel[ " + code + " ]未找到");
|
result.put("error","channel[ " + code + " ]未找到");
|
||||||
return result;
|
resultDeferredResult.setResult(result);
|
||||||
}else if (deviceChannel.getStatus() == 0) {
|
}else if (deviceChannel.getStatus() == 0) {
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("error","channel[ " + code + " ]offline");
|
result.put("error","channel[ " + code + " ]offline");
|
||||||
return result;
|
resultDeferredResult.setResult(result);
|
||||||
}
|
}
|
||||||
|
DeferredResult<ResponseEntity<String>> play = playController.play(serial, code);
|
||||||
|
|
||||||
// 查询是否已经在播放
|
play.setResultHandler((Object o)->{
|
||||||
StreamInfo streamInfo = storager.queryPlayByDevice(device.getDeviceId(), code);
|
ResponseEntity<String> responseEntity = (ResponseEntity)o;
|
||||||
if (streamInfo == null) {
|
StreamInfo streamInfo = JSON.parseObject(responseEntity.getBody(), StreamInfo.class);
|
||||||
logger.debug("streamInfo 等于null, 重新点播");
|
|
||||||
// streamInfo = cmder.playStreamCmd(device, code);
|
|
||||||
}else {
|
|
||||||
logger.debug("streamInfo 不等于null, 向流媒体查询是否正在推流");
|
|
||||||
String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase();
|
|
||||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId);
|
|
||||||
if (rtpInfo.getBoolean("exist")) {
|
|
||||||
logger.debug("向流媒体查询正在推流, 直接返回: " + streamInfo.getRtsp());
|
|
||||||
JSONObject result = new JSONObject();
|
|
||||||
result.put("StreamID", streamInfo.getSsrc());
|
|
||||||
result.put("DeviceID", device.getDeviceId());
|
|
||||||
result.put("ChannelID", code);
|
|
||||||
result.put("ChannelName", deviceChannel.getName());
|
|
||||||
result.put("ChannelCustomName", "");
|
|
||||||
result.put("FLV", streamInfo.getFlv());
|
|
||||||
result.put("WS_FLV", streamInfo.getWs_flv());
|
|
||||||
result.put("RTMP", streamInfo.getRtmp());
|
|
||||||
result.put("HLS", streamInfo.getHls());
|
|
||||||
result.put("RTSP", streamInfo.getRtsp());
|
|
||||||
result.put("CDN", "");
|
|
||||||
result.put("SnapURL", "");
|
|
||||||
result.put("Transport", device.getTransport());
|
|
||||||
result.put("StartAt", "");
|
|
||||||
result.put("Duration", "");
|
|
||||||
result.put("SourceVideoCodecName", "");
|
|
||||||
result.put("SourceVideoWidth", "");
|
|
||||||
result.put("SourceVideoHeight", "");
|
|
||||||
result.put("SourceVideoFrameRate", "");
|
|
||||||
result.put("SourceAudioCodecName", "");
|
|
||||||
result.put("SourceAudioSampleRate", "");
|
|
||||||
result.put("AudioEnable", "");
|
|
||||||
result.put("Ondemand", "");
|
|
||||||
result.put("InBytes", "");
|
|
||||||
result.put("InBitRate", "");
|
|
||||||
result.put("OutBytes", "");
|
|
||||||
result.put("NumOutputs", "");
|
|
||||||
result.put("CascadeSize", "");
|
|
||||||
result.put("RelaySize", "");
|
|
||||||
result.put("ChannelPTZType", 0);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
logger.debug("向流媒体查询没有推流, 重新点播");
|
|
||||||
storager.stopPlay(streamInfo);
|
|
||||||
// streamInfo = cmder.playStreamCmd(device, code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("设备预览 API调用,deviceId:%s ,channelId:%s",serial, code));
|
|
||||||
logger.debug("设备预览 API调用,ssrc:"+streamInfo.getSsrc()+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(streamInfo.getSsrc())));
|
|
||||||
}
|
|
||||||
boolean lockFlag = true;
|
|
||||||
long startTime = System.currentTimeMillis();
|
|
||||||
while (lockFlag) {
|
|
||||||
try {
|
|
||||||
if (System.currentTimeMillis() - startTime > 10 * 1000) {
|
|
||||||
storager.stopPlay(streamInfo);
|
|
||||||
logger.info("播放等待超时");
|
|
||||||
JSONObject result = new JSONObject();
|
|
||||||
result.put("error","timeout");
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
StreamInfo streamInfoNow = storager.queryPlayByDevice(serial, code);
|
|
||||||
logger.debug("正在向流媒体查询");
|
|
||||||
if (streamInfoNow != null && streamInfoNow.getFlv() != null) {
|
|
||||||
streamInfo = streamInfoNow;
|
|
||||||
logger.debug("向流媒体查询到: " + streamInfoNow.getRtsp());
|
|
||||||
lockFlag = false;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
Thread.sleep(2000);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(streamInfo!=null) {
|
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("StreamID", streamInfo.getSsrc());
|
result.put("StreamID", streamInfo.getStreamId());
|
||||||
result.put("DeviceID", device.getDeviceId());
|
result.put("DeviceID", device.getDeviceId());
|
||||||
result.put("ChannelID", code);
|
result.put("ChannelID", code);
|
||||||
result.put("ChannelName", deviceChannel.getName());
|
result.put("ChannelName", deviceChannel.getName());
|
||||||
@ -203,13 +138,9 @@ public class ApiStreamController {
|
|||||||
result.put("CascadeSize", "");
|
result.put("CascadeSize", "");
|
||||||
result.put("RelaySize", "");
|
result.put("RelaySize", "");
|
||||||
result.put("ChannelPTZType", 0);
|
result.put("ChannelPTZType", 0);
|
||||||
return result;
|
resultDeferredResult.setResult(result);
|
||||||
} else {
|
});
|
||||||
logger.warn("设备预览API调用失败!");
|
return resultDeferredResult;
|
||||||
JSONObject result = new JSONObject();
|
|
||||||
result.put("error","调用失败");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -228,14 +159,15 @@ public class ApiStreamController {
|
|||||||
@RequestParam(required = false)String check_outputs
|
@RequestParam(required = false)String check_outputs
|
||||||
|
|
||||||
){
|
){
|
||||||
StreamInfo streamInfo = storager.queryPlayByDevice(serial, code);
|
|
||||||
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code);
|
||||||
if (streamInfo == null) {
|
if (streamInfo == null) {
|
||||||
JSONObject result = new JSONObject();
|
JSONObject result = new JSONObject();
|
||||||
result.put("error","未找到流信息");
|
result.put("error","未找到流信息");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
cmder.streamByeCmd(streamInfo.getSsrc());
|
cmder.streamByeCmd(streamInfo.getStreamId());
|
||||||
storager.stopPlay(streamInfo);
|
redisCatchStorage.stopPlay(streamInfo);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,20 @@ spring:
|
|||||||
timeout: 10000
|
timeout: 10000
|
||||||
# [不可用] jdbc数据库配置, 暂不支持
|
# [不可用] jdbc数据库配置, 暂不支持
|
||||||
datasource:
|
datasource:
|
||||||
|
# name: eiot
|
||||||
|
# url: jdbc:mysql://127.0.0.1:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
||||||
|
# username:
|
||||||
|
# password:
|
||||||
|
# type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
# driver-class-name: com.mysql.jdbc.Driver
|
||||||
name: eiot
|
name: eiot
|
||||||
url: jdbc:mysql://127.0.0.1:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true
|
url: jdbc:sqlite::resource:wvp.sqlite
|
||||||
username:
|
username:
|
||||||
password:
|
password:
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
driver-class-name: com.mysql.jdbc.Driver
|
driver-class-name: org.sqlite.JDBC
|
||||||
|
max-active: 1
|
||||||
|
min-idle: 1
|
||||||
|
|
||||||
# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
||||||
server:
|
server:
|
||||||
@ -34,18 +42,18 @@ server:
|
|||||||
# 作为28181服务器的配置
|
# 作为28181服务器的配置
|
||||||
sip:
|
sip:
|
||||||
# [必须修改] 本机的IP, 必须是网卡上的IP
|
# [必须修改] 本机的IP, 必须是网卡上的IP
|
||||||
ip: 192.168.0.100
|
ip: 192.168.1.44
|
||||||
# [可选] 28181服务监听的端口
|
# [可选] 28181服务监听的端口
|
||||||
port: 5060
|
port: 5060
|
||||||
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
||||||
# 后两位为行业编码,定义参照附录D.3
|
# 后两位为行业编码,定义参照附录D.3
|
||||||
# 3701020049标识山东济南历下区 信息行业接入
|
# 3701020049标识山东济南历下区 信息行业接入
|
||||||
# [可选]
|
# [可选]
|
||||||
domain: 4401020049
|
domain: 3402000000
|
||||||
# [可选]
|
# [可选]
|
||||||
id: 44010200492000000001
|
id: 34020000002000000001
|
||||||
# [可选] 默认设备认证密码,后续扩展使用设备单独密码
|
# [可选] 默认设备认证密码,后续扩展使用设备单独密码
|
||||||
password: admin123
|
password: 12345678
|
||||||
|
|
||||||
# 登陆的用户名密码
|
# 登陆的用户名密码
|
||||||
auth:
|
auth:
|
||||||
@ -57,7 +65,7 @@ auth:
|
|||||||
#zlm服务器配置
|
#zlm服务器配置
|
||||||
media:
|
media:
|
||||||
# [必须修改] zlm服务器的内网IP
|
# [必须修改] zlm服务器的内网IP
|
||||||
ip: 192.168.0.100
|
ip: 192.168.1.44
|
||||||
# [可选] zlm服务器的公网IP, 内网部署置空即可
|
# [可选] zlm服务器的公网IP, 内网部署置空即可
|
||||||
wanIp:
|
wanIp:
|
||||||
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
|
# [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
|
||||||
@ -69,12 +77,12 @@ media:
|
|||||||
# [可选] zlm服务器的hook.admin_params=secret
|
# [可选] zlm服务器的hook.admin_params=secret
|
||||||
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
||||||
# [可选] zlm服务器的general.streamNoneReaderDelayMS
|
# [可选] zlm服务器的general.streamNoneReaderDelayMS
|
||||||
streamNoneReaderDelayMS: 18000 # 无人观看多久自动关闭流
|
streamNoneReaderDelayMS: 600000 # 无人观看多久自动关闭流, -1表示永不自动关闭,即 关闭按需拉流
|
||||||
# [可选] 关闭等待收到流编码信息后在返回,
|
# [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
|
||||||
# 设为false可以获得更好的兼容性,保证返回后流就可以播放,
|
autoApplyPlay: true
|
||||||
# 设为true可以快速打开播放窗口,可以获得更好的体验
|
# [可选] 部分设备需要扩展SDP,需要打开此设置
|
||||||
closeWaitRTPInfo: false
|
seniorSdp: false
|
||||||
# 启用udp多端口模式
|
# 启用udp多端口模式, 详细解释参考: https://github.com/xia-chu/ZLMediaKit/wiki/GB28181%E6%8E%A8%E6%B5%81 下的高阶使用
|
||||||
rtp:
|
rtp:
|
||||||
# [可选] 是否启用udp多端口模式, 开启后会在udpPortRange范围内选择端口用于媒体流传输
|
# [可选] 是否启用udp多端口模式, 开启后会在udpPortRange范围内选择端口用于媒体流传输
|
||||||
enable: true
|
enable: true
|
||||||
|
BIN
src/main/resources/wvp.sqlite
Normal file
BIN
src/main/resources/wvp.sqlite
Normal file
Binary file not shown.
@ -19,12 +19,12 @@
|
|||||||
<el-option label="设备" value="false"></el-option>
|
<el-option label="设备" value="false"></el-option>
|
||||||
<el-option label="子目录" value="true"></el-option>
|
<el-option label="子目录" value="true"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
在线状态: <el-select size="mini" @change="search" v-model="online" placeholder="请选择" default-first-option>
|
在线状态: <el-select size="mini" style="margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择" default-first-option>
|
||||||
<el-option label="全部" value=""></el-option>
|
<el-option label="全部" value=""></el-option>
|
||||||
<el-option label="在线" value="on"></el-option>
|
<el-option label="在线" value="true"></el-option>
|
||||||
<el-option label="离线" value="off"></el-option>
|
<el-option label="离线" value="false"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
<el-checkbox size="mini" style="margin-right: 1rem; float: right;" v-model="autoList" @change="autoListChange">自动刷新</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
|
<devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
|
||||||
<!--设备列表-->
|
<!--设备列表-->
|
||||||
@ -56,7 +56,7 @@
|
|||||||
<el-button-group>
|
<el-button-group>
|
||||||
<!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->
|
<!-- <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.parental == 0" @click="sendDevicePush(scope.row)">播放</el-button> -->
|
||||||
<el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
|
<el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
|
||||||
<el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="scope.row.play" @click="stopDevicePush(scope.row)">停止</el-button>
|
<el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button>
|
||||||
<el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.parental == 1" @click="changeSubchannel(scope.row)">查看</el-button>
|
<el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.parental == 1" @click="changeSubchannel(scope.row)">查看</el-button>
|
||||||
<el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button>
|
<el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">设备录象</el-button>
|
||||||
<!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
|
<!-- <el-button size="mini" @click="sendDevicePush(scope.row)">录像查询</el-button> -->
|
||||||
@ -98,13 +98,17 @@ export default {
|
|||||||
count: parseInt(this.$route.params.count),
|
count: parseInt(this.$route.params.count),
|
||||||
total: 0,
|
total: 0,
|
||||||
beforeUrl: "/videoList",
|
beforeUrl: "/videoList",
|
||||||
isLoging: false
|
isLoging: false,
|
||||||
|
autoList: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initData();
|
this.initData();
|
||||||
this.updateLooper = setInterval(this.initData, 10000);
|
if (this.autoList) {
|
||||||
|
this.updateLooper = setInterval(this.initData, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.$destroy('videojs');
|
this.$destroy('videojs');
|
||||||
@ -161,7 +165,7 @@ export default {
|
|||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
that.total = res.data.total;
|
that.total = res.data.total;
|
||||||
that.deviceChannelList = res.data.data;
|
that.deviceChannelList = res.data.list;
|
||||||
// 防止出现表格错位
|
// 防止出现表格错位
|
||||||
that.$nextTick(() => {
|
that.$nextTick(() => {
|
||||||
that.$refs.channelListTable.doLayout();
|
that.$refs.channelListTable.doLayout();
|
||||||
@ -179,17 +183,16 @@ export default {
|
|||||||
let deviceId = this.deviceId;
|
let deviceId = this.deviceId;
|
||||||
this.isLoging = true;
|
this.isLoging = true;
|
||||||
let channelId = itemData.channelId;
|
let channelId = itemData.channelId;
|
||||||
let getEncoding = itemData.hasAudio ? '1' : '0'
|
console.log("通知设备推流1:" + deviceId + " : " + channelId );
|
||||||
console.log("通知设备推流1:" + deviceId + " : " + channelId + ":" + getEncoding);
|
|
||||||
let that = this;
|
let that = this;
|
||||||
this.$axios({
|
this.$axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/api/play/' + deviceId + '/' + channelId + '?getEncoding=' + getEncoding
|
url: '/api/play/' + deviceId + '/' + channelId
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
console.log(res.data)
|
console.log(res.data)
|
||||||
let ssrc = res.data.ssrc;
|
let streamId = res.data.streamId;
|
||||||
that.isLoging = false;
|
that.isLoging = false;
|
||||||
if (!!ssrc) {
|
if (!!streamId) {
|
||||||
// that.$refs.devicePlayer.play(res.data, deviceId, channelId, itemData.hasAudio);
|
// that.$refs.devicePlayer.play(res.data, deviceId, channelId, itemData.hasAudio);
|
||||||
that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
|
that.$refs.devicePlayer.openDialog("media", deviceId, channelId, {
|
||||||
streamInfo: res.data,
|
streamInfo: res.data,
|
||||||
@ -212,7 +215,7 @@ export default {
|
|||||||
var that = this;
|
var that = this;
|
||||||
this.$axios({
|
this.$axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/play/' + itemData.ssrc + '/stop'
|
url: '/api/play/' + itemData.streamId + '/stop'
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
console.log(JSON.stringify(res));
|
console.log(JSON.stringify(res));
|
||||||
that.initData();
|
that.initData();
|
||||||
@ -258,7 +261,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
that.total = res.data.total;
|
that.total = res.data.total;
|
||||||
that.deviceChannelList = res.data.data;
|
that.deviceChannelList = res.data.list;
|
||||||
// 防止出现表格错位
|
// 防止出现表格错位
|
||||||
that.$nextTick(() => {
|
that.$nextTick(() => {
|
||||||
that.$refs.channelListTable.doLayout();
|
that.$refs.channelListTable.doLayout();
|
||||||
@ -283,6 +286,13 @@ export default {
|
|||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
console.log(JSON.stringify(res));
|
console.log(JSON.stringify(res));
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
autoListChange: function () {
|
||||||
|
if (this.autoList) {
|
||||||
|
this.updateLooper = setInterval(this.initData, 1500);
|
||||||
|
}else{
|
||||||
|
window.clearInterval(this.updateLooper);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="devicePlayer" v-loading="isLoging">
|
<div id="devicePlayer" v-loading="isLoging">
|
||||||
|
|
||||||
<el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()">
|
<el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()">
|
||||||
<!-- <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer> -->
|
<!-- <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer> -->
|
||||||
<player ref="videoPlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></player>
|
<player ref="videoPlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></player>
|
||||||
@ -121,7 +121,7 @@
|
|||||||
<p>采样率: {{item.sample_rate}}</p>
|
<p>采样率: {{item.sample_rate}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
@ -158,7 +158,6 @@ export default {
|
|||||||
searchHistoryResult: [] //媒体流历史记录搜索结果
|
searchHistoryResult: [] //媒体流历史记录搜索结果
|
||||||
},
|
},
|
||||||
showVideoDialog: false,
|
showVideoDialog: false,
|
||||||
ssrc: '',
|
|
||||||
streamId: '',
|
streamId: '',
|
||||||
convertKey: '',
|
convertKey: '',
|
||||||
deviceId: '',
|
deviceId: '',
|
||||||
@ -210,7 +209,6 @@ export default {
|
|||||||
this.tabActiveName = tab;
|
this.tabActiveName = tab;
|
||||||
this.channelId = channelId;
|
this.channelId = channelId;
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
this.ssrc = "";
|
|
||||||
this.streamId = "";
|
this.streamId = "";
|
||||||
this.videoUrl = ""
|
this.videoUrl = ""
|
||||||
if (!!this.$refs.videoPlayer) {
|
if (!!this.$refs.videoPlayer) {
|
||||||
@ -234,11 +232,10 @@ export default {
|
|||||||
console.log(val)
|
console.log(val)
|
||||||
},
|
},
|
||||||
play: function (streamInfo, hasAudio) {
|
play: function (streamInfo, hasAudio) {
|
||||||
|
|
||||||
this.hasaudio = hasAudio;
|
this.hasaudio = hasAudio;
|
||||||
this.isLoging = false;
|
this.isLoging = false;
|
||||||
this.videoUrl = streamInfo.ws_flv;
|
this.videoUrl = streamInfo.ws_flv;
|
||||||
this.ssrc = streamInfo.ssrc;
|
|
||||||
this.streamId = streamInfo.streamId;
|
this.streamId = streamInfo.streamId;
|
||||||
this.playFromStreamInfo(false, streamInfo)
|
this.playFromStreamInfo(false, streamInfo)
|
||||||
},
|
},
|
||||||
@ -248,7 +245,7 @@ export default {
|
|||||||
this.$refs.videoPlayer.pause()
|
this.$refs.videoPlayer.pause()
|
||||||
that.$axios({
|
that.$axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/play/' + that.ssrc + '/convert'
|
url: '/api/play/' + that.streamId + '/convert'
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
if (res.data.code == 0) {
|
if (res.data.code == 0) {
|
||||||
that.convertKey = res.data.key;
|
that.convertKey = res.data.key;
|
||||||
@ -317,7 +314,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.convertKey = ''
|
this.convertKey = ''
|
||||||
},
|
},
|
||||||
|
|
||||||
copySharedInfo: function (data) {
|
copySharedInfo: function (data) {
|
||||||
console.log('复制内容:' + data);
|
console.log('复制内容:' + data);
|
||||||
this.coverPlaying = false;
|
this.coverPlaying = false;
|
||||||
@ -368,9 +365,9 @@ export default {
|
|||||||
},
|
},
|
||||||
playRecord: function (row) {
|
playRecord: function (row) {
|
||||||
let that = this;
|
let that = this;
|
||||||
if (that.ssrc != "") {
|
if (that.streamId != "") {
|
||||||
that.stopPlayRecord(function () {
|
that.stopPlayRecord(function () {
|
||||||
that.ssrc = "",
|
that.streamId = "",
|
||||||
that.playRecord(row);
|
that.playRecord(row);
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -380,7 +377,7 @@ export default {
|
|||||||
row.endTime
|
row.endTime
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
var streamInfo = res.data;
|
var streamInfo = res.data;
|
||||||
that.ssrc = streamInfo.ssrc;
|
that.streamId = streamInfo.streamId;
|
||||||
that.videoUrl = streamInfo.ws_flv;
|
that.videoUrl = streamInfo.ws_flv;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -390,7 +387,7 @@ export default {
|
|||||||
this.videoUrl = '';
|
this.videoUrl = '';
|
||||||
this.$axios({
|
this.$axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: '/api/playback/' + this.ssrc + '/stop'
|
url: '/api/playback/' + this.streamId + '/stop'
|
||||||
}).then(function (res) {
|
}).then(function (res) {
|
||||||
if (callback) callback()
|
if (callback) callback()
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
||||||
<span style="font-size: 1rem; font-weight: bold;">设备列表</span>
|
<span style="font-size: 1rem; font-weight: bold;">设备列表</span>
|
||||||
<div style="position: absolute; right: 1rem; top: 0.3rem;">
|
<div style="position: absolute; right: 1rem; top: 0.3rem;">
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="getDeviceList()"></el-button>
|
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<devicePlayer ref="devicePlayer"></devicePlayer>
|
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<el-table-column label="地址" width="180" align="center">
|
<el-table-column label="地址" width="180" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div slot="reference" class="name-wrapper">
|
<div slot="reference" class="name-wrapper">
|
||||||
<el-tag size="medium">{{ scope.row.host.address }}</el-tag>
|
<el-tag size="medium">{{ scope.row.hostAddress }}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
<el-table-column label="操作" width="240" align="center" fixed="right">
|
<el-table-column label="操作" width="240" align="center" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button>
|
<el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新通道</el-button>
|
||||||
<el-button size="mini" icon="el-icon-s-open" type="primary" @click="showChannelList(scope.row)">查看通道</el-button>
|
<el-button size="mini" icon="el-icon-s-open" type="primary" @click="showChannelList(scope.row)">查看通道</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -90,7 +90,8 @@
|
|||||||
winHeight: window.innerHeight - 200,
|
winHeight: window.innerHeight - 200,
|
||||||
currentPage:1,
|
currentPage:1,
|
||||||
count:15,
|
count:15,
|
||||||
total:0
|
total:0,
|
||||||
|
getDeviceListLoading: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -130,7 +131,7 @@
|
|||||||
},
|
},
|
||||||
getDeviceList: function() {
|
getDeviceList: function() {
|
||||||
let that = this;
|
let that = this;
|
||||||
|
this.getDeviceListLoading = true;
|
||||||
this.$axios.get(`/api/devices`,{
|
this.$axios.get(`/api/devices`,{
|
||||||
params: {
|
params: {
|
||||||
page: that.currentPage - 1,
|
page: that.currentPage - 1,
|
||||||
@ -139,11 +140,14 @@
|
|||||||
} )
|
} )
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
console.log(res.data.list);
|
||||||
that.total = res.data.total;
|
that.total = res.data.total;
|
||||||
that.deviceList = res.data.data;
|
that.deviceList = res.data.list;
|
||||||
|
that.getDeviceListLoading = false;
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
that.getDeviceListLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -158,17 +162,31 @@
|
|||||||
refDevice: function(itemData) {
|
refDevice: function(itemData) {
|
||||||
///api/devices/{deviceId}/sync
|
///api/devices/{deviceId}/sync
|
||||||
console.log("刷新对应设备:" + itemData.deviceId);
|
console.log("刷新对应设备:" + itemData.deviceId);
|
||||||
|
var that = this;
|
||||||
|
that.$refs[itemData.deviceId + 'refbtn' ].loading = true;
|
||||||
this.$axios({
|
this.$axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/devices/' + itemData.deviceId + '/sync'
|
url: '/api/devices/' + itemData.deviceId + '/sync'
|
||||||
}).then(function(res) {
|
}).then(function(res) {
|
||||||
// console.log("刷新设备结果:"+JSON.stringify(res));
|
console.log("刷新设备结果:"+JSON.stringify(res));
|
||||||
|
if (!res.data.deviceId) {
|
||||||
|
that.$message({
|
||||||
|
showClose: true,
|
||||||
|
message: res.data,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
that.$message({
|
||||||
|
showClose: true,
|
||||||
|
message: '请求成功',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
that.initData()
|
||||||
|
that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
that.$message({
|
console.error(e)
|
||||||
showClose: true,
|
that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
|
||||||
message: '请求成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
});;
|
});;
|
||||||
},
|
},
|
||||||
//通知设备上传媒体流
|
//通知设备上传媒体流
|
||||||
|
Loading…
Reference in New Issue
Block a user