Commit 34135cce5d59f6ad7653737dd035bb1d441e185f

Authored by panlinlin
2 parents a63ae08f 730a64be

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