Commit e5370bbd6e74b7746db12ced5302ef97ef58a4ce

Authored by mrjackwang
Committed by GitHub
2 parents f65d2730 28d7fd3b

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

Showing 87 changed files with 1117 additions and 611 deletions
.gitignore
... ... @@ -3,7 +3,7 @@
3 3  
4 4 # Log file
5 5 *.log
6   -
  6 +logs/*
7 7 # BlueJ files
8 8 *.ctxt
9 9  
... ...
README.md
... ... @@ -105,6 +105,10 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
105 105 - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
106 106  
107 107 # docker快速体验
  108 +目前作者的docker-compose因为时间有限维护不及时,这里提供第三方提供的供大家使用,维护不易,大家记得给这位小伙伴点个star。
  109 +https://github.com/SaltFish001/wvp_pro_compose
  110 +[https://github.com/SaltFish001/wvp_pro_compose](https://github.com/SaltFish001/wvp_pro_compose)
  111 +这是作者维护的一个镜像,可能存在不及时的问题。
108 112 ```shell
109 113 docker pull 648540858/wvp_pro
110 114  
... ...
... ... @@ -90,8 +90,8 @@
90 90 <!-- druid数据库连接池 -->
91 91 <dependency>
92 92 <groupId>com.alibaba</groupId>
93   - <artifactId>druid</artifactId>
94   - <version>1.2.3</version>
  93 + <artifactId>druid-spring-boot-starter</artifactId>
  94 + <version>1.1.22</version>
95 95 </dependency>
96 96  
97 97 <!-- mysql数据库 -->
... ... @@ -183,6 +183,15 @@
183 183 <version>4.9.0</version>
184 184 </dependency>
185 185  
  186 + <!-- okhttp 调试日志 -->
  187 + <dependency>
  188 + <groupId>com.squareup.okhttp3</groupId>
  189 + <artifactId>logging-interceptor</artifactId>
  190 + <version>4.9.0</version>
  191 + </dependency>
  192 +
  193 +
  194 +
186 195 <!-- okhttp-digest -->
187 196 <dependency>
188 197 <groupId>com.burgstaller</groupId>
... ...
sql/mysql.sql
... ... @@ -44,7 +44,7 @@ CREATE TABLE `device` (
44 44 `charset` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
45 45 PRIMARY KEY (`id`),
46 46 UNIQUE KEY `device_deviceId_uindex` (`deviceId`)
47   -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  47 +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
48 48 /*!40101 SET character_set_client = @saved_cs_client */;
49 49  
50 50 --
... ... @@ -95,39 +95,41 @@ DROP TABLE IF EXISTS `device_channel`;
95 95 /*!40101 SET @saved_cs_client = @@character_set_client */;
96 96 /*!50503 SET character_set_client = utf8mb4 */;
97 97 CREATE TABLE `device_channel` (
98   - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
99   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
100   - `manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
101   - `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
102   - `owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
103   - `civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
104   - `block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
105   - `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
106   - `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  98 + `id` int NOT NULL AUTO_INCREMENT,
  99 + `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  100 + `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  101 + `manufacture` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  102 + `model` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  103 + `owner` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  104 + `civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  105 + `block` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  106 + `address` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  107 + `parentId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
107 108 `safetyWay` int DEFAULT NULL,
108 109 `registerWay` int DEFAULT NULL,
109   - `certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  110 + `certNum` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
110 111 `certifiable` int DEFAULT NULL,
111 112 `errCode` int DEFAULT NULL,
112   - `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
113   - `secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
114   - `ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  113 + `endTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  114 + `secrecy` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  115 + `ipAddress` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
115 116 `port` int DEFAULT NULL,
116   - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  117 + `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
117 118 `PTZType` int DEFAULT NULL,
118 119 `status` int DEFAULT NULL,
119 120 `longitude` double DEFAULT NULL,
120 121 `latitude` double DEFAULT NULL,
121   - `streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
122   - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
123   - `parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  122 + `streamId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  123 + `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  124 + `parental` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
124 125 `hasAudio` bit(1) DEFAULT NULL,
125   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
126   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  126 + `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  127 + `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
127 128 `subCount` int DEFAULT '0',
128   - PRIMARY KEY (`channelId`,`deviceId`) USING BTREE,
  129 + PRIMARY KEY (`id`),
  130 + UNIQUE KEY `device_channel_id_uindex` (`id`),
129 131 UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`)
130   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  132 +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
131 133 /*!40101 SET character_set_client = @saved_cs_client */;
132 134  
133 135 --
... ... @@ -196,7 +198,7 @@ CREATE TABLE `gb_stream` (
196 198 PRIMARY KEY (`gbStreamId`) USING BTREE,
197 199 UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
198 200 UNIQUE KEY `gbId` (`gbId`) USING BTREE
199   -) ENGINE=InnoDB AUTO_INCREMENT=291 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  201 +) ENGINE=InnoDB AUTO_INCREMENT=375 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
200 202 /*!40101 SET character_set_client = @saved_cs_client */;
201 203  
202 204 --
... ... @@ -226,7 +228,7 @@ CREATE TABLE `log` (
226 228 `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
227 229 `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
228 230 PRIMARY KEY (`id`) USING BTREE
229   -) ENGINE=InnoDB AUTO_INCREMENT=245 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  231 +) ENGINE=InnoDB AUTO_INCREMENT=313 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
230 232 /*!40101 SET character_set_client = @saved_cs_client */;
231 233  
232 234 --
... ... @@ -315,7 +317,7 @@ CREATE TABLE `parent_platform` (
315 317 PRIMARY KEY (`id`),
316 318 UNIQUE KEY `parent_platform_id_uindex` (`id`),
317 319 UNIQUE KEY `parent_platform_pk` (`serverGBId`)
318   -) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  320 +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
319 321 /*!40101 SET character_set_client = @saved_cs_client */;
320 322  
321 323 --
... ... @@ -361,13 +363,11 @@ DROP TABLE IF EXISTS `platform_gb_channel`;
361 363 /*!50503 SET character_set_client = utf8mb4 */;
362 364 CREATE TABLE `platform_gb_channel` (
363 365 `id` int NOT NULL AUTO_INCREMENT,
364   - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
365   - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
366   - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
367   - `deviceAndChannelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
368   - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  366 + `platformId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  367 + `catalogId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  368 + `deviceChannelId` int NOT NULL,
369 369 PRIMARY KEY (`id`)
370   -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  370 +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
371 371 /*!40101 SET character_set_client = @saved_cs_client */;
372 372  
373 373 --
... ... @@ -393,7 +393,7 @@ CREATE TABLE `platform_gb_stream` (
393 393 `id` int NOT NULL AUTO_INCREMENT,
394 394 PRIMARY KEY (`id`),
395 395 UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`)
396   -) ENGINE=InnoDB AUTO_INCREMENT=256 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  396 +) ENGINE=InnoDB AUTO_INCREMENT=406 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
397 397 /*!40101 SET character_set_client = @saved_cs_client */;
398 398  
399 399 --
... ... @@ -415,6 +415,7 @@ DROP TABLE IF EXISTS `stream_proxy`;
415 415 CREATE TABLE `stream_proxy` (
416 416 `id` int NOT NULL AUTO_INCREMENT,
417 417 `type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  418 + `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
418 419 `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
419 420 `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
420 421 `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
... ... @@ -464,7 +465,7 @@ CREATE TABLE `stream_push` (
464 465 `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
465 466 PRIMARY KEY (`id`),
466 467 UNIQUE KEY `stream_push_pk` (`app`,`stream`)
467   -) ENGINE=InnoDB AUTO_INCREMENT=310 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  468 +) ENGINE=InnoDB AUTO_INCREMENT=394 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
468 469 /*!40101 SET character_set_client = @saved_cs_client */;
469 470  
470 471 --
... ... @@ -541,4 +542,4 @@ UNLOCK TABLES;
541 542 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
542 543 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
543 544  
544   --- Dump completed on 2022-02-24 16:52:12
  545 +-- Dump completed on 2022-02-25 20:32:21
... ...
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp;
2 2  
3 3 import java.util.logging.LogManager;
4 4  
  5 +import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport;
5 6 import org.springframework.boot.SpringApplication;
6 7 import org.springframework.boot.autoconfigure.SpringBootApplication;
7 8 import org.springframework.boot.web.servlet.ServletComponentScan;
... ... @@ -17,6 +18,7 @@ import springfox.documentation.oas.annotations.EnableOpenApi;
17 18 @SpringBootApplication
18 19 @EnableScheduling
19 20 @EnableOpenApi
  21 +@EnableDruidSupport
20 22 public class VManageBootstrap extends LogManager {
21 23 private static String[] args;
22 24 private static ConfigurableApplicationContext context;
... ...
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
... ... @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray;
5 5 public class StreamInfo {
6 6  
7 7 private String app;
8   - private String streamId;
  8 + private String stream;
9 9 private String deviceID;
10 10 private String channelId;
11 11 private String flv;
... ... @@ -153,12 +153,12 @@ public class StreamInfo {
153 153 this.ws_ts = ws_ts;
154 154 }
155 155  
156   - public String getStreamId() {
157   - return streamId;
  156 + public String getStream() {
  157 + return stream;
158 158 }
159 159  
160   - public void setStreamId(String streamId) {
161   - this.streamId = streamId;
  160 + public void setStream(String stream) {
  161 + this.stream = stream;
162 162 }
163 163  
164 164 public String getRtc() {
... ...
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -29,6 +29,7 @@ public class VideoManagerConstants {
29 29 // 此处多了一个_,暂不修改
30 30 public static final String PLAYER_PREFIX = "VMP_PLAYER_";
31 31 public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
  32 + public static final String PLAY_INFO_PREFIX = "VMP_PLAY_INFO_";
32 33  
33 34 public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
34 35  
... ...
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
... ... @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.conf;
3 3 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
4 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
5 5 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
6 7 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
7 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
8 9 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
... ... @@ -30,7 +31,7 @@ public class SipPlatformRunner implements CommandLineRunner {
30 31 private EventPublisher publisher;
31 32  
32 33 @Autowired
33   - private ZLMRTPServerFactory zlmrtpServerFactory;
  34 + private ISIPCommanderForPlatform sipCommanderForPlatform;
34 35  
35 36  
36 37 @Override
... ... @@ -57,6 +58,9 @@ public class SipPlatformRunner implements CommandLineRunner {
57 58 parentPlatformCatch.setId(parentPlatform.getServerGBId());
58 59 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
59 60  
  61 + // 取消订阅
  62 + sipCommanderForPlatform.unregister(parentPlatform, null, null);
  63 + Thread.sleep(500);
60 64 // 发送平台未注册消息
61 65 publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId());
62 66 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java
... ... @@ -14,7 +14,7 @@ import springfox.documentation.spring.web.plugins.Docket;
14 14 @Configuration
15 15 public class Swagger3Config {
16 16  
17   - @Value("${swagger-ui.enabled}")
  17 + @Value("${swagger-ui.enabled: true}")
18 18 private boolean enable;
19 19  
20 20 @Bean
... ...
src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.druid;
  2 +
  3 +import com.alibaba.druid.support.http.StatViewServlet;
  4 +import com.alibaba.druid.support.http.WebStatFilter;
  5 +import org.springframework.beans.factory.annotation.Value;
  6 +import org.springframework.boot.web.servlet.FilterRegistrationBean;
  7 +import org.springframework.boot.web.servlet.ServletRegistrationBean;
  8 +import org.springframework.context.annotation.Bean;
  9 +
  10 +import javax.servlet.Filter;
  11 +import javax.servlet.Servlet;
  12 +
  13 +/**
  14 + * druid监控配置
  15 + * @author
  16 + */
  17 +public class DruidConfiguration {
  18 +
  19 + @Value("${rj-druid-manage.allow:127.0.0.1}")
  20 + private String allow;
  21 +
  22 + @Value("${rj-druid-manage.deny:}")
  23 + private String deny;
  24 +
  25 + @Value("${rj-druid-manage.loginUsername:admin}")
  26 + private String loginUsername;
  27 +
  28 + @Value("${rj-druid-manage.loginPassword:admin}")
  29 + private String loginPassword;
  30 +
  31 + @Value("${rj-druid-manage.resetEnable:false}")
  32 + private String resetEnable;
  33 +
  34 + /**
  35 + * druid监控页面开启
  36 + */
  37 + @Bean
  38 + public ServletRegistrationBean druidServlet() {
  39 + ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
  40 + // IP白名单
  41 + servletRegistrationBean.addInitParameter("allow", allow);
  42 + // IP黑名单(共同存在时,deny优先于allow)
  43 + servletRegistrationBean.addInitParameter("deny", deny);
  44 + //控制台管理用户
  45 + servletRegistrationBean.addInitParameter("loginUsername", loginUsername);
  46 + servletRegistrationBean.addInitParameter("loginPassword", loginPassword);
  47 + //是否能够重置数据 禁用HTML页面上的“Reset All”功能
  48 + servletRegistrationBean.addInitParameter("resetEnable", resetEnable);
  49 + return servletRegistrationBean;
  50 + }
  51 +
  52 + /**
  53 + * druid url监控配置
  54 + */
  55 + @Bean
  56 + public FilterRegistrationBean filterRegistrationBean() {
  57 + FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new WebStatFilter());
  58 + filterRegistrationBean.addUrlPatterns("/*");
  59 + filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
  60 + return filterRegistrationBean;
  61 + }
  62 +
  63 +
  64 +}
0 65 \ No newline at end of file
... ...
src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.druid;
  2 +
  3 +import org.springframework.boot.web.servlet.ServletComponentScan;
  4 +import org.springframework.context.annotation.Import;
  5 +
  6 +import java.lang.annotation.*;
  7 +
  8 +/**
  9 + * druid监控支持注解
  10 + *
  11 + * @author
  12 + * {@link DruidConfiguration} druid监控页面安全配置支持
  13 + * {@link ServletComponentScan} druid监控页面需要扫描servlet
  14 + */
  15 +@Target(ElementType.TYPE)
  16 +@Retention(RetentionPolicy.RUNTIME)
  17 +@Documented
  18 +@Inherited
  19 +@Import({
  20 + DruidConfiguration.class,
  21 +})
  22 +@ServletComponentScan
  23 +public @interface EnableDruidSupport {
  24 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
... ... @@ -3,6 +3,10 @@ package com.genersoft.iot.vmp.gb28181.bean;
3 3 public class DeviceChannel {
4 4  
5 5  
  6 + /**
  7 + * 数据库自赠ID
  8 + */
  9 + private int id;
6 10  
7 11 /**
8 12 * 通道id
... ... @@ -165,6 +169,14 @@ public class DeviceChannel {
165 169 */
166 170 private boolean hasAudio;
167 171  
  172 + public int getId() {
  173 + return id;
  174 + }
  175 +
  176 + public void setId(int id) {
  177 + this.id = id;
  178 + }
  179 +
168 180 public String getDeviceId() {
169 181 return deviceId;
170 182 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
... ... @@ -4,11 +4,12 @@ public class SsrcTransaction {
4 4  
5 5 private String deviceId;
6 6 private String channelId;
7   - private String ssrc;
8   - private String streamId;
  7 + private String callId;
  8 + private String stream;
9 9 private byte[] transaction;
10 10 private byte[] dialog;
11 11 private String mediaServerId;
  12 + private String ssrc;
12 13  
13 14 public String getDeviceId() {
14 15 return deviceId;
... ... @@ -26,20 +27,20 @@ public class SsrcTransaction {
26 27 this.channelId = channelId;
27 28 }
28 29  
29   - public String getSsrc() {
30   - return ssrc;
  30 + public String getCallId() {
  31 + return callId;
31 32 }
32 33  
33   - public void setSsrc(String ssrc) {
34   - this.ssrc = ssrc;
  34 + public void setCallId(String callId) {
  35 + this.callId = callId;
35 36 }
36 37  
37   - public String getStreamId() {
38   - return streamId;
  38 + public String getStream() {
  39 + return stream;
39 40 }
40 41  
41   - public void setStreamId(String streamId) {
42   - this.streamId = streamId;
  42 + public void setStream(String stream) {
  43 + this.stream = stream;
43 44 }
44 45  
45 46 public byte[] getTransaction() {
... ... @@ -65,4 +66,12 @@ public class SsrcTransaction {
65 66 public void setMediaServerId(String mediaServerId) {
66 67 this.mediaServerId = mediaServerId;
67 68 }
  69 +
  70 + public String getSsrc() {
  71 + return ssrc;
  72 + }
  73 +
  74 + public void setSsrc(String ssrc) {
  75 + this.ssrc = ssrc;
  76 + }
68 77 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
... ... @@ -18,15 +18,21 @@ public class SubscribeInfo {
18 18 this.fromTag = fromHeader.getTag();
19 19 ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME);
20 20 this.expires = expiresHeader.getExpires();
21   - this.event = ((EventHeader)request.getHeader(EventHeader.NAME)).getName();
  21 + EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME);
  22 + this.eventId = eventHeader.getEventId();
  23 + this.eventType = eventHeader.getEventType();
  24 + ViaHeader viaHeader = (ViaHeader)request.getHeader(ViaHeader.NAME);
  25 + this.branch = viaHeader.getBranch();
22 26 }
23 27  
24 28 private String id;
25 29 private int expires;
26 30 private String callId;
27   - private String event;
  31 + private String eventId;
  32 + private String eventType;
28 33 private String fromTag;
29 34 private String toTag;
  35 + private String branch;
30 36  
31 37 public String getId() {
32 38 return id;
... ... @@ -68,11 +74,27 @@ public class SubscribeInfo {
68 74 this.fromTag = fromTag;
69 75 }
70 76  
71   - public String getEvent() {
72   - return event;
  77 + public String getEventId() {
  78 + return eventId;
73 79 }
74 80  
75   - public void setEvent(String event) {
76   - this.event = event;
  81 + public void setEventId(String eventId) {
  82 + this.eventId = eventId;
  83 + }
  84 +
  85 + public String getEventType() {
  86 + return eventType;
  87 + }
  88 +
  89 + public void setEventType(String eventType) {
  90 + this.eventType = eventType;
  91 + }
  92 +
  93 + public String getBranch() {
  94 + return branch;
  95 + }
  96 +
  97 + public void setBranch(String branch) {
  98 + this.branch = branch;
77 99 }
78 100 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
... ... @@ -101,14 +101,14 @@ public class EventPublisher {
101 101 applicationEventPublisher.publishEvent(outEvent);
102 102 }
103 103  
104   - @Async
  104 +
105 105 public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) {
106 106 List<DeviceChannel> deviceChannelList = new ArrayList<>();
107 107 deviceChannelList.add(deviceChannel);
108 108 catalogEventPublish(platformId, deviceChannelList, type);
109 109 }
110 110  
111   - @Async
  111 +
112 112 public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) {
113 113 CatalogEvent outEvent = new CatalogEvent(this);
114 114 List<DeviceChannel> channels = new ArrayList<>();
... ... @@ -130,8 +130,8 @@ public class EventPublisher {
130 130 applicationEventPublisher.publishEvent(outEvent);
131 131 }
132 132  
133   - @Async
134   - public void catalogEventPublishForStream(String platformId, GbStream[] gbStreams, String type) {
  133 +
  134 + public void catalogEventPublishForStream(String platformId, List<GbStream> gbStreams, String type) {
135 135 CatalogEvent outEvent = new CatalogEvent(this);
136 136 outEvent.setGbStreams(gbStreams);
137 137 outEvent.setType(type);
... ... @@ -139,9 +139,10 @@ public class EventPublisher {
139 139 applicationEventPublisher.publishEvent(outEvent);
140 140 }
141 141  
142   - @Async
  142 +
143 143 public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) {
144   - GbStream[] gbStreams = {gbStream};
145   - catalogEventPublishForStream(platformId, gbStreams, type);
  144 + List<GbStream> gbStreamList = new ArrayList<>();
  145 + gbStreamList.add(gbStream);
  146 + catalogEventPublishForStream(platformId, gbStreamList, type);
146 147 }
147 148 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
... ... @@ -23,24 +23,36 @@ public class SipSubscribe {
23 23  
24 24 private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
25 25  
26   - private Map<String, Date> timeSubscribes = new ConcurrentHashMap<>();
  26 + private Map<String, Date> okTimeSubscribes = new ConcurrentHashMap<>();
  27 + private Map<String, Date> errorTimeSubscribes = new ConcurrentHashMap<>();
27 28  
28   -// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
  29 + // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
29 30 // @Scheduled(fixedRate= 100 * 60 * 60 )
30   - @Scheduled(cron="0 0 * * * ?") //每小时执行一次, 每个整点
  31 + @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
31 32 public void execute(){
32 33 logger.info("[定时任务] 清理过期的订阅信息");
33 34 Calendar calendar = Calendar.getInstance();
34 35 calendar.setTime(new Date());
35   - calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) - 1);
36   - for (String key : timeSubscribes.keySet()) {
37   - if (timeSubscribes.get(key).before(calendar.getTime())){
38   - logger.info("[定时任务] 清理过期的订阅信息: {}", key);
39   - errorSubscribes.remove(key);
  36 + calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 5);
  37 +
  38 + for (String key : okTimeSubscribes.keySet()) {
  39 + if (okTimeSubscribes.get(key).before(calendar.getTime())){
  40 +// logger.info("[定时任务] 清理过期的订阅信息: {}", key);
40 41 okSubscribes.remove(key);
41   - timeSubscribes.remove(key);
  42 + okTimeSubscribes.remove(key);
  43 + }
  44 + }
  45 + for (String key : errorTimeSubscribes.keySet()) {
  46 + if (errorTimeSubscribes.get(key).before(calendar.getTime())){
  47 +// logger.info("[定时任务] 清理过期的订阅信息: {}", key);
  48 + errorSubscribes.remove(key);
  49 + errorTimeSubscribes.remove(key);
42 50 }
43 51 }
  52 + logger.info("okTimeSubscribes.size:{}",okTimeSubscribes.size());
  53 + logger.info("okSubscribes.size:{}",okSubscribes.size());
  54 + logger.info("errorTimeSubscribes.size:{}",errorTimeSubscribes.size());
  55 + logger.info("errorSubscribes.size:{}",errorSubscribes.size());
44 56 }
45 57  
46 58 public interface Event {
... ... @@ -105,12 +117,12 @@ public class SipSubscribe {
105 117  
106 118 public void addErrorSubscribe(String key, SipSubscribe.Event event) {
107 119 errorSubscribes.put(key, event);
108   - timeSubscribes.put(key, new Date());
  120 + errorTimeSubscribes.put(key, new Date());
109 121 }
110 122  
111 123 public void addOkSubscribe(String key, SipSubscribe.Event event) {
112 124 okSubscribes.put(key, event);
113   - timeSubscribes.put(key, new Date());
  125 + okTimeSubscribes.put(key, new Date());
114 126 }
115 127  
116 128 public SipSubscribe.Event getErrorSubscribe(String key) {
... ... @@ -119,7 +131,7 @@ public class SipSubscribe {
119 131  
120 132 public void removeErrorSubscribe(String key) {
121 133 errorSubscribes.remove(key);
122   - timeSubscribes.remove(key);
  134 + errorTimeSubscribes.remove(key);
123 135 }
124 136  
125 137 public SipSubscribe.Event getOkSubscribe(String key) {
... ... @@ -128,7 +140,7 @@ public class SipSubscribe {
128 140  
129 141 public void removeOkSubscribe(String key) {
130 142 okSubscribes.remove(key);
131   - timeSubscribes.remove(key);
  143 + okTimeSubscribes.remove(key);
132 144 }
133 145 public int getErrorSubscribesSize(){
134 146 return errorSubscribes.size();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
... ... @@ -20,7 +20,7 @@ public class CatalogEvent extends ApplicationEvent {
20 20 public static final String UPDATE = "UPDATE"; // 更新
21 21  
22 22 private List<DeviceChannel> deviceChannels;
23   - private GbStream[] gbStreams;
  23 + private List<GbStream> gbStreams;
24 24 private String type;
25 25 private String platformId;
26 26  
... ... @@ -48,11 +48,11 @@ public class CatalogEvent extends ApplicationEvent {
48 48 this.platformId = platformId;
49 49 }
50 50  
51   - public GbStream[] getGbStreams() {
  51 + public List<GbStream> getGbStreams() {
52 52 return gbStreams;
53 53 }
54 54  
55   - public void setGbStreams(GbStream[] gbStreams) {
  55 + public void setGbStreams(List<GbStream> gbStreams) {
56 56 this.gbStreams = gbStreams;
57 57 }
58 58 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
... ... @@ -60,10 +60,14 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
60 60 Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
61 61 if (event.getPlatformId() != null) {
62 62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
63   - if (!parentPlatform.isStatus())return;
  63 + if (parentPlatform != null && !parentPlatform.isStatus())return;
64 64 String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId();
65 65 subscribe = redisCatchStorage.getSubscribe(key);
66   - if (subscribe == null) return;
  66 +
  67 + if (subscribe == null) {
  68 + logger.debug("发送订阅消息时发现订阅信息已经不存在");
  69 + return;
  70 + }
67 71 }else {
68 72 // 获取所用订阅
69 73 List<String> platforms = redisCatchStorage.getAllSubscribePlatform();
... ... @@ -94,7 +98,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
94 98 if (event.getDeviceChannels() != null) {
95 99 deviceChannelList.addAll(event.getDeviceChannels());
96 100 }
97   - if (event.getGbStreams() != null && event.getGbStreams().length > 0){
  101 + if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
98 102 for (GbStream gbStream : event.getGbStreams()) {
99 103 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId());
100 104 deviceChannelList.add(deviceChannelByStream);
... ... @@ -102,7 +106,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
102 106 }
103 107 if (deviceChannelList.size() > 0) {
104 108 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
105   - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe);
  109 + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
106 110 }
107 111 }else if (parentPlatformMap.keySet().size() > 0) {
108 112 for (String gbId : parentPlatformMap.keySet()) {
... ... @@ -117,7 +121,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
117 121 DeviceChannel deviceChannel = new DeviceChannel();
118 122 deviceChannel.setChannelId(gbId);
119 123 deviceChannelList.add(deviceChannel);
120   - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo);
  124 + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
121 125 }
122 126 }
123 127 }
... ... @@ -134,7 +138,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
134 138 if (event.getDeviceChannels() != null) {
135 139 deviceChannelList.addAll(event.getDeviceChannels());
136 140 }
137   - if (event.getGbStreams() != null && event.getGbStreams().length > 0){
  141 + if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
138 142 for (GbStream gbStream : event.getGbStreams()) {
139 143 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId());
140 144 deviceChannelList.add(deviceChannelByStream);
... ... @@ -142,7 +146,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
142 146 }
143 147 if (deviceChannelList.size() > 0) {
144 148 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
145   - sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe);
  149 + sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
146 150 }
147 151 }else if (parentPlatformMap.keySet().size() > 0) {
148 152 for (String gbId : parentPlatformMap.keySet()) {
... ... @@ -159,7 +163,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
159 163 GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId);
160 164 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform.getDeviceGBId());
161 165 deviceChannelList.add(deviceChannelByStream);
162   - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo);
  166 + sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
163 167 }
164 168 }
165 169 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
... ... @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
14 14 import gov.nist.javax.sip.stack.SIPDialog;
15 15 import org.springframework.beans.factory.annotation.Autowired;
16 16 import org.springframework.stereotype.Component;
  17 +import org.springframework.util.StringUtils;
17 18  
18 19 /**
19 20 * @description:视频流session管理器,管理视频预览、预览回放的通信句柄
... ... @@ -29,39 +30,55 @@ public class VideoStreamSessionManager {
29 30 @Autowired
30 31 private UserSetup userSetup;
31 32  
32   - public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
  33 + /**
  34 + * 添加一个点播/回放的事务信息
  35 + * 后续可以通过流Id/callID
  36 + * @param deviceId 设备ID
  37 + * @param channelId 通道ID
  38 + * @param callId 一次请求的CallID
  39 + * @param stream 流名称
  40 + * @param mediaServerId 所使用的流媒体ID
  41 + * @param transaction 事务
  42 + */
  43 + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){
33 44 SsrcTransaction ssrcTransaction = new SsrcTransaction();
34 45 ssrcTransaction.setDeviceId(deviceId);
35 46 ssrcTransaction.setChannelId(channelId);
36   - ssrcTransaction.setStreamId(streamId);
  47 + ssrcTransaction.setStream(stream);
37 48 byte[] transactionByteArray = SerializeUtils.serialize(transaction);
38 49 ssrcTransaction.setTransaction(transactionByteArray);
  50 + ssrcTransaction.setCallId(callId);
39 51 ssrcTransaction.setSsrc(ssrc);
40 52 ssrcTransaction.setMediaServerId(mediaServerId);
41 53  
42   - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction);
  54 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  55 + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
  56 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  57 + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
43 58 }
44 59  
45   - public void put(String deviceId, String channelId , Dialog dialog){
46   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  60 + public void put(String deviceId, String channelId, String callId, Dialog dialog){
  61 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
47 62 if (ssrcTransaction != null) {
48 63 byte[] dialogByteArray = SerializeUtils.serialize(dialog);
49 64 ssrcTransaction.setDialog(dialogByteArray);
50 65 }
51   - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction);
  66 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  67 + + "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
  68 + + ssrcTransaction.getStream(), ssrcTransaction);
52 69 }
53 70  
54 71  
55   - public ClientTransaction getTransaction(String deviceId, String channelId){
56   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  72 + public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){
  73 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
57 74 if (ssrcTransaction == null) return null;
58 75 byte[] transactionByteArray = ssrcTransaction.getTransaction();
59 76 ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
60 77 return clientTransaction;
61 78 }
62 79  
63   - public SIPDialog getDialog(String deviceId, String channelId){
64   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  80 + public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
  81 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
65 82 if (ssrcTransaction == null) return null;
66 83 byte[] dialogByteArray = ssrcTransaction.getDialog();
67 84 if (dialogByteArray == null) return null;
... ... @@ -69,36 +86,37 @@ public class VideoStreamSessionManager {
69 86 return dialog;
70 87 }
71 88  
72   - public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
73   - SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId);
74   - return ssrcTransaction;
  89 + public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
  90 + if (StringUtils.isEmpty(callId)) callId ="*";
  91 + if (StringUtils.isEmpty(stream)) stream ="*";
  92 + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
  93 + List<Object> scanResult = redisUtil.scan(key);
  94 + if (scanResult.size() == 0) return null;
  95 + return (SsrcTransaction)redisUtil.get((String) scanResult.get(0));
75 96 }
76 97  
77   - public String getStreamId(String deviceId, String channelId){
78   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
79   - if (ssrcTransaction == null) return null;
80   - return ssrcTransaction.getStreamId();
81   - }
82   - public String getMediaServerId(String deviceId, String channelId){
83   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  98 + public String getMediaServerId(String deviceId, String channelId, String stream){
  99 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
84 100 if (ssrcTransaction == null) return null;
85 101 return ssrcTransaction.getMediaServerId();
86 102 }
87 103  
88   - public String getSSRC(String deviceId, String channelId){
89   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  104 + public String getSSRC(String deviceId, String channelId, String stream){
  105 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
90 106 if (ssrcTransaction == null) return null;
91 107 return ssrcTransaction.getSsrc();
92 108 }
93 109  
94   - public void remove(String deviceId, String channelId) {
95   - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
  110 + public void remove(String deviceId, String channelId, String stream) {
  111 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
96 112 if (ssrcTransaction == null) return;
97   - redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId);
  113 + redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_"
  114 + + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
98 115 }
99 116  
  117 +
100 118 public List<SsrcTransaction> getAllSsrc() {
101   - List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
  119 + List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
102 120 List<SsrcTransaction> result= new ArrayList<>();
103 121 for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
104 122 String key = (String)ssrcTransactionKeys.get(i);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
... ... @@ -73,6 +73,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
73 73 @Override
74 74 @Async
75 75 public void processRequest(RequestEvent requestEvent) {
  76 + logger.debug("\n收到请求:\n{}", requestEvent.getRequest());
76 77 String method = requestEvent.getRequest().getMethod();
77 78 ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method);
78 79 if (sipRequestProcessor == null) {
... ... @@ -90,9 +91,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
90 91 @Override
91 92 @Async
92 93 public void processResponse(ResponseEvent responseEvent) {
93   - logger.debug(responseEvent.getResponse().toString());
94 94 Response response = responseEvent.getResponse();
95   - logger.debug(responseEvent.getResponse().toString());
  95 + logger.debug("\n收到响应:\n{}", responseEvent.getResponse());
96 96 int status = response.getStatusCode();
97 97 if (((status >= 200) && (status < 300)) || status == 401) { // Success!
98 98 CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
... ... @@ -107,8 +107,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
107 107 SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
108 108 if (subscribe != null) {
109 109 SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
110   - subscribe.response(eventResult);
111 110 sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
  111 + subscribe.response(eventResult);
112 112 }
113 113 }
114 114 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -119,8 +119,8 @@ public interface ISIPCommander {
119 119 /**
120 120 * 视频流停止
121 121 */
122   - void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
123   - void streamByeCmd(String deviceId, String channelId);
  122 + void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent);
  123 + void streamByeCmd(String deviceId, String channelId, String stream);
124 124  
125 125 /**
126 126 * 回放暂停
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
... ... @@ -17,7 +17,7 @@ public interface ISIPCommanderForPlatform {
17 17 * @return
18 18 */
19 19 boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
20   - boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
  20 + boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain);
21 21  
22 22 /**
23 23 * 向上级平台注销
... ... @@ -78,13 +78,13 @@ public interface ISIPCommanderForPlatform {
78 78 * @param parentPlatform
79 79 * @param deviceChannels
80 80 */
81   - boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo);
  81 + boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
82 82  
83 83 /**
84 84 * 回复catalog事件-删除
85 85 * @param parentPlatform
86 86 * @param deviceChannels
87 87 */
88   - boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo);
  88 + boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index);
89 89  
90 90 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
4 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
5 6 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
6 7 import gov.nist.javax.sip.message.MessageFactoryImpl;
7 8 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -127,7 +128,15 @@ public class SIPRequestHeaderPlarformProvider {
127 128  
128 129  
129 130 Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader);
130   -
  131 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
  132 + if (www == null) {
  133 + AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest");
  134 + authorizationHeader.setUsername(parentPlatform.getDeviceGBId());
  135 + authorizationHeader.setURI(requestURI);
  136 + authorizationHeader.setAlgorithm("MD5");
  137 + registerRequest.addHeader(authorizationHeader);
  138 + return registerRequest;
  139 + }
131 140 String realm = www.getRealm();
132 141 String nonce = www.getNonce();
133 142 String scheme = www.getScheme();
... ... @@ -138,7 +147,6 @@ public class SIPRequestHeaderPlarformProvider {
138 147  
139 148 callIdHeader.setCallId(callId);
140 149  
141   - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
142 150 String cNonce = null;
143 151 String nc = "00000001";
144 152 if (qop != null) {
... ... @@ -223,30 +231,30 @@ public class SIPRequestHeaderPlarformProvider {
223 231 UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
224 232 request.addHeader(userAgentHeader);
225 233  
226   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
  234 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
227 235 request.setContent(content, contentTypeHeader);
228 236 return request;
229 237 }
230 238  
231   - public Request createNotifyRequest(ParentPlatform parentPlatform, String content, String fromTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
  239 + public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
232 240 Request request = null;
233 241 // sipuri
234 242 SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
235 243 // via
236 244 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
237 245 ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
238   - parentPlatform.getTransport(), null);
  246 + parentPlatform.getTransport(), subscribeInfo.getBranch());
239 247 viaHeader.setRPort();
240 248 viaHeaders.add(viaHeader);
241 249 // from
242 250 SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
243 251 parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
244 252 Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
245   - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
  253 + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getToTag());
246 254 // to
247 255 SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
248 256 Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
249   - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
  257 + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag());
250 258  
251 259 // Forwards
252 260 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
... ... @@ -262,7 +270,22 @@ public class SIPRequestHeaderPlarformProvider {
262 270 UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
263 271 request.addHeader(userAgentHeader);
264 272  
265   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
  273 + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  274 + if (subscribeInfo.getEventId() != null) {
  275 + event.setEventId(subscribeInfo.getEventId());
  276 + }
  277 +
  278 + request.addHeader(event);
  279 +
  280 + SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");
  281 + request.setHeader(active);
  282 +
  283 + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
  284 + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
  285 + .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
  286 + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
  287 +
  288 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
266 289 request.setContent(content, contentTypeHeader);
267 290 return request;
268 291 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -67,7 +67,7 @@ public class SIPRequestHeaderProvider {
67 67  
68 68 request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
69 69 toHeader, viaHeaders, maxForwards);
70   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
  70 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
71 71 request.setContent(content, contentTypeHeader);
72 72 return request;
73 73 }
... ... @@ -217,7 +217,7 @@ public class SIPRequestHeaderProvider {
217 217 EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event);
218 218 request.addHeader(eventHeader);
219 219  
220   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
  220 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
221 221 request.setContent(content, contentTypeHeader);
222 222 return request;
223 223 }
... ... @@ -226,7 +226,7 @@ public class SIPRequestHeaderProvider {
226 226 throws PeerUnavailableException, ParseException, InvalidArgumentException {
227 227 Request request = null;
228 228 if (streamInfo == null) return null;
229   - Dialog dialog = streamSession.getDialog(streamInfo.getDeviceID(), streamInfo.getChannelId());
  229 + Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
230 230  
231 231 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
232 232 device.getHostAddress());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -331,7 +331,7 @@ public class SIPCommander implements ISIPCommander {
331 331 */
332 332 @Override
333 333 public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
334   - String streamId = ssrcInfo.getStreamId();
  334 + String streamId = ssrcInfo.getStream();
335 335 try {
336 336 if (device == null) return;
337 337 String streamMode = device.getStreamMode().toUpperCase();
... ... @@ -404,6 +404,8 @@ public class SIPCommander implements ISIPCommander {
404 404 }
405 405  
406 406 content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
  407 + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
  408 +// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
407 409  
408 410 String tm = Long.toString(System.currentTimeMillis());
409 411  
... ... @@ -412,14 +414,14 @@ public class SIPCommander implements ISIPCommander {
412 414  
413 415 Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
414 416  
415   - String finalStreamId = streamId;
416 417 transmitRequest(device, request, (e -> {
417   - streamSession.remove(device.getDeviceId(), channelId);
  418 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
418 419 mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
419 420 errorEvent.response(e);
420 421 }), e ->{
421   - streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
422   - streamSession.put(device.getDeviceId(), channelId , e.dialog);
  422 + // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
  423 + streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
  424 + streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
423 425 });
424 426  
425 427  
... ... @@ -441,12 +443,12 @@ public class SIPCommander implements ISIPCommander {
441 443 , SipSubscribe.Event errorEvent) {
442 444 try {
443 445  
444   - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  446 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
445 447  
446 448 // 添加订阅
447 449 JSONObject subscribeKey = new JSONObject();
448 450 subscribeKey.put("app", "rtp");
449   - subscribeKey.put("stream", ssrcInfo.getStreamId());
  451 + subscribeKey.put("stream", ssrcInfo.getStream());
450 452 subscribeKey.put("regist", true);
451 453 subscribeKey.put("mediaServerId", mediaServerItem.getId());
452 454 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
... ... @@ -466,8 +468,6 @@ public class SIPCommander implements ISIPCommander {
466 468 content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
467 469 +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
468 470  
469   -
470   -
471 471 String streamMode = device.getStreamMode().toUpperCase();
472 472  
473 473 if (userSetup.isSeniorSdp()) {
... ... @@ -527,8 +527,8 @@ public class SIPCommander implements ISIPCommander {
527 527  
528 528 transmitRequest(device, request, errorEvent, okEvent -> {
529 529 ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
530   - streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), responseEvent.getClientTransaction());
531   - streamSession.put(device.getDeviceId(), channelId, okEvent.dialog);
  530 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction());
  531 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
532 532 });
533 533 } catch ( SipException | ParseException | InvalidArgumentException e) {
534 534 e.printStackTrace();
... ... @@ -548,12 +548,12 @@ public class SIPCommander implements ISIPCommander {
548 548 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
549 549 , SipSubscribe.Event errorEvent) {
550 550 try {
551   - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  551 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
552 552  
553 553 // 添加订阅
554 554 JSONObject subscribeKey = new JSONObject();
555 555 subscribeKey.put("app", "rtp");
556   - subscribeKey.put("stream", ssrcInfo.getStreamId());
  556 + subscribeKey.put("stream", ssrcInfo.getStream());
557 557 subscribeKey.put("regist", true);
558 558 subscribeKey.put("mediaServerId", mediaServerItem.getId());
559 559 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
... ... @@ -634,7 +634,8 @@ public class SIPCommander implements ISIPCommander {
634 634 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
635 635  
636 636 ClientTransaction transaction = transmitRequest(device, request, errorEvent);
637   - streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction);
  637 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
  638 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
638 639  
639 640 } catch ( SipException | ParseException | InvalidArgumentException e) {
640 641 e.printStackTrace();
... ... @@ -645,17 +646,17 @@ public class SIPCommander implements ISIPCommander {
645 646 * 视频流停止, 不使用回调
646 647 */
647 648 @Override
648   - public void streamByeCmd(String deviceId, String channelId) {
649   - streamByeCmd(deviceId, channelId, null);
  649 + public void streamByeCmd(String deviceId, String channelId, String stream) {
  650 + streamByeCmd(deviceId, channelId, stream, null);
650 651 }
651 652  
652 653 /**
653 654 * 视频流停止
654 655 */
655 656 @Override
656   - public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
  657 + public void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent) {
657 658 try {
658   - ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
  659 + ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream);
659 660 if (transaction == null) {
660 661 logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
661 662 SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
... ... @@ -664,7 +665,7 @@ public class SIPCommander implements ISIPCommander {
664 665 }
665 666 return;
666 667 }
667   - SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
  668 + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, stream);
668 669 if (dialog == null) {
669 670 logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
670 671 return;
... ... @@ -708,11 +709,11 @@ public class SIPCommander implements ISIPCommander {
708 709  
709 710 dialog.sendRequest(clientTransaction);
710 711  
711   - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId);
  712 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callIdHeader.getCallId(), null);
712 713 if (ssrcTransaction != null) {
713 714 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
714 715 mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
715   - streamSession.remove(deviceId, channelId);
  716 + streamSession.remove(deviceId, channelId, ssrcTransaction.getStream());
716 717 }
717 718 } catch (SipException | ParseException e) {
718 719 e.printStackTrace();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -32,21 +32,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
32 32  
33 33 private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class);
34 34  
35   - // @Autowired
36   - // private SipConfig sipConfig;
37   -
38   - // @Autowired
39   - // private SIPRequestHeaderProvider headerProvider;
40   -
41 35 @Autowired
42 36 private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider;
43 37  
44   - // @Autowired
45   - // private VideoStreamSessionManager streamSession;
46   -
47   - // @Autowired
48   - // private IVideoManagerStorager storager;
49   -
50 38 @Autowired
51 39 private IRedisCatchStorage redisCatchStorage;
52 40  
... ... @@ -65,7 +53,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
65 53  
66 54 @Override
67 55 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
68   - return register(parentPlatform, null, null, errorEvent, okEvent);
  56 + return register(parentPlatform, null, null, errorEvent, okEvent, false);
69 57 }
70 58  
71 59 @Override
... ... @@ -77,15 +65,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
77 65 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
78 66 }
79 67  
80   - return register(parentPlatform, null, null, errorEvent, okEvent);
  68 + return register(parentPlatform, null, null, errorEvent, okEvent, false);
81 69 }
82 70  
83 71 @Override
84   - public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
  72 + public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
  73 + SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) {
85 74 try {
86 75 Request request = null;
87 76 String tm = Long.toString(System.currentTimeMillis());
88   - if (www == null ) {
  77 + if (!registerAgain ) {
89 78 // //callid
90 79 CallIdHeader callIdHeader = null;
91 80 if(parentPlatform.getTransport().equals("TCP")) {
... ... @@ -173,6 +162,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
173 162 }
174 163  
175 164 private void transmitRequest(ParentPlatform parentPlatform, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException {
  165 + logger.debug("\n发送消息:\n{}", request);
176 166 if("TCP".equals(parentPlatform.getTransport())) {
177 167 tcpSipProvider.sendRequest(request);
178 168  
... ... @@ -223,7 +213,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
223 213 catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
224 214 catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
225 215 catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
226   - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  216 + if (channel.getParentId() != null) {
  217 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  218 + }
227 219 catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
228 220 catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
229 221 catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
... ... @@ -358,7 +350,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
358 350  
359 351 String tm = Long.toString(System.currentTimeMillis());
360 352  
361   - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, deviceStatusXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader);
  353 + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform,
  354 + deviceStatusXml.toString(),callIdHeader,
  355 + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);
362 356 transmitRequest(parentPlatform, request);
363 357  
364 358 } catch (SipException | ParseException | InvalidArgumentException e) {
... ... @@ -369,65 +363,82 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
369 363 }
370 364  
371 365 @Override
372   - public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) {
  366 + public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
373 367 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
374 368 return false;
375 369 }
376   - for (DeviceChannel channel : deviceChannels) {
377   - try {
378   - StringBuffer catalogXml = new StringBuffer(600);
379   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
380   - catalogXml.append("<Notify>\r\n");
381   - catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
382   - catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
383   - catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n");
384   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
385   - catalogXml.append("<Item>\r\n");
386   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
387   - catalogXml.append("<Event>" + type + "</Event>\r\n");
388   - catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
389   - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
390   - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
391   - catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
392   - catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
393   - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
394   - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
395   - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
396   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
397   - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
398   - catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
399   - catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
400   - catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
401   - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
402   - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
403   - catalogXml.append("<Info>\r\n");
404   - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
405   - catalogXml.append("</Info>\r\n");
406   - catalogXml.append("</Item>\r\n");
407   - catalogXml.append("</DeviceList>\r\n");
408   - catalogXml.append("</Notify>\r\n");
  370 + if (index == null) {
  371 + index = 0;
  372 + }
409 373  
410   - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
411   - : udpSipProvider.getNewCallId();
412   - callIdHeader.setCallId(subscribeInfo.getCallId());
413   -
414   - String tm = Long.toString(System.currentTimeMillis());
415   -
416   - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader);
417   - transmitRequest(parentPlatform, request);
418   - Thread.sleep(10);
419   - } catch (SipException | ParseException | InvalidArgumentException e) {
420   - e.printStackTrace();
421   - return false;
422   - } catch (InterruptedException e) {
423   - e.printStackTrace();
  374 + try {
  375 + if (index > deviceChannels.size() - 1) {
  376 + return true;
424 377 }
  378 + Request request = getCatalogNotifyRequestForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo);
  379 + index += 1;
  380 + Integer finalIndex = index;
  381 + transmitRequest(parentPlatform, request, null, (eventResult -> {
  382 + sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex);
  383 + }));
  384 + } catch (SipException | ParseException | InvalidArgumentException e) {
  385 + e.printStackTrace();
  386 + return false;
425 387 }
426 388 return true;
427 389 }
428 390  
  391 + private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type,
  392 + SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException,
  393 + PeerUnavailableException {
  394 + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo);
  395 +
  396 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  397 + : udpSipProvider.getNewCallId();
  398 + callIdHeader.setCallId(subscribeInfo.getCallId());
  399 + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent,
  400 + callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);
  401 + return request;
  402 + }
  403 +
  404 + private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) {
  405 + StringBuffer catalogXml = new StringBuffer(600);
  406 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  407 + channel.setParentId(parentPlatform.getDeviceGBId());
  408 + }
  409 + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  410 + catalogXml.append("<Notify>\r\n");
  411 + catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
  412 + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  413 + catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  414 + catalogXml.append("<SumNum>1</SumNum>\r\n");
  415 + catalogXml.append("<DeviceList Num=\"1\">\r\n");
  416 + catalogXml.append("<Item>\r\n");
  417 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  418 + catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
  419 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  420 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  421 + catalogXml.append("<Owner>0</Owner>\r\n");
  422 + catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
  423 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  424 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  425 + if (channel.getParentId() != null) {
  426 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  427 + }
  428 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  429 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  430 + catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
  431 + if (!"presence".equals(subscribeInfo.getEventType())) {
  432 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  433 + }
  434 + catalogXml.append("</Item>\r\n");
  435 + catalogXml.append("</DeviceList>\r\n");
  436 + catalogXml.append("</Notify>\r\n");
  437 + return catalogXml.toString();
  438 + }
  439 +
429 440 @Override
430   - public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) {
  441 + public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
431 442 if (parentPlatform == null
432 443 || deviceChannels == null
433 444 || deviceChannels.size() == 0
... ... @@ -435,39 +446,55 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
435 446 return false;
436 447 }
437 448  
438   - for (DeviceChannel channel : deviceChannels) {
439   - try {
440   - StringBuffer catalogXml = new StringBuffer(600);
441   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
442   - catalogXml.append("<Notify>\r\n");
443   - catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
444   - catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
445   - catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n");
446   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
447   - catalogXml.append("<Item>\r\n");
448   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
449   - catalogXml.append("<Event>" + type + "</Event>\r\n");
450   - catalogXml.append("</Item>\r\n");
451   - catalogXml.append("</DeviceList>\r\n");
452   - catalogXml.append("</Notify>\r\n");
  449 + if (index == null) {
  450 + index = 0;
  451 + }
453 452  
454   - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  453 + if (index > deviceChannels.size() - 1) {
  454 + return true;
  455 + }
  456 + try {
  457 + String catalogXml = getCatalogXmlContentForCatalogOther(deviceChannels.get(index), type, parentPlatform);
  458 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
455 459 : udpSipProvider.getNewCallId();
456   - callIdHeader.setCallId(subscribeInfo.getCallId());
457   -
458   - String tm = Long.toString(System.currentTimeMillis());
459   -
460   - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader);
461   - transmitRequest(parentPlatform, request);
462   - Thread.sleep(200);
463   - } catch (SipException | ParseException | InvalidArgumentException e) {
464   - e.printStackTrace();
465   - return false;
466   - } catch (InterruptedException e) {
467   - e.printStackTrace();
468   - }
  460 + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml,
  461 + callIdHeader,
  462 + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo);
  463 + index += 1;
  464 + Integer finalIndex = index;
  465 + transmitRequest(parentPlatform, request, null, eventResult -> {
  466 + sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex);
  467 + });
  468 + } catch (SipException e) {
  469 + e.printStackTrace();
  470 + } catch (InvalidArgumentException e) {
  471 + e.printStackTrace();
  472 + } catch (ParseException e) {
  473 + e.printStackTrace();
469 474 }
  475 +
470 476 return true;
471 477 }
472 478  
  479 + private String getCatalogXmlContentForCatalogOther(DeviceChannel channel, String type, ParentPlatform parentPlatform) {
  480 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  481 + channel.setParentId(parentPlatform.getDeviceGBId());
  482 + }
  483 + StringBuffer catalogXml = new StringBuffer(600);
  484 + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  485 + catalogXml.append("<Notify>\r\n");
  486 + catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
  487 + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
  488 + catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  489 + catalogXml.append("<SumNum>1</SumNum>\r\n");
  490 + catalogXml.append("<DeviceList Num=\"1\">\r\n");
  491 + catalogXml.append("<Item>\r\n");
  492 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  493 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  494 + catalogXml.append("</Item>\r\n");
  495 + catalogXml.append("</DeviceList>\r\n");
  496 + catalogXml.append("</Notify>\r\n");
  497 + return catalogXml.toString();
  498 + }
  499 +
473 500 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
3 4 import gov.nist.javax.sip.SipProviderImpl;
4 5 import gov.nist.javax.sip.SipStackImpl;
5 6 import gov.nist.javax.sip.message.SIPRequest;
... ... @@ -160,13 +161,18 @@ public abstract class SIPRequestProcessorParent {
160 161 * @throws InvalidArgumentException
161 162 * @throws ParseException
162 163 */
163   - public void responseSdpAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
  164 + public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
164 165 Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
165 166 SipFactory sipFactory = SipFactory.getInstance();
166 167 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
167 168 response.setContent(sdp, contentTypeHeader);
168 169  
  170 + // 兼容国标中的使用编码@域名作为RequestURI的情况
169 171 SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
  172 + if (sipURI.getPort() == -1) {
  173 + sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
  174 + }
  175 + logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
170 176  
171 177 Address concatAddress = sipFactory.createAddressFactory().createAddress(
172 178 sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
... ... @@ -183,13 +189,18 @@ public abstract class SIPRequestProcessorParent {
183 189 * @throws InvalidArgumentException
184 190 * @throws ParseException
185 191 */
186   - public Response responseXmlAck(RequestEvent evt, String xml) throws SipException, InvalidArgumentException, ParseException {
  192 + public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException {
187 193 Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
188 194 SipFactory sipFactory = SipFactory.getInstance();
189   - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
  195 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
190 196 response.setContent(xml, contentTypeHeader);
191 197  
  198 + // 兼容国标中的使用编码@域名作为RequestURI的情况
192 199 SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
  200 + if (sipURI.getPort() == -1) {
  201 + sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort());
  202 + }
  203 + logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort());
193 204  
194 205 Address concatAddress = sipFactory.createAddressFactory().createAddress(
195 206 sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
... ... @@ -72,10 +72,10 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
72 72 if (deviceId == null) {
73 73 streamInfo = new StreamInfo();
74 74 streamInfo.setApp(sendRtpItem.getApp());
75   - streamInfo.setStreamId(sendRtpItem.getStreamId());
  75 + streamInfo.setStream(sendRtpItem.getStreamId());
76 76 }else {
77 77 streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
78   - sendRtpItem.setStreamId(streamInfo.getStreamId());
  78 + sendRtpItem.setStreamId(streamInfo.getStream());
79 79 streamInfo.setApp("rtp");
80 80 }
81 81  
... ... @@ -85,7 +85,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
85 85 Map<String, Object> param = new HashMap<>();
86 86 param.put("vhost","__defaultVhost__");
87 87 param.put("app",streamInfo.getApp());
88   - param.put("stream",streamInfo.getStreamId());
  88 + param.put("stream",streamInfo.getStream());
89 89 param.put("ssrc", sendRtpItem.getSsrc());
90 90 param.put("dst_url",sendRtpItem.getIp());
91 91 param.put("dst_port", sendRtpItem.getPort());
... ... @@ -98,21 +98,21 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
98 98 try {
99 99 if (System.currentTimeMillis() - startTime < 30 * 1000) {
100 100 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
101   - if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) {
  101 + if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStream())) {
102 102 rtpPushed = true;
103 103 logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]",
104   - streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort());
  104 + streamInfo.getApp() ,streamInfo.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort());
105 105 zlmrtpServerFactory.startSendRtpStream(mediaInfo, param);
106 106 } else {
107 107 logger.info("等待设备推流[{}/{}].......",
108   - streamInfo.getApp() ,streamInfo.getStreamId());
  108 + streamInfo.getApp() ,streamInfo.getStream());
109 109 Thread.sleep(1000);
110 110 continue;
111 111 }
112 112 } else {
113 113 rtpPushed = true;
114 114 logger.info("设备推流[{}/{}]超时,终止向上级推流",
115   - streamInfo.getApp() ,streamInfo.getStreamId());
  115 + streamInfo.getApp() ,streamInfo.getStream());
116 116 }
117 117 } catch (InterruptedException e) {
118 118 e.printStackTrace();
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
... ... @@ -89,18 +89,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
89 89 redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
90 90 if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) {
91 91 logger.info(streamId + "无其它观看者,通知设备停止推流");
92   - cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId);
  92 + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId, streamId);
93 93 }
94 94 }
95 95 // 可能是设备主动停止
96 96 Device device = storager.queryVideoDeviceByChannelId(platformGbId);
97 97 if (device != null) {
98 98 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);
  99 +
99 100 if (streamInfo != null) {
100 101 redisCatchStorage.stopPlay(streamInfo);
101 102 }
102 103 storager.stopPlay(device.getDeviceId(), channelId);
103   - mediaServerService.closeRTPServer(device, channelId);
  104 + mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
104 105 }
105 106 }
106 107 } catch (SipException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -252,7 +252,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
252 252 content.append("f=\r\n");
253 253  
254 254 try {
255   - responseSdpAck(evt, content.toString());
  255 + responseSdpAck(evt, content.toString(), platform);
256 256 } catch (SipException e) {
257 257 e.printStackTrace();
258 258 } catch (InvalidArgumentException e) {
... ... @@ -309,7 +309,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
309 309 content.append("f=\r\n");
310 310  
311 311 try {
312   - responseSdpAck(evt, content.toString());
  312 + responseSdpAck(evt, content.toString(), platform);
313 313 } catch (SipException e) {
314 314 e.printStackTrace();
315 315 } catch (InvalidArgumentException e) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
... ... @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 4 import com.genersoft.iot.vmp.conf.DynamicTask;
5 5 import com.genersoft.iot.vmp.conf.UserSetup;
6 6 import com.genersoft.iot.vmp.gb28181.bean.CmdType;
  7 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 8 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
8 9 import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask;
9 10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
... ... @@ -105,9 +106,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
105 106 logger.info("processRequest serverTransactionId is null.");
106 107 }
107 108 }
108   -
109   -
110   -
111 109 } catch (ParseException e) {
112 110 e.printStackTrace();
113 111 } catch (SipException e) {
... ... @@ -155,7 +153,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
155 153  
156 154  
157 155 try {
158   - Response response = responseXmlAck(evt, resultXml.toString());
  156 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
  157 + Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform);
159 158 ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
160 159 subscribeInfo.setToTag(toHeader.getTag());
161 160 redisCatchStorage.updateSubscribe(key, subscribeInfo);
... ... @@ -196,7 +195,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
196 195 }
197 196  
198 197 try {
199   - Response response = responseXmlAck(evt, resultXml.toString());
  198 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
  199 + Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform);
200 200 ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
201 201 subscribeInfo.setToTag(toHeader.getTag());
202 202 redisCatchStorage.updateSubscribe(key, subscribeInfo);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
... ... @@ -22,7 +22,7 @@ import org.springframework.util.StringUtils;
22 22  
23 23 import javax.sip.RequestEvent;
24 24  
25   -import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
  25 +import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
26 26  
27 27 @Component
28 28 public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
... ... @@ -105,6 +105,11 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
105 105 storager.insertMobilePosition(mobilePosition);
106 106 }
107 107 }
  108 + if (!StringUtils.isEmpty(deviceAlarm.getDeviceId())) {
  109 + if (deviceAlarm.getAlarmMethod().equals("5")) {
  110 + deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));
  111 + }
  112 + }
108 113 logger.debug("存储报警信息、报警分类");
109 114 // 存储报警信息、报警分类
110 115 deviceAlarmService.add(deviceAlarm);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
... ... @@ -72,6 +72,9 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
72 72 List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
73 73 if (catalogs.size() > 0) {
74 74 for (PlatformCatalog catalog : catalogs) {
  75 + if (catalog.getParentId().equals(catalog.getPlatformId())) {
  76 + catalog.setParentId(parentPlatform.getDeviceGBId());
  77 + }
75 78 DeviceChannel deviceChannel = new DeviceChannel();
76 79 deviceChannel.setChannelId(catalog.getId());
77 80 deviceChannel.setName(catalog.getName());
... ... @@ -83,30 +86,35 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
83 86 deviceChannel.setParental(1);
84 87 deviceChannel.setParentId(catalog.getParentId());
85 88 deviceChannel.setRegisterWay(1);
86   - deviceChannel.setCivilCode(config.getDomain());
  89 + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
87 90 deviceChannel.setModel("live");
88 91 deviceChannel.setOwner("wvp-pro");
89 92 deviceChannel.setSecrecy("0");
90 93 cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
91 94 // 防止发送过快
92   - Thread.sleep(50);
  95 + Thread.sleep(100);
93 96 }
94 97 }
95 98 // 回复级联的通道
96 99 if (channelReduces.size() > 0) {
97 100 for (ChannelReduce channelReduce : channelReduces) {
  101 + if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) {
  102 + channelReduce.setCatalogId(parentPlatform.getDeviceGBId());
  103 + }
98 104 DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
99 105 deviceChannel.setParental(0);
100 106 deviceChannel.setParentId(channelReduce.getCatalogId());
101   -
102 107 cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
103 108 // 防止发送过快
104   - Thread.sleep(50);
  109 + Thread.sleep(100);
105 110 }
106 111 }
107 112 // 回复直播的通道
108 113 if (gbStreams.size() > 0) {
109 114 for (GbStream gbStream : gbStreams) {
  115 + if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
  116 + gbStream.setCatalogId(null);
  117 + }
110 118 DeviceChannel deviceChannel = new DeviceChannel();
111 119 deviceChannel.setChannelId(gbStream.getGbId());
112 120 deviceChannel.setName(gbStream.getName());
... ... @@ -117,14 +125,14 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
117 125 deviceChannel.setStatus(gbStream.isStatus()?1:0);
118 126 deviceChannel.setParentId(gbStream.getCatalogId());
119 127 deviceChannel.setRegisterWay(1);
120   - deviceChannel.setCivilCode(config.getDomain());
  128 + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
121 129 deviceChannel.setModel("live");
122 130 deviceChannel.setOwner("wvp-pro");
123 131 deviceChannel.setParental(0);
124 132 deviceChannel.setSecrecy("0");
125 133 cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
126 134 // 防止发送过快
127   - Thread.sleep(50);
  135 + Thread.sleep(100);
128 136 }
129 137 }
130 138 if (size == 0) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
... ... @@ -68,6 +68,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
68 68 }
69 69 if (device.getPort() != rPort) {
70 70 device.setPort(rPort);
  71 + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
71 72 videoManagerStorager.updateDevice(device);
72 73 redisCatchStorage.updateDevice(device);
73 74 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
... ... @@ -62,7 +62,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
62 62 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*");
63 63 if (streamInfo != null) {
64 64 redisCatchStorage.stopPlayback(streamInfo);
65   - cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId());
  65 + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
66 66 }
67 67 }
68 68 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
... ... @@ -75,6 +75,9 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
75 75 int size = catalogs.size() + channelReduces.size() + gbStreams.size();
76 76 if (catalogs.size() > 0) {
77 77 for (PlatformCatalog catalog : catalogs) {
  78 + if (catalog.getParentId().equals(parentPlatform.getServerGBId())) {
  79 + catalog.setParentId(parentPlatform.getDeviceGBId());
  80 + }
78 81 DeviceChannel deviceChannel = new DeviceChannel();
79 82 deviceChannel.setChannelId(catalog.getId());
80 83 deviceChannel.setName(catalog.getName());
... ... @@ -86,30 +89,35 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
86 89 deviceChannel.setParental(1);
87 90 deviceChannel.setParentId(catalog.getParentId());
88 91 deviceChannel.setRegisterWay(1);
89   - deviceChannel.setCivilCode(config.getDomain());
  92 + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
90 93 deviceChannel.setModel("live");
91 94 deviceChannel.setOwner("wvp-pro");
92 95 deviceChannel.setSecrecy("0");
93 96 cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
94 97 // 防止发送过快
95   - Thread.sleep(50);
  98 + Thread.sleep(100);
96 99 }
97 100 }
98 101 // 回复级联的通道
99 102 if (channelReduces.size() > 0) {
100 103 for (ChannelReduce channelReduce : channelReduces) {
  104 + if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) {
  105 + channelReduce.setCatalogId(parentPlatform.getDeviceGBId());
  106 + }
101 107 DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
102   - // TODO 目前暂时认为这里只用通道没有目录
103 108 deviceChannel.setParental(0);
104 109 deviceChannel.setParentId(channelReduce.getCatalogId());
105 110 cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
106 111 // 防止发送过快
107   - Thread.sleep(50);
  112 + Thread.sleep(100);
108 113 }
109 114 }
110 115 // 回复直播的通道
111 116 if (gbStreams.size() > 0) {
112 117 for (GbStream gbStream : gbStreams) {
  118 + if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
  119 + gbStream.setCatalogId(parentPlatform.getDeviceGBId());
  120 + }
113 121 DeviceChannel deviceChannel = new DeviceChannel();
114 122 deviceChannel.setChannelId(gbStream.getGbId());
115 123 deviceChannel.setName(gbStream.getName());
... ... @@ -120,7 +128,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
120 128 deviceChannel.setStatus(gbStream.isStatus()?1:0);
121 129 deviceChannel.setParentId(gbStream.getCatalogId());
122 130 deviceChannel.setRegisterWay(1);
123   - deviceChannel.setCivilCode(config.getDomain());
  131 + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2));
124 132 deviceChannel.setModel("live");
125 133 deviceChannel.setOwner("wvp-pro");
126 134 deviceChannel.setParental(0);
... ... @@ -128,7 +136,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
128 136  
129 137 cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
130 138 // 防止发送过快
131   - Thread.sleep(50);
  139 + Thread.sleep(100);
132 140 }
133 141 }
134 142 if (size == 0) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
... ... @@ -78,7 +78,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
78 78  
79 79 if (response.getStatusCode() == 401) {
80 80 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
81   - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null);
  81 + sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true);
82 82 }else if (response.getStatusCode() == 200){
83 83 // 注册/注销成功
84 84 logger.info(String.format("%s %s成功", platformGBId, action));
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
... ... @@ -191,7 +191,7 @@ public class XmlUtil {
191 191 String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : "";
192 192 deviceChannel.setChannelId(channelId);
193 193 // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
194   - if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) {
  194 + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
195 195 deviceChannel.setStatus(1);
196 196 }
197 197 if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
... ... @@ -255,9 +255,14 @@ public class XmlUtil {
255 255 } else {
256 256 deviceChannel.setLatitude(0.00);
257 257 }
258   - if (XmlUtil.getText(itemDevice, "PTZType") == null
259   - || XmlUtil.getText(itemDevice, "PTZType") == "") {
260   - deviceChannel.setPTZType(0);
  258 + if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
  259 + //兼容INFO中的信息
  260 + Element info = itemDevice.element("Info");
  261 + if(XmlUtil.getText(info, "PTZType") == null || "".equals(XmlUtil.getText(info, "PTZType"))){
  262 + deviceChannel.setPTZType(0);
  263 + }else{
  264 + deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(info, "PTZType")));
  265 + }
261 266 } else {
262 267 deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
263 268 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -361,6 +361,9 @@ public class ZLMHttpHookListener {
361 361 if (mediaServerItem != null){
362 362 if (regist) {
363 363 StreamPushItem streamPushItem = null;
  364 + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks);
  365 + item.setStreamInfo(streamInfoByAppAndStream);
  366 +
364 367 redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
365 368 if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
366 369 || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
... ... @@ -378,7 +381,7 @@ public class ZLMHttpHookListener {
378 381 }
379 382 }
380 383 if (gbStreams.size() > 0) {
381   - eventPublisher.catalogEventPublishForStream(null, gbStreams.toArray(new GbStream[0]), CatalogEvent.ON);
  384 + eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON);
382 385 }
383 386  
384 387 }else {
... ... @@ -439,14 +442,16 @@ public class ZLMHttpHookListener {
439 442 if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
440 443 ret.put("close", false);
441 444 } else {
442   - cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
  445 + cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
  446 + streamInfoForPlayCatch.getStream());
443 447 redisCatchStorage.stopPlay(streamInfoForPlayCatch);
444 448 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
445 449 }
446 450 }else{
447 451 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId);
448 452 if (streamInfoForPlayBackCatch != null) {
449   - cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId());
  453 + cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(),
  454 + streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream());
450 455 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch);
451 456 }else {
452 457 StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId);
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
... ... @@ -91,6 +91,7 @@ public class ZLMHttpHookSubscribe {
91 91 }
92 92 }
93 93 if (null != result && result){
  94 + // TODO 报错未处理
94 95 iterator.remove();
95 96 }
96 97 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
... ... @@ -122,7 +122,6 @@ public class ZLMMediaListManager {
122 122 transform.setName(thirdPartyGB.getName());
123 123 }
124 124 }
125   - storager.updateMedia(transform);
126 125 if (!StringUtils.isEmpty(transform.getGbId())) {
127 126 // 如果这个国标ID已经给了其他推流且流已离线,则移除其他推流
128 127 List<GbStream> gbStreams = gbStreamMapper.selectByGBId(transform.getGbId());
... ... @@ -135,13 +134,16 @@ public class ZLMMediaListManager {
135 134 }
136 135 }
137 136 }
138   - if (gbStreamMapper.selectOne(transform.getApp(), transform.getStream()) != null) {
  137 + StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(transform.getApp(), transform.getStream());
  138 + if (streamProxyItem != null) {
  139 + transform.setGbStreamId(streamProxyItem.getGbStreamId());
139 140 gbStreamMapper.update(transform);
140 141 }else {
141 142 transform.setCreateStamp(System.currentTimeMillis());
142 143 gbStreamMapper.add(transform);
143 144 }
144 145 }
  146 + storager.updateMedia(transform);
145 147 return transform;
146 148 }
147 149  
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
... ... @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONObject;
5 5 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
6 6 import okhttp3.*;
  7 +import okhttp3.logging.HttpLoggingInterceptor;
7 8 import org.jetbrains.annotations.NotNull;
8 9 import org.slf4j.Logger;
9 10 import org.slf4j.LoggerFactory;
... ... @@ -25,8 +26,23 @@ public class ZLMRESTfulUtils {
25 26 void run(JSONObject response);
26 27 }
27 28  
  29 + private OkHttpClient getClient(){
  30 + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
  31 + if (logger.isDebugEnabled()) {
  32 + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
  33 + logger.debug("http请求参数:" + message);
  34 + });
  35 + logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
  36 + // OkHttp進行添加攔截器loggingInterceptor
  37 + httpClientBuilder.addInterceptor(logging);
  38 + }
  39 + return httpClientBuilder.build();
  40 + }
  41 +
  42 +
28 43 public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
29   - OkHttpClient client = new OkHttpClient();
  44 + OkHttpClient client = getClient();
  45 +
30 46 if (mediaServerItem == null) {
31 47 return null;
32 48 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
... ... @@ -92,6 +92,7 @@ public class ZLMRunner implements CommandLineRunner {
92 92  
93 93 // 获取所有的zlm, 并开启主动连接
94 94 List<MediaServerItem> all = mediaServerService.getAllFromDatabase();
  95 + mediaServerService.updateVmServer(all);
95 96 if (all.size() == 0) {
96 97 all.add(mediaConfig.getMediaSerItem());
97 98 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java
1 1 package com.genersoft.iot.vmp.media.zlm.dto;
2 2  
  3 +import com.genersoft.iot.vmp.common.StreamInfo;
  4 +
3 5 import java.util.List;
4 6  
5 7 public class MediaItem {
... ... @@ -281,6 +283,8 @@ public class MediaItem {
281 283 }
282 284 }
283 285  
  286 + private StreamInfo streamInfo;
  287 +
284 288 public String getApp() {
285 289 return app;
286 290 }
... ... @@ -402,4 +406,12 @@ public class MediaItem {
402 406 public void setMediaServerId(String mediaServerId) {
403 407 this.mediaServerId = mediaServerId;
404 408 }
  409 +
  410 + public StreamInfo getStreamInfo() {
  411 + return streamInfo;
  412 + }
  413 +
  414 + public void setStreamInfo(StreamInfo streamInfo) {
  415 + this.streamInfo = streamInfo;
  416 + }
405 417 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
... ... @@ -42,11 +42,13 @@ public interface IMediaServerService {
42 42  
43 43 void setZLMConfig(MediaServerItem mediaServerItem, boolean restart);
44 44  
  45 + void updateVmServer(List<MediaServerItem> mediaServerItemList);
  46 +
45 47 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId);
46 48  
47 49 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback);
48 50  
49   - void closeRTPServer(Device device, String channelId);
  51 + void closeRTPServer(Device device, String channelId, String ssrc);
50 52  
51 53 void clearRTPServer(MediaServerItem mediaServerItem);
52 54  
... ... @@ -74,6 +76,8 @@ public interface IMediaServerService {
74 76  
75 77 void delete(String id);
76 78  
  79 + void deleteDb(String id);
  80 +
77 81 MediaServerItem getDefaultMediaServer();
78 82  
79 83 void updateMediaServerKeepalive(String mediaServerId, JSONObject data);
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
... ... @@ -5,14 +5,16 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
7 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  8 +import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
8 9 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
  10 +import org.springframework.http.ResponseEntity;
  11 +import org.springframework.web.context.request.async.DeferredResult;
9 12  
10 13 /**
11 14 * 点播处理
12 15 */
13 16 public interface IPlayService {
14 17  
15   - void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
16 18 void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
17 19  
18 20 PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
... ... @@ -20,4 +22,6 @@ public interface IPlayService {
20 22 MediaServerItem getNewMediaServerItem(Device device);
21 23  
22 24 void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString);
  25 +
  26 + DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback errorCallBack);
23 27 }
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  4 +
  5 +public interface PlayBackCallback {
  6 +
  7 + void call(RequestMessage msg);
  8 +
  9 +}
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java
... ... @@ -4,12 +4,12 @@ public class SSRCInfo {
4 4  
5 5 private int port;
6 6 private String ssrc;
7   - private String StreamId;
  7 + private String Stream;
8 8  
9   - public SSRCInfo(int port, String ssrc, String streamId) {
  9 + public SSRCInfo(int port, String ssrc, String stream) {
10 10 this.port = port;
11 11 this.ssrc = ssrc;
12   - StreamId = streamId;
  12 + Stream = stream;
13 13 }
14 14  
15 15 public int getPort() {
... ... @@ -28,11 +28,11 @@ public class SSRCInfo {
28 28 this.ssrc = ssrc;
29 29 }
30 30  
31   - public String getStreamId() {
32   - return StreamId;
  31 + public String getStream() {
  32 + return Stream;
33 33 }
34 34  
35   - public void setStreamId(String streamId) {
36   - StreamId = streamId;
  35 + public void setStream(String stream) {
  36 + Stream = stream;
37 37 }
38 38 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
... ... @@ -103,7 +103,7 @@ public class GbStreamServiceImpl implements IGbStreamService {
103 103 deviceChannel.setStatus(gbStream.isStatus()?1:0);
104 104 deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId);
105 105 deviceChannel.setRegisterWay(1);
106   - deviceChannel.setCivilCode(sipConfig.getDomain());
  106 + deviceChannel.setCivilCode(sipConfig.getDomain().substring(0, sipConfig.getDomain().length() - 2));
107 107 deviceChannel.setModel("live");
108 108 deviceChannel.setOwner("wvp-pro");
109 109 deviceChannel.setParental(0);
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
... ... @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONArray;
5 5 import com.alibaba.fastjson.JSONObject;
6 6 import com.genersoft.iot.vmp.common.VideoManagerConstants;
  7 +import com.genersoft.iot.vmp.conf.MediaConfig;
7 8 import com.genersoft.iot.vmp.conf.SipConfig;
8 9 import com.genersoft.iot.vmp.conf.UserSetup;
9 10 import com.genersoft.iot.vmp.gb28181.bean.Device;
... ... @@ -45,8 +46,7 @@ import java.util.*;
45 46 * 媒体服务器节点管理
46 47 */
47 48 @Service
48   -@Order(value=2)
49   -public class MediaServerServiceImpl implements IMediaServerService, CommandLineRunner {
  49 +public class MediaServerServiceImpl implements IMediaServerService {
50 50  
51 51 private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class);
52 52  
... ... @@ -101,9 +101,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
101 101 * 初始化
102 102 */
103 103 @Override
104   - public void run(String... args) throws Exception {
  104 + public void updateVmServer(List<MediaServerItem> mediaServerItemList) {
105 105 logger.info("[缓存初始化] Media Server ");
106   - List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll();
107 106 for (MediaServerItem mediaServerItem : mediaServerItemList) {
108 107 if (StringUtils.isEmpty(mediaServerItem.getId())) {
109 108 continue;
... ... @@ -161,15 +160,16 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
161 160 }
162 161  
163 162 @Override
164   - public void closeRTPServer(Device device, String channelId) {
165   - String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId);
  163 + public void closeRTPServer(Device device, String channelId, String stream) {
  164 + String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId, stream);
  165 + String ssrc = streamSession.getSSRC(device.getDeviceId(), channelId, stream);
166 166 MediaServerItem mediaServerItem = this.getOne(mediaServerId);
167 167 if (mediaServerItem != null) {
168 168 String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
169 169 zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
170   - releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId));
  170 + releaseSsrc(mediaServerItem, ssrc);
171 171 }
172   - streamSession.remove(device.getDeviceId(), channelId);
  172 + streamSession.remove(device.getDeviceId(), channelId, stream);
173 173 }
174 174  
175 175 @Override
... ... @@ -223,7 +223,8 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
223 223 String key = (String) mediaServerKey;
224 224 MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key);
225 225 // 检查状态
226   - if (redisUtil.zScore(onlineKey, mediaServerItem.getId()) != null) {
  226 + Double aDouble = redisUtil.zScore(onlineKey, mediaServerItem.getId());
  227 + if (aDouble != null) {
227 228 mediaServerItem.setStatus(true);
228 229 }
229 230 result.add(mediaServerItem);
... ... @@ -278,6 +279,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
278 279  
279 280 @Override
280 281 public MediaServerItem getDefaultMediaServer() {
  282 +
281 283 return mediaServerMapper.queryDefault();
282 284 }
283 285  
... ... @@ -607,6 +609,11 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
607 609 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + id;
608 610 redisUtil.del(key);
609 611 }
  612 + @Override
  613 + public void deleteDb(String id){
  614 + //同步删除数据库中的数据
  615 + mediaServerMapper.delOne(id);
  616 + }
610 617  
611 618 @Override
612 619 public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) {
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
... ... @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
4 4 import com.alibaba.fastjson.JSONArray;
5 5 import com.alibaba.fastjson.JSONObject;
6 6 import com.genersoft.iot.vmp.common.StreamInfo;
  7 +import com.genersoft.iot.vmp.conf.MediaConfig;
7 8 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
8 9 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
9 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
... ... @@ -26,6 +27,10 @@ public class MediaServiceImpl implements IMediaService {
26 27 @Autowired
27 28 private IMediaServerService mediaServerService;
28 29  
  30 +
  31 + @Autowired
  32 + private MediaConfig mediaConfig;
  33 +
29 34 @Autowired
30 35 private ZLMRESTfulUtils zlmresTfulUtils;
31 36  
... ... @@ -39,15 +44,12 @@ public class MediaServiceImpl implements IMediaService {
39 44 @Override
40 45 public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
41 46 StreamInfo streamInfo = null;
42   -
43   - MediaServerItem mediaInfo;
44 47 if (mediaServerId == null) {
45   - mediaInfo = mediaServerService.getDefaultMediaServer();
46   - }else {
47   - mediaInfo = mediaServerService.getOne(mediaServerId);
  48 + mediaServerId = mediaConfig.getId();
48 49 }
  50 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);;
49 51 if (mediaInfo == null) {
50   - return streamInfo;
  52 + return null;
51 53 }
52 54 JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream);
53 55 if (mediaList != null) {
... ... @@ -72,7 +74,7 @@ public class MediaServiceImpl implements IMediaService {
72 74 @Override
73 75 public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) {
74 76 StreamInfo streamInfoResult = new StreamInfo();
75   - streamInfoResult.setStreamId(stream);
  77 + streamInfoResult.setStream(stream);
76 78 streamInfoResult.setApp(app);
77 79 if (addr == null) {
78 80 addr = mediaInfo.getStreamIp();
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -16,10 +16,10 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
16 16 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
17 17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
18 18 import com.genersoft.iot.vmp.service.IMediaServerService;
  19 +import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
19 20 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
20 21 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21 22 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
22   -import com.genersoft.iot.vmp.utils.redis.RedisUtil;
23 23 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
24 24 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
25 25 import com.genersoft.iot.vmp.service.IMediaService;
... ... @@ -54,9 +54,6 @@ public class PlayServiceImpl implements IPlayService {
54 54 private IRedisCatchStorage redisCatchStorage;
55 55  
56 56 @Autowired
57   - private RedisUtil redis;
58   -
59   - @Autowired
60 57 private DeferredResultHolder resultHolder;
61 58  
62 59 @Autowired
... ... @@ -104,19 +101,21 @@ public class PlayServiceImpl implements IPlayService {
104 101 logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
105 102 WVPResult wvpResult = new WVPResult();
106 103 wvpResult.setCode(-1);
107   - SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
  104 + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, streamInfo.getStream());
108 105 if (dialog != null) {
109 106 wvpResult.setMsg("收流超时,请稍候重试");
110 107 }else {
111 108 wvpResult.setMsg("点播超时,请稍候重试");
112 109 }
  110 +
113 111 msg.setData(wvpResult);
114 112 // 点播超时回复BYE
115   - cmder.streamByeCmd(device.getDeviceId(), channelId);
  113 + cmder.streamByeCmd(device.getDeviceId(), channelId, streamInfo.getStream());
116 114 // 释放rtpserver
117   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
  115 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, streamInfo.getStream());
118 116 // 回复之前所有的点播请求
119 117 resultHolder.invokeAllResult(msg);
  118 + // TODO 释放ssrc
120 119 });
121 120 result.onCompletion(()->{
122 121 // 点播结束时调用截图接口
... ... @@ -154,14 +153,12 @@ public class PlayServiceImpl implements IPlayService {
154 153 }
155 154 });
156 155 if (streamInfo == null) {
157   - SSRCInfo ssrcInfo;
158 156 String streamId = null;
159 157 if (mediaServerItem.isRtpEnable()) {
160 158 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
161 159 }
162 160  
163   - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
164   -
  161 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
165 162 // 发送点播消息
166 163 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
167 164 logger.info("收到订阅消息: " + response.toJSONString());
... ... @@ -173,7 +170,7 @@ public class PlayServiceImpl implements IPlayService {
173 170 WVPResult wvpResult = new WVPResult();
174 171 wvpResult.setCode(-1);
175 172 // 点播返回sip错误
176   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
  173 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
177 174 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
178 175 msg.setData(wvpResult);
179 176 resultHolder.invokeAllResult(msg);
... ... @@ -184,7 +181,7 @@ public class PlayServiceImpl implements IPlayService {
184 181  
185 182 });
186 183 } else {
187   - String streamId = streamInfo.getStreamId();
  184 + String streamId = streamInfo.getStream();
188 185 if (streamId == null) {
189 186 WVPResult wvpResult = new WVPResult();
190 187 wvpResult.setCode(-1);
... ... @@ -213,18 +210,16 @@ public class PlayServiceImpl implements IPlayService {
213 210 // TODO 点播前是否重置状态
214 211 redisCatchStorage.stopPlay(streamInfo);
215 212 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
216   - SSRCInfo ssrcInfo;
217 213 String streamId2 = null;
218 214 if (mediaServerItem.isRtpEnable()) {
219 215 streamId2 = String.format("%s_%s", device.getDeviceId(), channelId);
220 216 }
221   - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);
222   -
  217 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);
223 218 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
224 219 logger.info("收到订阅消息: " + response.toJSONString());
225 220 onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid);
226 221 }, (event) -> {
227   - mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
  222 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
228 223 WVPResult wvpResult = new WVPResult();
229 224 wvpResult.setCode(-1);
230 225 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
... ... @@ -242,12 +237,12 @@ public class PlayServiceImpl implements IPlayService {
242 237 RequestMessage msg = new RequestMessage();
243 238 msg.setId(uuid);
244 239 msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
245   - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
  240 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId);
246 241 if (streamInfo != null) {
247 242 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
248 243 if (deviceChannel != null) {
249   - deviceChannel.setStreamId(streamInfo.getStreamId());
250   - storager.startPlay(deviceId, channelId, streamInfo.getStreamId());
  244 + deviceChannel.setStreamId(streamInfo.getStream());
  245 + storager.startPlay(deviceId, channelId, streamInfo.getStream());
251 246 }
252 247 redisCatchStorage.startPlay(streamInfo);
253 248 msg.setData(JSON.toJSONString(streamInfo));
... ... @@ -284,29 +279,53 @@ public class PlayServiceImpl implements IPlayService {
284 279  
285 280  
286 281 @Override
287   - public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
  282 + public DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback callback) {
  283 + String uuid = UUID.randomUUID().toString();
  284 + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
  285 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(30000L);
  286 + Device device = storager.queryVideoDevice(deviceId);
  287 + if (device == null) {
  288 + result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
  289 + return result;
  290 + }
  291 +
  292 + MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
  293 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);
  294 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result);
288 295 RequestMessage msg = new RequestMessage();
289   - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId);
290 296 msg.setId(uuid);
291   - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
292   - if (streamInfo != null) {
  297 + msg.setKey(key);
  298 + result.onTimeout(()->{
  299 + msg.setData("回放超时");
  300 + callback.call(msg);
  301 + });
  302 + cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
  303 + logger.info("收到订阅消息: " + response.toJSONString());
  304 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
  305 + if (streamInfo == null) {
  306 + logger.warn("设备回放API调用失败!");
  307 + msg.setData("设备回放API调用失败!");
  308 + callback.call(msg);
  309 + return;
  310 + }
293 311 redisCatchStorage.startPlayback(streamInfo);
294 312 msg.setData(JSON.toJSONString(streamInfo));
295   - resultHolder.invokeResult(msg);
296   - } else {
297   - logger.warn("设备回放API调用失败!");
298   - msg.setData("设备回放API调用失败!");
299   - resultHolder.invokeResult(msg);
300   - }
  313 + callback.call(msg);
  314 + }, event -> {
  315 + msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
  316 + callback.call(msg);
  317 + });
  318 + return result;
301 319 }
302 320  
303 321  
  322 +
304 323 @Override
305 324 public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) {
306 325 RequestMessage msg = new RequestMessage();
307 326 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);
308 327 msg.setId(uuid);
309   - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid);
  328 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
310 329 if (streamInfo != null) {
311 330 redisCatchStorage.startDownload(streamInfo);
312 331 msg.setData(JSON.toJSONString(streamInfo));
... ... @@ -319,7 +338,7 @@ public class PlayServiceImpl implements IPlayService {
319 338 }
320 339  
321 340  
322   - public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
  341 + public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) {
323 342 String streamId = resonse.getString("stream");
324 343 JSONArray tracks = resonse.getJSONArray("tracks");
325 344 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java
... ... @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.service.impl;
3 3 import com.alibaba.fastjson.JSON;
4 4 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
5 5 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
6 8 import org.springframework.beans.factory.annotation.Autowired;
7 9 import org.springframework.data.redis.connection.Message;
8 10 import org.springframework.data.redis.connection.MessageListener;
... ... @@ -11,11 +13,14 @@ import org.springframework.stereotype.Component;
11 13 @Component
12 14 public class RedisGPSMsgListener implements MessageListener {
13 15  
  16 + private final static Logger logger = LoggerFactory.getLogger(RedisGPSMsgListener.class);
  17 +
14 18 @Autowired
15 19 private IRedisCatchStorage redisCatchStorage;
16 20  
17 21 @Override
18 22 public void onMessage(Message message, byte[] bytes) {
  23 + logger.debug("收到来自REDIS的GPS通知: {}", new String(message.getBody()));
19 24 GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
20 25 redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
21 26 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
... ... @@ -132,7 +132,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
132 132 }else {
133 133 streamLive = true;
134 134 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
135   - mediaInfo, param.getApp(), param.getStream(), null);
  135 + mediaInfo, param.getApp(), param.getStream(), null, null);
136 136 wvpResult.setData(streamInfo);
137 137  
138 138 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
... ... @@ -377,7 +377,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
377 377  
378 378 if (streamPushItemsForPlatform.size() > 0) {
379 379 List<StreamPushItem> streamPushItemListFroPlatform = new ArrayList<>();
380   - Map<String, List<StreamPushItem>> platformForEvent = new HashMap<>();
  380 + Map<String, List<GbStream>> platformForEvent = new HashMap<>();
381 381 // 遍历存储结果,查找app+Stream->platformId+catalogId的对应关系,然后执行批量写入
382 382 for (StreamPushItem streamPushItem : streamPushItemsForPlatform) {
383 383 List<String[]> platFormInfoList = streamPushItemsForAll.get(streamPushItem.getApp() + streamPushItem.getStream());
... ... @@ -390,16 +390,17 @@ public class StreamPushServiceImpl implements IStreamPushService {
390 390 // 数组 platFormInfoArray 0 为平台ID。 1为目录ID
391 391 streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]);
392 392  
393   - List<StreamPushItem> streamPushItemsInPlatform = platformForEvent.get(streamPushItem.getPlatformId());
394   - if (streamPushItemsInPlatform == null) {
395   - streamPushItemsInPlatform = new ArrayList<>();
396   - platformForEvent.put(platFormInfoArray[0], streamPushItemsInPlatform);
  393 + List<GbStream> gbStreamList = platformForEvent.get(streamPushItem.getPlatformId());
  394 + if (gbStreamList == null) {
  395 + gbStreamList = new ArrayList<>();
  396 + platformForEvent.put(platFormInfoArray[0], gbStreamList);
397 397 }
398 398 // 为发送通知整理数据
  399 + streamPushItemForPlatform.setName(streamPushItem.getName());
399 400 streamPushItemForPlatform.setApp(streamPushItem.getApp());
400 401 streamPushItemForPlatform.setStream(streamPushItem.getStream());
401 402 streamPushItemForPlatform.setGbId(streamPushItem.getGbId());
402   - streamPushItemsInPlatform.add(streamPushItemForPlatform);
  403 + gbStreamList.add(streamPushItemForPlatform);
403 404 }
404 405 if (platFormInfoArray.length > 1) {
405 406 streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]);
... ... @@ -416,7 +417,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
416 417 // 发送通知
417 418 for (String platformId : platformForEvent.keySet()) {
418 419 eventPublisher.catalogEventPublishForStream(
419   - platformId, platformForEvent.get(platformId).toArray(new GbStream[0]), CatalogEvent.ADD);
  420 + platformId, platformForEvent.get(platformId), CatalogEvent.ADD);
420 421 }
421 422 }
422 423 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
7 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 8 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
9 9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  10 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 11 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
11 12  
12 13 import java.util.List;
... ... @@ -220,4 +221,5 @@ public interface IRedisCatchStorage {
220 221 void addMemInfo(double memInfo);
221 222  
222 223 void addNetInfo(Map<String, String> networkInterfaces);
  224 +
223 225 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
... ... @@ -87,26 +87,27 @@ public interface DeviceChannelMapper {
87 87 void startPlay(String deviceId, String channelId, String streamId);
88 88  
89 89 @Select(value = {" <script>" +
90   - "SELECT dc.channelId, "+
91   - "dc.deviceId, " +
92   - "dc.name, " +
93   - "de.manufacturer, " +
94   - "de.hostAddress, " +
95   - "dc.subCount, " +
96   - "pgc.platformId as platformId, " +
97   - "pgc.catalogId as catalogId " +
98   - "FROM device_channel dc " +
99   - "LEFT JOIN device de ON dc.deviceId = de.deviceId " +
100   - "LEFT JOIN platform_gb_channel pgc on de.deviceId = pgc.deviceId and pgc.channelId = dc.channelId " +
101   - "LEFT JOIN device_channel dc2 ON dc2.deviceId = de.deviceId AND dc2.parentId = dc.channelId " +
  90 + "SELECT " +
  91 + " dc.id,\n" +
  92 + " dc.channelId,\n" +
  93 + " dc.deviceId,\n" +
  94 + " dc.name,\n" +
  95 + " de.manufacturer,\n" +
  96 + " de.hostAddress,\n" +
  97 + " dc.subCount,\n" +
  98 + " pgc.platformId as platformId,\n" +
  99 + " pgc.catalogId as catalogId " +
  100 + " FROM device_channel dc " +
  101 + " LEFT JOIN device de ON dc.deviceId = de.deviceId " +
  102 + " LEFT JOIN platform_gb_channel pgc on pgc.deviceChannelId = dc.id " +
102 103 " WHERE 1=1 " +
103 104 " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " +
104 105 " <if test='online == true' > AND dc.status=1</if> " +
105 106 " <if test='online == false' > AND dc.status=0</if> " +
106   - " <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc2.channelId is not null</if> " +
107   - " <if test='hasSubChannel!= null and hasSubChannel == false' > AND dc2.channelId is null</if> " +
108   - " <if test='catalogId == null ' > AND ((pgc.platformId IS NULL AND pgc.catalogId IS NULL) or (pgc.platformId != #{platformId}))</if> " +
109   - " <if test='catalogId != null ' > AND pgc.platformId =#{platformId} AND pgc.catalogId = #{catalogId}</if> " +
  107 + " <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc.subCount > 0</if> " +
  108 + " <if test='hasSubChannel!= null and hasSubChannel == false' > AND dc.subCount == 0</if> " +
  109 + " <if test='catalogId == null ' > AND dc.id not in (select deviceChannelId from platform_gb_channel where platformId=#{platformId} ) </if> " +
  110 + " <if test='catalogId != null ' > AND pgc.platformId = #{platformId} and pgc.catalogId=#{catalogId} </if> " +
110 111 " ORDER BY dc.deviceId, dc.channelId ASC" +
111 112 " </script>"})
112 113 List<ChannelReduce> queryChannelListInAll(String query, Boolean online, Boolean hasSubChannel, String platformId, String catalogId);
... ... @@ -196,8 +197,8 @@ public interface DeviceChannelMapper {
196 197 List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId);
197 198  
198 199 @Select(" SELECT\n" +
  200 + " id,\n" +
199 201 " channelId,\n" +
200   - " channelId as id,\n" +
201 202 " deviceId,\n" +
202 203 " parentId,\n" +
203 204 " status,\n" +
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
... ... @@ -74,7 +74,7 @@ public interface DeviceMapper {
74 74 "<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" +
75 75 "<if test=\"expires != null\">, expires=${expires}</if>" +
76 76 "<if test=\"charset != null\">, charset='${charset}'</if>" +
77   - "<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=#{subscribeCycleForCatalog}</if>" +
  77 + "<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=${subscribeCycleForCatalog}</if>" +
78 78 "WHERE deviceId='${deviceId}'"+
79 79 " </script>"})
80 80 int update(Device device);
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
... ... @@ -19,6 +19,7 @@ public interface GbStreamMapper {
19 19 "('${app}', '${stream}', '${gbId}', '${name}', " +
20 20 "'${longitude}', '${latitude}', '${streamType}', " +
21 21 "'${mediaServerId}', ${status}, ${createStamp})")
  22 + @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
22 23 int add(GbStream gbStream);
23 24  
24 25 @Update("UPDATE gb_stream " +
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
... ... @@ -21,27 +21,31 @@ public interface PlatformChannelMapper {
21 21 * 查询列表里已经关联的
22 22 */
23 23 @Select("<script> "+
24   - "SELECT deviceAndChannelId FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceAndChannelId in" +
25   - "<foreach collection='deviceAndChannelIds' open='(' item='id_' separator=',' close=')'> '${id_}'</foreach> ORDER BY deviceAndChannelId ASC" +
  24 + "SELECT deviceChannelId FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" +
  25 + "<foreach collection='channelReduces' open='(' item='item' separator=',' close=')'> '${item.id}'</foreach>" +
26 26 "</script>")
27   - List<String> findChannelRelatedPlatform(String platformId, List<String> deviceAndChannelIds);
  27 + List<Integer> findChannelRelatedPlatform(String platformId, List<ChannelReduce> channelReduces);
28 28  
29 29 @Insert("<script> "+
30   - "INSERT INTO platform_gb_channel (channelId, deviceId, platformId, deviceAndChannelId, catalogId) VALUES" +
  30 + "INSERT INTO platform_gb_channel (platformId, deviceChannelId, catalogId) VALUES" +
31 31 "<foreach collection='channelReducesToAdd' item='item' separator=','>" +
32   - " ('${item.channelId}','${item.deviceId}', '${platformId}', '${item.deviceId}_${item.channelId}' , '${item.catalogId}' )" +
  32 + " ('${platformId}', '${item.id}' , '${item.catalogId}' )" +
33 33 "</foreach>" +
34 34 "</script>")
35 35 int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd);
36 36  
37 37 @Delete("<script> "+
38   - "DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceAndChannelId in" +
39   - "<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.deviceId}_${item.channelId}'</foreach>" +
  38 + "DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" +
  39 + "<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.id}'</foreach>" +
40 40 "</script>")
41 41 int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel);
42 42  
43 43 @Delete("<script> "+
44   - "DELETE FROM platform_gb_channel WHERE deviceId='${deviceId}' " +
  44 + "DELETE FROM platform_gb_channel WHERE deviceChannelId in " +
  45 + "( select temp.deviceChannelId from " +
  46 + "(select pgc.deviceChannelId from platform_gb_channel pgc " +
  47 + "left join device_channel dc on dc.id = pgc.deviceChannelId where dc.deviceId =#{deviceId} " +
  48 + ") temp)" +
45 49 "</script>")
46 50 int delChannelForDeviceId(String deviceId);
47 51  
... ... @@ -50,16 +54,19 @@ public interface PlatformChannelMapper {
50 54 "</script>")
51 55 int cleanChannelForGB(String platformId);
52 56  
53   - @Select("SELECT * FROM device_channel WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE " +
54   - "platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'")
  57 + @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}' and pgc.platformId='${platformId}'")
55 58 DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
56 59  
57   - @Select("select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " +
58   - "from device_channel dc left join platform_gb_channel pgc on dc.deviceId = pgc.deviceId and dc.channelId = pgc.channelId " +
59   - "where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}")
  60 + @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " +
  61 + " from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId " +
  62 + " where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}")
60 63 List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId);
61 64  
62   - @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE platformId='${platformId}' AND channelId='${channelId}')")
  65 + @Select("select d.*\n" +
  66 + "from platform_gb_channel pgc\n" +
  67 + " left join device_channel dc on dc.id = pgc.deviceChannelId\n" +
  68 + " left join device d on dc.deviceId = d.deviceId\n" +
  69 + "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}")
63 70 Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
64 71  
65 72 @Delete("<script> "+
... ... @@ -79,8 +86,10 @@ public interface PlatformChannelMapper {
79 86 "parent_platform pp " +
80 87 "left join platform_gb_channel pgc on " +
81 88 "pp.serverGBId = pgc.platformId " +
  89 + "left join device_channel dc on " +
  90 + "dc.id = pgc.deviceChannelId " +
82 91 "WHERE " +
83   - "pgc.channelId = #{channelId} and pp.status = true " +
  92 + "dc.channelId = #{channelId} and pp.status = true " +
84 93 "AND pp.serverGBId IN" +
85 94 "<foreach collection='platforms' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
86 95 "</script> ")
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
... ... @@ -19,6 +19,7 @@ public interface StreamProxyMapper {
19 19  
20 20 @Update("UPDATE stream_proxy " +
21 21 "SET type=#{type}, " +
  22 + "name=#{name}," +
22 23 "app=#{app}," +
23 24 "name=#{name}," +
24 25 "stream=#{stream}," +
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
... ... @@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.storager.dao;
3 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4 4 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
5 5 import org.apache.ibatis.annotations.*;
6   -import org.omg.PortableInterceptor.INACTIVE;
  6 +// import org.omg.PortableInterceptor.INACTIVE;
7 7 import org.springframework.stereotype.Repository;
8 8  
9 9 import java.util.Collection;
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
10 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 11 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
12 12 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  13 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
13 14 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
14 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15 16 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
... ... @@ -91,7 +92,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
91 92 */
92 93 @Override
93 94 public boolean startPlay(StreamInfo stream) {
94   - return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()),
  95 + return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(),
  96 + stream.getStream(), stream.getDeviceID(), stream.getChannelId()),
95 97 stream);
96 98 }
97 99  
... ... @@ -105,7 +107,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
105 107 if (streamInfo == null) return false;
106 108 return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
107 109 userSetup.getServerId(),
108   - streamInfo.getStreamId(),
  110 + streamInfo.getStream(),
109 111 streamInfo.getDeviceID(),
110 112 streamInfo.getChannelId()));
111 113 }
... ... @@ -119,7 +121,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
119 121 return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s",
120 122 VideoManagerConstants.PLAYER_PREFIX,
121 123 userSetup.getServerId(),
122   - streamInfo.getStreamId(),
  124 + streamInfo.getStream(),
123 125 streamInfo.getDeviceID(),
124 126 streamInfo.getChannelId()));
125 127 }
... ... @@ -165,14 +167,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
165 167  
166 168 @Override
167 169 public boolean startPlayback(StreamInfo stream) {
168   - return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),stream.getStreamId(),
169   - stream.getDeviceID(), stream.getChannelId()), stream);
  170 + return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  171 + userSetup.getServerId(), stream.getStream(), stream.getDeviceID(), stream.getChannelId()), stream);
170 172 }
171 173  
172 174 @Override
173 175 public boolean startDownload(StreamInfo streamInfo) {
174   - return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),streamInfo.getStreamId(),
175   - streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
  176 + return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),
  177 + streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
176 178 }
177 179  
178 180 @Override
... ... @@ -186,7 +188,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
186 188 }
187 189 return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
188 190 userSetup.getServerId(),
189   - streamInfo.getStreamId(),
  191 + streamInfo.getStream(),
190 192 streamInfo.getDeviceID(),
191 193 streamInfo.getChannelId()));
192 194 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
1 1 package com.genersoft.iot.vmp.storager.impl;
2 2  
  3 +import com.genersoft.iot.vmp.common.StreamInfo;
3 4 import com.genersoft.iot.vmp.conf.SipConfig;
4 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 6 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
... ... @@ -156,7 +157,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
156 157 public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
157 158 String channelId = channel.getChannelId();
158 159 channel.setDeviceId(deviceId);
159   - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId()));
  160 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  161 + if (streamInfo != null) {
  162 + channel.setStreamId(streamInfo.getStream());
  163 + }
160 164 String now = this.format.format(System.currentTimeMillis());
161 165 channel.setUpdateTime(now);
162 166 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
... ... @@ -178,7 +182,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
178 182 if (channelList.size() == 0) {
179 183 for (DeviceChannel channel : channels) {
180 184 channel.setDeviceId(deviceId);
181   - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId()));
  185 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
  186 + if (streamInfo != null) {
  187 + channel.setStreamId(streamInfo.getStream());
  188 + }
182 189 String now = this.format.format(System.currentTimeMillis());
183 190 channel.setUpdateTime(now);
184 191 channel.setCreateTime(now);
... ... @@ -189,9 +196,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
189 196 channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
190 197 }
191 198 for (DeviceChannel channel : channels) {
192   - String channelId = channel.getChannelId();
193 199 channel.setDeviceId(deviceId);
194   - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId()));
  200 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
  201 + if (streamInfo != null) {
  202 + channel.setStreamId(streamInfo.getStream());
  203 + }
195 204 String now = this.format.format(System.currentTimeMillis());
196 205 channel.setUpdateTime(now);
197 206 if (channelsInStore.get(channel.getChannelId()) != null) {
... ... @@ -607,19 +616,19 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
607 616 @Override
608 617 public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
609 618  
610   - Map<String, ChannelReduce> deviceAndChannels = new HashMap<>();
  619 + Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
611 620 for (ChannelReduce channelReduce : channelReduces) {
612 621 channelReduce.setCatalogId(catalogId);
613   - deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce);
  622 + deviceAndChannels.put(channelReduce.getId(), channelReduce);
614 623 }
615   - List<String> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
  624 + List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
616 625 // 查询当前已经存在的
617   - List<String> relatedPlatformchannels = platformChannelMapper.findChannelRelatedPlatform(platformId, deviceAndChannelList);
618   - if (relatedPlatformchannels != null) {
619   - deviceAndChannelList.removeAll(relatedPlatformchannels);
  626 + List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
  627 + if (deviceAndChannelList != null) {
  628 + deviceAndChannelList.removeAll(channelIds);
620 629 }
621   - for (String relatedPlatformchannel : relatedPlatformchannels) {
622   - deviceAndChannels.remove(relatedPlatformchannel);
  630 + for (Integer channelId : channelIds) {
  631 + deviceAndChannels.remove(channelId);
623 632 }
624 633 List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
625 634 // 对剩下的数据进行存储
... ...
src/main/java/com/genersoft/iot/vmp/utils/node/BaseNode.java
... ... @@ -18,7 +18,7 @@ public class BaseNode&lt;T&gt; implements INode&lt;T&gt; {
18 18 /**
19 19 * 主键ID
20 20 */
21   - protected String id;
  21 + protected int id;
22 22  
23 23 /**
24 24 * 父节点ID
... ...
src/main/java/com/genersoft/iot/vmp/utils/node/ForestNode.java
... ... @@ -19,7 +19,7 @@ public class ForestNode extends BaseNode&lt;ForestNode&gt; {
19 19 */
20 20 private Object content;
21 21  
22   - public ForestNode(String id, String parentId, Object content) {
  22 + public ForestNode(int id, String parentId, Object content) {
23 23 this.id = id;
24 24 this.parentId = parentId;
25 25 this.content = content;
... ...
src/main/java/com/genersoft/iot/vmp/utils/node/ForestNodeManager.java
... ... @@ -17,12 +17,12 @@ public class ForestNodeManager&lt;T extends INode&lt;T&gt;&gt; {
17 17 /**
18 18 * 森林的所有节点
19 19 */
20   - private final ImmutableMap<String, T> nodeMap;
  20 + private final ImmutableMap<Integer, T> nodeMap;
21 21  
22 22 /**
23 23 * 森林的父节点ID
24 24 */
25   - private final Map<String, Object> parentIdMap = Maps.newHashMap();
  25 + private final Map<Integer, Object> parentIdMap = Maps.newHashMap();
26 26  
27 27 public ForestNodeManager(List<T> nodes) {
28 28 nodeMap = Maps.uniqueIndex(nodes, INode::getId);
... ... @@ -46,7 +46,7 @@ public class ForestNodeManager&lt;T extends INode&lt;T&gt;&gt; {
46 46 *
47 47 * @param parentId 父节点ID
48 48 */
49   - public void addParentId(String parentId) {
  49 + public void addParentId(int parentId) {
50 50 parentIdMap.put(parentId, "");
51 51 }
52 52  
... ...
src/main/java/com/genersoft/iot/vmp/utils/node/INode.java
... ... @@ -14,7 +14,7 @@ public interface INode&lt;T&gt; extends Serializable {
14 14 *
15 15 * @return String
16 16 */
17   - String getId();
  17 + int getId();
18 18  
19 19 /**
20 20 * 父主键
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/bean/DeviceChannelTree.java
... ... @@ -19,7 +19,7 @@ public class DeviceChannelTree extends DeviceChannel implements INode&lt;DeviceChan
19 19 /**
20 20 * 主键ID
21 21 */
22   - private String id;
  22 + private int id;
23 23  
24 24 /**
25 25 * 父节点ID
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -204,10 +204,7 @@ public class DeviceQuery {
204 204 if (logger.isDebugEnabled()) {
205 205 logger.debug("设备信息删除API调用,deviceId:" + deviceId);
206 206 }
207   -
208   - if (offLineDetector.isOnline(deviceId)) {
209   - return new ResponseEntity<String>("不允许删除在线设备!", HttpStatus.NOT_ACCEPTABLE);
210   - }
  207 +
211 208 // 清除redis记录
212 209 boolean isSuccess = storager.delete(deviceId);
213 210 if (isSuccess) {
... ... @@ -319,20 +316,20 @@ public class DeviceQuery {
319 316 if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset());
320 317 if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId());
321 318  
322   - if ((deviceInStore.getSubscribeCycleForCatalog() <=0 && device.getSubscribeCycleForCatalog() > 0)
323   - || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
324   - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
325   - // 开启订阅
326   - deviceService.addCatalogSubscribe(deviceInStore);
327   - }
328   - if (deviceInStore.getSubscribeCycleForCatalog() > 0 && device.getSubscribeCycleForCatalog() <= 0) {
329   - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog());
330   - // 取消订阅
331   - deviceService.removeCatalogSubscribe(deviceInStore);
  319 + if (device.getSubscribeCycleForCatalog() > 0) {
  320 + if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
  321 + // 开启订阅
  322 + deviceService.addCatalogSubscribe(deviceInStore);
  323 + }
  324 + }else if (device.getSubscribeCycleForCatalog() == 0) {
  325 + if (deviceInStore.getSubscribeCycleForCatalog() != 0) {
  326 + // 取消订阅
  327 + deviceService.removeCatalogSubscribe(deviceInStore);
  328 + }
332 329 }
333 330  
334   - storager.updateDevice(deviceInStore);
335   - cmder.deviceInfoQuery(deviceInStore);
  331 + storager.updateDevice(device);
  332 + cmder.deviceInfoQuery(device);
336 333 }
337 334 WVPResult<String> result = new WVPResult<>();
338 335 result.setCode(0);
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
1 1 package com.genersoft.iot.vmp.vmanager.gb28181.media;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.service.IMediaServerService;
4 5 import com.genersoft.iot.vmp.service.IStreamPushService;
5 6 import com.genersoft.iot.vmp.service.IMediaService;
6 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
... ... @@ -9,6 +10,7 @@ import io.swagger.annotations.Api;
9 10 import io.swagger.annotations.ApiImplicitParam;
10 11 import io.swagger.annotations.ApiImplicitParams;
11 12 import io.swagger.annotations.ApiOperation;
  13 +import org.apache.commons.lang3.StringUtils;
12 14 import org.slf4j.Logger;
13 15 import org.slf4j.LoggerFactory;
14 16 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -33,6 +35,9 @@ public class MediaController {
33 35 @Autowired
34 36 private IMediaService mediaService;
35 37  
  38 + @Autowired
  39 + private IMediaServerService mediaServerService;
  40 +
36 41  
37 42 /**
38 43 * 根据应用名和流id获取播放地址
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
... ... @@ -149,8 +149,16 @@ public class PlatformController {
149 149 if (updateResult) {
150 150 // 保存时启用就发送注册
151 151 if (parentPlatform.isEnable()) {
152   - // 只要保存就发送注册
153   - commanderForPlatform.register(parentPlatform, null, null);
  152 + if (parentPlatformOld.isStatus()) {
  153 + commanderForPlatform.unregister(parentPlatformOld, null, eventResult -> {
  154 + // 只要保存就发送注册
  155 + commanderForPlatform.register(parentPlatform, null, null);
  156 + });
  157 + }else {
  158 + // 只要保存就发送注册
  159 + commanderForPlatform.register(parentPlatform, null, null);
  160 + }
  161 +
154 162 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销
155 163 commanderForPlatform.unregister(parentPlatform, null, null);
156 164 }
... ... @@ -203,10 +211,21 @@ public class PlatformController {
203 211 if (updateResult) {
204 212 // 保存时启用就发送注册
205 213 if (parentPlatform.isEnable()) {
206   - // 只要保存就发送注册
207   - commanderForPlatform.register(parentPlatform, null, null);
  214 + if (parentPlatformOld.isStatus()) {
  215 + commanderForPlatform.unregister(parentPlatformOld, null, null);
  216 + try {
  217 + Thread.sleep(500);
  218 + } catch (InterruptedException e) {
  219 + e.printStackTrace();
  220 + }
  221 + // 只要保存就发送注册
  222 + commanderForPlatform.register(parentPlatform, null, null);
  223 + }else {
  224 + // 只要保存就发送注册
  225 + commanderForPlatform.register(parentPlatform, null, null);
  226 + }
208 227 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销
209   - commanderForPlatform.unregister(parentPlatform, null, null);
  228 + commanderForPlatform.unregister(parentPlatformOld, null, null);
210 229 }
211 230 wvpResult.setCode(0);
212 231 wvpResult.setMsg("success");
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java
1 1 package com.genersoft.iot.vmp.vmanager.gb28181.platform.bean;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  4 +
3 5 /**
4 6 * 精简的channel信息展示,主要是选择通道的时候展示列表使用
5 7 */
6 8 public class ChannelReduce {
7 9  
8 10 /**
  11 + * deviceChannel的数据库自增ID
  12 + */
  13 + private int id;
  14 +
  15 + /**
9 16 * 通道id
10 17 */
11 18 private String channelId;
... ... @@ -45,6 +52,13 @@ public class ChannelReduce {
45 52 */
46 53 private String catalogId;
47 54  
  55 + public int getId() {
  56 + return id;
  57 + }
  58 +
  59 + public void setId(int id) {
  60 + this.id = id;
  61 + }
48 62  
49 63 public String getChannelId() {
50 64 return channelId;
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
... ... @@ -110,26 +110,26 @@ public class PlayController {
110 110 String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId;
111 111 resultHolder.put(key, uuid, result);
112 112 Device device = storager.queryVideoDevice(deviceId);
113   - cmder.streamByeCmd(deviceId, channelId, (event) -> {
114   - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
115   - if (streamInfo == null) {
116   - RequestMessage msg = new RequestMessage();
117   - msg.setId(uuid);
118   - msg.setKey(key);
119   - msg.setData("点播未找到");
120   - resultHolder.invokeAllResult(msg);
121   - storager.stopPlay(deviceId, channelId);
122   - }else {
123   - redisCatchStorage.stopPlay(streamInfo);
124   - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
125   - RequestMessage msg = new RequestMessage();
126   - msg.setId(uuid);
127   - msg.setKey(key);
128   - //Response response = event.getResponse();
129   - msg.setData(String.format("success"));
130   - resultHolder.invokeAllResult(msg);
131   - }
132   - mediaServerService.closeRTPServer(device, channelId);
  113 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  114 + if (streamInfo == null) {
  115 + RequestMessage msg = new RequestMessage();
  116 + msg.setId(uuid);
  117 + msg.setKey(key);
  118 + msg.setData("点播未找到");
  119 + resultHolder.invokeAllResult(msg);
  120 + storager.stopPlay(deviceId, channelId);
  121 + return result;
  122 + }
  123 + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), (event) -> {
  124 + redisCatchStorage.stopPlay(streamInfo);
  125 + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
  126 + RequestMessage msg = new RequestMessage();
  127 + msg.setId(uuid);
  128 + msg.setKey(key);
  129 + //Response response = event.getResponse();
  130 + msg.setData(String.format("success"));
  131 + resultHolder.invokeAllResult(msg);
  132 + mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
133 133 });
134 134  
135 135 if (deviceId != null || channelId != null) {
... ... @@ -329,7 +329,7 @@ public class PlayController {
329 329 jsonObject.put("deviceId", transaction.getDeviceId());
330 330 jsonObject.put("channelId", transaction.getChannelId());
331 331 jsonObject.put("ssrc", transaction.getSsrc());
332   - jsonObject.put("streamId", transaction.getStreamId());
  332 + jsonObject.put("streamId", transaction.getStream());
333 333 objects.add(jsonObject);
334 334 }
335 335  
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
... ... @@ -96,7 +96,7 @@ public class DownloadController {
96 96 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
97 97 if (streamInfo != null) {
98 98 // 停止之前的下载
99   - cmder.streamByeCmd(deviceId, channelId);
  99 + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream());
100 100 }
101 101  
102 102 MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
... ... @@ -114,7 +114,7 @@ public class DownloadController {
114 114  
115 115 cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
116 116 logger.info("收到订阅消息: " + response.toJSONString());
117   - playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString());
  117 + playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid);
118 118 }, event -> {
119 119 RequestMessage msg = new RequestMessage();
120 120 msg.setId(uuid);
... ... @@ -130,11 +130,12 @@ public class DownloadController {
130 130 @ApiImplicitParams({
131 131 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
132 132 @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
  133 + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class),
133 134 })
134   - @GetMapping("/stop/{deviceId}/{channelId}")
135   - public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) {
  135 + @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
  136 + public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
136 137  
137   - cmder.streamByeCmd(deviceId, channelId);
  138 + cmder.streamByeCmd(deviceId, channelId, stream);
138 139  
139 140 if (logger.isDebugEnabled()) {
140 141 logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId));
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
18 18 import org.springframework.beans.factory.annotation.Autowired;
19 19 import org.springframework.http.HttpStatus;
20 20 import org.springframework.http.ResponseEntity;
  21 +import org.springframework.util.StringUtils;
21 22 import org.springframework.web.bind.annotation.CrossOrigin;
22 23 import org.springframework.web.bind.annotation.GetMapping;
23 24 import org.springframework.web.bind.annotation.PathVariable;
... ... @@ -75,52 +76,8 @@ public class PlaybackController {
75 76 if (logger.isDebugEnabled()) {
76 77 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
77 78 }
78   - String uuid = UUID.randomUUID().toString();
79   - String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
80   - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
81   - Device device = storager.queryVideoDevice(deviceId);
82   - if (device == null) {
83   - result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
84   - return result;
85   - }
86   - MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
87   - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);
88   -
89   - // 超时处理
90   - result.onTimeout(()->{
91   - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
92   - RequestMessage msg = new RequestMessage();
93   - msg.setId(uuid);
94   - msg.setKey(key);
95   - msg.setData("Timeout");
96   - resultHolder.invokeResult(msg);
97   - });
98   -
99   - StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
100   - if (streamInfo != null) {
101   - // 停止之前的回放
102   - cmder.streamByeCmd(deviceId, channelId);
103   - }
104   - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result);
105   -
106   - if (newMediaServerItem == null) {
107   - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
108   - RequestMessage msg = new RequestMessage();
109   - msg.setId(uuid);
110   - msg.setKey(key);
111   - msg.setData("Timeout");
112   - resultHolder.invokeResult(msg);
113   - return result;
114   - }
115 79  
116   - cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
117   - logger.info("收到订阅消息: " + response.toJSONString());
118   - playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
119   - }, event -> {
120   - RequestMessage msg = new RequestMessage();
121   - msg.setId(uuid);
122   - msg.setKey(key);
123   - msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
  80 + DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, msg->{
124 81 resultHolder.invokeResult(msg);
125 82 });
126 83  
... ... @@ -131,24 +88,31 @@ public class PlaybackController {
131 88 @ApiImplicitParams({
132 89 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
133 90 @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
  91 + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class),
134 92 })
135   - @GetMapping("/stop/{deviceId}/{channelId}")
136   - public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) {
  93 + @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
  94 + public ResponseEntity<String> playStop(
  95 + @PathVariable String deviceId,
  96 + @PathVariable String channelId,
  97 + @PathVariable String stream) {
137 98  
138   - cmder.streamByeCmd(deviceId, channelId);
  99 + cmder.streamByeCmd(deviceId, channelId, stream);
139 100  
140 101 if (logger.isDebugEnabled()) {
141 102 logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId));
142 103 }
  104 + if (StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(channelId) || StringUtils.isEmpty(stream)) {
  105 + return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
  106 + }
143 107  
144 108 if (deviceId != null && channelId != null) {
145 109 JSONObject json = new JSONObject();
146 110 json.put("deviceId", deviceId);
147 111 json.put("channelId", channelId);
148   - return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
  112 + return new ResponseEntity<>(json.toString(), HttpStatus.OK);
149 113 } else {
150 114 logger.warn("设备录像回放停止API调用失败!");
151   - return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
  115 + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
152 116 }
153 117 }
154 118  
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
... ... @@ -158,6 +158,7 @@ public class ServerController {
158 158 public WVPResult<String> deleteMediaServer(@RequestParam String id){
159 159 if (mediaServerService.getOne(id) != null) {
160 160 mediaServerService.delete(id);
  161 + mediaServerService.deleteDb(id);
161 162 }else {
162 163 WVPResult<String> result = new WVPResult<>();
163 164 result.setCode(-1);
... ...
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
... ... @@ -103,7 +103,7 @@ public class ApiStreamController {
103 103 PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{
104 104 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code);
105 105 JSONObject result = new JSONObject();
106   - result.put("StreamID", streamInfo.getStreamId());
  106 + result.put("StreamID", streamInfo.getStream());
107 107 result.put("DeviceID", device.getDeviceId());
108 108 result.put("ChannelID", code);
109 109 result.put("ChannelName", deviceChannel.getName());
... ... @@ -177,7 +177,7 @@ public class ApiStreamController {
177 177 result.put("error","未找到流信息");
178 178 return result;
179 179 }
180   - cmder.streamByeCmd(serial, code);
  180 + cmder.streamByeCmd(serial, code, streamInfo.getStream());
181 181 redisCatchStorage.stopPlay(streamInfo);
182 182 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
183 183 return null;
... ...
src/main/resources/all-application.yml
... ... @@ -30,24 +30,44 @@ spring:
30 30 poolMaxWait: 5
31 31 # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
32 32 datasource:
33   - # 使用mysql 打开23-28行注释, 删除29-36行
34   - # name: wvp
35   - # url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true
36   - # username:
37   - # password:
38   - # type: com.alibaba.druid.pool.DruidDataSource
39   - # driver-class-name: com.mysql.cj.jdbc.Driver
40   - name: eiot
41   - url: jdbc:sqlite::resource:wvp.sqlite
42   - username:
43   - password:
44 33 type: com.alibaba.druid.pool.DruidDataSource
45   - driver-class-name: org.sqlite.JDBC
46   - journal_mode: WAL
47   - synchronous: NORMAL
48   - transaction_mode: IMMEDIATE
49   - max-active: 1
50   - min-idle: 1
  34 + driver-class-name: com.mysql.cj.jdbc.Driver
  35 + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false
  36 + username: root
  37 + password: root123
  38 + druid:
  39 + initialSize: 10 # 连接池初始化连接数
  40 + maxActive: 200 # 连接池最大连接数
  41 + minIdle: 5 # 连接池最小空闲连接数
  42 + maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
  43 + keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。
  44 + validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
  45 + testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
  46 + testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
  47 + testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
  48 + poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小
  49 + timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
  50 + minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒
  51 + filters: stat,wall,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j, 防御sql注入的filter:wall
  52 + useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据
  53 + # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
  54 + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000
  55 + #stat-view-servlet.url-pattern: /admin/druid/*
  56 +
  57 +# druid管理监控页面的一些配置
  58 +rj-druid-manage:
  59 + allow: # 访问druid监控页面的IP白名单
  60 + deny: 192.168.1.100 # 访问druid监控页面IP黑名单
  61 + loginUsername: rjAdmin # 访问druid监控页面账号
  62 + loginPassword: rj@2022 # 访问druid监控页面密码
  63 +
  64 +#mybatis:
  65 +# configuration:
  66 +# # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
  67 +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  68 +# # 返回类型为Map,显示null对应的字段
  69 +# call-setters-on-nulls: true
  70 +## [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
51 71  
52 72 # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
53 73 server:
... ... @@ -136,15 +156,8 @@ media:
136 156  
137 157 # [可选] 日志配置, 一般不需要改
138 158 logging:
139   - file:
140   - name: logs/wvp.log
141   - max-history: 30
142   - max-size: 10MB
143   - total-size-cap: 300MB
144   - level:
145   - com.genersoft.iot: debug
146   - com.genersoft.iot.vmp.storager.dao: info
147   - com.genersoft.iot.vmp.gb28181: debug
  159 + config: classpath:logback-spring-local.xml
  160 +
148 161 # [根据业务需求配置]
149 162 user-settings:
150 163 # [可选] 服务ID,不写则为000000
... ... @@ -173,7 +186,7 @@ user-settings:
173 186 # 是否将日志存储进数据库
174 187 logInDatebase: true
175 188 # 第三方匹配,用于从stream钟获取有效信息
176   - thirdPartyGBIdReg: [\s\S]*
  189 + thirdPartyGBIdReg: "[\\s\\S]*"
177 190  
178 191 # 在线文档: swagger-ui(生产环境建议关闭)
179 192 swagger-ui:
... ...
src/main/resources/application-dev.yml
... ... @@ -16,24 +16,41 @@ spring:
16 16 password:
17 17 # [可选] 超时时间
18 18 timeout: 10000
19   - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
  19 + # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
  20 + # mysql数据源
20 21 datasource:
21   - # 使用mysql 打开23-28行注释, 删除29-36行
22   - name: wvp
23   - url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false
24   - username:
25   - password:
26 22 type: com.alibaba.druid.pool.DruidDataSource
27 23 driver-class-name: com.mysql.cj.jdbc.Driver
  24 + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false
  25 + username: root
  26 + password: root123
  27 + druid:
  28 + initialSize: 10 # 连接池初始化连接数
  29 + maxActive: 200 # 连接池最大连接数
  30 + minIdle: 5 # 连接池最小空闲连接数
  31 + maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。
  32 + keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。
  33 + validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
  34 + testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
  35 + testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
  36 + testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
  37 + poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小
  38 + timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒
  39 + minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒
  40 + filters: stat,wall,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j, 防御sql注入的filter:wall
  41 + useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据
  42 + # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
  43 + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000
  44 + #stat-view-servlet.url-pattern: /admin/druid/*
28 45  
29   -# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
  46 +#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
30 47 server:
31 48 port: 18080
32 49  
33 50 # 作为28181服务器的配置
34 51 sip:
35 52 # [必须修改] 本机的IP
36   - ip:
  53 + ip: 192.168.118.70
37 54 # [可选] 28181服务监听的端口
38 55 port: 5060
39 56 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
... ... @@ -48,10 +65,9 @@ sip:
48 65  
49 66 #zlm 默认服务器配置
50 67 media:
51   - # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId
52   - id:
  68 + id: FQ3TF8yT83wh5Wvz
53 69 # [必须修改] zlm服务器的内网IP
54   - ip:
  70 + ip: 192.168.118.70
55 71 # [必须修改] zlm服务器的http.port
56 72 http-port: 80
57 73 # [可选] zlm服务器的hook.admin_params=secret
... ... @@ -68,25 +84,7 @@ media:
68 84 record-assist-port: 18081
69 85 # [可选] 日志配置, 一般不需要改
70 86 logging:
71   - file:
72   - name: logs/wvp.log
73   - max-history: 30
74   - max-size: 10MB
75   - total-size-cap: 300MB
76   - level:
77   - com.genersoft.iot: debug
78   - com.genersoft.iot.vmp.storager.dao: info
79   - com.genersoft.iot.vmp.gb28181: info
80   -
81   -# [根据业务需求配置]
82   -user-settings:
83   - # 推流直播是否录制
84   - record-push-live: true
85   - auto-apply-play: false
86   -
87   -# 在线文档: swagger-ui(生产环境建议关闭)
88   -swagger-ui:
89   - enabled: true
  87 + config: classpath:logback-spring-local.xml
90 88  
91 89 # 版本信息, 不需修改
92 90 version:
... ...
src/main/resources/application-docker.yml
... ... @@ -69,16 +69,9 @@ media:
69 69 sdp-ip: ${sip.ip}
70 70 stream-ip: ${sip.ip}
71 71 # [可选] 日志配置, 一般不需要改
  72 +# [可选] 日志配置, 一般不需要改
72 73 logging:
73   - file:
74   - name: logs/wvp.log
75   - max-history: 30
76   - max-size: 10MB
77   - total-size-cap: 300MB
78   - level:
79   - com.genersoft.iot: debug
80   - com.genersoft.iot.vmp.storager.dao: info
81   - com.genersoft.iot.vmp.gb28181: info
  74 + config: classpath:logback-spring-local.xml
82 75  
83 76 # [根据业务需求配置]
84 77 user-settings:
... ...
src/main/resources/application.yml
1 1 spring:
2 2 profiles:
3   - active: local
  3 + active: dev
... ...
src/main/resources/logback-spring-local.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<configuration debug="false">
  3 + <!--定义日志文件的存储地址 -->
  4 + <springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/>
  5 + <property name="LOG_HOME" value="logs/${spring.application.name}" />
  6 +
  7 + <!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />-->
  8 + <!-- 控制台输出 -->
  9 + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  10 + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  11 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  12 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
  13 + </encoder>
  14 + </appender>
  15 +
  16 + <!-- 按照每天生成日志文件 DEBUG以上级别的日志,仅用于测试环境,正式环境为info级别以上的日志-->
  17 + <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
  18 +
  19 + <!-- 文件路径 -->
  20 + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  21 + <!--历史日志文件输出的文件名 -->
  22 + <FileNamePattern>${LOG_HOME}/wvp-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
  23 + <!--日志文件保留天数 -->
  24 + <MaxHistory>30</MaxHistory>
  25 + <maxFileSize>20MB</maxFileSize>
  26 + </rollingPolicy>
  27 + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  28 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  29 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
  30 + </encoder>
  31 + <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  32 + <!--与ThresholdFilter的区别,允许onmatch-->
  33 + <!--设置日志级别 接收info级别的日志-->
  34 + <level>DEBUG</level>
  35 + </filter>
  36 + </appender>
  37 +
  38 + <!-- 生成 error格式日志开始 -->
  39 + <appender name="RollingFileError" class="ch.qos.logback.core.rolling.RollingFileAppender">
  40 +
  41 + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  42 + <!--历史日志文件输出的文件名 -->
  43 + <FileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
  44 + <!--日志文件保留天数 -->
  45 + <MaxHistory>30</MaxHistory>
  46 + <maxFileSize>20MB</maxFileSize>
  47 + </rollingPolicy>
  48 + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  49 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  50 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
  51 + </encoder>
  52 + <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  53 + <!--设置日志级别,过滤掉info日志,只输入error日志-->
  54 + <level>WARN</level>
  55 + <!-- <onMatch>ACCEPT</onMatch> &lt;!&ndash; 用过滤器,只接受ERROR级别的日志信息,其余全部过滤掉 &ndash;&gt;-->
  56 + <!-- <onMismatch>DENY</onMismatch>-->
  57 + </filter>
  58 + </appender>
  59 +
  60 + <!-- 生成 druid日志追加 -->
  61 + <appender name="druidSqlRollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
  62 + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  63 + <!--历史日志文件输出的文件名 -->
  64 + <FileNamePattern>${LOG_HOME}/druid-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
  65 + <!--日志文件保留天数 -->
  66 + <MaxHistory>30</MaxHistory>
  67 + <maxFileSize>50MB</maxFileSize>
  68 + </rollingPolicy>
  69 + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
  70 + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
  71 + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
  72 + </encoder>
  73 + </appender>
  74 +
  75 +
  76 + <!-- 日志输出级别 -->
  77 + <root level="INFO">
  78 + <appender-ref ref="STDOUT" />
  79 + <appender-ref ref="RollingFile" />
  80 + <appender-ref ref="RollingFileError" />
  81 + </root>
  82 +
  83 + <logger name="com.genersoft.iot.vmp.storager.dao" level="INFO">
  84 + <appender-ref ref="STDOUT"/>
  85 + </logger>
  86 + <logger name="com.genersoft.iot.vmp.gb28181" level="INFO">
  87 + <appender-ref ref="STDOUT"/>
  88 + </logger>
  89 +
  90 + <!--记录druid-sql的记录-->
  91 + <logger name="druid.sql.Statement" level="debug" additivity="true">
  92 + <!--AppenderRef ref="Console"/-->
  93 + <!-- <appender-ref ref="RollingFile"/>-->
  94 + <appender-ref ref="RollingFileError"/>
  95 + <appender-ref ref="druidSqlRollingFile"/>
  96 + </logger>
  97 +</configuration>
0 98 \ No newline at end of file
... ...
web_src/src/components/DeviceList.vue
... ... @@ -55,14 +55,14 @@
55 55 <el-table-column prop="createTime" label="创建时间" align="center" width="140">
56 56 </el-table-column>
57 57  
58   - <el-table-column label="操作" width="360" align="center" fixed="right">
  58 + <el-table-column label="操作" width="450" align="center" fixed="right">
59 59 <template slot-scope="scope">
60 60 <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>
61 61 <el-button-group>
62 62 <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button>
63 63 <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>
64 64 <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>
65   - <el-button size="mini" icon="el-icon-delete" type="danger" v-if="scope.row.online==0" @click="deleteDevice(scope.row)">删除</el-button>
  65 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button>
66 66 </el-button-group>
67 67 </template>
68 68 </el-table-column>
... ... @@ -165,15 +165,29 @@
165 165  
166 166 },
167 167 deleteDevice: function(row) {
168   - let that = this;
169   - this.$axios({
170   - method: 'delete',
171   - url:`/api/device/query/devices/${row.deviceId}/delete`
172   - }).then((res)=>{
173   - this.getDeviceList();
174   - }).catch((error) =>{
175   - console.log(error);
176   - });
  168 + let msg = "确定删除此设备?"
  169 + if (row.online !== 0) {
  170 + msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>"
  171 + }
  172 + this.$confirm(msg, '提示', {
  173 + dangerouslyUseHTMLString : true,
  174 + confirmButtonText: '确定',
  175 + cancelButtonText: '取消',
  176 + center: true,
  177 + type: 'warning'
  178 + }).then(() => {
  179 + this.$axios({
  180 + method: 'delete',
  181 + url:`/api/device/query/devices/${row.deviceId}/delete`
  182 + }).then((res)=>{
  183 + this.getDeviceList();
  184 + }).catch((error) =>{
  185 + console.log(error);
  186 + });
  187 + }).catch(() => {
  188 +
  189 + });
  190 +
177 191  
178 192 },
179 193 showChannelList: function(row) {
... ...
web_src/src/components/channelList.vue
... ... @@ -28,9 +28,7 @@
28 28 <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
29 29 <!--设备列表-->
30 30 <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%">
31   - <el-table-column prop="channelId" label="通道编号" width="210">
32   - </el-table-column>
33   - <el-table-column prop="deviceId" label="设备编号" width="210">
  31 + <el-table-column prop="channelId" label="通道编号" width="200">
34 32 </el-table-column>
35 33 <el-table-column prop="name" label="通道名称">
36 34 </el-table-column>
... ...
web_src/src/components/dialog/changePassword.vue
... ... @@ -75,7 +75,10 @@ export default {
75 75 isLoging: false,
76 76 rules: {
77 77 oldPassword: [{ required: true, validator: validatePass0, trigger: "blur" }],
78   - newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }],
  78 + newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
  79 + pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
  80 + message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
  81 + },],
79 82 confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
80 83 },
81 84 };
... ...
web_src/src/components/dialog/devicePlayer.vue
... ... @@ -307,7 +307,7 @@ export default {
307 307 this.isLoging = false;
308 308 // this.videoUrl = streamInfo.rtc;
309 309 this.videoUrl = this.getUrlByStreamInfo(streamInfo);
310   - this.streamId = streamInfo.streamId;
  310 + this.streamId = streamInfo.stream;
311 311 this.app = streamInfo.app;
312 312 this.mediaServerId = streamInfo.mediaServerId;
313 313 this.playFromStreamInfo(false, streamInfo)
... ... @@ -485,8 +485,9 @@ export default {
485 485 }).then(function (res) {
486 486 var streamInfo = res.data;
487 487 that.app = streamInfo.app;
488   - that.streamId = streamInfo.streamId;
  488 + that.streamId = streamInfo.stream;
489 489 that.mediaServerId = streamInfo.mediaServerId;
  490 + that.ssrc = streamInfo.ssrc;
490 491 that.videoUrl = that.getUrlByStreamInfo(streamInfo);
491 492 that.recordPlay = true;
492 493 });
... ... @@ -497,7 +498,7 @@ export default {
497 498 this.videoUrl = '';
498 499 this.$axios({
499 500 method: 'get',
500   - url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId
  501 + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
501 502 }).then(function (res) {
502 503 if (callback) callback()
503 504 });
... ... @@ -517,7 +518,7 @@ export default {
517 518 }).then(function (res) {
518 519 var streamInfo = res.data;
519 520 that.app = streamInfo.app;
520   - that.streamId = streamInfo.streamId;
  521 + that.streamId = streamInfo.stream;
521 522 that.mediaServerId = streamInfo.mediaServerId;
522 523 that.videoUrl = that.getUrlByStreamInfo(streamInfo);
523 524 that.recordPlay = true;
... ... @@ -529,7 +530,7 @@ export default {
529 530 this.videoUrl = '';
530 531 this.$axios({
531 532 method: 'get',
532   - url: '/api/download/stop/' + this.deviceId + "/" + this.channelId
  533 + url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
533 534 }).then(function (res) {
534 535 if (callback) callback()
535 536 });
... ... @@ -539,8 +540,6 @@ export default {
539 540 let that = this;
540 541 this.$axios({
541 542 method: 'post',
542   - // url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown +
543   - // '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'
544 543 url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
545 544 }).then(function (res) {});
546 545 },
... ...