Commit 9a96597e666fa32caefcfff5246b4cb722e9b1bc

Authored by 648540858
2 parents c32ba1de 674ab18c

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

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
Showing 84 changed files with 2088 additions and 651 deletions

Too many changes to show.

To preserve performance only 84 of 116 files are displayed.

libs/jdbc-x86/bcprov-jdk15on-1.70.jar 0 → 100644
No preview for this file type
libs/jdbc-x86/kingbase8-8.6.0.jar 0 → 100644
No preview for this file type
libs/jdbc-x86/kingbase8-8.6.0.jre6.jar 0 → 100644
No preview for this file type
libs/jdbc-x86/kingbase8-8.6.0.jre7.jar 0 → 100644
No preview for this file type
libs/jdbc-x86/postgresql-42.2.9.jar 0 → 100644
No preview for this file type
libs/jdbc-x86/postgresql-42.2.9.jre6.jar 0 → 100644
No preview for this file type
libs/jdbc-x86/postgresql-42.2.9.jre7.jar 0 → 100644
No preview for this file type
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 11
12 <groupId>com.genersoft</groupId> 12 <groupId>com.genersoft</groupId>
13 <artifactId>wvp-pro</artifactId> 13 <artifactId>wvp-pro</artifactId>
14 - <version>2.6.9</version> 14 + <version>2.7.0</version>
15 <name>web video platform</name> 15 <name>web video platform</name>
16 <description>国标28181视频平台</description> 16 <description>国标28181视频平台</description>
17 <packaging>${project.packaging}</packaging> 17 <packaging>${project.packaging}</packaging>
@@ -143,17 +143,24 @@ @@ -143,17 +143,24 @@
143 <version>42.5.1</version> 143 <version>42.5.1</version>
144 </dependency> 144 </dependency>
145 145
146 - <!-- kingbase人大金仓 -->  
147 - <!-- 手动下载驱动后安装 -->  
148 - <!-- mvn install:install-file -Dfile=/home/lin/soft/kingbase/jdbc-aarch/kingbase8-8.6.0.jar -DgroupId=com.kingbase -DartifactId=kingbase8  
149 - -Dversion=8.6.0 -Dpackaging=jar -->  
150 - <dependency>  
151 - <groupId>com.kingbase</groupId>  
152 - <artifactId>kingbase8</artifactId>  
153 - <version>8.6.0</version>  
154 - <scope>system</scope>  
155 - <systemPath>${basedir}/libs/jdbc-aarch/kingbase8-8.6.0.jar</systemPath>  
156 - </dependency> 146 + <!-- kingbase人大金仓 -->
  147 + <!-- 手动下载驱动后安装 -->
  148 + <!-- mvn install:install-file -Dfile=/home/lin/soft/kingbase/jdbc-aarch/kingbase8-8.6.0.jar -DgroupId=com.kingbase -DartifactId=kingbase8 -Dversion=8.6.0 -Dpackaging=jar
  149 + -->
  150 + <dependency>
  151 + <groupId>com.kingbase</groupId>
  152 + <artifactId>kingbase8</artifactId>
  153 + <version>8.6.0</version>
  154 + <scope>system</scope>
  155 + <systemPath>${basedir}/libs/jdbc-aarch/kingbase8-8.6.0.jar</systemPath>
  156 + </dependency>
  157 + <dependency>
  158 + <groupId>com.kingbase</groupId>
  159 + <artifactId>kingbase8</artifactId>
  160 + <version>8.6.0</version>
  161 + <scope>system</scope>
  162 + <systemPath>${basedir}/libs/jdbc-x86/kingbase8-8.6.0.jar</systemPath>
  163 + </dependency>
157 164
158 <!--Mybatis分页插件 --> 165 <!--Mybatis分页插件 -->
159 <dependency> 166 <dependency>
@@ -163,21 +170,16 @@ @@ -163,21 +170,16 @@
163 </dependency> 170 </dependency>
164 171
165 <!--在线文档 --> 172 <!--在线文档 -->
  173 + <!--在线文档 -->
166 <dependency> 174 <dependency>
167 <groupId>org.springdoc</groupId> 175 <groupId>org.springdoc</groupId>
168 <artifactId>springdoc-openapi-ui</artifactId> 176 <artifactId>springdoc-openapi-ui</artifactId>
169 - <version>1.7.0</version>  
170 - <exclusions>  
171 - <exclusion>  
172 - <groupId>org.yaml</groupId>  
173 - <artifactId>snakeyaml</artifactId>  
174 - </exclusion>  
175 - </exclusions> 177 + <version>1.6.10</version>
176 </dependency> 178 </dependency>
177 <dependency> 179 <dependency>
178 - <groupId>org.yaml</groupId>  
179 - <artifactId>snakeyaml</artifactId>  
180 - <version>2.2</version> 180 + <groupId>org.springdoc</groupId>
  181 + <artifactId>springdoc-openapi-security</artifactId>
  182 + <version>1.6.10</version>
181 </dependency> 183 </dependency>
182 184
183 <dependency> 185 <dependency>
sql/2.6.9更新.sql deleted 100644 → 0
1 -alter table wvp_device_channel  
2 - change stream_id stream_id varying(255)  
3 -  
4 -alter table wvp_platform  
5 - add auto_push_channel bool default false  
6 -  
7 -alter table wvp_stream_proxy  
8 - add stream_key character varying(255)  
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
1 package com.genersoft.iot.vmp.common; 1 package com.genersoft.iot.vmp.common;
2 2
  3 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
3 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
4 5
5 import java.io.Serializable; 6 import java.io.Serializable;
@@ -76,6 +77,8 @@ public class StreamInfo implements Serializable, Cloneable{ @@ -76,6 +77,8 @@ public class StreamInfo implements Serializable, Cloneable{
76 private String endTime; 77 private String endTime;
77 @Schema(description = "进度(录像下载使用)") 78 @Schema(description = "进度(录像下载使用)")
78 private double progress; 79 private double progress;
  80 + @Schema(description = "文件下载地址(录像下载使用)")
  81 + private DownloadFileInfo downLoadFilePath;
79 82
80 @Schema(description = "是否暂停(录像回放使用)") 83 @Schema(description = "是否暂停(录像回放使用)")
81 private boolean pause; 84 private boolean pause;
@@ -605,5 +608,11 @@ public class StreamInfo implements Serializable, Cloneable{ @@ -605,5 +608,11 @@ public class StreamInfo implements Serializable, Cloneable{
605 this.subStream = subStream; 608 this.subStream = subStream;
606 } 609 }
607 610
  611 + public DownloadFileInfo getDownLoadFilePath() {
  612 + return downLoadFilePath;
  613 + }
608 614
  615 + public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) {
  616 + this.downLoadFilePath = downLoadFilePath;
  617 + }
609 } 618 }
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -53,7 +53,7 @@ public class VideoManagerConstants { @@ -53,7 +53,7 @@ public class VideoManagerConstants {
53 53
54 public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_"; 54 public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
55 55
56 - public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_"; 56 + public static final String MEDIA_STREAM_AUTHORITY = "VMP_MEDIA_STREAM_AUTHORITY_";
57 57
58 public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_"; 58 public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
59 59
@@ -71,6 +71,7 @@ public class VideoManagerConstants { @@ -71,6 +71,7 @@ public class VideoManagerConstants {
71 public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_"; 71 public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_";
72 72
73 public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_"; 73 public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_";
  74 + public static final String PUSH_STREAM_LIST = "VMP_PUSH_STREAM_LIST_";
74 75
75 76
76 77
src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf;
  2 +
  3 +
  4 +import com.alibaba.fastjson2.JSONObject;
  5 +import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
  6 +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  7 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  8 +import com.genersoft.iot.vmp.service.IMediaServerService;
  9 +import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
  10 +import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
  11 +import com.genersoft.iot.vmp.vmanager.cloudRecord.CloudRecordController;
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.scheduling.annotation.Scheduled;
  16 +import org.springframework.stereotype.Component;
  17 +
  18 +import java.io.File;
  19 +import java.util.ArrayList;
  20 +import java.util.Calendar;
  21 +import java.util.Date;
  22 +import java.util.List;
  23 +
  24 +/**
  25 + * 录像文件定时删除
  26 + */
  27 +@Component
  28 +public class CloudRecordTimer {
  29 +
  30 + private final static Logger logger = LoggerFactory.getLogger(CloudRecordTimer.class);
  31 +
  32 + @Autowired
  33 + private IMediaServerService mediaServerService;
  34 +
  35 + @Autowired
  36 + private CloudRecordServiceMapper cloudRecordServiceMapper;
  37 +
  38 + @Autowired
  39 + private ZLMRESTfulUtils zlmresTfulUtils;
  40 +
  41 + /**
  42 + * 定时查询待删除的录像文件
  43 + */
  44 +// @Scheduled(fixedRate = 10000) //每五秒执行一次,方便测试
  45 + @Scheduled(cron = "0 0 0 * * ?") //每天的0点执行
  46 + public void execute(){
  47 + logger.info("[录像文件定时清理] 开始清理过期录像文件");
  48 + // 获取配置了assist的流媒体节点
  49 + List<MediaServerItem> mediaServerItemList = mediaServerService.getAllOnline();
  50 + if (mediaServerItemList.isEmpty()) {
  51 + return;
  52 + }
  53 + long result = 0;
  54 + for (MediaServerItem mediaServerItem : mediaServerItemList) {
  55 +
  56 + Calendar lastCalendar = Calendar.getInstance();
  57 + if (mediaServerItem.getRecordDay() > 0) {
  58 + lastCalendar.setTime(new Date());
  59 + // 获取保存的最后截至日[期,因为每个节点都有一个日期,也就是支持每个节点设置不同的保存日期,
  60 + lastCalendar.add(Calendar.DAY_OF_MONTH, -mediaServerItem.getRecordDay());
  61 + Long lastDate = lastCalendar.getTimeInMillis();
  62 +
  63 + // 获取到截至日期之前的录像文件列表,文件列表满足未被收藏和保持的。这两个字段目前共能一致,
  64 + // 为我自己业务系统相关的代码,大家使用的时候直接使用收藏(collect)这一个类型即可
  65 + List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.queryRecordListForDelete(lastDate, mediaServerItem.getId());
  66 + if (cloudRecordItemList.isEmpty()) {
  67 + continue;
  68 + }
  69 + // TODO 后续可以删除空了的过期日期文件夹
  70 + for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
  71 + String date = new File(cloudRecordItem.getFilePath()).getParentFile().getName();
  72 + JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(),
  73 + cloudRecordItem.getStream(), date, cloudRecordItem.getFileName());
  74 + if (jsonObject.getInteger("code") != 0) {
  75 + logger.warn("[录像文件定时清理] 删除磁盘文件错误: {}:{}", cloudRecordItem.getFilePath(), jsonObject);
  76 + }
  77 + }
  78 + result += cloudRecordServiceMapper.deleteList(cloudRecordItemList);
  79 + }
  80 + }
  81 + logger.info("[录像文件定时清理] 共清理{}个过期录像文件", result);
  82 + }
  83 +}
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -81,6 +81,12 @@ public class MediaConfig{ @@ -81,6 +81,12 @@ public class MediaConfig{
81 @Value("${media.record-assist-port:0}") 81 @Value("${media.record-assist-port:0}")
82 private Integer recordAssistPort = 0; 82 private Integer recordAssistPort = 0;
83 83
  84 + @Value("${media.record-day:7}")
  85 + private Integer recordDay;
  86 +
  87 + @Value("${media.record-path:}")
  88 + private String recordPath;
  89 +
84 public String getId() { 90 public String getId() {
85 return id; 91 return id;
86 } 92 }
@@ -212,13 +218,32 @@ public class MediaConfig{ @@ -212,13 +218,32 @@ public class MediaConfig{
212 mediaServerItem.setSendRtpPortRange(rtpSendPortRange); 218 mediaServerItem.setSendRtpPortRange(rtpSendPortRange);
213 mediaServerItem.setRecordAssistPort(recordAssistPort); 219 mediaServerItem.setRecordAssistPort(recordAssistPort);
214 mediaServerItem.setHookAliveInterval(30.00f); 220 mediaServerItem.setHookAliveInterval(30.00f);
215 - 221 + mediaServerItem.setRecordDay(recordDay);
  222 + if (recordPath != null) {
  223 + mediaServerItem.setRecordPath(recordPath);
  224 + }
216 mediaServerItem.setCreateTime(DateUtil.getNow()); 225 mediaServerItem.setCreateTime(DateUtil.getNow());
217 mediaServerItem.setUpdateTime(DateUtil.getNow()); 226 mediaServerItem.setUpdateTime(DateUtil.getNow());
218 227
219 return mediaServerItem; 228 return mediaServerItem;
220 } 229 }
221 230
  231 + public Integer getRecordDay() {
  232 + return recordDay;
  233 + }
  234 +
  235 + public void setRecordDay(Integer recordDay) {
  236 + this.recordDay = recordDay;
  237 + }
  238 +
  239 + public String getRecordPath() {
  240 + return recordPath;
  241 + }
  242 +
  243 + public void setRecordPath(String recordPath) {
  244 + this.recordPath = recordPath;
  245 + }
  246 +
222 public String getRtpSendPortRange() { 247 public String getRtpSendPortRange() {
223 return rtpSendPortRange; 248 return rtpSendPortRange;
224 } 249 }
src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
  3 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
  4 +import io.swagger.v3.oas.models.Components;
3 import io.swagger.v3.oas.models.OpenAPI; 5 import io.swagger.v3.oas.models.OpenAPI;
4 import io.swagger.v3.oas.models.info.Contact; 6 import io.swagger.v3.oas.models.info.Contact;
5 import io.swagger.v3.oas.models.info.Info; 7 import io.swagger.v3.oas.models.info.Info;
6 import io.swagger.v3.oas.models.info.License; 8 import io.swagger.v3.oas.models.info.License;
  9 +import io.swagger.v3.oas.models.security.SecurityScheme;
7 import org.springframework.core.annotation.Order; 10 import org.springframework.core.annotation.Order;
8 import org.springdoc.core.GroupedOpenApi; 11 import org.springdoc.core.GroupedOpenApi;
9 import org.springframework.beans.factory.annotation.Value; 12 import org.springframework.beans.factory.annotation.Value;
@@ -26,10 +29,14 @@ public class SpringDocConfig { @@ -26,10 +29,14 @@ public class SpringDocConfig {
26 contact.setName("pan"); 29 contact.setName("pan");
27 contact.setEmail("648540858@qq.com"); 30 contact.setEmail("648540858@qq.com");
28 return new OpenAPI() 31 return new OpenAPI()
  32 + .components(new Components()
  33 + .addSecuritySchemes(JwtUtils.HEADER, new SecurityScheme()
  34 + .type(SecurityScheme.Type.HTTP)
  35 + .bearerFormat("JWT")))
29 .info(new Info().title("WVP-PRO 接口文档") 36 .info(new Info().title("WVP-PRO 接口文档")
30 .contact(contact) 37 .contact(contact)
31 .description("开箱即用的28181协议视频平台") 38 .description("开箱即用的28181协议视频平台")
32 - .version("v2.0") 39 + .version("v3.1.0")
33 .license(new License().name("Apache 2.0").url("http://springdoc.org"))); 40 .license(new License().name("Apache 2.0").url("http://springdoc.org")));
34 } 41 }
35 42
src/main/java/com/genersoft/iot/vmp/conf/SystemInfoTimerTask.java
@@ -39,4 +39,6 @@ public class SystemInfoTimerTask { @@ -39,4 +39,6 @@ public class SystemInfoTimerTask {
39 } 39 }
40 40
41 } 41 }
  42 +
  43 +
42 } 44 }
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
@@ -56,8 +56,6 @@ public class UserSetting { @@ -56,8 +56,6 @@ public class UserSetting {
56 56
57 private String serverId = "000000"; 57 private String serverId = "000000";
58 58
59 - private String recordPath = null;  
60 -  
61 private String thirdPartyGBIdReg = "[\\s\\S]*"; 59 private String thirdPartyGBIdReg = "[\\s\\S]*";
62 60
63 private String broadcastForPlatform = "UDP"; 61 private String broadcastForPlatform = "UDP";
@@ -262,14 +260,6 @@ public class UserSetting { @@ -262,14 +260,6 @@ public class UserSetting {
262 this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify; 260 this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify;
263 } 261 }
264 262
265 - public String getRecordPath() {  
266 - return recordPath;  
267 - }  
268 -  
269 - public void setRecordPath(String recordPath) {  
270 - this.recordPath = recordPath;  
271 - }  
272 -  
273 public int getMaxNotifyCountQueue() { 263 public int getMaxNotifyCountQueue() {
274 return maxNotifyCountQueue; 264 return maxNotifyCountQueue;
275 } 265 }
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java
@@ -28,7 +28,7 @@ public class JwtUtils implements InitializingBean { @@ -28,7 +28,7 @@ public class JwtUtils implements InitializingBean {
28 28
29 private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); 29 private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
30 30
31 - private static final String HEADER = "access-token"; 31 + public static final String HEADER = "access-token";
32 32
33 private static final String AUDIENCE = "Audience"; 33 private static final String AUDIENCE = "Audience";
34 34
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
@@ -68,6 +68,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -68,6 +68,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
68 matchers.add("/"); 68 matchers.add("/");
69 matchers.add("/#/**"); 69 matchers.add("/#/**");
70 matchers.add("/static/**"); 70 matchers.add("/static/**");
  71 + matchers.add("/swagger-ui.html");
  72 + matchers.add("/swagger-ui/");
71 matchers.add("/index.html"); 73 matchers.add("/index.html");
72 matchers.add("/doc.html"); 74 matchers.add("/doc.html");
73 matchers.add("/webjars/**"); 75 matchers.add("/webjars/**");
@@ -77,7 +79,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -77,7 +79,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
77 matchers.add("/api/device/query/snap/**"); 79 matchers.add("/api/device/query/snap/**");
78 matchers.add("/record_proxy/*/**"); 80 matchers.add("/record_proxy/*/**");
79 matchers.add("/api/emit"); 81 matchers.add("/api/emit");
80 - matchers.addAll(userSetting.getInterfaceAuthenticationExcludes()); 82 + matchers.add("/favicon.ico");
81 // 可以直接访问的静态数据 83 // 可以直接访问的静态数据
82 web.ignoring().antMatchers(matchers.toArray(new String[0])); 84 web.ignoring().antMatchers(matchers.toArray(new String[0]));
83 } 85 }
@@ -114,7 +116,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -114,7 +116,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
114 .authorizeRequests() 116 .authorizeRequests()
115 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() 117 .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
116 .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll() 118 .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
117 - .antMatchers("/api/user/login", "/index/hook/**").permitAll() 119 + .antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html").permitAll()
118 .anyRequest().authenticated() 120 .anyRequest().authenticated()
119 // 异常处理器 121 // 异常处理器
120 .and() 122 .and()
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -148,13 +148,13 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -148,13 +148,13 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
148 if (event.getDeviceChannels() != null) { 148 if (event.getDeviceChannels() != null) {
149 deviceChannelList.addAll(event.getDeviceChannels()); 149 deviceChannelList.addAll(event.getDeviceChannels());
150 } 150 }
151 - if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ 151 + if (event.getGbStreams() != null && !event.getGbStreams().isEmpty()){
152 for (GbStream gbStream : event.getGbStreams()) { 152 for (GbStream gbStream : event.getGbStreams()) {
153 deviceChannelList.add( 153 deviceChannelList.add(
154 gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), parentPlatform)); 154 gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), parentPlatform));
155 } 155 }
156 } 156 }
157 - if (deviceChannelList.size() > 0) { 157 + if (!deviceChannelList.isEmpty()) {
158 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); 158 logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
159 try { 159 try {
160 sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null); 160 sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
@@ -163,10 +163,10 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -163,10 +163,10 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
163 logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); 163 logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
164 } 164 }
165 } 165 }
166 - }else if (parentPlatformMap.keySet().size() > 0) { 166 + }else if (!parentPlatformMap.keySet().isEmpty()) {
167 for (String gbId : parentPlatformMap.keySet()) { 167 for (String gbId : parentPlatformMap.keySet()) {
168 List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId); 168 List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
169 - if (parentPlatforms != null && parentPlatforms.size() > 0) { 169 + if (parentPlatforms != null && !parentPlatforms.isEmpty()) {
170 for (ParentPlatform platform : parentPlatforms) { 170 for (ParentPlatform platform : parentPlatforms) {
171 SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId()); 171 SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
172 if (subscribeInfo == null) { 172 if (subscribeInfo == null) {
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -75,6 +75,33 @@ public class VideoStreamSessionManager { @@ -75,6 +75,33 @@ public class VideoStreamSessionManager {
75 return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0)); 75 return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
76 } 76 }
77 77
  78 + public SsrcTransaction getSsrcTransactionByCallId(String callId){
  79 +
  80 + if (ObjectUtils.isEmpty(callId)) {
  81 + return null;
  82 + }
  83 + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_" + callId+ "_*";
  84 + List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
  85 + if (!scanResult.isEmpty()) {
  86 + return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
  87 + }else {
  88 + key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_play_*";
  89 + scanResult = RedisUtil.scan(redisTemplate, key);
  90 + if (scanResult.isEmpty()) {
  91 + return null;
  92 + }
  93 + for (Object keyObj : scanResult) {
  94 + SsrcTransaction ssrcTransaction = (SsrcTransaction)redisTemplate.opsForValue().get(keyObj);
  95 + if (ssrcTransaction.getSipTransactionInfo() != null &&
  96 + ssrcTransaction.getSipTransactionInfo().getCallId().equals(callId)) {
  97 + return ssrcTransaction;
  98 + }
  99 + }
  100 + return null;
  101 + }
  102 +
  103 + }
  104 +
78 public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){ 105 public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
79 if (ObjectUtils.isEmpty(deviceId)) { 106 if (ObjectUtils.isEmpty(deviceId)) {
80 deviceId ="*"; 107 deviceId ="*";
@@ -117,8 +144,19 @@ public class VideoStreamSessionManager { @@ -117,8 +144,19 @@ public class VideoStreamSessionManager {
117 } 144 }
118 145
119 public void remove(String deviceId, String channelId, String stream) { 146 public void remove(String deviceId, String channelId, String stream) {
120 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);  
121 - if (ssrcTransaction == null) { 147 + List<SsrcTransaction> ssrcTransactionList = getSsrcTransactionForAll(deviceId, channelId, null, stream);
  148 + if (ssrcTransactionList == null || ssrcTransactionList.isEmpty()) {
  149 + return;
  150 + }
  151 + for (SsrcTransaction ssrcTransaction : ssrcTransactionList) {
  152 + redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
  153 + + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
  154 + }
  155 + }
  156 +
  157 + public void removeByCallId(String deviceId, String channelId, String callId) {
  158 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
  159 + if (ssrcTransaction == null ) {
122 return; 160 return;
123 } 161 }
124 redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" 162 redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
@@ -129,4 +129,6 @@ public class SipRunner implements CommandLineRunner { @@ -129,4 +129,6 @@ public class SipRunner implements CommandLineRunner {
129 } 129 }
130 } 130 }
131 } 131 }
  132 +
  133 +
132 } 134 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -164,6 +164,7 @@ public class SIPRequestHeaderProvider { @@ -164,6 +164,7 @@ public class SIPRequestHeaderProvider {
164 Request request = null; 164 Request request = null;
165 //请求行 165 //请求行
166 SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress()); 166 SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(channelId, device.getHostAddress());
  167 +// SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
167 // via 168 // via
168 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); 169 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
169 ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag()); 170 ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
@@ -174,6 +175,7 @@ public class SIPRequestHeaderProvider { @@ -174,6 +175,7 @@ public class SIPRequestHeaderProvider {
174 FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag()); 175 FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
175 //to 176 //to
176 SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress()); 177 SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(channelId,device.getHostAddress());
  178 +// SipURI toSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(),device.getHostAddress());
177 Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI); 179 Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipURI);
178 ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag()); 180 ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
179 181
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -40,6 +40,8 @@ import javax.sip.SipFactory; @@ -40,6 +40,8 @@ import javax.sip.SipFactory;
40 import javax.sip.header.CallIdHeader; 40 import javax.sip.header.CallIdHeader;
41 import javax.sip.message.Request; 41 import javax.sip.message.Request;
42 import java.text.ParseException; 42 import java.text.ParseException;
  43 +import java.util.ArrayList;
  44 +import java.util.List;
43 45
44 /** 46 /**
45 * @description:设备能力接口,用于定义设备的控制、查询能力 47 * @description:设备能力接口,用于定义设备的控制、查询能力
@@ -677,22 +679,21 @@ public class SIPCommander implements ISIPCommander { @@ -677,22 +679,21 @@ public class SIPCommander implements ISIPCommander {
677 */ 679 */
678 @Override 680 @Override
679 public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { 681 public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException {
680 - SsrcTransaction ssrcTransaction;  
681 - if (callId != null) {  
682 - ssrcTransaction = streamSession.getSsrcTransaction(null, null, callId, null);  
683 - }else {  
684 - ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, stream);  
685 - }  
686 - if (ssrcTransaction == null) { 682 + List<SsrcTransaction> ssrcTransactionList = streamSession.getSsrcTransactionForAll(device.getDeviceId(), channelId, callId, stream);
  683 + if (ssrcTransactionList == null || ssrcTransactionList.isEmpty()) {
  684 + logger.info("[发送BYE] 未找到事务信息,设备: device: {}, channel: {}", device.getDeviceId(), channelId);
687 throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream); 685 throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream);
688 } 686 }
689 687
690 - mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());  
691 - mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());  
692 - streamSession.remove(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); 688 + for (SsrcTransaction ssrcTransaction : ssrcTransactionList) {
  689 + logger.info("[发送BYE] 设备: device: {}, channel: {}, callId: {}", device.getDeviceId(), channelId, ssrcTransaction.getCallId());
  690 + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
693 691
694 - Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo());  
695 - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); 692 + mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());
  693 + streamSession.removeByCallId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getCallId());
  694 + Request byteRequest = headerProvider.createByteRequest(device, channelId, ssrcTransaction.getSipTransactionInfo());
  695 + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent);
  696 + }
696 } 697 }
697 698
698 @Override 699 @Override
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -579,7 +579,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -579,7 +579,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
579 579
580 @Override 580 @Override
581 public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException { 581 public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
582 - if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { 582 + if (parentPlatform == null || deviceChannels == null || deviceChannels.isEmpty() || subscribeInfo == null) {
583 return; 583 return;
584 } 584 }
585 if (index == null) { 585 if (index == null) {
@@ -597,6 +597,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -597,6 +597,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
597 Integer finalIndex = index; 597 Integer finalIndex = index;
598 String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels, 598 String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
599 deviceChannels.size(), type, subscribeInfo); 599 deviceChannels.size(), type, subscribeInfo);
  600 + logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
600 sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> { 601 sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
601 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg); 602 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
602 }, (eventResult -> { 603 }, (eventResult -> {
@@ -620,7 +621,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -620,7 +621,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
620 621
621 SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo); 622 SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
622 623
623 - sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest); 624 + sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest, errorEvent, okEvent);
624 } 625 }
625 626
626 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) { 627 private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
@@ -632,9 +633,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -632,9 +633,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
632 .append("<CmdType>Catalog</CmdType>\r\n") 633 .append("<CmdType>Catalog</CmdType>\r\n")
633 .append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n") 634 .append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n")
634 .append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n") 635 .append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
635 - .append("<SumNum>1</SumNum>\r\n") 636 + .append("<SumNum>"+ sumNum +"</SumNum>\r\n")
636 .append("<DeviceList Num=\"" + channels.size() + "\">\r\n"); 637 .append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
637 - if (channels.size() > 0) { 638 + if (!channels.isEmpty()) {
638 for (DeviceChannel channel : channels) { 639 for (DeviceChannel channel : channels) {
639 if (parentPlatform.getServerGBId().equals(channel.getParentId())) { 640 if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
640 channel.setParentId(parentPlatform.getDeviceGBId()); 641 channel.setParentId(parentPlatform.getDeviceGBId());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -33,6 +33,7 @@ import javax.sip.header.CallIdHeader; @@ -33,6 +33,7 @@ import javax.sip.header.CallIdHeader;
33 import javax.sip.message.Response; 33 import javax.sip.message.Response;
34 import java.text.ParseException; 34 import java.text.ParseException;
35 import java.util.HashMap; 35 import java.util.HashMap;
  36 +import java.util.List;
36 import java.util.Map; 37 import java.util.Map;
37 38
38 /** 39 /**
@@ -167,14 +168,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -167,14 +168,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
167 } 168 }
168 } 169 }
169 170
170 - // 发流端发送的停止  
171 - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);  
172 - if (ssrcTransaction == null ) {  
173 - logger.info("[收到bye] 但是无法获取推流信息和发流信息,忽略此请求");  
174 - logger.info(request.toString());  
175 - return;  
176 - }  
177 - 171 + // 可能是设备发送的停止
  172 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId());
  173 + if (ssrcTransaction == null) {
  174 + return;
  175 + }
  176 + logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
178 177
179 ParentPlatform platform = platformService.queryPlatformByServerGBId(ssrcTransaction.getDeviceId()); 178 ParentPlatform platform = platformService.queryPlatformByServerGBId(ssrcTransaction.getDeviceId());
180 if (platform != null ) { 179 if (platform != null ) {
@@ -216,7 +215,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -216,7 +215,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
216 if (mediaServerItem != null) { 215 if (mediaServerItem != null) {
217 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc()); 216 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc());
218 } 217 }
219 - streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcTransaction.getStream()); 218 + streamSession.removeByCallId(device.getDeviceId(), channel.getChannelId(), ssrcTransaction.getCallId());
220 if (ssrcTransaction.getType() == InviteSessionType.BROADCAST) { 219 if (ssrcTransaction.getType() == InviteSessionType.BROADCAST) {
221 // 查找来源的对讲设备,发送停止 220 // 查找来源的对讲设备,发送停止
222 Device sourceDevice = storager.queryVideoDeviceByPlatformIdAndChannelId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); 221 Device sourceDevice = storager.queryVideoDeviceByPlatformIdAndChannelId(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -152,7 +152,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -152,7 +152,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
152 String requesterId = SipUtils.getUserIdFromFromHeader(request); 152 String requesterId = SipUtils.getUserIdFromFromHeader(request);
153 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); 153 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
154 if (requesterId == null || channelId == null) { 154 if (requesterId == null || channelId == null) {
155 - logger.info("无法从FromHeader的Address中获取到平台id,返回400"); 155 + logger.info("无法从请求中获取到平台id,返回400");
156 // 参数不全, 发400,请求错误 156 // 参数不全, 发400,请求错误
157 try { 157 try {
158 responseAck(request, Response.BAD_REQUEST); 158 responseAck(request, Response.BAD_REQUEST);
@@ -745,13 +745,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -745,13 +745,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
745 dynamicTask.startDelay(callIdHeader.getCallId(), () -> { 745 dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
746 logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream()); 746 logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
747 try { 747 try {
  748 + redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream());
748 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); 749 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
749 responseAck(request, Response.REQUEST_TIMEOUT); // 超时 750 responseAck(request, Response.REQUEST_TIMEOUT); // 超时
750 - } catch (SipException e) {  
751 - logger.error("未处理的异常 ", e);  
752 - } catch (InvalidArgumentException e) {  
753 - logger.error("未处理的异常 ", e);  
754 - } catch (ParseException e) { 751 + } catch (SipException | InvalidArgumentException | ParseException e) {
755 logger.error("未处理的异常 ", e); 752 logger.error("未处理的异常 ", e);
756 } 753 }
757 }, userSetting.getPlatformPlayTimeout()); 754 }, userSetting.getPlatformPlayTimeout());
@@ -762,6 +759,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -762,6 +759,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
762 // 添加在本机上线的通知 759 // 添加在本机上线的通知
763 mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> { 760 mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> {
764 dynamicTask.stop(callIdHeader.getCallId()); 761 dynamicTask.stop(callIdHeader.getCallId());
  762 + redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream());
765 if (serverId.equals(userSetting.getServerId())) { 763 if (serverId.equals(userSetting.getServerId())) {
766 SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, 764 SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
767 app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); 765 app, stream, channelId, mediaTransmissionTCP, platform.isRtcp());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
@@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils; @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
13 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 13 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
14 import com.genersoft.iot.vmp.service.IDeviceChannelService; 14 import com.genersoft.iot.vmp.service.IDeviceChannelService;
15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  16 +import com.genersoft.iot.vmp.utils.DateUtil;
16 import org.dom4j.DocumentException; 17 import org.dom4j.DocumentException;
17 import org.dom4j.Element; 18 import org.dom4j.Element;
18 import org.slf4j.Logger; 19 import org.slf4j.Logger;
@@ -185,6 +186,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -185,6 +186,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
185 // 判断此通道是否存在 186 // 判断此通道是否存在
186 DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId()); 187 DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId());
187 if (deviceChannel != null) { 188 if (deviceChannel != null) {
  189 + logger.info("[增加通道] 已存在,不发送通知只更新,设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
188 channel.setId(deviceChannel.getId()); 190 channel.setId(deviceChannel.getId());
189 updateChannelMap.put(channel.getChannelId(), channel); 191 updateChannelMap.put(channel.getChannelId(), channel);
190 if (updateChannelMap.keySet().size() > 300) { 192 if (updateChannelMap.keySet().size() > 300) {
@@ -222,6 +224,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -222,6 +224,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
222 DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId()); 224 DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId());
223 if (deviceChannelForUpdate != null) { 225 if (deviceChannelForUpdate != null) {
224 channel.setId(deviceChannelForUpdate.getId()); 226 channel.setId(deviceChannelForUpdate.getId());
  227 + channel.setUpdateTime(DateUtil.getNow());
225 updateChannelMap.put(channel.getChannelId(), channel); 228 updateChannelMap.put(channel.getChannelId(), channel);
226 if (updateChannelMap.keySet().size() > 300) { 229 if (updateChannelMap.keySet().size() > 300) {
227 executeSaveForUpdate(); 230 executeSaveForUpdate();
@@ -244,11 +247,11 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -244,11 +247,11 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
244 // 转发变化信息 247 // 转发变化信息
245 eventPublisher.catalogEventPublish(null, channel, event); 248 eventPublisher.catalogEventPublish(null, channel, event);
246 249
247 - if (updateChannelMap.keySet().size() > 0  
248 - || addChannelMap.keySet().size() > 0  
249 - || updateChannelOnlineList.size() > 0  
250 - || updateChannelOfflineList.size() > 0  
251 - || deleteChannelList.size() > 0) { 250 + if (!updateChannelMap.keySet().isEmpty()
  251 + || !addChannelMap.keySet().isEmpty()
  252 + || !updateChannelOnlineList.isEmpty()
  253 + || !updateChannelOfflineList.isEmpty()
  254 + || !deleteChannelList.isEmpty()) {
252 255
253 if (!dynamicTask.contains(talkKey)) { 256 if (!dynamicTask.contains(talkKey)) {
254 dynamicTask.startDelay(talkKey, this::executeSave, 1000); 257 dynamicTask.startDelay(talkKey, this::executeSave, 1000);
@@ -262,16 +265,36 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -262,16 +265,36 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
262 } 265 }
263 266
264 private void executeSave(){ 267 private void executeSave(){
265 - executeSaveForAdd();  
266 - executeSaveForUpdate();  
267 - executeSaveForDelete();  
268 - executeSaveForOnline();  
269 - executeSaveForOffline(); 268 + try {
  269 + executeSaveForAdd();
  270 + } catch (Exception e) {
  271 + logger.error("[存储收到的增加通道] 异常: ", e );
  272 + }
  273 + try {
  274 + executeSaveForUpdate();
  275 + } catch (Exception e) {
  276 + logger.error("[存储收到的更新通道] 异常: ", e );
  277 + }
  278 + try {
  279 + executeSaveForDelete();
  280 + } catch (Exception e) {
  281 + logger.error("[存储收到的删除通道] 异常: ", e );
  282 + }
  283 + try {
  284 + executeSaveForOnline();
  285 + } catch (Exception e) {
  286 + logger.error("[存储收到的通道上线] 异常: ", e );
  287 + }
  288 + try {
  289 + executeSaveForOffline();
  290 + } catch (Exception e) {
  291 + logger.error("[存储收到的通道离线] 异常: ", e );
  292 + }
270 dynamicTask.stop(talkKey); 293 dynamicTask.stop(talkKey);
271 } 294 }
272 295
273 private void executeSaveForUpdate(){ 296 private void executeSaveForUpdate(){
274 - if (updateChannelMap.values().size() > 0) { 297 + if (!updateChannelMap.values().isEmpty()) {
275 ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values()); 298 ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values());
276 updateChannelMap.clear(); 299 updateChannelMap.clear();
277 deviceChannelService.batchUpdateChannel(deviceChannels); 300 deviceChannelService.batchUpdateChannel(deviceChannels);
@@ -280,7 +303,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -280,7 +303,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
280 } 303 }
281 304
282 private void executeSaveForAdd(){ 305 private void executeSaveForAdd(){
283 - if (addChannelMap.values().size() > 0) { 306 + if (!addChannelMap.values().isEmpty()) {
284 ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values()); 307 ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values());
285 addChannelMap.clear(); 308 addChannelMap.clear();
286 deviceChannelService.batchAddChannel(deviceChannels); 309 deviceChannelService.batchAddChannel(deviceChannels);
@@ -288,21 +311,21 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @@ -288,21 +311,21 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
288 } 311 }
289 312
290 private void executeSaveForDelete(){ 313 private void executeSaveForDelete(){
291 - if (deleteChannelList.size() > 0) { 314 + if (!deleteChannelList.isEmpty()) {
292 deviceChannelService.deleteChannels(deleteChannelList); 315 deviceChannelService.deleteChannels(deleteChannelList);
293 deleteChannelList.clear(); 316 deleteChannelList.clear();
294 } 317 }
295 } 318 }
296 319
297 private void executeSaveForOnline(){ 320 private void executeSaveForOnline(){
298 - if (updateChannelOnlineList.size() > 0) { 321 + if (!updateChannelOnlineList.isEmpty()) {
299 deviceChannelService.channelsOnline(updateChannelOnlineList); 322 deviceChannelService.channelsOnline(updateChannelOnlineList);
300 updateChannelOnlineList.clear(); 323 updateChannelOnlineList.clear();
301 } 324 }
302 } 325 }
303 326
304 private void executeSaveForOffline(){ 327 private void executeSaveForOffline(){
305 - if (updateChannelOfflineList.size() > 0) { 328 + if (!updateChannelOfflineList.isEmpty()) {
306 deviceChannelService.channelsOffline(updateChannelOfflineList); 329 deviceChannelService.channelsOffline(updateChannelOfflineList);
307 updateChannelOfflineList.clear(); 330 updateChannelOfflineList.clear();
308 } 331 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -76,7 +76,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @@ -76,7 +76,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
76 76
77 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress()); 77 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
78 if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) { 78 if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
79 - logger.info("[心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort()); 79 + logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
80 device.setPort(remoteAddressInfo.getPort()); 80 device.setPort(remoteAddressInfo.getPort());
81 device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); 81 device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
82 device.setIp(remoteAddressInfo.getIp()); 82 device.setIp(remoteAddressInfo.getIp());
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
9 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 9 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
10 import com.genersoft.iot.vmp.utils.DateUtil; 10 import com.genersoft.iot.vmp.utils.DateUtil;
  11 +import org.apache.commons.lang3.StringUtils;
11 import org.apache.commons.lang3.math.NumberUtils; 12 import org.apache.commons.lang3.math.NumberUtils;
12 import org.dom4j.Attribute; 13 import org.dom4j.Attribute;
13 import org.dom4j.Document; 14 import org.dom4j.Document;
@@ -214,8 +215,11 @@ public class XmlUtil { @@ -214,8 +215,11 @@ public class XmlUtil {
214 return deviceChannel; 215 return deviceChannel;
215 } 216 }
216 Element nameElement = itemDevice.element("Name"); 217 Element nameElement = itemDevice.element("Name");
217 - if (nameElement != null) { 218 + // 当通道名称为空时,设置通道名称为通道编码,避免级联时因通道名称为空导致上级接收通道失败
  219 + if (nameElement != null && StringUtils.isNotBlank(nameElement.getText())) {
218 deviceChannel.setName(nameElement.getText()); 220 deviceChannel.setName(nameElement.getText());
  221 + } else {
  222 + deviceChannel.setName(channelId);
219 } 223 }
220 if(channelId.length() <= 8) { 224 if(channelId.length() <= 8) {
221 deviceChannel.setHasAudio(false); 225 deviceChannel.setHasAudio(false);
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -9,33 +9,58 @@ import org.jetbrains.annotations.NotNull; @@ -9,33 +9,58 @@ import org.jetbrains.annotations.NotNull;
9 import org.slf4j.Logger; 9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
11 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
  12 +import org.springframework.util.ObjectUtils;
12 13
13 import java.io.IOException; 14 import java.io.IOException;
14 import java.net.ConnectException; 15 import java.net.ConnectException;
  16 +import java.net.SocketTimeoutException;
15 import java.util.HashMap; 17 import java.util.HashMap;
  18 +import java.util.List;
16 import java.util.Map; 19 import java.util.Map;
17 import java.util.Objects; 20 import java.util.Objects;
  21 +import java.util.concurrent.TimeUnit;
18 22
19 @Component 23 @Component
20 public class AssistRESTfulUtils { 24 public class AssistRESTfulUtils {
21 25
22 private final static Logger logger = LoggerFactory.getLogger(AssistRESTfulUtils.class); 26 private final static Logger logger = LoggerFactory.getLogger(AssistRESTfulUtils.class);
23 27
  28 +
  29 + private OkHttpClient client;
  30 +
  31 +
24 public interface RequestCallback{ 32 public interface RequestCallback{
25 void run(JSONObject response); 33 void run(JSONObject response);
26 } 34 }
27 35
28 private OkHttpClient getClient(){ 36 private OkHttpClient getClient(){
29 - OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();  
30 - if (logger.isDebugEnabled()) {  
31 - HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {  
32 - logger.debug("http请求参数:" + message);  
33 - });  
34 - logging.setLevel(HttpLoggingInterceptor.Level.BASIC);  
35 - // OkHttp進行添加攔截器loggingInterceptor  
36 - httpClientBuilder.addInterceptor(logging); 37 + return getClient(null);
  38 + }
  39 +
  40 + private OkHttpClient getClient(Integer readTimeOut){
  41 + if (client == null) {
  42 + if (readTimeOut == null) {
  43 + readTimeOut = 10;
  44 + }
  45 + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
  46 + // 设置连接超时时间
  47 + httpClientBuilder.connectTimeout(8, TimeUnit.SECONDS);
  48 + // 设置读取超时时间
  49 + httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS);
  50 + // 设置连接池
  51 + httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES));
  52 + if (logger.isDebugEnabled()) {
  53 + HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
  54 + logger.debug("http请求参数:" + message);
  55 + });
  56 + logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
  57 + // OkHttp進行添加攔截器loggingInterceptor
  58 + httpClientBuilder.addInterceptor(logging);
  59 + }
  60 + client = httpClientBuilder.build();
37 } 61 }
38 - return httpClientBuilder.build(); 62 + return client;
  63 +
39 } 64 }
40 65
41 66
@@ -123,13 +148,91 @@ public class AssistRESTfulUtils { @@ -123,13 +148,91 @@ public class AssistRESTfulUtils {
123 return responseJSON; 148 return responseJSON;
124 } 149 }
125 150
  151 + public JSONObject sendPost(MediaServerItem mediaServerItem, String api, JSONObject param, ZLMRESTfulUtils.RequestCallback callback, Integer readTimeOut) {
  152 + OkHttpClient client = getClient(readTimeOut);
126 153
127 - public JSONObject fileDuration(MediaServerItem mediaServerItem, String app, String stream, RequestCallback callback){  
128 - Map<String, Object> param = new HashMap<>();  
129 - param.put("app",app);  
130 - param.put("stream",stream);  
131 - param.put("recordIng",true);  
132 - return sendGet(mediaServerItem, "api/record/file/duration",param, callback); 154 + if (mediaServerItem == null) {
  155 + return null;
  156 + }
  157 + String url = String.format("http://%s:%s/%s", mediaServerItem.getIp(), mediaServerItem.getRecordAssistPort(), api);
  158 + JSONObject responseJSON = new JSONObject();
  159 + //-2自定义流媒体 调用错误码
  160 + responseJSON.put("code",-2);
  161 + responseJSON.put("msg","ASSIST调用失败");
  162 +
  163 + RequestBody requestBodyJson = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param.toString());
  164 +
  165 + Request request = new Request.Builder()
  166 + .post(requestBodyJson)
  167 + .url(url)
  168 + .addHeader("Content-Type", "application/json")
  169 + .build();
  170 + if (callback == null) {
  171 + try {
  172 + Response response = client.newCall(request).execute();
  173 + if (response.isSuccessful()) {
  174 + ResponseBody responseBody = response.body();
  175 + if (responseBody != null) {
  176 + String responseStr = responseBody.string();
  177 + responseJSON = JSON.parseObject(responseStr);
  178 + }
  179 + }else {
  180 + response.close();
  181 + Objects.requireNonNull(response.body()).close();
  182 + }
  183 + }catch (IOException e) {
  184 + logger.error(String.format("[ %s ]ASSIST请求失败: %s", url, e.getMessage()));
  185 +
  186 + if(e instanceof SocketTimeoutException){
  187 + //读取超时超时异常
  188 + logger.error(String.format("读取ASSIST数据失败: %s, %s", url, e.getMessage()));
  189 + }
  190 + if(e instanceof ConnectException){
  191 + //判断连接异常,我这里是报Failed to connect to 10.7.5.144
  192 + logger.error(String.format("连接ASSIST失败: %s, %s", url, e.getMessage()));
  193 + }
  194 +
  195 + }catch (Exception e){
  196 + logger.error(String.format("访问ASSIST失败: %s, %s", url, e.getMessage()));
  197 + }
  198 + }else {
  199 + client.newCall(request).enqueue(new Callback(){
  200 +
  201 + @Override
  202 + public void onResponse(@NotNull Call call, @NotNull Response response){
  203 + if (response.isSuccessful()) {
  204 + try {
  205 + String responseStr = Objects.requireNonNull(response.body()).string();
  206 + callback.run(JSON.parseObject(responseStr));
  207 + } catch (IOException e) {
  208 + logger.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));
  209 + }
  210 +
  211 + }else {
  212 + response.close();
  213 + Objects.requireNonNull(response.body()).close();
  214 + }
  215 + }
  216 +
  217 + @Override
  218 + public void onFailure(@NotNull Call call, @NotNull IOException e) {
  219 + logger.error(String.format("连接ZLM失败: %s, %s", call.request().toString(), e.getMessage()));
  220 +
  221 + if(e instanceof SocketTimeoutException){
  222 + //读取超时超时异常
  223 + logger.error(String.format("读取ZLM数据失败: %s, %s", call.request().toString(), e.getMessage()));
  224 + }
  225 + if(e instanceof ConnectException){
  226 + //判断连接异常,我这里是报Failed to connect to 10.7.5.144
  227 + logger.error(String.format("连接ZLM失败: %s, %s", call.request().toString(), e.getMessage()));
  228 + }
  229 + }
  230 + });
  231 + }
  232 +
  233 +
  234 +
  235 + return responseJSON;
133 } 236 }
134 237
135 public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){ 238 public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){
@@ -137,33 +240,41 @@ public class AssistRESTfulUtils { @@ -137,33 +240,41 @@ public class AssistRESTfulUtils {
137 return sendGet(mediaServerItem, "api/record/info",param, callback); 240 return sendGet(mediaServerItem, "api/record/info",param, callback);
138 } 241 }
139 242
140 - public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){  
141 - Map<String, Object> param = new HashMap<>();  
142 - param.put("app",app);  
143 - param.put("stream",stream);  
144 - param.put("callId",callId);  
145 - return sendGet(mediaServerItem, "api/record/addStreamCallInfo",param, callback);  
146 - } 243 + public JSONObject addTask(MediaServerItem mediaServerItem, String app, String stream, String startTime,
  244 + String endTime, String callId, List<String> filePathList, String remoteHost) {
147 245
148 - public JSONObject getDateList(MediaServerItem mediaServerItem, String app, String stream, int year, int month) {  
149 - Map<String, Object> param = new HashMap<>();  
150 - param.put("app", app);  
151 - param.put("stream", stream);  
152 - param.put("year", year);  
153 - param.put("month", month);  
154 - return sendGet(mediaServerItem, "api/record/date/list", param, null); 246 + JSONObject videoTaskInfoJSON = new JSONObject();
  247 + videoTaskInfoJSON.put("app", app);
  248 + videoTaskInfoJSON.put("stream", stream);
  249 + videoTaskInfoJSON.put("startTime", startTime);
  250 + videoTaskInfoJSON.put("endTime", endTime);
  251 + videoTaskInfoJSON.put("callId", callId);
  252 + videoTaskInfoJSON.put("filePathList", filePathList);
  253 + if (!ObjectUtils.isEmpty(remoteHost)) {
  254 + videoTaskInfoJSON.put("remoteHost", remoteHost);
  255 + }
  256 +
  257 + return sendPost(mediaServerItem, "api/record/file/download/task/add", videoTaskInfoJSON, null, 30);
155 } 258 }
156 259
157 - public JSONObject getFileList(MediaServerItem mediaServerItem, int page, int count, String app, String stream,  
158 - String startTime, String endTime) { 260 + public JSONObject queryTaskList(MediaServerItem mediaServerItem, String app, String stream, String callId, String taskId, Boolean isEnd) {
159 Map<String, Object> param = new HashMap<>(); 261 Map<String, Object> param = new HashMap<>();
160 - param.put("app", app);  
161 - param.put("stream", stream);  
162 - param.put("page", page);  
163 - param.put("count", count);  
164 - param.put("startTime", startTime);  
165 - param.put("endTime", endTime);  
166 - return sendGet(mediaServerItem, "api/record/file/listWithDate", param, null);  
167 - } 262 + if (!ObjectUtils.isEmpty(app)) {
  263 + param.put("app", app);
  264 + }
  265 + if (!ObjectUtils.isEmpty(stream)) {
  266 + param.put("stream", stream);
  267 + }
  268 + if (!ObjectUtils.isEmpty(callId)) {
  269 + param.put("callId", callId);
  270 + }
  271 + if (!ObjectUtils.isEmpty(taskId)) {
  272 + param.put("taskId", taskId);
  273 + }
  274 + if (!ObjectUtils.isEmpty(isEnd)) {
  275 + param.put("isEnd", isEnd);
  276 + }
168 277
  278 + return sendGet(mediaServerItem, "api/record/file/download/task/list", param, null);
  279 + }
169 } 280 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -118,6 +118,9 @@ public class ZLMHttpHookListener { @@ -118,6 +118,9 @@ public class ZLMHttpHookListener {
118 private IUserService userService; 118 private IUserService userService;
119 119
120 @Autowired 120 @Autowired
  121 + private ICloudRecordService cloudRecordService;
  122 +
  123 + @Autowired
121 private VideoStreamSessionManager sessionManager; 124 private VideoStreamSessionManager sessionManager;
122 125
123 @Autowired 126 @Autowired
@@ -238,12 +241,6 @@ public class ZLMHttpHookListener { @@ -238,12 +241,6 @@ public class ZLMHttpHookListener {
238 streamAuthorityInfo.setSign(sign); 241 streamAuthorityInfo.setSign(sign);
239 // 鉴权通过 242 // 鉴权通过
240 redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); 243 redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
241 - // 通知assist新的callId  
242 - if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {  
243 - taskExecutor.execute(() -> {  
244 - assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);  
245 - });  
246 - }  
247 } 244 }
248 } else { 245 } else {
249 zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId()); 246 zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId());
@@ -251,6 +248,7 @@ public class ZLMHttpHookListener { @@ -251,6 +248,7 @@ public class ZLMHttpHookListener {
251 248
252 249
253 HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); 250 HookResultForOnPublish result = HookResultForOnPublish.SUCCESS();
  251 + result.setEnable_audio(true);
254 taskExecutor.execute(() -> { 252 taskExecutor.execute(() -> {
255 ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); 253 ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
256 if (subscribe != null) { 254 if (subscribe != null) {
@@ -268,7 +266,6 @@ public class ZLMHttpHookListener { @@ -268,7 +266,6 @@ public class ZLMHttpHookListener {
268 } else { 266 } else {
269 result.setEnable_mp4(userSetting.isRecordPushLive()); 267 result.setEnable_mp4(userSetting.isRecordPushLive());
270 } 268 }
271 -  
272 // 国标流 269 // 国标流
273 if ("rtp".equals(param.getApp()) ) { 270 if ("rtp".equals(param.getApp()) ) {
274 271
@@ -278,14 +275,24 @@ public class ZLMHttpHookListener { @@ -278,14 +275,24 @@ public class ZLMHttpHookListener {
278 if (!mediaInfo.isRtpEnable() && inviteInfo == null) { 275 if (!mediaInfo.isRtpEnable() && inviteInfo == null) {
279 String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16)); 276 String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16));
280 inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc); 277 inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc);
281 - result.setStream_replace(inviteInfo.getStream());  
282 - logger.info("[ZLM HOOK]推流鉴权 stream: {} 替换为 {}", param.getStream(), inviteInfo.getStream()); 278 + if (inviteInfo != null) {
  279 + result.setStream_replace(inviteInfo.getStream());
  280 + logger.info("[ZLM HOOK]推流鉴权 stream: {} 替换为 {}", param.getStream(), inviteInfo.getStream());
  281 + }
283 } 282 }
284 283
285 // 设置音频信息及录制信息 284 // 设置音频信息及录制信息
286 - List<SsrcTransaction> ssrcTransactionForAll = (inviteInfo == null ? null :  
287 - sessionManager.getSsrcTransactionForAll(inviteInfo.getDeviceId(), inviteInfo.getChannelId(), null, null)); 285 + List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream());
288 if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) { 286 if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) {
  287 +
  288 + // 为录制国标模拟一个鉴权信息, 方便后续写入录像文件时使用
  289 + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
  290 + streamAuthorityInfo.setApp(param.getApp());
  291 + streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream());
  292 + streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId());
  293 +
  294 + redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo);
  295 +
289 String deviceId = ssrcTransactionForAll.get(0).getDeviceId(); 296 String deviceId = ssrcTransactionForAll.get(0).getDeviceId();
290 String channelId = ssrcTransactionForAll.get(0).getChannelId(); 297 String channelId = ssrcTransactionForAll.get(0).getChannelId();
291 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); 298 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
@@ -294,38 +301,29 @@ public class ZLMHttpHookListener { @@ -294,38 +301,29 @@ public class ZLMHttpHookListener {
294 } 301 }
295 // 如果是录像下载就设置视频间隔十秒 302 // 如果是录像下载就设置视频间隔十秒
296 if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { 303 if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) {
297 - result.setMp4_max_second(10);  
298 - result.setEnable_mp4(true); 304 + // 获取录像的总时长,然后设置为这个视频的时长
  305 + InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, param.getStream());
  306 + if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) {
  307 + String startTime = inviteInfoForDownload.getStreamInfo().getStartTime();
  308 + String endTime = inviteInfoForDownload.getStreamInfo().getEndTime();
  309 + long difference = DateUtil.getDifference(startTime, endTime) / 1000;
  310 + result.setMp4_max_second((int) difference);
  311 + result.setEnable_mp4(true);
  312 + // 设置为2保证得到的mp4的时长是正常的
  313 + result.setModify_stamp(2);
  314 + }
299 } 315 }
300 // 如果是talk对讲,则默认获取声音 316 // 如果是talk对讲,则默认获取声音
301 if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) { 317 if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) {
302 result.setEnable_audio(true); 318 result.setEnable_audio(true);
303 } 319 }
304 } 320 }
305 - }else if (param.getApp().equals("broadcast")) { 321 + }
  322 + else if (param.getApp().equals("broadcast")) {
306 result.setEnable_audio(true); 323 result.setEnable_audio(true);
307 }else if (param.getApp().equals("talk")) { 324 }else if (param.getApp().equals("talk")) {
308 result.setEnable_audio(true); 325 result.setEnable_audio(true);
309 } 326 }
310 -  
311 - if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {  
312 - logger.info("推流时发现尚未设置录像路径,从assist服务中读取");  
313 - JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null);  
314 - if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0) {  
315 - JSONObject dataJson = info.getJSONObject("data");  
316 - if (dataJson != null) {  
317 - String recordPath = dataJson.getString("record");  
318 - userSetting.setRecordPath(recordPath);  
319 - result.setMp4_save_path(recordPath);  
320 - // 修改zlm中的录像路径  
321 - if (mediaInfo.isAutoConfig()) {  
322 - taskExecutor.execute(() -> {  
323 - mediaServerService.setZLMConfig(mediaInfo, false);  
324 - });  
325 - }  
326 - }  
327 - }  
328 - }  
329 if (param.getApp().equalsIgnoreCase("rtp")) { 327 if (param.getApp().equalsIgnoreCase("rtp")) {
330 String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); 328 String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream();
331 OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey); 329 OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey);
@@ -371,13 +369,11 @@ public class ZLMHttpHookListener { @@ -371,13 +369,11 @@ public class ZLMHttpHookListener {
371 369
372 List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); 370 List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
373 // TODO 重构此处逻辑 371 // TODO 重构此处逻辑
374 - boolean isPush = false;  
375 if (param.isRegist()) { 372 if (param.isRegist()) {
376 - // 处理流注册的鉴权信息 373 + // 处理流注册的鉴权信息, 流注销这里不再删除鉴权信息,下次来了新的鉴权信息会对就的进行覆盖
377 if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() 374 if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
378 || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() 375 || param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
379 || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { 376 || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
380 - isPush = true;  
381 StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); 377 StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
382 if (streamAuthorityInfo == null) { 378 if (streamAuthorityInfo == null) {
383 streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); 379 streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
@@ -387,8 +383,6 @@ public class ZLMHttpHookListener { @@ -387,8 +383,6 @@ public class ZLMHttpHookListener {
387 } 383 }
388 redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); 384 redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
389 } 385 }
390 - } else {  
391 - redisCatchStorage.removeStreamAuthorityInfo(param.getApp(), param.getStream());  
392 } 386 }
393 387
394 if ("rtsp".equals(param.getSchema())) { 388 if ("rtsp".equals(param.getSchema())) {
@@ -470,35 +464,40 @@ public class ZLMHttpHookListener { @@ -470,35 +464,40 @@ public class ZLMHttpHookListener {
470 } else { 464 } else {
471 if (!"rtp".equals(param.getApp())) { 465 if (!"rtp".equals(param.getApp())) {
472 String type = OriginType.values()[param.getOriginType()].getType(); 466 String type = OriginType.values()[param.getOriginType()].getType();
473 - MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());  
474 -  
475 - if (mediaServerItem != null) {  
476 - if (param.isRegist()) {  
477 - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());  
478 - String callId = null;  
479 - if (streamAuthorityInfo != null) {  
480 - callId = streamAuthorityInfo.getCallId();  
481 - }  
482 - StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,  
483 - param.getApp(), param.getStream(), param.getTracks(), callId);  
484 - param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));  
485 - redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param);  
486 - if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()  
487 - || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()  
488 - || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {  
489 - param.setSeverId(userSetting.getServerId());  
490 - zlmMediaListManager.addPush(param);  
491 - }  
492 - } else {  
493 - // 兼容流注销时类型从redis记录获取  
494 - OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo(  
495 - param.getApp(), param.getStream(), param.getMediaServerId());  
496 - if (onStreamChangedHookParam != null) {  
497 - type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType();  
498 - redisCatchStorage.removeStream(mediaServerItem.getId(), type, param.getApp(), param.getStream()); 467 + if (param.isRegist()) {
  468 + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(
  469 + param.getApp(), param.getStream());
  470 + String callId = null;
  471 + if (streamAuthorityInfo != null) {
  472 + callId = streamAuthorityInfo.getCallId();
  473 + }
  474 + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo,
  475 + param.getApp(), param.getStream(), tracks, callId);
  476 + param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
  477 + redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param);
  478 + if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
  479 + || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
  480 + || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
  481 + param.setSeverId(userSetting.getServerId());
  482 + zlmMediaListManager.addPush(param);
  483 +
  484 + // 冗余数据,自己系统中自用
  485 + redisCatchStorage.addPushListItem(param.getApp(), param.getStream(), param);
  486 + }
  487 + } else {
  488 + // 兼容流注销时类型从redis记录获取
  489 + OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo(
  490 + param.getApp(), param.getStream(), param.getMediaServerId());
  491 + if (onStreamChangedHookParam != null) {
  492 + type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType();
  493 + redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream());
  494 + if ("PUSH".equalsIgnoreCase(type)) {
  495 + // 冗余数据,自己系统中自用
  496 + redisCatchStorage.removePushListItem(param.getApp(), param.getStream(), param.getMediaServerId());
499 } 497 }
500 - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());  
501 - if (gbStream != null) { 498 + }
  499 + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
  500 + if (gbStream != null) {
502 // eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); 501 // eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
503 } 502 }
504 zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); 503 zlmMediaListManager.removeMedia(param.getApp(), param.getStream());
@@ -618,11 +617,15 @@ public class ZLMHttpHookListener { @@ -618,11 +617,15 @@ public class ZLMHttpHookListener {
618 if (info != null) { 617 if (info != null) {
619 cmder.streamByeCmd(device, inviteInfo.getChannelId(), 618 cmder.streamByeCmd(device, inviteInfo.getChannelId(),
620 inviteInfo.getStream(), null); 619 inviteInfo.getStream(), null);
  620 + }else {
  621 + logger.info("[无人观看] 未找到设备的点播信息: {}, 流:{}", inviteInfo.getDeviceId(), param.getStream());
621 } 622 }
622 } catch (InvalidArgumentException | ParseException | SipException | 623 } catch (InvalidArgumentException | ParseException | SipException |
623 SsrcTransactionNotFoundException e) { 624 SsrcTransactionNotFoundException e) {
624 logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage()); 625 logger.error("[无人观看]点播, 发送BYE失败 {}", e.getMessage());
625 } 626 }
  627 + }else {
  628 + logger.info("[无人观看] 未找到设备: {},流:{}", inviteInfo.getDeviceId(), param.getStream());
626 } 629 }
627 630
628 inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), 631 inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(),
@@ -858,7 +861,7 @@ public class ZLMHttpHookListener { @@ -858,7 +861,7 @@ public class ZLMHttpHookListener {
858 taskExecutor.execute(() -> { 861 taskExecutor.execute(() -> {
859 JSONObject json = (JSONObject) JSON.toJSON(param); 862 JSONObject json = (JSONObject) JSON.toJSON(param);
860 List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout); 863 List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);
861 - if (subscribes != null && subscribes.size() > 0) { 864 + if (subscribes != null && !subscribes.isEmpty()) {
862 for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { 865 for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
863 subscribe.response(null, param); 866 subscribe.response(null, param);
864 } 867 }
@@ -868,6 +871,28 @@ public class ZLMHttpHookListener { @@ -868,6 +871,28 @@ public class ZLMHttpHookListener {
868 return HookResult.SUCCESS(); 871 return HookResult.SUCCESS();
869 } 872 }
870 873
  874 + /**
  875 + * 录像完成事件
  876 + */
  877 + @ResponseBody
  878 + @PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
  879 + public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) {
  880 + logger.info("[ZLM HOOK] 录像完成事件:{}->{}", param.getMediaServerId(), param.getFile_path());
  881 +
  882 + taskExecutor.execute(() -> {
  883 + List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4);
  884 + if (subscribes != null && !subscribes.isEmpty()) {
  885 + for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
  886 + subscribe.response(null, param);
  887 + }
  888 + }
  889 + cloudRecordService.addRecord(param);
  890 +
  891 + });
  892 +
  893 + return HookResult.SUCCESS();
  894 + }
  895 +
871 private Map<String, String> urlParamToMap(String params) { 896 private Map<String, String> urlParamToMap(String params) {
872 HashMap<String, String> map = new HashMap<>(); 897 HashMap<String, String> map = new HashMap<>();
873 if (ObjectUtils.isEmpty(params)) { 898 if (ObjectUtils.isEmpty(params)) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -25,8 +25,6 @@ public class ZLMRESTfulUtils { @@ -25,8 +25,6 @@ public class ZLMRESTfulUtils {
25 25
26 private OkHttpClient client; 26 private OkHttpClient client;
27 27
28 -  
29 -  
30 public interface RequestCallback{ 28 public interface RequestCallback{
31 void run(JSONObject response); 29 void run(JSONObject response);
32 } 30 }
@@ -405,4 +403,14 @@ public class ZLMRESTfulUtils { @@ -405,4 +403,14 @@ public class ZLMRESTfulUtils {
405 param.put("stream_id", streamId); 403 param.put("stream_id", streamId);
406 return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null); 404 return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null);
407 } 405 }
  406 +
  407 + public JSONObject deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
  408 + Map<String, Object> param = new HashMap<>(1);
  409 + param.put("vhost", "__defaultVhost__");
  410 + param.put("app", app);
  411 + param.put("stream", stream);
  412 + param.put("period", date);
  413 + param.put("name", fileName);
  414 + return sendPost(mediaServerItem, "deleteRecordDirectory",param, null);
  415 + }
408 } 416 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java
@@ -57,4 +57,15 @@ public class HookSubscribeFactory { @@ -57,4 +57,15 @@ public class HookSubscribeFactory {
57 return hookSubscribe; 57 return hookSubscribe;
58 } 58 }
59 59
  60 + public static HookSubscribeForRecordMp4 on_record_mp4(String mediaServerId, String app, String stream) {
  61 + HookSubscribeForRecordMp4 hookSubscribe = new HookSubscribeForRecordMp4();
  62 + JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject();
  63 + subscribeKey.put("app", app);
  64 + subscribeKey.put("stream", stream);
  65 + subscribeKey.put("mediaServerId", mediaServerId);
  66 + hookSubscribe.setContent(subscribeKey);
  67 +
  68 + return hookSubscribe;
  69 + }
  70 +
60 } 71 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRecordMp4.java 0 → 100755
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +import com.alibaba.fastjson2.JSONObject;
  4 +import com.alibaba.fastjson2.annotation.JSONField;
  5 +
  6 +import java.time.Instant;
  7 +
  8 +/**
  9 + * hook订阅-录像完成
  10 + * @author lin
  11 + */
  12 +public class HookSubscribeForRecordMp4 implements IHookSubscribe{
  13 +
  14 + private HookType hookType = HookType.on_record_mp4;
  15 +
  16 + private JSONObject content;
  17 +
  18 + @JSONField(format="yyyy-MM-dd HH:mm:ss")
  19 + private Instant expires;
  20 +
  21 + @Override
  22 + public HookType getHookType() {
  23 + return hookType;
  24 + }
  25 +
  26 + @Override
  27 + public JSONObject getContent() {
  28 + return content;
  29 + }
  30 +
  31 + public void setContent(JSONObject content) {
  32 + this.content = content;
  33 + }
  34 +
  35 + @Override
  36 + public Instant getExpires() {
  37 + return expires;
  38 + }
  39 +
  40 + @Override
  41 + public void setExpires(Instant expires) {
  42 + this.expires = expires;
  43 + }
  44 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
@@ -80,9 +80,11 @@ public class MediaServerItem{ @@ -80,9 +80,11 @@ public class MediaServerItem{
80 @Schema(description = "是否是默认ZLM") 80 @Schema(description = "是否是默认ZLM")
81 private boolean defaultServer; 81 private boolean defaultServer;
82 82
83 - @Schema(description = "当前使用到的端口")  
84 - private int currentPort; 83 + @Schema(description = "录像存储时长")
  84 + private int recordDay;
85 85
  86 + @Schema(description = "录像存储路径")
  87 + private String recordPath;
86 88
87 public MediaServerItem() { 89 public MediaServerItem() {
88 } 90 }
@@ -269,14 +271,6 @@ public class MediaServerItem{ @@ -269,14 +271,6 @@ public class MediaServerItem{
269 this.updateTime = updateTime; 271 this.updateTime = updateTime;
270 } 272 }
271 273
272 - public int getCurrentPort() {  
273 - return currentPort;  
274 - }  
275 -  
276 - public void setCurrentPort(int currentPort) {  
277 - this.currentPort = currentPort;  
278 - }  
279 -  
280 public boolean isStatus() { 274 public boolean isStatus() {
281 return status; 275 return status;
282 } 276 }
@@ -308,4 +302,20 @@ public class MediaServerItem{ @@ -308,4 +302,20 @@ public class MediaServerItem{
308 public void setSendRtpPortRange(String sendRtpPortRange) { 302 public void setSendRtpPortRange(String sendRtpPortRange) {
309 this.sendRtpPortRange = sendRtpPortRange; 303 this.sendRtpPortRange = sendRtpPortRange;
310 } 304 }
  305 +
  306 + public int getRecordDay() {
  307 + return recordDay;
  308 + }
  309 +
  310 + public void setRecordDay(int recordDay) {
  311 + this.recordDay = recordDay;
  312 + }
  313 +
  314 + public String getRecordPath() {
  315 + return recordPath;
  316 + }
  317 +
  318 + public void setRecordPath(String recordPath) {
  319 + this.recordPath = recordPath;
  320 + }
311 } 321 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java
@@ -7,6 +7,7 @@ public class HookResultForOnPublish extends HookResult{ @@ -7,6 +7,7 @@ public class HookResultForOnPublish extends HookResult{
7 private int mp4_max_second; 7 private int mp4_max_second;
8 private String mp4_save_path; 8 private String mp4_save_path;
9 private String stream_replace; 9 private String stream_replace;
  10 + private Integer modify_stamp;
10 11
11 public HookResultForOnPublish() { 12 public HookResultForOnPublish() {
12 } 13 }
@@ -60,14 +61,23 @@ public class HookResultForOnPublish extends HookResult{ @@ -60,14 +61,23 @@ public class HookResultForOnPublish extends HookResult{
60 this.stream_replace = stream_replace; 61 this.stream_replace = stream_replace;
61 } 62 }
62 63
  64 + public Integer getModify_stamp() {
  65 + return modify_stamp;
  66 + }
  67 +
  68 + public void setModify_stamp(Integer modify_stamp) {
  69 + this.modify_stamp = modify_stamp;
  70 + }
  71 +
63 @Override 72 @Override
64 public String toString() { 73 public String toString() {
65 return "HookResultForOnPublish{" + 74 return "HookResultForOnPublish{" +
66 "enable_audio=" + enable_audio + 75 "enable_audio=" + enable_audio +
67 ", enable_mp4=" + enable_mp4 + 76 ", enable_mp4=" + enable_mp4 +
68 ", mp4_max_second=" + mp4_max_second + 77 ", mp4_max_second=" + mp4_max_second +
69 - ", stream_replace=" + stream_replace +  
70 ", mp4_save_path='" + mp4_save_path + '\'' + 78 ", mp4_save_path='" + mp4_save_path + '\'' +
  79 + ", stream_replace='" + stream_replace + '\'' +
  80 + ", modify_stamp='" + modify_stamp + '\'' +
71 '}'; 81 '}';
72 } 82 }
73 } 83 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java 0 → 100755
  1 +package com.genersoft.iot.vmp.media.zlm.dto.hook;
  2 +
  3 +/**
  4 + * zlm hook事件中的on_rtp_server_timeout事件的参数
  5 + * @author lin
  6 + */
  7 +public class OnRecordMp4HookParam extends HookParam{
  8 + private String app;
  9 + private String stream;
  10 + private String file_name;
  11 + private String file_path;
  12 + private long file_size;
  13 + private String folder;
  14 + private String url;
  15 + private String vhost;
  16 + private long start_time;
  17 + private double time_len;
  18 +
  19 + public String getApp() {
  20 + return app;
  21 + }
  22 +
  23 + public void setApp(String app) {
  24 + this.app = app;
  25 + }
  26 +
  27 + public String getStream() {
  28 + return stream;
  29 + }
  30 +
  31 + public void setStream(String stream) {
  32 + this.stream = stream;
  33 + }
  34 +
  35 + public String getFile_name() {
  36 + return file_name;
  37 + }
  38 +
  39 + public void setFile_name(String file_name) {
  40 + this.file_name = file_name;
  41 + }
  42 +
  43 + public String getFile_path() {
  44 + return file_path;
  45 + }
  46 +
  47 + public void setFile_path(String file_path) {
  48 + this.file_path = file_path;
  49 + }
  50 +
  51 + public long getFile_size() {
  52 + return file_size;
  53 + }
  54 +
  55 + public void setFile_size(long file_size) {
  56 + this.file_size = file_size;
  57 + }
  58 +
  59 + public String getFolder() {
  60 + return folder;
  61 + }
  62 +
  63 + public void setFolder(String folder) {
  64 + this.folder = folder;
  65 + }
  66 +
  67 + public String getUrl() {
  68 + return url;
  69 + }
  70 +
  71 + public void setUrl(String url) {
  72 + this.url = url;
  73 + }
  74 +
  75 + public String getVhost() {
  76 + return vhost;
  77 + }
  78 +
  79 + public void setVhost(String vhost) {
  80 + this.vhost = vhost;
  81 + }
  82 +
  83 + public long getStart_time() {
  84 + return start_time;
  85 + }
  86 +
  87 + public void setStart_time(long start_time) {
  88 + this.start_time = start_time;
  89 + }
  90 +
  91 + public double getTime_len() {
  92 + return time_len;
  93 + }
  94 +
  95 + public void setTime_len(double time_len) {
  96 + this.time_len = time_len;
  97 + }
  98 +
  99 + @Override
  100 + public String toString() {
  101 + return "OnRecordMp4HookParam{" +
  102 + "app='" + app + '\'' +
  103 + ", stream='" + stream + '\'' +
  104 + ", file_name='" + file_name + '\'' +
  105 + ", file_path='" + file_path + '\'' +
  106 + ", file_size='" + file_size + '\'' +
  107 + ", folder='" + folder + '\'' +
  108 + ", url='" + url + '\'' +
  109 + ", vhost='" + vhost + '\'' +
  110 + ", start_time=" + start_time +
  111 + ", time_len=" + time_len +
  112 + '}';
  113 + }
  114 +}
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java 0 → 100755
  1 +package com.genersoft.iot.vmp.service;
  2 +
  3 +import com.alibaba.fastjson2.JSONArray;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  5 +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
  6 +import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
  7 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
  8 +import com.github.pagehelper.PageInfo;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 云端录像管理
  14 + * @author lin
  15 + */
  16 +public interface ICloudRecordService {
  17 +
  18 + /**
  19 + * 分页回去云端录像列表
  20 + */
  21 + PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems);
  22 +
  23 + /**
  24 + * 根据hook消息增加一条记录
  25 + */
  26 + void addRecord(OnRecordMp4HookParam param);
  27 +
  28 + /**
  29 + * 获取所有的日期
  30 + */
  31 + List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems);
  32 +
  33 + /**
  34 + * 添加合并任务
  35 + */
  36 + String addTask(String app, String stream, String mediaServerId, String startTime, String endTime, String callId, String remoteHost);
  37 +
  38 +
  39 + /**
  40 + * 查询合并任务列表
  41 + */
  42 + JSONArray queryTask(String app, String stream, String callId, String taskId, String mediaServerId, Boolean isEnd);
  43 +
  44 + /**
  45 + * 收藏视频,收藏的视频过期不会删除
  46 + */
  47 + int changeCollect(boolean result, String app, String stream, String mediaServerId, String startTime, String endTime, String callId);
  48 +
  49 + /**
  50 + * 添加指定录像收藏
  51 + */
  52 + int changeCollectById(Integer recordId, boolean result);
  53 +
  54 + /**
  55 + * 获取播放地址
  56 + */
  57 + DownloadFileInfo getPlayUrlPath(Integer recordId);
  58 +}
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -89,21 +89,12 @@ public interface IMediaServerService { @@ -89,21 +89,12 @@ public interface IMediaServerService {
89 89
90 void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data); 90 void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data);
91 91
92 - boolean checkRtpServer(MediaServerItem mediaServerItem, String rtp, String stream);  
93 -  
94 /** 92 /**
95 * 获取负载信息 93 * 获取负载信息
96 * @return 94 * @return
97 */ 95 */
98 MediaServerLoad getLoad(MediaServerItem mediaServerItem); 96 MediaServerLoad getLoad(MediaServerItem mediaServerItem);
99 97
100 - /**  
101 - * 按时间查找录像文件  
102 - */  
103 - List<RecordFile> getRecords(String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems); 98 + List<MediaServerItem> getAllWithAssistPort();
104 99
105 - /**  
106 - * 查找存在录像文件的时间  
107 - */  
108 - List<String> getRecordDates(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems);  
109 } 100 }
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -33,11 +33,6 @@ public interface IPlayService { @@ -33,11 +33,6 @@ public interface IPlayService {
33 33
34 MediaServerItem getNewMediaServerItem(Device device); 34 MediaServerItem getNewMediaServerItem(Device device);
35 35
36 - /**  
37 - * 获取包含assist服务的节点  
38 - */  
39 - MediaServerItem getNewMediaServerItemHasAssist(Device device);  
40 -  
41 void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); 36 void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
42 void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); 37 void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
43 void zlmServerOffline(String mediaServerId); 38 void zlmServerOffline(String mediaServerId);
@@ -72,5 +67,4 @@ public interface IPlayService { @@ -72,5 +67,4 @@ public interface IPlayService {
72 67
73 void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback); 68 void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback);
74 69
75 -  
76 } 70 }
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
@@ -114,4 +114,5 @@ public interface IStreamPushService { @@ -114,4 +114,5 @@ public interface IStreamPushService {
114 * @return 114 * @return
115 */ 115 */
116 ResourceBaseInfo getOverview(); 116 ResourceBaseInfo getOverview();
  117 +
117 } 118 }
src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
  4 +
  5 +/**
  6 + * 云端录像数据
  7 + */
  8 +public class CloudRecordItem {
  9 + /**
  10 + * 主键
  11 + */
  12 + private int id;
  13 +
  14 + /**
  15 + * 应用名
  16 + */
  17 + private String app;
  18 +
  19 + /**
  20 + * 流
  21 + */
  22 + private String stream;
  23 +
  24 + /**
  25 + * 健全ID
  26 + */
  27 + private String callId;
  28 +
  29 + /**
  30 + * 开始时间
  31 + */
  32 + private long startTime;
  33 +
  34 + /**
  35 + * 结束时间
  36 + */
  37 + private long endTime;
  38 +
  39 + /**
  40 + * ZLM Id
  41 + */
  42 + private String mediaServerId;
  43 +
  44 + /**
  45 + * 文件名称
  46 + */
  47 + private String fileName;
  48 +
  49 + /**
  50 + * 文件路径
  51 + */
  52 + private String filePath;
  53 +
  54 + /**
  55 + * 文件夹
  56 + */
  57 + private String folder;
  58 +
  59 + /**
  60 + * 收藏,收藏的文件不移除
  61 + */
  62 + private Boolean collect;
  63 +
  64 + /**
  65 + * 保留,收藏的文件不移除
  66 + */
  67 + private Boolean reserve;
  68 +
  69 + /**
  70 + * 文件大小
  71 + */
  72 + private long fileSize;
  73 +
  74 + /**
  75 + * 文件时长
  76 + */
  77 + private long timeLen;
  78 +
  79 + public static CloudRecordItem getInstance(OnRecordMp4HookParam param) {
  80 + CloudRecordItem cloudRecordItem = new CloudRecordItem();
  81 + cloudRecordItem.setApp(param.getApp());
  82 + cloudRecordItem.setStream(param.getStream());
  83 + cloudRecordItem.setStartTime(param.getStart_time()*1000);
  84 + cloudRecordItem.setFileName(param.getFile_name());
  85 + cloudRecordItem.setFolder(param.getFolder());
  86 + cloudRecordItem.setFileSize(param.getFile_size());
  87 + cloudRecordItem.setFilePath(param.getFile_path());
  88 + cloudRecordItem.setMediaServerId(param.getMediaServerId());
  89 + cloudRecordItem.setTimeLen((long) param.getTime_len() * 1000);
  90 + cloudRecordItem.setEndTime((param.getStart_time() + (long)param.getTime_len()) * 1000);
  91 + return cloudRecordItem;
  92 + }
  93 +
  94 + public int getId() {
  95 + return id;
  96 + }
  97 +
  98 + public void setId(int id) {
  99 + this.id = id;
  100 + }
  101 +
  102 + public String getApp() {
  103 + return app;
  104 + }
  105 +
  106 + public void setApp(String app) {
  107 + this.app = app;
  108 + }
  109 +
  110 + public String getStream() {
  111 + return stream;
  112 + }
  113 +
  114 + public void setStream(String stream) {
  115 + this.stream = stream;
  116 + }
  117 +
  118 + public String getCallId() {
  119 + return callId;
  120 + }
  121 +
  122 + public void setCallId(String callId) {
  123 + this.callId = callId;
  124 + }
  125 +
  126 + public long getStartTime() {
  127 + return startTime;
  128 + }
  129 +
  130 + public void setStartTime(long startTime) {
  131 + this.startTime = startTime;
  132 + }
  133 +
  134 + public long getEndTime() {
  135 + return endTime;
  136 + }
  137 +
  138 + public void setEndTime(long endTime) {
  139 + this.endTime = endTime;
  140 + }
  141 +
  142 + public String getMediaServerId() {
  143 + return mediaServerId;
  144 + }
  145 +
  146 + public void setMediaServerId(String mediaServerId) {
  147 + this.mediaServerId = mediaServerId;
  148 + }
  149 +
  150 + public String getFileName() {
  151 + return fileName;
  152 + }
  153 +
  154 + public void setFileName(String fileName) {
  155 + this.fileName = fileName;
  156 + }
  157 +
  158 + public String getFilePath() {
  159 + return filePath;
  160 + }
  161 +
  162 + public void setFilePath(String filePath) {
  163 + this.filePath = filePath;
  164 + }
  165 +
  166 + public String getFolder() {
  167 + return folder;
  168 + }
  169 +
  170 + public void setFolder(String folder) {
  171 + this.folder = folder;
  172 + }
  173 +
  174 + public long getFileSize() {
  175 + return fileSize;
  176 + }
  177 +
  178 + public void setFileSize(long fileSize) {
  179 + this.fileSize = fileSize;
  180 + }
  181 +
  182 + public long getTimeLen() {
  183 + return timeLen;
  184 + }
  185 +
  186 + public void setTimeLen(long timeLen) {
  187 + this.timeLen = timeLen;
  188 + }
  189 +
  190 + public Boolean getCollect() {
  191 + return collect;
  192 + }
  193 +
  194 + public void setCollect(Boolean collect) {
  195 + this.collect = collect;
  196 + }
  197 +
  198 + public Boolean getReserve() {
  199 + return reserve;
  200 + }
  201 +
  202 + public void setReserve(Boolean reserve) {
  203 + this.reserve = reserve;
  204 + }
  205 +}
src/main/java/com/genersoft/iot/vmp/service/bean/DownloadFileInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +public class DownloadFileInfo {
  4 +
  5 + private String httpPath;
  6 + private String httpsPath;
  7 + private String httpDomainPath;
  8 + private String httpsDomainPath;
  9 +
  10 + public String getHttpPath() {
  11 + return httpPath;
  12 + }
  13 +
  14 + public void setHttpPath(String httpPath) {
  15 + this.httpPath = httpPath;
  16 + }
  17 +
  18 + public String getHttpsPath() {
  19 + return httpsPath;
  20 + }
  21 +
  22 + public void setHttpsPath(String httpsPath) {
  23 + this.httpsPath = httpsPath;
  24 + }
  25 +
  26 + public String getHttpDomainPath() {
  27 + return httpDomainPath;
  28 + }
  29 +
  30 + public void setHttpDomainPath(String httpDomainPath) {
  31 + this.httpDomainPath = httpDomainPath;
  32 + }
  33 +
  34 + public String getHttpsDomainPath() {
  35 + return httpsDomainPath;
  36 + }
  37 +
  38 + public void setHttpsDomainPath(String httpsDomainPath) {
  39 + this.httpsDomainPath = httpsDomainPath;
  40 + }
  41 +}
src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java
@@ -29,12 +29,12 @@ public class WvpRedisMsg { @@ -29,12 +29,12 @@ public class WvpRedisMsg {
29 * 消息的ID 29 * 消息的ID
30 */ 30 */
31 private String serial; 31 private String serial;
32 - private Object content; 32 + private String content;
33 33
34 private final static String requestTag = "req"; 34 private final static String requestTag = "req";
35 private final static String responseTag = "res"; 35 private final static String responseTag = "res";
36 36
37 - public static WvpRedisMsg getRequestInstance(String fromId, String toId, String cmd, String serial, Object content) { 37 + public static WvpRedisMsg getRequestInstance(String fromId, String toId, String cmd, String serial, String content) {
38 WvpRedisMsg wvpRedisMsg = new WvpRedisMsg(); 38 WvpRedisMsg wvpRedisMsg = new WvpRedisMsg();
39 wvpRedisMsg.setType(requestTag); 39 wvpRedisMsg.setType(requestTag);
40 wvpRedisMsg.setFromId(fromId); 40 wvpRedisMsg.setFromId(fromId);
@@ -51,7 +51,7 @@ public class WvpRedisMsg { @@ -51,7 +51,7 @@ public class WvpRedisMsg {
51 return wvpRedisMsg; 51 return wvpRedisMsg;
52 } 52 }
53 53
54 - public static WvpRedisMsg getResponseInstance(String fromId, String toId, String cmd, String serial, Object content) { 54 + public static WvpRedisMsg getResponseInstance(String fromId, String toId, String cmd, String serial, String content) {
55 WvpRedisMsg wvpRedisMsg = new WvpRedisMsg(); 55 WvpRedisMsg wvpRedisMsg = new WvpRedisMsg();
56 wvpRedisMsg.setType(responseTag); 56 wvpRedisMsg.setType(responseTag);
57 wvpRedisMsg.setFromId(fromId); 57 wvpRedisMsg.setFromId(fromId);
@@ -106,11 +106,11 @@ public class WvpRedisMsg { @@ -106,11 +106,11 @@ public class WvpRedisMsg {
106 this.cmd = cmd; 106 this.cmd = cmd;
107 } 107 }
108 108
109 - public Object getContent() { 109 + public String getContent() {
110 return content; 110 return content;
111 } 111 }
112 112
113 - public void setContent(Object content) { 113 + public void setContent(String content) {
114 this.content = content; 114 this.content = content;
115 } 115 }
116 } 116 }
src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.impl;
  2 +
  3 +import com.alibaba.fastjson2.JSONArray;
  4 +import com.alibaba.fastjson2.JSONObject;
  5 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
  6 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  7 +import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
  8 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  9 +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
  10 +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
  11 +import com.genersoft.iot.vmp.service.ICloudRecordService;
  12 +import com.genersoft.iot.vmp.service.IMediaServerService;
  13 +import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
  14 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
  15 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  16 +import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
  17 +import com.genersoft.iot.vmp.utils.CloudRecordUtils;
  18 +import com.genersoft.iot.vmp.utils.DateUtil;
  19 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
  20 +import com.github.pagehelper.PageHelper;
  21 +import com.github.pagehelper.PageInfo;
  22 +import org.apache.commons.lang3.ObjectUtils;
  23 +import org.slf4j.Logger;
  24 +import org.slf4j.LoggerFactory;
  25 +import org.springframework.beans.factory.annotation.Autowired;
  26 +import org.springframework.stereotype.Service;
  27 +
  28 +import java.time.*;
  29 +import java.util.*;
  30 +
  31 +@Service
  32 +public class CloudRecordServiceImpl implements ICloudRecordService {
  33 +
  34 + private final static Logger logger = LoggerFactory.getLogger(CloudRecordServiceImpl.class);
  35 +
  36 + @Autowired
  37 + private CloudRecordServiceMapper cloudRecordServiceMapper;
  38 +
  39 + @Autowired
  40 + private IMediaServerService mediaServerService;
  41 +
  42 + @Autowired
  43 + private IRedisCatchStorage redisCatchStorage;
  44 +
  45 + @Autowired
  46 + private AssistRESTfulUtils assistRESTfulUtils;
  47 +
  48 + @Autowired
  49 + private VideoStreamSessionManager streamSession;
  50 +
  51 + @Override
  52 + public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) {
  53 + // 开始时间和结束时间在数据库中都是以秒为单位的
  54 + Long startTimeStamp = null;
  55 + Long endTimeStamp = null;
  56 + if (startTime != null ) {
  57 + if (!DateUtil.verification(startTime, DateUtil.formatter)) {
  58 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间格式错误,正确格式为: " + DateUtil.formatter);
  59 + }
  60 + startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
  61 +
  62 + }
  63 + if (endTime != null ) {
  64 + if (!DateUtil.verification(endTime, DateUtil.formatter)) {
  65 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "结束时间格式错误,正确格式为: " + DateUtil.formatter);
  66 + }
  67 + endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
  68 +
  69 + }
  70 + PageHelper.startPage(page, count);
  71 + List<CloudRecordItem> all = cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
  72 + null, mediaServerItems);
  73 + return new PageInfo<>(all);
  74 + }
  75 +
  76 + @Override
  77 + public List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems) {
  78 + LocalDate startDate = LocalDate.of(year, month, 1);
  79 + LocalDate endDate;
  80 + if (month == 12) {
  81 + endDate = LocalDate.of(year + 1, 1, 1);
  82 + }else {
  83 + endDate = LocalDate.of(year, month + 1, 1);
  84 + }
  85 + long startTimeStamp = startDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond();
  86 + long endTimeStamp = endDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond();
  87 + List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp,
  88 + endTimeStamp, null, mediaServerItems);
  89 + if (cloudRecordItemList.isEmpty()) {
  90 + return new ArrayList<>();
  91 + }
  92 + Set<String> resultSet = new HashSet<>();
  93 + cloudRecordItemList.stream().forEach(cloudRecordItem -> {
  94 + String date = DateUtil.timestampTo_yyyy_MM_dd(cloudRecordItem.getStartTime());
  95 + resultSet.add(date);
  96 + });
  97 + return new ArrayList<>(resultSet);
  98 + }
  99 +
  100 + @Override
  101 + public void addRecord(OnRecordMp4HookParam param) {
  102 + CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(param);
  103 + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
  104 + if (streamAuthorityInfo != null) {
  105 + cloudRecordItem.setCallId(streamAuthorityInfo.getCallId());
  106 + }
  107 + logger.info("[添加录像记录] {}/{} 文件大小:{}, 时长: {}秒", param.getApp(), param.getStream(), param.getFile_size(),param.getTime_len());
  108 + cloudRecordServiceMapper.add(cloudRecordItem);
  109 + }
  110 +
  111 + @Override
  112 + public String addTask(String app, String stream, String mediaServerId, String startTime, String endTime, String callId, String remoteHost) {
  113 + // 参数校验
  114 + assert app != null;
  115 + assert stream != null;
  116 + MediaServerItem mediaServerItem = null;
  117 + if (mediaServerId == null) {
  118 + mediaServerItem = mediaServerService.getDefaultMediaServer();
  119 + }else {
  120 + mediaServerItem = mediaServerService.getOne(mediaServerId);
  121 + }
  122 + if (mediaServerItem == null) {
  123 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的流媒体");
  124 + }else {
  125 + if (remoteHost == null) {
  126 + remoteHost = "http://" + mediaServerItem.getStreamIp() + ":" + mediaServerItem.getRecordAssistPort();
  127 + }
  128 + }
  129 + if (mediaServerItem.getRecordAssistPort() == 0) {
  130 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "为配置Assist服务");
  131 + }
  132 + Long startTimeStamp = null;
  133 + Long endTimeStamp = null;
  134 + if (startTime != null) {
  135 + startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
  136 + }
  137 + if (endTime != null) {
  138 + endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
  139 + }
  140 +
  141 + List<MediaServerItem> mediaServers = new ArrayList<>();
  142 + mediaServers.add(mediaServerItem);
  143 + // 检索相关的录像文件
  144 + List<String> filePathList = cloudRecordServiceMapper.queryRecordFilePathList(app, stream, startTimeStamp, endTimeStamp, callId, mediaServers);
  145 + if (filePathList == null || filePathList.isEmpty()) {
  146 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未检索到视频文件");
  147 + }
  148 + JSONObject result = assistRESTfulUtils.addTask(mediaServerItem, app, stream, startTime, endTime, callId, filePathList, remoteHost);
  149 + if (result.getInteger("code") != 0) {
  150 + throw new ControllerException(result.getInteger("code"), result.getString("msg"));
  151 + }
  152 + return result.getString("data");
  153 + }
  154 +
  155 + @Override
  156 + public JSONArray queryTask(String app, String stream, String callId, String taskId, String mediaServerId, Boolean isEnd) {
  157 + MediaServerItem mediaServerItem = null;
  158 + if (mediaServerId == null) {
  159 + mediaServerItem = mediaServerService.getDefaultMediaServer();
  160 + }else {
  161 + mediaServerItem = mediaServerService.getOne(mediaServerId);
  162 + }
  163 + if (mediaServerItem == null) {
  164 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的流媒体");
  165 + }
  166 + JSONObject result = assistRESTfulUtils.queryTaskList(mediaServerItem, app, stream, callId, taskId, isEnd);
  167 + if (result.getInteger("code") != 0) {
  168 + throw new ControllerException(result.getInteger("code"), result.getString("msg"));
  169 + }
  170 + return result.getJSONArray("data");
  171 + }
  172 +
  173 + @Override
  174 + public int changeCollect(boolean result, String app, String stream, String mediaServerId, String startTime, String endTime, String callId) {
  175 + // 开始时间和结束时间在数据库中都是以秒为单位的
  176 + Long startTimeStamp = null;
  177 + Long endTimeStamp = null;
  178 + if (startTime != null ) {
  179 + if (!DateUtil.verification(startTime, DateUtil.formatter)) {
  180 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间格式错误,正确格式为: " + DateUtil.formatter);
  181 + }
  182 + startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
  183 +
  184 + }
  185 + if (endTime != null ) {
  186 + if (!DateUtil.verification(endTime, DateUtil.formatter)) {
  187 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "结束时间格式错误,正确格式为: " + DateUtil.formatter);
  188 + }
  189 + endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
  190 +
  191 + }
  192 +
  193 + List<MediaServerItem> mediaServerItems;
  194 + if (!ObjectUtils.isEmpty(mediaServerId)) {
  195 + mediaServerItems = new ArrayList<>();
  196 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  197 + if (mediaServerItem == null) {
  198 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
  199 + }
  200 + mediaServerItems.add(mediaServerItem);
  201 + } else {
  202 + mediaServerItems = null;
  203 + }
  204 +
  205 + List<CloudRecordItem> all = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp, endTimeStamp,
  206 + callId, mediaServerItems);
  207 + if (all.isEmpty()) {
  208 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到待收藏的视频");
  209 + }
  210 + int limitCount = 50;
  211 + int resultCount = 0;
  212 + if (all.size() > limitCount) {
  213 + for (int i = 0; i < all.size(); i += limitCount) {
  214 + int toIndex = i + limitCount;
  215 + if (i + limitCount > all.size()) {
  216 + toIndex = all.size();
  217 + }
  218 + resultCount += cloudRecordServiceMapper.updateCollectList(result, all.subList(i, toIndex));
  219 +
  220 + }
  221 + }else {
  222 + resultCount = cloudRecordServiceMapper.updateCollectList(result, all);
  223 + }
  224 + return resultCount;
  225 + }
  226 +
  227 + @Override
  228 + public int changeCollectById(Integer recordId, boolean result) {
  229 + return cloudRecordServiceMapper.changeCollectById(result, recordId);
  230 + }
  231 +
  232 + @Override
  233 + public DownloadFileInfo getPlayUrlPath(Integer recordId) {
  234 + CloudRecordItem recordItem = cloudRecordServiceMapper.queryOne(recordId);
  235 + if (recordItem == null) {
  236 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在");
  237 + }
  238 + String filePath = recordItem.getFilePath();
  239 + MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
  240 + return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
  241 + }
  242 +}
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -162,6 +162,19 @@ public class DeviceServiceImpl implements IDeviceService { @@ -162,6 +162,19 @@ public class DeviceServiceImpl implements IDeviceService {
162 sync(device); 162 sync(device);
163 // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台 163 // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
164 } 164 }
  165 + // 上线添加订阅
  166 + if (device.getSubscribeCycleForCatalog() > 0) {
  167 + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
  168 + addCatalogSubscribe(device);
  169 + }
  170 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  171 + addMobilePositionSubscribe(device);
  172 + }
  173 + if (userSetting.getDeviceStatusNotify()) {
  174 + // 发送redis消息
  175 + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, true);
  176 + }
  177 +
165 }else { 178 }else {
166 if (deviceChannelMapper.queryAllChannels(device.getDeviceId()).size() == 0) { 179 if (deviceChannelMapper.queryAllChannels(device.getDeviceId()).size() == 0) {
167 logger.info("[设备上线]: {},通道数为0,查询通道信息", device.getDeviceId()); 180 logger.info("[设备上线]: {},通道数为0,查询通道信息", device.getDeviceId());
@@ -174,22 +187,10 @@ public class DeviceServiceImpl implements IDeviceService { @@ -174,22 +187,10 @@ public class DeviceServiceImpl implements IDeviceService {
174 187
175 } 188 }
176 189
177 - // 上线添加订阅  
178 - if (device.getSubscribeCycleForCatalog() > 0) {  
179 - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅  
180 - addCatalogSubscribe(device);  
181 - }  
182 - if (device.getSubscribeCycleForMobilePosition() > 0) {  
183 - addMobilePositionSubscribe(device);  
184 - }  
185 // 刷新过期任务 190 // 刷新过期任务
186 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); 191 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
187 // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 192 // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线
188 dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3); 193 dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3);
189 - if (userSetting.getDeviceStatusNotify()) {  
190 - // 发送redis消息  
191 - redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, true);  
192 - }  
193 194
194 // 195 //
195 // try { 196 // try {
@@ -213,6 +214,13 @@ public class DeviceServiceImpl implements IDeviceService { @@ -213,6 +214,13 @@ public class DeviceServiceImpl implements IDeviceService {
213 } 214 }
214 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId; 215 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId;
215 dynamicTask.stop(registerExpireTaskKey); 216 dynamicTask.stop(registerExpireTaskKey);
  217 + if (device.isOnLine()) {
  218 + if (userSetting.getDeviceStatusNotify()) {
  219 + // 发送redis消息
  220 + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
  221 + }
  222 + }
  223 +
216 device.setOnLine(false); 224 device.setOnLine(false);
217 redisCatchStorage.updateDevice(device); 225 redisCatchStorage.updateDevice(device);
218 deviceMapper.update(device); 226 deviceMapper.update(device);
@@ -224,7 +232,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -224,7 +232,7 @@ public class DeviceServiceImpl implements IDeviceService {
224 for (SsrcTransaction ssrcTransaction : ssrcTransactions) { 232 for (SsrcTransaction ssrcTransaction : ssrcTransactions) {
225 mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); 233 mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());
226 mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); 234 mediaServerService.closeRTPServer(ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());
227 - streamSession.remove(deviceId, ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); 235 + streamSession.removeByCallId(deviceId, ssrcTransaction.getChannelId(), ssrcTransaction.getCallId());
228 } 236 }
229 } 237 }
230 // 移除订阅 238 // 移除订阅
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
@@ -250,9 +250,6 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -250,9 +250,6 @@ public class GbStreamServiceImpl implements IGbStreamService {
250 if (platform == null) { 250 if (platform == null) {
251 return ; 251 return ;
252 } 252 }
253 - if (ObjectUtils.isEmpty(catalogId)) {  
254 - catalogId = platform.getDeviceGBId();  
255 - }  
256 if (platformGbStreamMapper.delByPlatformAndCatalogId(platformId, catalogId) > 0) { 253 if (platformGbStreamMapper.delByPlatformAndCatalogId(platformId, catalogId) > 0) {
257 List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId); 254 List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId);
258 List<DeviceChannel> deviceChannelList = new ArrayList<>(); 255 List<DeviceChannel> deviceChannelList = new ArrayList<>();
src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java
@@ -116,9 +116,12 @@ public class InviteStreamServiceImpl implements IInviteStreamService { @@ -116,9 +116,12 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
116 ":" + (stream != null ? stream : "*") 116 ":" + (stream != null ? stream : "*")
117 + ":*"; 117 + ":*";
118 List<Object> scanResult = RedisUtil.scan(redisTemplate, key); 118 List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
119 - if (scanResult.size() != 1) { 119 + if (scanResult.isEmpty()) {
120 return null; 120 return null;
121 } 121 }
  122 + if (scanResult.size() != 1) {
  123 + logger.warn("[获取InviteInfo] 发现 key: {}存在多条", key);
  124 + }
122 125
123 return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0)); 126 return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0));
124 } 127 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -165,14 +165,13 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -165,14 +165,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
165 if (streamId == null) { 165 if (streamId == null) {
166 streamId = String.format("%08x", Long.parseLong(ssrc)).toUpperCase(); 166 streamId = String.format("%08x", Long.parseLong(ssrc)).toUpperCase();
167 } 167 }
168 - int ssrcCheckParam = 0;  
169 - if (ssrcCheck && tcpMode > 1) { 168 + if (ssrcCheck && tcpMode > 0) {
170 // 目前zlm不支持 tcp模式更新ssrc,暂时关闭ssrc校验 169 // 目前zlm不支持 tcp模式更新ssrc,暂时关闭ssrc校验
171 - logger.warn("[openRTPServer] TCP被动/TCP主动收流时,默认关闭ssrc检验"); 170 + logger.warn("[openRTPServer] 平台对接时下级可能自定义ssrc,但是tcp模式zlm收流目前无法更新ssrc,可能收流超时,此时请使用udp收流或者关闭ssrc校验");
172 } 171 }
173 int rtpServerPort; 172 int rtpServerPort;
174 if (mediaServerItem.isRtpEnable()) { 173 if (mediaServerItem.isRtpEnable()) {
175 - rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, (ssrcCheck && tcpMode == 0) ? Long.parseLong(ssrc) : 0, port, onlyAuto, reUsePort, tcpMode); 174 + rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, onlyAuto, reUsePort, tcpMode);
176 } else { 175 } else {
177 rtpServerPort = mediaServerItem.getRtpProxyPort(); 176 rtpServerPort = mediaServerItem.getRtpProxyPort();
178 } 177 }
@@ -205,7 +204,10 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -205,7 +204,10 @@ public class MediaServerServiceImpl implements IMediaServerService {
205 @Override 204 @Override
206 public void closeRTPServer(String mediaServerId, String streamId) { 205 public void closeRTPServer(String mediaServerId, String streamId) {
207 MediaServerItem mediaServerItem = this.getOne(mediaServerId); 206 MediaServerItem mediaServerItem = this.getOne(mediaServerId);
208 - closeRTPServer(mediaServerItem, streamId); 207 + if (mediaServerItem.isRtpEnable()) {
  208 + closeRTPServer(mediaServerItem, streamId);
  209 + }
  210 + zlmresTfulUtils.closeStreams(mediaServerItem, "rtp", streamId);
209 } 211 }
210 212
211 @Override 213 @Override
@@ -428,17 +430,6 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -428,17 +430,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
428 430
429 431
430 if (serverItem.isAutoConfig()) { 432 if (serverItem.isAutoConfig()) {
431 - // 查看assist服务的录像路径配置  
432 - if (serverItem.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {  
433 - JSONObject info = assistRESTfulUtils.getInfo(serverItem, null);  
434 - if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) {  
435 - JSONObject dataJson = info.getJSONObject("data");  
436 - if (dataJson != null) {  
437 - String recordPath = dataJson.getString("record");  
438 - userSetting.setRecordPath(recordPath);  
439 - }  
440 - }  
441 - }  
442 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); 433 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
443 } 434 }
444 final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); 435 final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId();
@@ -573,7 +564,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -573,7 +564,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
573 logger.info("[ZLM] 正在设置 :{} -> {}:{}", 564 logger.info("[ZLM] 正在设置 :{} -> {}:{}",
574 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); 565 mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
575 String protocol = sslEnabled ? "https" : "http"; 566 String protocol = sslEnabled ? "https" : "http";
576 - String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); 567 + String hookPrefix = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
577 568
578 Map<String, Object> param = new HashMap<>(); 569 Map<String, Object> param = new HashMap<>();
579 param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline 570 param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
@@ -582,25 +573,21 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -582,25 +573,21 @@ public class MediaServerServiceImpl implements IMediaServerService {
582 } 573 }
583 param.put("hook.enable","1"); 574 param.put("hook.enable","1");
584 param.put("hook.on_flow_report",""); 575 param.put("hook.on_flow_report","");
585 - param.put("hook.on_play",String.format("%s/on_play", hookPrex)); 576 + param.put("hook.on_play",String.format("%s/on_play", hookPrefix));
586 param.put("hook.on_http_access",""); 577 param.put("hook.on_http_access","");
587 - param.put("hook.on_publish", String.format("%s/on_publish", hookPrex)); 578 + param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix));
588 param.put("hook.on_record_ts",""); 579 param.put("hook.on_record_ts","");
589 param.put("hook.on_rtsp_auth",""); 580 param.put("hook.on_rtsp_auth","");
590 param.put("hook.on_rtsp_realm",""); 581 param.put("hook.on_rtsp_realm","");
591 - param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex)); 582 + param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrefix));
592 param.put("hook.on_shell_login",""); 583 param.put("hook.on_shell_login","");
593 - param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex));  
594 - param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));  
595 - param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));  
596 - param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));  
597 - param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrex));  
598 - param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrex));  
599 - if (mediaServerItem.getRecordAssistPort() > 0) {  
600 - param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort()));  
601 - }else {  
602 - param.put("hook.on_record_mp4","");  
603 - } 584 + param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix));
  585 + param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix));
  586 + param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix));
  587 + param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix));
  588 + param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix));
  589 + param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix));
  590 + param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix));
604 param.put("hook.timeoutSec","20"); 591 param.put("hook.timeoutSec","20");
605 // 推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。 592 // 推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
606 // 置0关闭此特性(推流断开会导致立即断开播放器) 593 // 置0关闭此特性(推流断开会导致立即断开播放器)
@@ -609,15 +596,14 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -609,15 +596,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
609 param.put("protocol.continue_push_ms", "3000" ); 596 param.put("protocol.continue_push_ms", "3000" );
610 // 最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track, 设置此选项优化那些音频错误的不规范流, 597 // 最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track, 设置此选项优化那些音频错误的不规范流,
611 // 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项 598 // 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项
612 -// param.put("general.wait_track_ready_ms", "3000" );  
613 if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) { 599 if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
614 param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); 600 param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
615 } 601 }
616 602
617 - if (userSetting.getRecordPath() != null) {  
618 - File recordPathFile = new File(userSetting.getRecordPath());  
619 - File mp4SavePathFile = recordPathFile.getParentFile().getAbsoluteFile();  
620 - param.put("protocol.mp4_save_path", mp4SavePathFile.getAbsoluteFile()); 603 + if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) {
  604 + File recordPathFile = new File(mediaServerItem.getRecordPath());
  605 + param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath());
  606 + param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath());
621 param.put("record.appName", recordPathFile.getName()); 607 param.put("record.appName", recordPathFile.getName());
622 } 608 }
623 609
@@ -722,6 +708,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -722,6 +708,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
722 ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); 708 ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
723 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); 709 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
724 redisTemplate.opsForValue().set(key, mediaServerItem); 710 redisTemplate.opsForValue().set(key, mediaServerItem);
  711 + resetOnlineServerItem(mediaServerItem);
725 clearRTPServer(mediaServerItem); 712 clearRTPServer(mediaServerItem);
726 } 713 }
727 final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId(); 714 final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId();
@@ -750,15 +737,6 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -750,15 +737,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
750 } 737 }
751 738
752 @Override 739 @Override
753 - public boolean checkRtpServer(MediaServerItem mediaServerItem, String app, String stream) {  
754 - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, stream);  
755 - if(rtpInfo.getInteger("code") == 0){  
756 - return rtpInfo.getBoolean("exist");  
757 - }  
758 - return false;  
759 - }  
760 -  
761 - @Override  
762 public MediaServerLoad getLoad(MediaServerItem mediaServerItem) { 740 public MediaServerLoad getLoad(MediaServerItem mediaServerItem) {
763 MediaServerLoad result = new MediaServerLoad(); 741 MediaServerLoad result = new MediaServerLoad();
764 result.setId(mediaServerItem.getId()); 742 result.setId(mediaServerItem.getId());
@@ -771,88 +749,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -771,88 +749,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
771 } 749 }
772 750
773 @Override 751 @Override
774 - public List<RecordFile> getRecords(String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) {  
775 - Assert.notNull(app, "app不存在");  
776 - Assert.notNull(stream, "stream不存在");  
777 - Assert.notNull(startTime, "startTime不存在");  
778 - Assert.notNull(endTime, "endTime不存在");  
779 - Assert.notEmpty(mediaServerItems, "流媒体列表为空");  
780 -  
781 - CompletableFuture[] completableFutures = new CompletableFuture[mediaServerItems.size()];  
782 - for (int i = 0; i < mediaServerItems.size(); i++) {  
783 - completableFutures[i] = getRecordFilesForOne(app, stream, startTime, endTime, mediaServerItems.get(i));  
784 - }  
785 - List<RecordFile> result = new ArrayList<>();  
786 - for (int i = 0; i < completableFutures.length; i++) {  
787 - try {  
788 - List<RecordFile> list = (List<RecordFile>) completableFutures[i].get();  
789 - if (!list.isEmpty()) {  
790 - for (int g = 0; g < list.size(); g++) {  
791 - list.get(g).setMediaServerId(mediaServerItems.get(i).getId());  
792 - }  
793 - result.addAll(list);  
794 - }  
795 - } catch (InterruptedException e) {  
796 - throw new RuntimeException(e);  
797 - } catch (ExecutionException e) {  
798 - throw new RuntimeException(e);  
799 - }  
800 - }  
801 - Comparator<RecordFile> comparator = Comparator.comparing(RecordFile::getFileName);  
802 - result.sort(comparator);  
803 - return result;  
804 - }  
805 -  
806 - @Override  
807 - public List<String> getRecordDates(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems) {  
808 - Assert.notNull(app, "app不存在");  
809 - Assert.notNull(stream, "stream不存在");  
810 - Assert.notEmpty(mediaServerItems, "流媒体列表为空");  
811 - CompletableFuture[] completableFutures = new CompletableFuture[mediaServerItems.size()];  
812 -  
813 - for (int i = 0; i < mediaServerItems.size(); i++) {  
814 - completableFutures[i] = getRecordDatesForOne(app, stream, year, month, mediaServerItems.get(i));  
815 - }  
816 - List<String> result = new ArrayList<>();  
817 - CompletableFuture.allOf(completableFutures).join();  
818 - for (CompletableFuture completableFuture : completableFutures) {  
819 - try {  
820 - List<String> list = (List<String>) completableFuture.get();  
821 - result.addAll(list);  
822 - } catch (InterruptedException e) {  
823 - throw new RuntimeException(e);  
824 - } catch (ExecutionException e) {  
825 - throw new RuntimeException(e);  
826 - }  
827 - }  
828 - Collections.sort(result);  
829 - return result;  
830 - }  
831 -  
832 - @Async  
833 - public CompletableFuture<List<String>> getRecordDatesForOne(String app, String stream, int year, int month, MediaServerItem mediaServerItem) {  
834 - JSONObject fileListJson = assistRESTfulUtils.getDateList(mediaServerItem, app, stream, year, month);  
835 - if (fileListJson != null && !fileListJson.isEmpty()) {  
836 - if (fileListJson.getString("code") != null && fileListJson.getInteger("code") == 0) {  
837 - JSONArray data = fileListJson.getJSONArray("data");  
838 - return CompletableFuture.completedFuture(data.toJavaList(String.class));  
839 - }  
840 - }  
841 - return CompletableFuture.completedFuture(new ArrayList<>());  
842 - }  
843 -  
844 - @Async  
845 - public CompletableFuture<List<RecordFile>> getRecordFilesForOne(String app, String stream, String startTime, String endTime, MediaServerItem mediaServerItem) {  
846 - JSONObject fileListJson = assistRESTfulUtils.getFileList(mediaServerItem, 1, 100000000, app, stream, startTime, endTime);  
847 - if (fileListJson != null && !fileListJson.isEmpty()) {  
848 - if (fileListJson.getString("code") != null && fileListJson.getInteger("code") == 0) {  
849 - JSONObject data = fileListJson.getJSONObject("data");  
850 - JSONArray list = data.getJSONArray("list");  
851 - if (list != null) {  
852 - return CompletableFuture.completedFuture(list.toJavaList(RecordFile.class));  
853 - }  
854 - }  
855 - }  
856 - return CompletableFuture.completedFuture(new ArrayList<>()); 752 + public List<MediaServerItem> getAllWithAssistPort() {
  753 + return mediaServerMapper.queryAllWithAssistPort();
857 } 754 }
858 } 755 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -64,7 +64,7 @@ public class MediaServiceImpl implements IMediaService { @@ -64,7 +64,7 @@ public class MediaServiceImpl implements IMediaService {
64 if (data == null) { 64 if (data == null) {
65 return null; 65 return null;
66 } 66 }
67 - JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class); 67 + JSONObject mediaJSON = data.getJSONObject(0);
68 JSONArray tracks = mediaJSON.getJSONArray("tracks"); 68 JSONArray tracks = mediaJSON.getJSONArray("tracks");
69 if (authority) { 69 if (authority) {
70 streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld, true); 70 streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld, true);
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
@@ -169,7 +169,7 @@ public class PlatformServiceImpl implements IPlatformService { @@ -169,7 +169,7 @@ public class PlatformServiceImpl implements IPlatformService {
169 dynamicTask.stop(registerTaskKey); 169 dynamicTask.stop(registerTaskKey);
170 // 注销旧的 170 // 注销旧的
171 try { 171 try {
172 - if (parentPlatformOld.isStatus()) { 172 + if (parentPlatformOld.isStatus() && parentPlatformCatchOld != null) {
173 logger.info("保存平台{}时发现旧平台在线,发送注销命令", parentPlatformOld.getServerGBId()); 173 logger.info("保存平台{}时发现旧平台在线,发送注销命令", parentPlatformOld.getServerGBId());
174 commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> { 174 commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> {
175 logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId()); 175 logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId());
@@ -286,6 +286,7 @@ public class PlatformServiceImpl implements IPlatformService { @@ -286,6 +286,7 @@ public class PlatformServiceImpl implements IPlatformService {
286 } 286 }
287 if (parentPlatform.isAutoPushChannel()) { 287 if (parentPlatform.isAutoPushChannel()) {
288 if (subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId()) == null) { 288 if (subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId()) == null) {
  289 + logger.info("[国标级联]:{}, 添加自动通道推送模拟订阅信息", parentPlatform.getServerGBId());
289 addSimulatedSubscribeInfo(parentPlatform); 290 addSimulatedSubscribeInfo(parentPlatform);
290 } 291 }
291 }else { 292 }else {
@@ -363,9 +364,16 @@ public class PlatformServiceImpl implements IPlatformService { @@ -363,9 +364,16 @@ public class PlatformServiceImpl implements IPlatformService {
363 // 清除心跳任务 364 // 清除心跳任务
364 dynamicTask.stop(keepaliveTaskKey); 365 dynamicTask.stop(keepaliveTaskKey);
365 } 366 }
366 - // 停止目录订阅回复  
367 - logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId());  
368 - subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); 367 + // 停止订阅回复
  368 + SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId());
  369 + if (catalogSubscribe != null) {
  370 + if (catalogSubscribe.getExpires() > 0) {
  371 + logger.info("[平台离线] {}, 停止目录订阅回复", parentPlatform.getServerGBId());
  372 + subscribeHolder.removeCatalogSubscribe(parentPlatform.getServerGBId());
  373 + }
  374 + }
  375 + logger.info("[平台离线] {}, 停止移动位置订阅回复", parentPlatform.getServerGBId());
  376 + subscribeHolder.removeMobilePositionSubscribe(parentPlatform.getServerGBId());
369 // 发起定时自动重新注册 377 // 发起定时自动重新注册
370 if (!stopRegister) { 378 if (!stopRegister) {
371 // 设置为60秒自动尝试重新注册 379 // 设置为60秒自动尝试重新注册
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
  3 +import com.alibaba.fastjson2.JSONArray;
3 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
4 import com.genersoft.iot.vmp.common.InviteInfo; 5 import com.genersoft.iot.vmp.common.InviteInfo;
5 import com.genersoft.iot.vmp.common.InviteSessionStatus; 6 import com.genersoft.iot.vmp.common.InviteSessionStatus;
@@ -19,13 +20,19 @@ import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; @@ -19,13 +20,19 @@ import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
19 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
21 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 22 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
  23 +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  24 +import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
  25 +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
  26 +import com.genersoft.iot.vmp.media.zlm.dto.*;
22 import com.genersoft.iot.vmp.media.zlm.*; 27 import com.genersoft.iot.vmp.media.zlm.*;
23 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; 28 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
24 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; 29 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
25 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 30 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
26 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; 31 import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
  32 +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
27 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; 33 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
28 import com.genersoft.iot.vmp.service.*; 34 import com.genersoft.iot.vmp.service.*;
  35 +import com.genersoft.iot.vmp.service.bean.*;
29 import com.genersoft.iot.vmp.service.bean.ErrorCallback; 36 import com.genersoft.iot.vmp.service.bean.ErrorCallback;
30 import com.genersoft.iot.vmp.service.bean.InviteErrorCode; 37 import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
31 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; 38 import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg;
@@ -33,6 +40,8 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -33,6 +40,8 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
33 import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; 40 import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
34 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 41 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
35 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 42 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  43 +import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
  44 +import com.genersoft.iot.vmp.utils.CloudRecordUtils;
36 import com.genersoft.iot.vmp.utils.DateUtil; 45 import com.genersoft.iot.vmp.utils.DateUtil;
37 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; 46 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
38 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 47 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
@@ -90,12 +99,18 @@ public class PlayServiceImpl implements IPlayService { @@ -90,12 +99,18 @@ public class PlayServiceImpl implements IPlayService {
90 private IInviteStreamService inviteStreamService; 99 private IInviteStreamService inviteStreamService;
91 100
92 @Autowired 101 @Autowired
  102 + private ZlmHttpHookSubscribe subscribe;
  103 +
  104 + @Autowired
93 private SendRtpPortManager sendRtpPortManager; 105 private SendRtpPortManager sendRtpPortManager;
94 106
95 @Autowired 107 @Autowired
96 private ZLMRESTfulUtils zlmresTfulUtils; 108 private ZLMRESTfulUtils zlmresTfulUtils;
97 109
98 @Autowired 110 @Autowired
  111 + private ZLMServerFactory zlmServerFactory;
  112 +
  113 + @Autowired
99 private AssistRESTfulUtils assistRESTfulUtils; 114 private AssistRESTfulUtils assistRESTfulUtils;
100 115
101 @Autowired 116 @Autowired
@@ -117,7 +132,7 @@ public class PlayServiceImpl implements IPlayService { @@ -117,7 +132,7 @@ public class PlayServiceImpl implements IPlayService {
117 private DynamicTask dynamicTask; 132 private DynamicTask dynamicTask;
118 133
119 @Autowired 134 @Autowired
120 - private ZlmHttpHookSubscribe subscribe; 135 + private CloudRecordServiceMapper cloudRecordServiceMapper;
121 136
122 @Autowired 137 @Autowired
123 private ISIPCommanderForPlatform commanderForPlatform; 138 private ISIPCommanderForPlatform commanderForPlatform;
@@ -407,6 +422,15 @@ public class PlayServiceImpl implements IPlayService { @@ -407,6 +422,15 @@ public class PlayServiceImpl implements IPlayService {
407 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); 422 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
408 subscribe.removeSubscribe(hookSubscribe); 423 subscribe.removeSubscribe(hookSubscribe);
409 } 424 }
  425 + }else {
  426 + logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流类型:{},端口:{}, SSRC: {}",
  427 + device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流",
  428 + ssrcInfo.getPort(), ssrcInfo.getSsrc());
  429 +
  430 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  431 +
  432 + mediaServerService.closeRTPServer(mediaServerItem.getId(), ssrcInfo.getStream());
  433 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
410 } 434 }
411 }, userSetting.getPlayTimeout()); 435 }, userSetting.getPlayTimeout());
412 436
@@ -437,6 +461,7 @@ public class PlayServiceImpl implements IPlayService { @@ -437,6 +461,7 @@ public class PlayServiceImpl implements IPlayService {
437 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, 461 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
438 timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY); 462 timeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAY);
439 }, (event) -> { 463 }, (event) -> {
  464 + logger.info("[点播失败] deviceId: {}, channelId:{}, {}: {}", device.getDeviceId(), channelId, event.statusCode, event.msg);
440 dynamicTask.stop(timeOutTaskKey); 465 dynamicTask.stop(timeOutTaskKey);
441 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 466 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
442 // 释放ssrc 467 // 释放ssrc
@@ -478,7 +503,13 @@ public class PlayServiceImpl implements IPlayService { @@ -478,7 +503,13 @@ public class PlayServiceImpl implements IPlayService {
478 if (!device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { 503 if (!device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
479 return; 504 return;
480 } 505 }
481 - String substring = contentString.substring(0, contentString.indexOf("y=")); 506 +
  507 + String substring;
  508 + if (contentString.indexOf("y=") > 0) {
  509 + substring = contentString.substring(0, contentString.indexOf("y="));
  510 + }else {
  511 + substring = contentString;
  512 + }
482 try { 513 try {
483 SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring); 514 SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
484 int port = -1; 515 int port = -1;
@@ -598,23 +629,6 @@ public class PlayServiceImpl implements IPlayService { @@ -598,23 +629,6 @@ public class PlayServiceImpl implements IPlayService {
598 } 629 }
599 630
600 @Override 631 @Override
601 - public MediaServerItem getNewMediaServerItemHasAssist(Device device) {  
602 - if (device == null) {  
603 - return null;  
604 - }  
605 - MediaServerItem mediaServerItem;  
606 - if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) {  
607 - mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(true);  
608 - } else {  
609 - mediaServerItem = mediaServerService.getOne(device.getMediaServerId());  
610 - }  
611 - if (mediaServerItem == null) {  
612 - logger.warn("[获取可用的ZLM节点]未找到可使用的ZLM...");  
613 - }  
614 - return mediaServerItem;  
615 - }  
616 -  
617 - @Override  
618 public void playBack(String deviceId, String channelId, String startTime, 632 public void playBack(String deviceId, String channelId, String startTime,
619 String endTime, ErrorCallback<Object> callback) { 633 String endTime, ErrorCallback<Object> callback) {
620 Device device = storager.queryVideoDevice(deviceId); 634 Device device = storager.queryVideoDevice(deviceId);
@@ -711,7 +725,6 @@ public class PlayServiceImpl implements IPlayService { @@ -711,7 +725,6 @@ public class PlayServiceImpl implements IPlayService {
711 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题 725 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
712 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, 726 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
713 playBackTimeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAYBACK); 727 playBackTimeOutTaskKey, callback, inviteInfo, InviteSessionType.PLAYBACK);
714 -  
715 }, errorEvent); 728 }, errorEvent);
716 } catch (InvalidArgumentException | SipException | ParseException e) { 729 } catch (InvalidArgumentException | SipException | ParseException e) {
717 logger.error("[命令发送失败] 录像回放: {}", e.getMessage()); 730 logger.error("[命令发送失败] 录像回放: {}", e.getMessage());
@@ -732,6 +745,10 @@ public class PlayServiceImpl implements IPlayService { @@ -732,6 +745,10 @@ public class PlayServiceImpl implements IPlayService {
732 ResponseEvent responseEvent = (ResponseEvent) eventResult.event; 745 ResponseEvent responseEvent = (ResponseEvent) eventResult.event;
733 String contentString = new String(responseEvent.getResponse().getRawContent()); 746 String contentString = new String(responseEvent.getResponse().getRawContent());
734 String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); 747 String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString);
  748 + // 兼容回复的消息中缺少ssrc(y字段)的情况
  749 + if (ssrcInResponse == null) {
  750 + ssrcInResponse = ssrcInfo.getSsrc();
  751 + }
735 if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { 752 if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
736 // ssrc 一致 753 // ssrc 一致
737 if (mediaServerItem.isRtpEnable()) { 754 if (mediaServerItem.isRtpEnable()) {
@@ -809,13 +826,15 @@ public class PlayServiceImpl implements IPlayService { @@ -809,13 +826,15 @@ public class PlayServiceImpl implements IPlayService {
809 } 826 }
810 827
811 828
  829 +
  830 +
812 @Override 831 @Override
813 public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) { 832 public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) {
814 Device device = storager.queryVideoDevice(deviceId); 833 Device device = storager.queryVideoDevice(deviceId);
815 if (device == null) { 834 if (device == null) {
816 return; 835 return;
817 } 836 }
818 - MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); 837 + MediaServerItem newMediaServerItem = this.getNewMediaServerItem(device);
819 if (newMediaServerItem == null) { 838 if (newMediaServerItem == null) {
820 callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), 839 callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(),
821 InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(), 840 InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(),
@@ -894,6 +913,28 @@ public class PlayServiceImpl implements IPlayService { @@ -894,6 +913,28 @@ public class PlayServiceImpl implements IPlayService {
894 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题 913 // 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
895 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId, 914 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
896 downLoadTimeOutTaskKey, callback, inviteInfo, InviteSessionType.DOWNLOAD); 915 downLoadTimeOutTaskKey, callback, inviteInfo, InviteSessionType.DOWNLOAD);
  916 +
  917 + // 注册录像回调事件,录像下载结束后写入下载地址
  918 + ZlmHttpHookSubscribe.Event hookEventForRecord = (mediaServerItemInuse, hookParam) -> {
  919 + logger.info("[录像下载] 收到录像写入磁盘消息: , {}/{}-{}",
  920 + inviteInfo.getDeviceId(), inviteInfo.getChannelId(), ssrcInfo.getStream());
  921 + logger.info("[录像下载] 收到录像写入磁盘消息内容: " + hookParam);
  922 + OnRecordMp4HookParam recordMp4HookParam = (OnRecordMp4HookParam)hookParam;
  923 + String filePath = recordMp4HookParam.getFile_path();
  924 + DownloadFileInfo downloadFileInfo = CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
  925 + InviteInfo inviteInfoForNew = inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId()
  926 + , inviteInfo.getChannelId(), inviteInfo.getStream());
  927 + inviteInfoForNew.getStreamInfo().setDownLoadFilePath(downloadFileInfo);
  928 + inviteStreamService.updateInviteInfo(inviteInfoForNew);
  929 + };
  930 + HookSubscribeForRecordMp4 hookSubscribe = HookSubscribeFactory.on_record_mp4(
  931 + mediaServerItem.getId(), "rtp", ssrcInfo.getStream());
  932 +
  933 + // 设置过期时间,下载失败时自动处理订阅数据
  934 +// long difference = DateUtil.getDifference(startTime, endTime)/1000;
  935 +// Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(difference * 2));
  936 +// hookSubscribe.setExpires(expiresInstant);
  937 + subscribe.addSubscribe(hookSubscribe, hookEventForRecord);
897 }); 938 });
898 } catch (InvalidArgumentException | SipException | ParseException e) { 939 } catch (InvalidArgumentException | SipException | ParseException e) {
899 logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); 940 logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
@@ -909,47 +950,71 @@ public class PlayServiceImpl implements IPlayService { @@ -909,47 +950,71 @@ public class PlayServiceImpl implements IPlayService {
909 @Override 950 @Override
910 public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) { 951 public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) {
911 InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream); 952 InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream);
  953 + if (inviteInfo == null || inviteInfo.getStreamInfo() == null) {
  954 + logger.warn("[获取下载进度] 未查询到录像下载的信息");
  955 + return null;
  956 + }
912 957
913 - if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {  
914 - if (inviteInfo.getStreamInfo().getProgress() == 1) {  
915 - return inviteInfo.getStreamInfo();  
916 - } 958 + if (inviteInfo.getStreamInfo().getProgress() == 1) {
  959 + return inviteInfo.getStreamInfo();
  960 + }
917 961
918 - // 获取当前已下载时长  
919 - String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();  
920 - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);  
921 - if (mediaServerItem == null) {  
922 - logger.warn("查询录像信息时发现节点已离线");  
923 - return null;  
924 - }  
925 - if (mediaServerItem.getRecordAssistPort() > 0) {  
926 - JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream(), null);  
927 - if (jsonObject == null) {  
928 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败");  
929 - }  
930 - if (jsonObject.getInteger("code") == 0) {  
931 - long duration = jsonObject.getLong("data"); 962 + // 获取当前已下载时长
  963 + String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();
  964 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  965 + if (mediaServerItem == null) {
  966 + logger.warn("[获取下载进度] 查询录像信息时发现节点不存在");
  967 + return null;
  968 + }
  969 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, null, stream);
932 970
933 - if (duration == 0) {  
934 - inviteInfo.getStreamInfo().setProgress(0);  
935 - } else {  
936 - String startTime = inviteInfo.getStreamInfo().getStartTime();  
937 - String endTime = inviteInfo.getStreamInfo().getEndTime();  
938 - long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);  
939 - long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);  
940 -  
941 - BigDecimal currentCount = new BigDecimal(duration / 1000);  
942 - BigDecimal totalCount = new BigDecimal(end - start);  
943 - BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP);  
944 - double process = divide.doubleValue();  
945 - inviteInfo.getStreamInfo().setProgress(process);  
946 - }  
947 - inviteStreamService.updateInviteInfo(inviteInfo);  
948 - } 971 + if (ssrcTransaction == null) {
  972 + logger.warn("[获取下载进度] 下载已结束");
  973 + return null;
  974 + }
  975 +
  976 + JSONObject mediaListJson= zlmresTfulUtils.getMediaList(mediaServerItem, "rtp", stream);
  977 + if (mediaListJson == null) {
  978 + logger.warn("[获取下载进度] 从zlm查询进度失败");
  979 + return null;
  980 + }
  981 + if (mediaListJson.getInteger("code") != 0) {
  982 + logger.warn("[获取下载进度] 从zlm查询进度出现错误: {}", mediaListJson.getString("msg"));
  983 + return null;
  984 + }
  985 + JSONArray data = mediaListJson.getJSONArray("data");
  986 + if (data == null) {
  987 + logger.warn("[获取下载进度] 从zlm查询进度时未返回数据");
  988 + return null;
  989 + }
  990 + JSONObject mediaJSON = data.getJSONObject(0);
  991 + JSONArray tracks = mediaJSON.getJSONArray("tracks");
  992 + if (tracks.isEmpty()) {
  993 + logger.warn("[获取下载进度] 从zlm查询进度时未返回数据");
  994 + return null;
  995 + }
  996 + JSONObject jsonObject = tracks.getJSONObject(0);
  997 + long duration = jsonObject.getLongValue("duration");
  998 + if (duration == 0) {
  999 + inviteInfo.getStreamInfo().setProgress(0);
  1000 + } else {
  1001 + String startTime = inviteInfo.getStreamInfo().getStartTime();
  1002 + String endTime = inviteInfo.getStreamInfo().getEndTime();
  1003 + // 此时start和end单位是秒
  1004 + long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
  1005 + long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
  1006 +
  1007 + BigDecimal currentCount = new BigDecimal(duration);
  1008 + BigDecimal totalCount = new BigDecimal((end - start) * 1000);
  1009 + BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP);
  1010 + double process = divide.doubleValue();
  1011 + if (process > 0.999) {
  1012 + process = 1.0;
949 } 1013 }
950 - return inviteInfo.getStreamInfo(); 1014 + inviteInfo.getStreamInfo().setProgress(process);
951 } 1015 }
952 - return null; 1016 + inviteStreamService.updateInviteInfo(inviteInfo);
  1017 + return inviteInfo.getStreamInfo();
953 } 1018 }
954 1019
955 private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) { 1020 private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) {
@@ -1219,7 +1284,12 @@ public class PlayServiceImpl implements IPlayService { @@ -1219,7 +1284,12 @@ public class PlayServiceImpl implements IPlayService {
1219 throw new ServiceException("mediaServer不存在"); 1284 throw new ServiceException("mediaServer不存在");
1220 } 1285 }
1221 // zlm 暂停RTP超时检查 1286 // zlm 暂停RTP超时检查
1222 - JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamId); 1287 + // 使用zlm中的流ID
  1288 + String streamKey = inviteInfo.getStream();
  1289 + if (!mediaServerItem.isRtpEnable()) {
  1290 + streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase();
  1291 + }
  1292 + JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamKey);
1223 if (jsonObject == null || jsonObject.getInteger("code") != 0) { 1293 if (jsonObject == null || jsonObject.getInteger("code") != 0) {
1224 throw new ServiceException("暂停RTP接收失败"); 1294 throw new ServiceException("暂停RTP接收失败");
1225 } 1295 }
@@ -1242,7 +1312,12 @@ public class PlayServiceImpl implements IPlayService { @@ -1242,7 +1312,12 @@ public class PlayServiceImpl implements IPlayService {
1242 throw new ServiceException("mediaServer不存在"); 1312 throw new ServiceException("mediaServer不存在");
1243 } 1313 }
1244 // zlm 暂停RTP超时检查 1314 // zlm 暂停RTP超时检查
1245 - JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamId); 1315 + // 使用zlm中的流ID
  1316 + String streamKey = inviteInfo.getStream();
  1317 + if (!mediaServerItem.isRtpEnable()) {
  1318 + streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase();
  1319 + }
  1320 + JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamKey);
1246 if (jsonObject == null || jsonObject.getInteger("code") != 0) { 1321 if (jsonObject == null || jsonObject.getInteger("code") != 0) {
1247 throw new ServiceException("继续RTP接收失败"); 1322 throw new ServiceException("继续RTP接收失败");
1248 } 1323 }
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -126,7 +126,13 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -126,7 +126,13 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
126 } 126 }
127 JSONArray dataArray = jsonObject.getJSONArray("data"); 127 JSONArray dataArray = jsonObject.getJSONArray("data");
128 JSONObject mediaServerConfig = dataArray.getJSONObject(0); 128 JSONObject mediaServerConfig = dataArray.getJSONObject(0);
  129 + if (ObjectUtils.isEmpty(param.getFfmpegCmdKey())) {
  130 + param.setFfmpegCmdKey("ffmpeg.cmd");
  131 + }
129 String ffmpegCmd = mediaServerConfig.getString(param.getFfmpegCmdKey()); 132 String ffmpegCmd = mediaServerConfig.getString(param.getFfmpegCmdKey());
  133 + if (ffmpegCmd == null) {
  134 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "ffmpeg拉流代理无法获取ffmpeg cmd");
  135 + }
130 String schema = getSchemaFromFFmpegCmd(ffmpegCmd); 136 String schema = getSchemaFromFFmpegCmd(ffmpegCmd);
131 if (schema == null) { 137 if (schema == null) {
132 throw new ControllerException(ErrorCode.ERROR100.getCode(), "ffmpeg拉流代理无法从ffmpeg cmd中获取到输出格式"); 138 throw new ControllerException(ErrorCode.ERROR100.getCode(), "ffmpeg拉流代理无法从ffmpeg cmd中获取到输出格式");
@@ -401,6 +407,8 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -401,6 +407,8 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
401 logger.info("启用代理失败: {}/{}->{}({})", app, stream, jsonObject.getString("msg"), 407 logger.info("启用代理失败: {}/{}->{}({})", app, stream, jsonObject.getString("msg"),
402 streamProxy.getSrcUrl() == null? streamProxy.getUrl():streamProxy.getSrcUrl()); 408 streamProxy.getSrcUrl() == null? streamProxy.getUrl():streamProxy.getSrcUrl());
403 } 409 }
  410 + } else if (streamProxy != null && streamProxy.isEnable()) {
  411 + return true ;
404 } 412 }
405 return result; 413 return result;
406 } 414 }
@@ -452,7 +460,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -452,7 +460,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
452 streamProxyMapper.deleteAutoRemoveItemByMediaServerId(mediaServerId); 460 streamProxyMapper.deleteAutoRemoveItemByMediaServerId(mediaServerId);
453 461
454 // 移除拉流代理生成的流信息 462 // 移除拉流代理生成的流信息
455 -// syncPullStream(mediaServerId); 463 + syncPullStream(mediaServerId);
456 464
457 // 恢复流代理, 只查找这个这个流媒体 465 // 恢复流代理, 只查找这个这个流媒体
458 List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer( 466 List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer(
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
@@ -282,6 +282,8 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -282,6 +282,8 @@ public class StreamPushServiceImpl implements IStreamPushService {
282 redisCatchStorage.sendStreamChangeMsg(type, jsonObject); 282 redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
283 // 移除redis内流的信息 283 // 移除redis内流的信息
284 redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream()); 284 redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream());
  285 + // 冗余数据,自己系统中自用
  286 + redisCatchStorage.removePushListItem(offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream(), mediaServerItem.getId());
285 } 287 }
286 } 288 }
287 289
@@ -319,6 +321,9 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -319,6 +321,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
319 jsonObject.put("register", false); 321 jsonObject.put("register", false);
320 jsonObject.put("mediaServerId", mediaServerId); 322 jsonObject.put("mediaServerId", mediaServerId);
321 redisCatchStorage.sendStreamChangeMsg(type, jsonObject); 323 redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
  324 +
  325 + // 冗余数据,自己系统中自用
  326 + redisCatchStorage.removePushListItem(onStreamChangedHookParam.getApp(), onStreamChangedHookParam.getStream(), mediaServerId);
322 } 327 }
323 } 328 }
324 } 329 }
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
@@ -113,8 +113,8 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -113,8 +113,8 @@ public class RedisGbPlayMsgListener implements MessageListener {
113 while (!taskQueue.isEmpty()) { 113 while (!taskQueue.isEmpty()) {
114 Message msg = taskQueue.poll(); 114 Message msg = taskQueue.poll();
115 try { 115 try {
116 - JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class);  
117 - WvpRedisMsg wvpRedisMsg = JSON.to(WvpRedisMsg.class, msgJSON); 116 + WvpRedisMsg wvpRedisMsg = JSON.parseObject(msg.getBody(), WvpRedisMsg.class);
  117 + logger.info("[收到REDIS通知] 消息: {}", JSON.toJSONString(wvpRedisMsg));
118 if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { 118 if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) {
119 continue; 119 continue;
120 } 120 }
@@ -123,7 +123,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -123,7 +123,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
123 123
124 switch (wvpRedisMsg.getCmd()){ 124 switch (wvpRedisMsg.getCmd()){
125 case WvpRedisMsgCmd.GET_SEND_ITEM: 125 case WvpRedisMsgCmd.GET_SEND_ITEM:
126 - RequestSendItemMsg content = JSON.to(RequestSendItemMsg.class, wvpRedisMsg.getContent()); 126 + RequestSendItemMsg content = JSON.parseObject(wvpRedisMsg.getContent(), RequestSendItemMsg.class);
127 requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); 127 requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
128 break; 128 break;
129 case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: 129 case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
@@ -242,7 +242,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -242,7 +242,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
242 result.setData(content); 242 result.setData(content);
243 243
244 WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId, 244 WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId,
245 - WvpRedisMsgCmd.REQUEST_PUSH_STREAM, serial, result); 245 + WvpRedisMsgCmd.REQUEST_PUSH_STREAM, serial, JSON.toJSONString(result));
246 JSONObject jsonObject = (JSONObject)JSON.toJSON(response); 246 JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
247 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); 247 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
248 } 248 }
@@ -260,7 +260,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -260,7 +260,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
260 result.setMsg("流媒体不存在"); 260 result.setMsg("流媒体不存在");
261 261
262 WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId, 262 WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId,
263 - WvpRedisMsgCmd.GET_SEND_ITEM, serial, result); 263 + WvpRedisMsgCmd.GET_SEND_ITEM, serial, JSON.toJSONString(result));
264 264
265 JSONObject jsonObject = (JSONObject)JSON.toJSON(response); 265 JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
266 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); 266 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
@@ -283,7 +283,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -283,7 +283,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
283 WVPResult<SendRtpItem> result = new WVPResult<>(); 283 WVPResult<SendRtpItem> result = new WVPResult<>();
284 result.setCode(ERROR_CODE_TIMEOUT); 284 result.setCode(ERROR_CODE_TIMEOUT);
285 WvpRedisMsg response = WvpRedisMsg.getResponseInstance( 285 WvpRedisMsg response = WvpRedisMsg.getResponseInstance(
286 - userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result 286 + userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, JSON.toJSONString(result)
287 ); 287 );
288 JSONObject jsonObject = (JSONObject)JSON.toJSON(response); 288 JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
289 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); 289 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
@@ -324,7 +324,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -324,7 +324,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
324 result.setData(responseSendItemMsg); 324 result.setData(responseSendItemMsg);
325 325
326 WvpRedisMsg response = WvpRedisMsg.getResponseInstance( 326 WvpRedisMsg response = WvpRedisMsg.getResponseInstance(
327 - userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result 327 + userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, JSON.toJSONString(result)
328 ); 328 );
329 JSONObject jsonObject = (JSONObject)JSON.toJSON(response); 329 JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
330 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); 330 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
@@ -350,7 +350,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -350,7 +350,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
350 requestSendItemMsg.setServerId(serverId); 350 requestSendItemMsg.setServerId(serverId);
351 String key = UUID.randomUUID().toString(); 351 String key = UUID.randomUUID().toString();
352 WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, WvpRedisMsgCmd.GET_SEND_ITEM, 352 WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, WvpRedisMsgCmd.GET_SEND_ITEM,
353 - key, requestSendItemMsg); 353 + key, JSON.toJSONString(requestSendItemMsg));
354 354
355 JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg); 355 JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg);
356 logger.info("[请求推流SendItem] {}: {}", serverId, jsonObject); 356 logger.info("[请求推流SendItem] {}: {}", serverId, jsonObject);
@@ -375,7 +375,7 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -375,7 +375,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
375 public void sendMsgForStartSendRtpStream(String serverId, RequestPushStreamMsg param, PlayMsgCallbackForStartSendRtpStream callback) { 375 public void sendMsgForStartSendRtpStream(String serverId, RequestPushStreamMsg param, PlayMsgCallbackForStartSendRtpStream callback) {
376 String key = UUID.randomUUID().toString(); 376 String key = UUID.randomUUID().toString();
377 WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, 377 WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId,
378 - WvpRedisMsgCmd.REQUEST_PUSH_STREAM, key, param); 378 + WvpRedisMsgCmd.REQUEST_PUSH_STREAM, key, JSON.toJSONString(param));
379 379
380 JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg); 380 JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg);
381 logger.info("[REDIS 请求其他平台推流] {}: {}", serverId, jsonObject); 381 logger.info("[REDIS 请求其他平台推流] {}: {}", serverId, jsonObject);
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java
@@ -50,11 +50,12 @@ public class RedisGpsMsgListener implements MessageListener { @@ -50,11 +50,12 @@ public class RedisGpsMsgListener implements MessageListener {
50 Message msg = taskQueue.poll(); 50 Message msg = taskQueue.poll();
51 try { 51 try {
52 GPSMsgInfo gpsMsgInfo = JSON.parseObject(msg.getBody(), GPSMsgInfo.class); 52 GPSMsgInfo gpsMsgInfo = JSON.parseObject(msg.getBody(), GPSMsgInfo.class);
  53 + logger.info("[REDIS的位置变化通知], {}", JSON.toJSONString(gpsMsgInfo));
53 // 只是放入redis缓存起来 54 // 只是放入redis缓存起来
54 redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); 55 redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
55 }catch (Exception e) { 56 }catch (Exception e) {
56 - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));  
57 - logger.error("[REDIS的ALARM通知] 异常内容: ", e); 57 + logger.warn("[REDIS的位置变化通知] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  58 + logger.error("[REDIS的位置变化通知] 异常内容: ", e);
58 } 59 }
59 } 60 }
60 }); 61 });
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -208,4 +208,8 @@ public interface IRedisCatchStorage { @@ -208,4 +208,8 @@ public interface IRedisCatchStorage {
208 void sendPlatformStartPlayMsg(MessageForPushChannel messageForPushChannel); 208 void sendPlatformStartPlayMsg(MessageForPushChannel messageForPushChannel);
209 209
210 void sendPlatformStopPlayMsg(MessageForPushChannel messageForPushChannel); 210 void sendPlatformStopPlayMsg(MessageForPushChannel messageForPushChannel);
  211 +
  212 + void addPushListItem(String app, String stream, OnStreamChangedHookParam param);
  213 +
  214 + void removePushListItem(String app, String stream, String mediaServerId);
211 } 215 }
src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java 0 → 100644
  1 +package com.genersoft.iot.vmp.storager.dao;
  2 +
  3 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  4 +import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
  5 +import org.apache.ibatis.annotations.*;
  6 +
  7 +import java.util.List;
  8 +
  9 +@Mapper
  10 +public interface CloudRecordServiceMapper {
  11 +
  12 + @Insert(" <script>" +
  13 + "INSERT INTO wvp_cloud_record (" +
  14 + " app," +
  15 + " stream," +
  16 + "<if test=\"callId != null\"> call_id,</if>" +
  17 + " start_time," +
  18 + " end_time," +
  19 + " media_server_id," +
  20 + " file_name," +
  21 + " folder," +
  22 + " file_path," +
  23 + " file_size," +
  24 + " time_len ) " +
  25 + "VALUES (" +
  26 + " #{app}," +
  27 + " #{stream}," +
  28 + " <if test=\"callId != null\"> #{callId},</if>" +
  29 + " #{startTime}," +
  30 + " #{endTime}," +
  31 + " #{mediaServerId}," +
  32 + " #{fileName}," +
  33 + " #{folder}," +
  34 + " #{filePath}," +
  35 + " #{fileSize}," +
  36 + " #{timeLen})" +
  37 + " </script>")
  38 + int add(CloudRecordItem cloudRecordItem);
  39 +
  40 + @Select(" <script>" +
  41 + "select * " +
  42 + " from wvp_cloud_record " +
  43 + " where 0 = 0" +
  44 + " <if test='query != null'> AND (app LIKE concat('%',#{query},'%') OR stream LIKE concat('%',#{query},'%') )</if> " +
  45 + " <if test= 'app != null '> and app=#{app}</if>" +
  46 + " <if test= 'stream != null '> and stream=#{stream}</if>" +
  47 + " <if test= 'startTimeStamp != null '> and end_time &gt;= #{startTimeStamp}</if>" +
  48 + " <if test= 'endTimeStamp != null '> and start_time &lt;= #{endTimeStamp}</if>" +
  49 + " <if test= 'callId != null '> and call_id = #{callId}</if>" +
  50 + " <if test= 'mediaServerItemList != null ' > and media_server_id in " +
  51 + " <foreach collection='mediaServerItemList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
  52 + " </if>" +
  53 + " order by start_time DESC" +
  54 +
  55 + " </script>")
  56 + List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream,
  57 + @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
  58 + @Param("callId")String callId, List<MediaServerItem> mediaServerItemList);
  59 +
  60 +
  61 + @Select(" <script>" +
  62 + "select file_path" +
  63 + " from wvp_cloud_record " +
  64 + " where 0 = 0" +
  65 + " <if test= 'app != null '> and app=#{app}</if>" +
  66 + " <if test= 'stream != null '> and stream=#{stream}</if>" +
  67 + " <if test= 'startTimeStamp != null '> and end_time &gt;= #{startTimeStamp}</if>" +
  68 + " <if test= 'endTimeStamp != null '> and start_time &lt;= #{endTimeStamp}</if>" +
  69 + " <if test= 'callId != null '> and call_id = #{callId}</if>" +
  70 + " <if test= 'mediaServerItemList != null ' > and media_server_id in " +
  71 + " <foreach collection='mediaServerItemList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
  72 + " </if>" +
  73 + " </script>")
  74 + List<String> queryRecordFilePathList(@Param("app") String app, @Param("stream") String stream,
  75 + @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
  76 + @Param("callId")String callId, List<MediaServerItem> mediaServerItemList);
  77 +
  78 + @Update(" <script>" +
  79 + "update wvp_cloud_record set collect = #{collect} where file_path in " +
  80 + " <foreach collection='cloudRecordItemList' item='item' open='(' separator=',' close=')' > #{item.filePath}</foreach>" +
  81 + " </script>")
  82 + int updateCollectList(@Param("collect") boolean collect, List<CloudRecordItem> cloudRecordItemList);
  83 +
  84 + @Delete(" <script>" +
  85 + "delete from wvp_cloud_record where media_server_id=#{mediaServerId} and file_path in " +
  86 + " <foreach collection='filePathList' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
  87 + " </script>")
  88 + void deleteByFileList(List<String> filePathList, @Param("mediaServerId") String mediaServerId);
  89 +
  90 +
  91 + @Select(" <script>" +
  92 + "select *" +
  93 + " from wvp_cloud_record " +
  94 + " where collect = false and end_time &lt;= #{endTimeStamp} and media_server_id = #{mediaServerId} " +
  95 + " </script>")
  96 + List<CloudRecordItem> queryRecordListForDelete(@Param("endTimeStamp")Long endTimeStamp, String mediaServerId);
  97 +
  98 + @Update(" <script>" +
  99 + "update wvp_cloud_record set collect = #{collect} where id = #{recordId} " +
  100 + " </script>")
  101 + int changeCollectById(@Param("collect") boolean collect, @Param("recordId") Integer recordId);
  102 +
  103 + @Delete(" <script>" +
  104 + "delete from wvp_cloud_record where id in " +
  105 + " <foreach collection='cloudRecordItemIdList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
  106 + " </script>")
  107 + int deleteList(List<CloudRecordItem> cloudRecordItemIdList);
  108 +
  109 + @Select(" <script>" +
  110 + "select *" +
  111 + " from wvp_cloud_record " +
  112 + "where call_id = #{callId}" +
  113 + " </script>")
  114 + List<CloudRecordItem> getListByCallId(@Param("callId") String callId);
  115 +
  116 + @Select(" <script>" +
  117 + "select *" +
  118 + " from wvp_cloud_record " +
  119 + "where id = #{id}" +
  120 + " </script>")
  121 + CloudRecordItem queryOne(@Param("id") Integer id);
  122 +}
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -6,7 +6,6 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; @@ -6,7 +6,6 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform;
6 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; 6 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
7 import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; 7 import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
8 import org.apache.ibatis.annotations.*; 8 import org.apache.ibatis.annotations.*;
9 -import org.apache.ibatis.annotations.Param;  
10 import org.springframework.stereotype.Repository; 9 import org.springframework.stereotype.Repository;
11 10
12 import java.util.List; 11 import java.util.List;
@@ -31,7 +30,7 @@ public interface DeviceChannelMapper { @@ -31,7 +30,7 @@ public interface DeviceChannelMapper {
31 @Update(value = {" <script>" + 30 @Update(value = {" <script>" +
32 "UPDATE wvp_device_channel " + 31 "UPDATE wvp_device_channel " +
33 "SET update_time=#{updateTime}" + 32 "SET update_time=#{updateTime}" +
34 - "<if test='name != null'>, name=#{name}</if>" + 33 + ", custom_name=#{name}" +
35 "<if test='manufacture != null'>, manufacture=#{manufacture}</if>" + 34 "<if test='manufacture != null'>, manufacture=#{manufacture}</if>" +
36 "<if test='model != null'>, model=#{model}</if>" + 35 "<if test='model != null'>, model=#{model}</if>" +
37 "<if test='owner != null'>, owner=#{owner}</if>" + 36 "<if test='owner != null'>, owner=#{owner}</if>" +
@@ -49,12 +48,12 @@ public interface DeviceChannelMapper { @@ -49,12 +48,12 @@ public interface DeviceChannelMapper {
49 "<if test='ipAddress != null'>, ip_address=#{ipAddress}</if>" + 48 "<if test='ipAddress != null'>, ip_address=#{ipAddress}</if>" +
50 "<if test='port != null'>, port=#{port}</if>" + 49 "<if test='port != null'>, port=#{port}</if>" +
51 "<if test='password != null'>, password=#{password}</if>" + 50 "<if test='password != null'>, password=#{password}</if>" +
52 - "<if test='PTZType != null'>, ptz_type=#{PTZType}</if>" + 51 + "<if test='PTZType != null'>, custom_ptz_type=#{PTZType}</if>" +
53 "<if test='status != null'>, status=#{status}</if>" + 52 "<if test='status != null'>, status=#{status}</if>" +
54 "<if test='streamId != null'>, stream_id=#{streamId}</if>" + 53 "<if test='streamId != null'>, stream_id=#{streamId}</if>" +
55 "<if test='hasAudio != null'>, has_audio=#{hasAudio}</if>" + 54 "<if test='hasAudio != null'>, has_audio=#{hasAudio}</if>" +
56 - "<if test='longitude != null'>, longitude=#{longitude}</if>" +  
57 - "<if test='latitude != null'>, latitude=#{latitude}</if>" + 55 + ", custom_longitude=#{longitude}" +
  56 + ", custom_latitude=#{latitude}" +
58 "<if test='longitudeGcj02 != null'>, longitude_gcj02=#{longitudeGcj02}</if>" + 57 "<if test='longitudeGcj02 != null'>, longitude_gcj02=#{longitudeGcj02}</if>" +
59 "<if test='latitudeGcj02 != null'>, latitude_gcj02=#{latitudeGcj02}</if>" + 58 "<if test='latitudeGcj02 != null'>, latitude_gcj02=#{latitudeGcj02}</if>" +
60 "<if test='longitudeWgs84 != null'>, longitude_wgs84=#{longitudeWgs84}</if>" + 59 "<if test='longitudeWgs84 != null'>, longitude_wgs84=#{longitudeWgs84}</if>" +
@@ -67,7 +66,43 @@ public interface DeviceChannelMapper { @@ -67,7 +66,43 @@ public interface DeviceChannelMapper {
67 66
68 @Select(value = {" <script>" + 67 @Select(value = {" <script>" +
69 "SELECT " + 68 "SELECT " +
70 - "dc.* " + 69 + "dc.id, " +
  70 + "dc.channel_id, " +
  71 + "COALESCE(dc.custom_name, dc.name) AS name, " +
  72 + "dc.manufacture, " +
  73 + "dc.model, " +
  74 + "dc.owner, " +
  75 + "dc.civil_code, " +
  76 + "dc.block, " +
  77 + "dc.address, " +
  78 + "dc.parent_id, " +
  79 + "dc.safety_way, " +
  80 + "dc.register_way, " +
  81 + "dc.cert_num, " +
  82 + "dc.certifiable, " +
  83 + "dc.err_code, " +
  84 + "dc.end_time, " +
  85 + "dc.secrecy, " +
  86 + "dc.ip_address, " +
  87 + "dc.port, " +
  88 + "dc.password, " +
  89 + "COALESCE(dc.custom_ptz_type, dc.ptz_type) AS ptz_type, " +
  90 + "dc.status, " +
  91 + "COALESCE(dc.custom_longitude, dc.longitude) AS longitude, " +
  92 + "COALESCE(dc.custom_latitude, dc.latitude) AS latitude, " +
  93 + "dc.stream_id, " +
  94 + "dc.device_id, " +
  95 + "dc.parental, " +
  96 + "dc.has_audio, " +
  97 + "dc.create_time, " +
  98 + "dc.update_time, " +
  99 + "dc.sub_count, " +
  100 + "dc.longitude_gcj02, " +
  101 + "dc.latitude_gcj02, " +
  102 + "dc.longitude_wgs84, " +
  103 + "dc.latitude_wgs84, " +
  104 + "dc.business_group_id, " +
  105 + "dc.gps_time " +
71 "from " + 106 "from " +
72 "wvp_device_channel dc " + 107 "wvp_device_channel dc " +
73 "WHERE " + 108 "WHERE " +
@@ -154,7 +189,7 @@ public interface DeviceChannelMapper { @@ -154,7 +189,7 @@ public interface DeviceChannelMapper {
154 " dc.id,\n" + 189 " dc.id,\n" +
155 " dc.channel_id,\n" + 190 " dc.channel_id,\n" +
156 " dc.device_id,\n" + 191 " dc.device_id,\n" +
157 - " dc.name,\n" + 192 + " COALESCE(dc.custom_name, dc.name) AS name,\n" +
158 " de.manufacturer,\n" + 193 " de.manufacturer,\n" +
159 " de.host_address,\n" + 194 " de.host_address,\n" +
160 " dc.sub_count,\n" + 195 " dc.sub_count,\n" +
@@ -392,10 +427,10 @@ public interface DeviceChannelMapper { @@ -392,10 +427,10 @@ public interface DeviceChannelMapper {
392 @Select("select * from wvp_device_channel where device_id=#{deviceId} and SUBSTRING(channel_id, 11, 3)=#{typeCode}") 427 @Select("select * from wvp_device_channel where device_id=#{deviceId} and SUBSTRING(channel_id, 11, 3)=#{typeCode}")
393 List<DeviceChannel> getBusinessGroups(@Param("deviceId") String deviceId, @Param("typeCode") String typeCode); 428 List<DeviceChannel> getBusinessGroups(@Param("deviceId") String deviceId, @Param("typeCode") String typeCode);
394 429
395 - @Select("select dc.id, dc.channel_id, dc.device_id, dc.name, dc.manufacture,dc.model,dc.owner, pc.civil_code,dc.block, " + 430 + @Select("select dc.id, dc.channel_id, dc.device_id, COALESCE(dc.custom_name, dc.name) AS name, dc.manufacture,dc.model,dc.owner, pc.civil_code,dc.block, " +
396 " dc.address, '0' as parental,'0' as channel_type, pc.id as parent_id, dc.safety_way, dc.register_way,dc.cert_num, dc.certifiable, " + 431 " dc.address, '0' as parental,'0' as channel_type, pc.id as parent_id, dc.safety_way, dc.register_way,dc.cert_num, dc.certifiable, " +
397 - " dc.err_code,dc.end_time, dc.secrecy, dc.ip_address, dc.port, dc.ptz_type, dc.password, dc.status, " +  
398 - " dc.longitude_wgs84 as longitude, dc.latitude_wgs84 as latitude, pc.business_group_id " + 432 + " dc.err_code,dc.end_time, dc.secrecy, dc.ip_address, dc.port, COALESCE(dc.custom_ptz_type, dc.ptz_type) AS ptz_type, dc.password, dc.status, " +
  433 + " COALESCE(dc.custom_longitude, dc.longitude) AS longitude, COALESCE(dc.custom_latitude, dc.latitude) AS latitude, pc.business_group_id " +
399 " from wvp_device_channel dc" + 434 " from wvp_device_channel dc" +
400 " LEFT JOIN wvp_platform_gb_channel pgc on dc.id = pgc.device_channel_id" + 435 " LEFT JOIN wvp_platform_gb_channel pgc on dc.id = pgc.device_channel_id" +
401 " LEFT JOIN wvp_platform_catalog pc on pgc.catalog_id = pc.id and pgc.platform_id = pc.platform_id" + 436 " LEFT JOIN wvp_platform_catalog pc on pgc.catalog_id = pc.id and pgc.platform_id = pc.platform_id" +
@@ -457,7 +492,44 @@ public interface DeviceChannelMapper { @@ -457,7 +492,44 @@ public interface DeviceChannelMapper {
457 void clearPlay(String deviceId); 492 void clearPlay(String deviceId);
458 // 设备主子码流逻辑END 493 // 设备主子码流逻辑END
459 @Select(value = {" <script>" + 494 @Select(value = {" <script>" +
460 - "select * " + 495 + "SELECT id,\n" +
  496 + " channel_id,\n" +
  497 + " COALESCE(custom_name, name) AS name,\n" +
  498 + " custom_name,\n" +
  499 + " manufacture,\n" +
  500 + " model,\n" +
  501 + " owner,\n" +
  502 + " civil_code,\n" +
  503 + " block,\n" +
  504 + " address,\n" +
  505 + " parent_id,\n" +
  506 + " safety_way,\n" +
  507 + " register_way,\n" +
  508 + " cert_num,\n" +
  509 + " certifiable,\n" +
  510 + " err_code,\n" +
  511 + " end_time,\n" +
  512 + " secrecy,\n" +
  513 + " ip_address,\n" +
  514 + " port,\n" +
  515 + " password,\n" +
  516 + " COALESCE(custom_ptz_type, ptz_type) AS ptz_type,\n" +
  517 + " status,\n" +
  518 + " COALESCE(custom_longitude, longitude) AS longitude,\n" +
  519 + " COALESCE(custom_latitude, latitude) AS latitude,\n" +
  520 + " stream_id,\n" +
  521 + " device_id,\n" +
  522 + " parental,\n" +
  523 + " has_audio,\n" +
  524 + " create_time,\n" +
  525 + " update_time,\n" +
  526 + " sub_count,\n" +
  527 + " longitude_gcj02,\n" +
  528 + " latitude_gcj02,\n" +
  529 + " longitude_wgs84,\n" +
  530 + " latitude_wgs84,\n" +
  531 + " business_group_id,\n" +
  532 + " gps_time\n" +
461 "from wvp_device_channel " + 533 "from wvp_device_channel " +
462 "where device_id=#{deviceId}" + 534 "where device_id=#{deviceId}" +
463 " <if test='parentId != null and parentId != deviceId'> and parent_id = #{parentId} </if>" + 535 " <if test='parentId != null and parentId != deviceId'> and parent_id = #{parentId} </if>" +
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
@@ -158,7 +158,7 @@ public interface GbStreamMapper { @@ -158,7 +158,7 @@ public interface GbStreamMapper {
158 " <foreach collection='list' item='item' index='index' separator=';'>"+ 158 " <foreach collection='list' item='item' index='index' separator=';'>"+
159 "UPDATE wvp_gb_stream " + 159 "UPDATE wvp_gb_stream " +
160 " SET name=#{item.name},"+ 160 " SET name=#{item.name},"+
161 - " gb_id=#{item.gb_id}"+ 161 + " gb_id=#{item.gbId}"+
162 " WHERE app=#{item.app} and stream=#{item.stream}"+ 162 " WHERE app=#{item.app} and stream=#{item.stream}"+
163 "</foreach>"+ 163 "</foreach>"+
164 "</script>") 164 "</script>")
src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java
@@ -31,6 +31,8 @@ public interface MediaServerMapper { @@ -31,6 +31,8 @@ public interface MediaServerMapper {
31 "rtp_port_range,"+ 31 "rtp_port_range,"+
32 "send_rtp_port_range,"+ 32 "send_rtp_port_range,"+
33 "record_assist_port,"+ 33 "record_assist_port,"+
  34 + "record_day,"+
  35 + "record_path,"+
34 "default_server,"+ 36 "default_server,"+
35 "create_time,"+ 37 "create_time,"+
36 "update_time,"+ 38 "update_time,"+
@@ -55,6 +57,8 @@ public interface MediaServerMapper { @@ -55,6 +57,8 @@ public interface MediaServerMapper {
55 "#{rtpPortRange}, " + 57 "#{rtpPortRange}, " +
56 "#{sendRtpPortRange}, " + 58 "#{sendRtpPortRange}, " +
57 "#{recordAssistPort}, " + 59 "#{recordAssistPort}, " +
  60 + "#{recordDay}, " +
  61 + "#{recordPath}, " +
58 "#{defaultServer}, " + 62 "#{defaultServer}, " +
59 "#{createTime}, " + 63 "#{createTime}, " +
60 "#{updateTime}, " + 64 "#{updateTime}, " +
@@ -82,6 +86,8 @@ public interface MediaServerMapper { @@ -82,6 +86,8 @@ public interface MediaServerMapper {
82 "<if test=\"secret != null\">, secret=#{secret}</if>" + 86 "<if test=\"secret != null\">, secret=#{secret}</if>" +
83 "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" + 87 "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" +
84 "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + 88 "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
  89 + "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
  90 + "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
85 "WHERE id=#{id}"+ 91 "WHERE id=#{id}"+
86 " </script>"}) 92 " </script>"})
87 int update(MediaServerItem mediaServerItem); 93 int update(MediaServerItem mediaServerItem);
@@ -105,6 +111,8 @@ public interface MediaServerMapper { @@ -105,6 +111,8 @@ public interface MediaServerMapper {
105 "<if test=\"sendRtpPortRange != null\">, send_rtp_port_range=#{sendRtpPortRange}</if>" + 111 "<if test=\"sendRtpPortRange != null\">, send_rtp_port_range=#{sendRtpPortRange}</if>" +
106 "<if test=\"secret != null\">, secret=#{secret}</if>" + 112 "<if test=\"secret != null\">, secret=#{secret}</if>" +
107 "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" + 113 "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" +
  114 + "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
  115 + "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
108 "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + 116 "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
109 "WHERE ip=#{ip} and http_port=#{httpPort}"+ 117 "WHERE ip=#{ip} and http_port=#{httpPort}"+
110 " </script>"}) 118 " </script>"})
@@ -130,4 +138,8 @@ public interface MediaServerMapper { @@ -130,4 +138,8 @@ public interface MediaServerMapper {
130 138
131 @Select("SELECT * FROM wvp_media_server WHERE default_server=true") 139 @Select("SELECT * FROM wvp_media_server WHERE default_server=true")
132 MediaServerItem queryDefault(); 140 MediaServerItem queryDefault();
  141 +
  142 + @Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0")
  143 + List<MediaServerItem> queryAllWithAssistPort();
  144 +
133 } 145 }
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
@@ -117,8 +117,6 @@ public interface PlatformChannelMapper { @@ -117,8 +117,6 @@ public interface PlatformChannelMapper {
117 "where dc.channel_id = #{channelId} and pgc.platform_id=#{platformId}") 117 "where dc.channel_id = #{channelId} and pgc.platform_id=#{platformId}")
118 List<Device> queryDeviceInfoByPlatformIdAndChannelId(@Param("platformId") String platformId, @Param("channelId") String channelId); 118 List<Device> queryDeviceInfoByPlatformIdAndChannelId(@Param("platformId") String platformId, @Param("channelId") String channelId);
119 119
120 - @Select("SELECT pgc.platform_id from wvp_platform_gb_channel pgc left join wvp_device_channel dc on dc.id = pgc.device_channel_id WHERE dc.channel_id='${channelId}'")  
121 - List<String> queryParentPlatformByChannelId(String channelId);  
122 -  
123 - 120 + @Select("SELECT pgc.platform_id from wvp_platform_gb_channel pgc left join wvp_device_channel dc on dc.id = pgc.device_channel_id WHERE dc.channel_id=#{channelId}")
  121 + List<String> queryParentPlatformByChannelId(@Param("channelId") String channelId);
124 } 122 }
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
@@ -103,6 +103,9 @@ public interface PlatformGbStreamMapper { @@ -103,6 +103,9 @@ public interface PlatformGbStreamMapper {
103 "</script>") 103 "</script>")
104 void delByAppAndStreamsByPlatformId(@Param("gbStreams") List<GbStream> gbStreams, @Param("platformId") String platformId); 104 void delByAppAndStreamsByPlatformId(@Param("gbStreams") List<GbStream> gbStreams, @Param("platformId") String platformId);
105 105
106 - @Delete("DELETE from wvp_platform_gb_stream WHERE platform_id=#{platformId} and catalog_id=#{catalogId}") 106 + @Delete("<script> "+
  107 + "DELETE from wvp_platform_gb_stream WHERE platform_id=#{platformId}" +
  108 + " <if test='catalogId != null' > and catalog_id=#{catalogId}</if>" +
  109 + "</script>")
107 int delByPlatformAndCatalogId(@Param("platformId") String platformId, @Param("catalogId") String catalogId); 110 int delByPlatformAndCatalogId(@Param("platformId") String platformId, @Param("catalogId") String catalogId);
108 } 111 }
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
@@ -13,9 +13,9 @@ import java.util.List; @@ -13,9 +13,9 @@ import java.util.List;
13 public interface StreamPushMapper { 13 public interface StreamPushMapper {
14 14
15 @Insert("INSERT INTO wvp_stream_push (app, stream, total_reader_count, origin_type, origin_type_str, " + 15 @Insert("INSERT INTO wvp_stream_push (app, stream, total_reader_count, origin_type, origin_type_str, " +
16 - "push_time, alive_second, media_server_id, update_time, create_time, push_ing, self) VALUES" + 16 + "push_time, alive_second, media_server_id, server_id, update_time, create_time, push_ing, self) VALUES" +
17 "(#{app}, #{stream}, #{totalReaderCount}, #{originType}, #{originTypeStr}, " + 17 "(#{app}, #{stream}, #{totalReaderCount}, #{originType}, #{originTypeStr}, " +
18 - "#{pushTime}, #{aliveSecond}, #{mediaServerId} , #{updateTime} , #{createTime}, " + 18 + "#{pushTime}, #{aliveSecond}, #{mediaServerId} , #{serverId} , #{updateTime} , #{createTime}, " +
19 "#{pushIng}, #{self} )") 19 "#{pushIng}, #{self} )")
20 int add(StreamPushItem streamPushItem); 20 int add(StreamPushItem streamPushItem);
21 21
@@ -24,6 +24,7 @@ public interface StreamPushMapper { @@ -24,6 +24,7 @@ public interface StreamPushMapper {
24 "UPDATE wvp_stream_push " + 24 "UPDATE wvp_stream_push " +
25 "SET update_time=#{updateTime}" + 25 "SET update_time=#{updateTime}" +
26 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" + 26 "<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
  27 + "<if test=\"serverId != null\">, server_id=#{serverId}</if>" +
27 "<if test=\"totalReaderCount != null\">, total_reader_count=#{totalReaderCount}</if>" + 28 "<if test=\"totalReaderCount != null\">, total_reader_count=#{totalReaderCount}</if>" +
28 "<if test=\"originType != null\">, origin_type=#{originType}</if>" + 29 "<if test=\"originType != null\">, origin_type=#{originType}</if>" +
29 "<if test=\"originTypeStr != null\">, origin_type_str=#{originTypeStr}</if>" + 30 "<if test=\"originTypeStr != null\">, origin_type_str=#{originTypeStr}</if>" +
@@ -89,10 +90,10 @@ public interface StreamPushMapper { @@ -89,10 +90,10 @@ public interface StreamPushMapper {
89 90
90 @Insert("<script>" + 91 @Insert("<script>" +
91 "Insert INTO wvp_stream_push (app, stream, total_reader_count, origin_type, origin_type_str, " + 92 "Insert INTO wvp_stream_push (app, stream, total_reader_count, origin_type, origin_type_str, " +
92 - "create_time, alive_second, media_server_id, status, push_ing) " + 93 + "create_time, alive_second, media_server_id, server_id, status, push_ing) " +
93 "VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" + 94 "VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" +
94 "( #{item.app}, #{item.stream}, #{item.totalReaderCount}, #{item.originType}, " + 95 "( #{item.app}, #{item.stream}, #{item.totalReaderCount}, #{item.originType}, " +
95 - "#{item.originTypeStr},#{item.createTime}, #{item.aliveSecond}, #{item.mediaServerId}, #{item.status} ," + 96 + "#{item.originTypeStr},#{item.createTime}, #{item.aliveSecond}, #{item.mediaServerId},#{item.serverId}, #{item.status} ," +
96 " #{item.pushIng} )" + 97 " #{item.pushIng} )" +
97 " </foreach>" + 98 " </foreach>" +
98 "</script>") 99 "</script>")
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -609,14 +609,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -609,14 +609,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
609 @Override 609 @Override
610 public void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online) { 610 public void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online) {
611 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_DEVICE_STATUS; 611 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_DEVICE_STATUS;
612 - logger.info("[redis通知] 发送 推送设备/通道状态, {}/{}-{}", deviceId, channelId, online);  
613 StringBuilder msg = new StringBuilder(); 612 StringBuilder msg = new StringBuilder();
614 msg.append(deviceId); 613 msg.append(deviceId);
615 if (channelId != null) { 614 if (channelId != null) {
616 msg.append(":").append(channelId); 615 msg.append(":").append(channelId);
617 } 616 }
618 msg.append(" ").append(online? "ON":"OFF"); 617 msg.append(" ").append(online? "ON":"OFF");
619 - logger.info("[redis通知] 推送状态-> {} ", msg); 618 + logger.info("[redis通知] 推送设备/通道状态-> {} ", msg);
620 // 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号 619 // 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号
621 stringRedisTemplate.convertAndSend(key, msg.toString()); 620 stringRedisTemplate.convertAndSend(key, msg.toString());
622 } 621 }
@@ -650,4 +649,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -650,4 +649,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
650 logger.info("[redis发送通知] 发送 上级平台停止观看 {}: {}/{}->{}", key, msg.getApp(), msg.getStream(), msg.getPlatFormId()); 649 logger.info("[redis发送通知] 发送 上级平台停止观看 {}: {}/{}->{}", key, msg.getApp(), msg.getStream(), msg.getPlatFormId());
651 redisTemplate.convertAndSend(key, JSON.toJSON(msg)); 650 redisTemplate.convertAndSend(key, JSON.toJSON(msg));
652 } 651 }
  652 +
  653 + @Override
  654 + public void addPushListItem(String app, String stream, OnStreamChangedHookParam param) {
  655 + String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
  656 + redisTemplate.opsForValue().set(key, param);
  657 + }
  658 +
  659 + @Override
  660 + public void removePushListItem(String app, String stream, String mediaServerId) {
  661 + String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
  662 + OnStreamChangedHookParam param = (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key);
  663 + if (param != null && param.getMediaServerId().equalsIgnoreCase(mediaServerId)) {
  664 + redisTemplate.delete(key);
  665 + }
  666 +
  667 + }
653 } 668 }
src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java 0 → 100644
  1 +package com.genersoft.iot.vmp.utils;
  2 +
  3 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  4 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
  5 +
  6 +public class CloudRecordUtils {
  7 +
  8 + public static DownloadFileInfo getDownloadFilePath(MediaServerItem mediaServerItem, String filePath) {
  9 + DownloadFileInfo downloadFileInfo = new DownloadFileInfo();
  10 +
  11 + String pathTemplate = "%s://%s:%s/index/api/downloadFile?file_path=" + filePath;
  12 +
  13 + downloadFileInfo.setHttpPath(String.format(pathTemplate, "http", mediaServerItem.getStreamIp(),
  14 + mediaServerItem.getHttpPort()));
  15 +
  16 + if (mediaServerItem.getHttpSSlPort() > 0) {
  17 + downloadFileInfo.setHttpsPath(String.format(pathTemplate, "https", mediaServerItem.getStreamIp(),
  18 + mediaServerItem.getHttpSSlPort()));
  19 + }
  20 + return downloadFileInfo;
  21 + }
  22 +}
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java
@@ -40,11 +40,17 @@ public class DateUtil { @@ -40,11 +40,17 @@ public class DateUtil {
40 */ 40 */
41 public static final String URL_PATTERN = "yyyyMMddHHmmss"; 41 public static final String URL_PATTERN = "yyyyMMddHHmmss";
42 42
  43 + /**
  44 + * 日期格式
  45 + */
  46 + public static final String date_PATTERN = "yyyy-MM-dd";
  47 +
43 public static final String zoneStr = "Asia/Shanghai"; 48 public static final String zoneStr = "Asia/Shanghai";
44 49
45 public static final DateTimeFormatter formatterCompatibleISO8601 = DateTimeFormatter.ofPattern(ISO8601_COMPATIBLE_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); 50 public static final DateTimeFormatter formatterCompatibleISO8601 = DateTimeFormatter.ofPattern(ISO8601_COMPATIBLE_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
46 public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(ISO8601_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); 51 public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(ISO8601_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
47 public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); 52 public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
  53 + public static final DateTimeFormatter DateFormatter = DateTimeFormatter.ofPattern(date_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
48 public static final DateTimeFormatter urlFormatter = DateTimeFormatter.ofPattern(URL_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr)); 54 public static final DateTimeFormatter urlFormatter = DateTimeFormatter.ofPattern(URL_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
49 55
50 public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { 56 public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {
@@ -72,6 +78,22 @@ public class DateUtil { @@ -72,6 +78,22 @@ public class DateUtil {
72 } 78 }
73 79
74 /** 80 /**
  81 + * 时间戳 转 yyyy_MM_dd_HH_mm_ss
  82 + */
  83 + public static String timestampTo_yyyy_MM_dd_HH_mm_ss(long timestamp) {
  84 + Instant instant = Instant.ofEpochSecond(timestamp);
  85 + return formatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
  86 + }
  87 +
  88 + /**
  89 + * 时间戳 转 yyyy_MM_dd
  90 + */
  91 + public static String timestampTo_yyyy_MM_dd(long timestamp) {
  92 + Instant instant = Instant.ofEpochMilli(timestamp);
  93 + return DateFormatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
  94 + }
  95 +
  96 + /**
75 * 获取当前时间 97 * 获取当前时间
76 * @return 98 * @return
77 */ 99 */
@@ -117,4 +139,13 @@ public class DateUtil { @@ -117,4 +139,13 @@ public class DateUtil {
117 Instant beforeInstant = Instant.from(formatter.parse(keepaliveTime)); 139 Instant beforeInstant = Instant.from(formatter.parse(keepaliveTime));
118 return ChronoUnit.MILLIS.between(beforeInstant, Instant.now()); 140 return ChronoUnit.MILLIS.between(beforeInstant, Instant.now());
119 } 141 }
  142 +
  143 + public static long getDifference(String startTime, String endTime) {
  144 + if (ObjectUtils.isEmpty(startTime) || ObjectUtils.isEmpty(endTime)) {
  145 + return 0;
  146 + }
  147 + Instant startInstant = Instant.from(formatter.parse(startTime));
  148 + Instant endInstant = Instant.from(formatter.parse(endTime));
  149 + return ChronoUnit.MILLIS.between(endInstant, startInstant);
  150 + }
120 } 151 }
src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java
1 package com.genersoft.iot.vmp.vmanager.bean; 1 package com.genersoft.iot.vmp.vmanager.bean;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
4 import io.swagger.v3.oas.annotations.media.Schema; 5 import io.swagger.v3.oas.annotations.media.Schema;
5 6
6 @Schema(description = "流信息") 7 @Schema(description = "流信息")
@@ -93,6 +94,9 @@ public class StreamContent { @@ -93,6 +94,9 @@ public class StreamContent {
93 @Schema(description = "结束时间") 94 @Schema(description = "结束时间")
94 private String endTime; 95 private String endTime;
95 96
  97 + @Schema(description = "文件下载地址(录像下载使用)")
  98 + private DownloadFileInfo downLoadFilePath;
  99 +
96 private double progress; 100 private double progress;
97 101
98 public StreamContent(StreamInfo streamInfo) { 102 public StreamContent(StreamInfo streamInfo) {
@@ -170,6 +174,10 @@ public class StreamContent { @@ -170,6 +174,10 @@ public class StreamContent {
170 this.startTime = streamInfo.getStartTime(); 174 this.startTime = streamInfo.getStartTime();
171 this.endTime = streamInfo.getEndTime(); 175 this.endTime = streamInfo.getEndTime();
172 this.progress = streamInfo.getProgress(); 176 this.progress = streamInfo.getProgress();
  177 +
  178 + if (streamInfo.getDownLoadFilePath() != null) {
  179 + this.downLoadFilePath = streamInfo.getDownLoadFilePath();
  180 + }
173 } 181 }
174 182
175 public String getApp() { 183 public String getApp() {
@@ -411,4 +419,12 @@ public class StreamContent { @@ -411,4 +419,12 @@ public class StreamContent {
411 public void setProgress(double progress) { 419 public void setProgress(double progress) {
412 this.progress = progress; 420 this.progress = progress;
413 } 421 }
  422 +
  423 + public DownloadFileInfo getDownLoadFilePath() {
  424 + return downLoadFilePath;
  425 + }
  426 +
  427 + public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) {
  428 + this.downLoadFilePath = downLoadFilePath;
  429 + }
414 } 430 }
src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java
1 package com.genersoft.iot.vmp.vmanager.cloudRecord; 1 package com.genersoft.iot.vmp.vmanager.cloudRecord;
2 2
  3 +import com.alibaba.fastjson2.JSONArray;
3 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.conf.exception.ControllerException; 6 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  7 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
6 import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; 8 import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
7 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; 9 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
8 -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;  
9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  11 +import com.genersoft.iot.vmp.service.ICloudRecordService;
10 import com.genersoft.iot.vmp.service.IMediaServerService; 12 import com.genersoft.iot.vmp.service.IMediaServerService;
  13 +import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
  14 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
11 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 15 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
12 -import com.genersoft.iot.vmp.vmanager.bean.PageInfo;  
13 -import com.genersoft.iot.vmp.vmanager.bean.RecordFile; 16 +import com.github.pagehelper.PageInfo;
14 import io.swagger.v3.oas.annotations.Operation; 17 import io.swagger.v3.oas.annotations.Operation;
15 import io.swagger.v3.oas.annotations.Parameter; 18 import io.swagger.v3.oas.annotations.Parameter;
  19 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
16 import io.swagger.v3.oas.annotations.tags.Tag; 20 import io.swagger.v3.oas.annotations.tags.Tag;
17 import org.apache.commons.lang3.ObjectUtils; 21 import org.apache.commons.lang3.ObjectUtils;
18 import org.slf4j.Logger; 22 import org.slf4j.Logger;
@@ -32,40 +36,27 @@ import java.util.List; @@ -32,40 +36,27 @@ import java.util.List;
32 @RequestMapping("/api/cloud/record") 36 @RequestMapping("/api/cloud/record")
33 public class CloudRecordController { 37 public class CloudRecordController {
34 38
35 - @Autowired  
36 - private ZLMServerFactory zlmServerFactory;  
37 -  
38 - @Autowired  
39 - private SendRtpPortManager sendRtpPortManager;  
40 39
41 private final static Logger logger = LoggerFactory.getLogger(CloudRecordController.class); 40 private final static Logger logger = LoggerFactory.getLogger(CloudRecordController.class);
42 41
43 @Autowired 42 @Autowired
44 - private ZlmHttpHookSubscribe hookSubscribe; 43 + private ICloudRecordService cloudRecordService;
45 44
46 @Autowired 45 @Autowired
47 private IMediaServerService mediaServerService; 46 private IMediaServerService mediaServerService;
48 47
49 - @Autowired  
50 - private UserSetting userSetting;  
51 -  
52 - @Autowired  
53 - private DynamicTask dynamicTask;  
54 -  
55 - @Autowired  
56 - private RedisTemplate<Object, Object> redisTemplate;  
57 48
58 @ResponseBody 49 @ResponseBody
59 @GetMapping("/date/list") 50 @GetMapping("/date/list")
60 - @Operation(summary = "查询存在云端录像的日期") 51 + @Operation(summary = "查询存在云端录像的日期", security = @SecurityRequirement(name = JwtUtils.HEADER))
61 @Parameter(name = "app", description = "应用名", required = true) 52 @Parameter(name = "app", description = "应用名", required = true)
62 @Parameter(name = "stream", description = "流ID", required = true) 53 @Parameter(name = "stream", description = "流ID", required = true)
63 @Parameter(name = "year", description = "年,置空则查询当年", required = false) 54 @Parameter(name = "year", description = "年,置空则查询当年", required = false)
64 @Parameter(name = "month", description = "月,置空则查询当月", required = false) 55 @Parameter(name = "month", description = "月,置空则查询当月", required = false)
65 @Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部", required = false) 56 @Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部", required = false)
66 public List<String> openRtpServer( 57 public List<String> openRtpServer(
67 - @RequestParam String app,  
68 - @RequestParam String stream, 58 + @RequestParam(required = true) String app,
  59 + @RequestParam(required = true) String stream,
69 @RequestParam(required = false) int year, 60 @RequestParam(required = false) int year,
70 @RequestParam(required = false) int month, 61 @RequestParam(required = false) int month,
71 @RequestParam(required = false) String mediaServerId 62 @RequestParam(required = false) String mediaServerId
@@ -95,26 +86,28 @@ public class CloudRecordController { @@ -95,26 +86,28 @@ public class CloudRecordController {
95 return new ArrayList<>(); 86 return new ArrayList<>();
96 } 87 }
97 88
98 - return mediaServerService.getRecordDates(app, stream, year, month, mediaServerItems); 89 + return cloudRecordService.getDateList(app, stream, year, month, mediaServerItems);
99 } 90 }
100 91
101 @ResponseBody 92 @ResponseBody
102 @GetMapping("/list") 93 @GetMapping("/list")
103 - @Operation(summary = "分页查询云端录像")  
104 - @Parameter(name = "app", description = "应用名", required = true)  
105 - @Parameter(name = "stream", description = "流ID", required = true)  
106 - @Parameter(name = "page", description = "当前页", required = false)  
107 - @Parameter(name = "count", description = "每页查询数量", required = false)  
108 - @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = true)  
109 - @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = true) 94 + @Operation(summary = "分页查询云端录像", security = @SecurityRequirement(name = JwtUtils.HEADER))
  95 + @Parameter(name = "query", description = "检索内容", required = false)
  96 + @Parameter(name = "app", description = "应用名", required = false)
  97 + @Parameter(name = "stream", description = "流ID", required = false)
  98 + @Parameter(name = "page", description = "当前页", required = true)
  99 + @Parameter(name = "count", description = "每页查询数量", required = true)
  100 + @Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = false)
  101 + @Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = false)
110 @Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部流媒体", required = false) 102 @Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部流媒体", required = false)
111 - public PageInfo<RecordFile> openRtpServer(  
112 - @RequestParam String app,  
113 - @RequestParam String stream, 103 + public PageInfo<CloudRecordItem> openRtpServer(
  104 + @RequestParam(required = false) String query,
  105 + @RequestParam(required = false) String app,
  106 + @RequestParam(required = false) String stream,
114 @RequestParam int page, 107 @RequestParam int page,
115 @RequestParam int count, 108 @RequestParam int count,
116 - @RequestParam String startTime,  
117 - @RequestParam String endTime, 109 + @RequestParam(required = false) String startTime,
  110 + @RequestParam(required = false) String endTime,
118 @RequestParam(required = false) String mediaServerId 111 @RequestParam(required = false) String mediaServerId
119 112
120 ) { 113 ) {
@@ -133,13 +126,128 @@ public class CloudRecordController { @@ -133,13 +126,128 @@ public class CloudRecordController {
133 mediaServerItems = mediaServerService.getAll(); 126 mediaServerItems = mediaServerService.getAll();
134 } 127 }
135 if (mediaServerItems.isEmpty()) { 128 if (mediaServerItems.isEmpty()) {
136 - return new PageInfo<>(); 129 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
  130 + }
  131 + if (query != null && ObjectUtils.isEmpty(query.trim())) {
  132 + query = null;
  133 + }
  134 + if (app != null && ObjectUtils.isEmpty(app.trim())) {
  135 + app = null;
  136 + }
  137 + if (stream != null && ObjectUtils.isEmpty(stream.trim())) {
  138 + stream = null;
  139 + }
  140 + if (startTime != null && ObjectUtils.isEmpty(startTime.trim())) {
  141 + startTime = null;
  142 + }
  143 + if (endTime != null && ObjectUtils.isEmpty(endTime.trim())) {
  144 + endTime = null;
137 } 145 }
138 - List<RecordFile> records = mediaServerService.getRecords(app, stream, startTime, endTime, mediaServerItems);  
139 - PageInfo<RecordFile> pageInfo = new PageInfo<>(records);  
140 - pageInfo.startPage(page, count);  
141 - return pageInfo; 146 + return cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServerItems);
142 } 147 }
143 148
  149 + @ResponseBody
  150 + @GetMapping("/task/add")
  151 + @Operation(summary = "添加合并任务")
  152 + @Parameter(name = "app", description = "应用名", required = false)
  153 + @Parameter(name = "stream", description = "流ID", required = false)
  154 + @Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
  155 + @Parameter(name = "startTime", description = "鉴权ID", required = false)
  156 + @Parameter(name = "endTime", description = "鉴权ID", required = false)
  157 + @Parameter(name = "callId", description = "鉴权ID", required = false)
  158 + @Parameter(name = "remoteHost", description = "返回地址时的远程地址", required = false)
  159 + public String addTask(
  160 + @RequestParam(required = false) String app,
  161 + @RequestParam(required = false) String stream,
  162 + @RequestParam(required = false) String mediaServerId,
  163 + @RequestParam(required = false) String startTime,
  164 + @RequestParam(required = false) String endTime,
  165 + @RequestParam(required = false) String callId,
  166 + @RequestParam(required = false) String remoteHost
  167 + ){
  168 + return cloudRecordService.addTask(app, stream, mediaServerId, startTime, endTime, callId, remoteHost);
  169 + }
  170 +
  171 + @ResponseBody
  172 + @GetMapping("/task/list")
  173 + @Operation(summary = "查询合并任务")
  174 + @Parameter(name = "taskId", description = "任务Id", required = false)
  175 + @Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
  176 + @Parameter(name = "isEnd", description = "是否结束", required = false)
  177 + public JSONArray queryTaskList(
  178 + @RequestParam(required = false) String app,
  179 + @RequestParam(required = false) String stream,
  180 + @RequestParam(required = false) String callId,
  181 + @RequestParam(required = false) String taskId,
  182 + @RequestParam(required = false) String mediaServerId,
  183 + @RequestParam(required = false) Boolean isEnd
  184 + ){
  185 + return cloudRecordService.queryTask(app, stream, callId, taskId, mediaServerId, isEnd);
  186 + }
144 187
  188 + @ResponseBody
  189 + @GetMapping("/collect/add")
  190 + @Operation(summary = "添加收藏")
  191 + @Parameter(name = "app", description = "应用名", required = false)
  192 + @Parameter(name = "stream", description = "流ID", required = false)
  193 + @Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
  194 + @Parameter(name = "startTime", description = "鉴权ID", required = false)
  195 + @Parameter(name = "endTime", description = "鉴权ID", required = false)
  196 + @Parameter(name = "callId", description = "鉴权ID", required = false)
  197 + @Parameter(name = "recordId", description = "录像记录的ID,用于精准收藏一个视频文件", required = false)
  198 + public int addCollect(
  199 + @RequestParam(required = false) String app,
  200 + @RequestParam(required = false) String stream,
  201 + @RequestParam(required = false) String mediaServerId,
  202 + @RequestParam(required = false) String startTime,
  203 + @RequestParam(required = false) String endTime,
  204 + @RequestParam(required = false) String callId,
  205 + @RequestParam(required = false) Integer recordId
  206 + ){
  207 + logger.info("[云端录像] 添加收藏,app={},stream={},mediaServerId={},startTime={},endTime={},callId={},recordId={}",
  208 + app, stream, mediaServerId, startTime, endTime, callId, recordId);
  209 + if (recordId != null) {
  210 + return cloudRecordService.changeCollectById(recordId, true);
  211 + }else {
  212 + return cloudRecordService.changeCollect(true, app, stream, mediaServerId, startTime, endTime, callId);
  213 + }
  214 + }
  215 +
  216 + @ResponseBody
  217 + @GetMapping("/collect/delete")
  218 + @Operation(summary = "移除收藏")
  219 + @Parameter(name = "app", description = "应用名", required = false)
  220 + @Parameter(name = "stream", description = "流ID", required = false)
  221 + @Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
  222 + @Parameter(name = "startTime", description = "鉴权ID", required = false)
  223 + @Parameter(name = "endTime", description = "鉴权ID", required = false)
  224 + @Parameter(name = "callId", description = "鉴权ID", required = false)
  225 + @Parameter(name = "recordId", description = "录像记录的ID,用于精准精准移除一个视频文件的收藏", required = false)
  226 + public int deleteCollect(
  227 + @RequestParam(required = false) String app,
  228 + @RequestParam(required = false) String stream,
  229 + @RequestParam(required = false) String mediaServerId,
  230 + @RequestParam(required = false) String startTime,
  231 + @RequestParam(required = false) String endTime,
  232 + @RequestParam(required = false) String callId,
  233 + @RequestParam(required = false) Integer recordId
  234 + ){
  235 + logger.info("[云端录像] 移除收藏,app={},stream={},mediaServerId={},startTime={},endTime={},callId={},recordId={}",
  236 + app, stream, mediaServerId, startTime, endTime, callId, recordId);
  237 + if (recordId != null) {
  238 + return cloudRecordService.changeCollectById(recordId, false);
  239 + }else {
  240 + return cloudRecordService.changeCollect(false, app, stream, mediaServerId, startTime, endTime, callId);
  241 + }
  242 + }
  243 +
  244 + @ResponseBody
  245 + @GetMapping("/play/path")
  246 + @Operation(summary = "获取播放地址")
  247 + @Parameter(name = "recordId", description = "录像记录的ID", required = true)
  248 + public DownloadFileInfo getPlayUrlPath(
  249 + @RequestParam(required = true) Integer recordId
  250 + ){
  251 + return cloudRecordService.getPlayUrlPath(recordId);
  252 + }
145 } 253 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition; 1 package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
2 2
3 import com.genersoft.iot.vmp.conf.exception.ControllerException; 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  4 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; 6 import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
@@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
13 import com.github.pagehelper.util.StringUtil; 14 import com.github.pagehelper.util.StringUtil;
14 import io.swagger.v3.oas.annotations.Operation; 15 import io.swagger.v3.oas.annotations.Operation;
15 import io.swagger.v3.oas.annotations.Parameter; 16 import io.swagger.v3.oas.annotations.Parameter;
  17 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
16 import io.swagger.v3.oas.annotations.tags.Tag; 18 import io.swagger.v3.oas.annotations.tags.Tag;
17 import org.slf4j.Logger; 19 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
@@ -59,7 +61,7 @@ public class MobilePositionController { @@ -59,7 +61,7 @@ public class MobilePositionController {
59 * @param end 结束时间 61 * @param end 结束时间
60 * @return 62 * @return
61 */ 63 */
62 - @Operation(summary = "查询历史轨迹") 64 + @Operation(summary = "查询历史轨迹", security = @SecurityRequirement(name = JwtUtils.HEADER))
63 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 65 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
64 @Parameter(name = "channelId", description = "通道国标编号") 66 @Parameter(name = "channelId", description = "通道国标编号")
65 @Parameter(name = "start", description = "开始时间") 67 @Parameter(name = "start", description = "开始时间")
@@ -84,7 +86,7 @@ public class MobilePositionController { @@ -84,7 +86,7 @@ public class MobilePositionController {
84 * @param deviceId 设备ID 86 * @param deviceId 设备ID
85 * @return 87 * @return
86 */ 88 */
87 - @Operation(summary = "查询设备最新位置") 89 + @Operation(summary = "查询设备最新位置", security = @SecurityRequirement(name = JwtUtils.HEADER))
88 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 90 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
89 @GetMapping("/latest/{deviceId}") 91 @GetMapping("/latest/{deviceId}")
90 public MobilePosition latestPosition(@PathVariable String deviceId) { 92 public MobilePosition latestPosition(@PathVariable String deviceId) {
@@ -96,7 +98,7 @@ public class MobilePositionController { @@ -96,7 +98,7 @@ public class MobilePositionController {
96 * @param deviceId 设备ID 98 * @param deviceId 设备ID
97 * @return 99 * @return
98 */ 100 */
99 - @Operation(summary = "获取移动位置信息") 101 + @Operation(summary = "获取移动位置信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
100 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 102 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
101 @GetMapping("/realtime/{deviceId}") 103 @GetMapping("/realtime/{deviceId}")
102 public DeferredResult<MobilePosition> realTimePosition(@PathVariable String deviceId) { 104 public DeferredResult<MobilePosition> realTimePosition(@PathVariable String deviceId) {
@@ -136,7 +138,7 @@ public class MobilePositionController { @@ -136,7 +138,7 @@ public class MobilePositionController {
136 * @param interval 上报时间间隔 138 * @param interval 上报时间间隔
137 * @return true = 命令发送成功 139 * @return true = 命令发送成功
138 */ 140 */
139 - @Operation(summary = "订阅位置信息") 141 + @Operation(summary = "订阅位置信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
140 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 142 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
141 @Parameter(name = "expires", description = "订阅超时时间", required = true) 143 @Parameter(name = "expires", description = "订阅超时时间", required = true)
142 @Parameter(name = "interval", description = "上报时间间隔", required = true) 144 @Parameter(name = "interval", description = "上报时间间隔", required = true)
@@ -162,7 +164,7 @@ public class MobilePositionController { @@ -162,7 +164,7 @@ public class MobilePositionController {
162 * @param deviceId 设备ID 164 * @param deviceId 设备ID
163 * @return true = 命令发送成功 165 * @return true = 命令发送成功
164 */ 166 */
165 - @Operation(summary = "数据位置信息格式处理") 167 + @Operation(summary = "数据位置信息格式处理", security = @SecurityRequirement(name = JwtUtils.HEADER))
166 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 168 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
167 @GetMapping("/transform/{deviceId}") 169 @GetMapping("/transform/{deviceId}")
168 public void positionTransform(@PathVariable String deviceId) { 170 public void positionTransform(@PathVariable String deviceId) {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.alarm; 1 package com.genersoft.iot.vmp.vmanager.gb28181.alarm;
2 2
3 import com.genersoft.iot.vmp.conf.exception.ControllerException; 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  4 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
@@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
13 import com.github.pagehelper.PageInfo; 14 import com.github.pagehelper.PageInfo;
14 import io.swagger.v3.oas.annotations.Operation; 15 import io.swagger.v3.oas.annotations.Operation;
15 import io.swagger.v3.oas.annotations.Parameter; 16 import io.swagger.v3.oas.annotations.Parameter;
  17 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
16 import io.swagger.v3.oas.annotations.tags.Tag; 18 import io.swagger.v3.oas.annotations.tags.Tag;
17 import org.slf4j.Logger; 19 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory; 20 import org.slf4j.LoggerFactory;
@@ -56,7 +58,7 @@ public class AlarmController { @@ -56,7 +58,7 @@ public class AlarmController {
56 * @return 58 * @return
57 */ 59 */
58 @DeleteMapping("/delete") 60 @DeleteMapping("/delete")
59 - @Operation(summary = "删除报警") 61 + @Operation(summary = "删除报警", security = @SecurityRequirement(name = JwtUtils.HEADER))
60 @Parameter(name = "id", description = "ID") 62 @Parameter(name = "id", description = "ID")
61 @Parameter(name = "deviceIds", description = "多个设备id,逗号分隔") 63 @Parameter(name = "deviceIds", description = "多个设备id,逗号分隔")
62 @Parameter(name = "time", description = "结束时间") 64 @Parameter(name = "time", description = "结束时间")
@@ -93,7 +95,7 @@ public class AlarmController { @@ -93,7 +95,7 @@ public class AlarmController {
93 * @return 95 * @return
94 */ 96 */
95 @GetMapping("/test/notify/alarm") 97 @GetMapping("/test/notify/alarm")
96 - @Operation(summary = "测试向上级/设备发送模拟报警通知") 98 + @Operation(summary = "测试向上级/设备发送模拟报警通知", security = @SecurityRequirement(name = JwtUtils.HEADER))
97 @Parameter(name = "deviceId", description = "设备国标编号") 99 @Parameter(name = "deviceId", description = "设备国标编号")
98 public void delete(@RequestParam String deviceId) { 100 public void delete(@RequestParam String deviceId) {
99 Device device = storage.queryVideoDevice(deviceId); 101 Device device = storage.queryVideoDevice(deviceId);
@@ -141,7 +143,7 @@ public class AlarmController { @@ -141,7 +143,7 @@ public class AlarmController {
141 * @param endTime 结束时间 143 * @param endTime 结束时间
142 * @return 144 * @return
143 */ 145 */
144 - @Operation(summary = "分页查询报警") 146 + @Operation(summary = "分页查询报警", security = @SecurityRequirement(name = JwtUtils.HEADER))
145 @Parameter(name = "page",description = "当前页",required = true) 147 @Parameter(name = "page",description = "当前页",required = true)
146 @Parameter(name = "count",description = "每页查询数量",required = true) 148 @Parameter(name = "count",description = "每页查询数量",required = true)
147 @Parameter(name = "deviceId",description = "设备id") 149 @Parameter(name = "deviceId",description = "设备id")
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
@@ -9,6 +9,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device; @@ -9,6 +9,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device;
9 9
10 import com.alibaba.fastjson2.JSONObject; 10 import com.alibaba.fastjson2.JSONObject;
11 import com.genersoft.iot.vmp.conf.exception.ControllerException; 11 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  12 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
12 import com.genersoft.iot.vmp.gb28181.bean.Device; 13 import com.genersoft.iot.vmp.gb28181.bean.Device;
13 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
14 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 15 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
@@ -17,6 +18,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -17,6 +18,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 18 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
18 import io.swagger.v3.oas.annotations.Operation; 19 import io.swagger.v3.oas.annotations.Operation;
19 import io.swagger.v3.oas.annotations.Parameter; 20 import io.swagger.v3.oas.annotations.Parameter;
  21 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
20 import io.swagger.v3.oas.annotations.tags.Tag; 22 import io.swagger.v3.oas.annotations.tags.Tag;
21 import org.slf4j.Logger; 23 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
@@ -57,7 +59,7 @@ public class DeviceConfig { @@ -57,7 +59,7 @@ public class DeviceConfig {
57 * @return 59 * @return
58 */ 60 */
59 @GetMapping("/basicParam/{deviceId}") 61 @GetMapping("/basicParam/{deviceId}")
60 - @Operation(summary = "基本配置设置命令") 62 + @Operation(summary = "基本配置设置命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
61 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 63 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
62 @Parameter(name = "channelId", description = "通道国标编号", required = true) 64 @Parameter(name = "channelId", description = "通道国标编号", required = true)
63 @Parameter(name = "name", description = "名称") 65 @Parameter(name = "name", description = "名称")
@@ -113,7 +115,7 @@ public class DeviceConfig { @@ -113,7 +115,7 @@ public class DeviceConfig {
113 * @param channelId 通道ID 115 * @param channelId 通道ID
114 * @return 116 * @return
115 */ 117 */
116 - @Operation(summary = "设备配置查询请求") 118 + @Operation(summary = "设备配置查询请求", security = @SecurityRequirement(name = JwtUtils.HEADER))
117 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 119 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
118 @Parameter(name = "channelId", description = "通道国标编号", required = true) 120 @Parameter(name = "channelId", description = "通道国标编号", required = true)
119 @Parameter(name = "configType", description = "配置类型") 121 @Parameter(name = "configType", description = "配置类型")
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -9,6 +9,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device; @@ -9,6 +9,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device;
9 9
10 import com.alibaba.fastjson2.JSONObject; 10 import com.alibaba.fastjson2.JSONObject;
11 import com.genersoft.iot.vmp.conf.exception.ControllerException; 11 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  12 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
12 import com.genersoft.iot.vmp.gb28181.bean.Device; 13 import com.genersoft.iot.vmp.gb28181.bean.Device;
13 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
14 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 15 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
@@ -17,6 +18,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -17,6 +18,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 18 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
18 import io.swagger.v3.oas.annotations.Operation; 19 import io.swagger.v3.oas.annotations.Operation;
19 import io.swagger.v3.oas.annotations.Parameter; 20 import io.swagger.v3.oas.annotations.Parameter;
  21 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
20 import io.swagger.v3.oas.annotations.tags.Tag; 22 import io.swagger.v3.oas.annotations.tags.Tag;
21 import org.slf4j.Logger; 23 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
@@ -53,7 +55,7 @@ public class DeviceControl { @@ -53,7 +55,7 @@ public class DeviceControl {
53 * 55 *
54 * @param deviceId 设备ID 56 * @param deviceId 设备ID
55 */ 57 */
56 - @Operation(summary = "远程启动控制命令") 58 + @Operation(summary = "远程启动控制命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
57 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 59 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
58 @GetMapping("/teleboot/{deviceId}") 60 @GetMapping("/teleboot/{deviceId}")
59 public void teleBootApi(@PathVariable String deviceId) { 61 public void teleBootApi(@PathVariable String deviceId) {
@@ -76,7 +78,7 @@ public class DeviceControl { @@ -76,7 +78,7 @@ public class DeviceControl {
76 * @param recordCmdStr Record:手动录像,StopRecord:停止手动录像 78 * @param recordCmdStr Record:手动录像,StopRecord:停止手动录像
77 * @param channelId 通道编码(可选) 79 * @param channelId 通道编码(可选)
78 */ 80 */
79 - @Operation(summary = "录像控制") 81 + @Operation(summary = "录像控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
80 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 82 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
81 @Parameter(name = "channelId", description = "通道国标编号", required = true) 83 @Parameter(name = "channelId", description = "通道国标编号", required = true)
82 @Parameter(name = "recordCmdStr", description = "命令, 可选值:Record(手动录像),StopRecord(停止手动录像)", required = true) 84 @Parameter(name = "recordCmdStr", description = "命令, 可选值:Record(手动录像),StopRecord(停止手动录像)", required = true)
@@ -125,7 +127,7 @@ public class DeviceControl { @@ -125,7 +127,7 @@ public class DeviceControl {
125 * @param deviceId 设备ID 127 * @param deviceId 设备ID
126 * @param guardCmdStr SetGuard:布防,ResetGuard:撤防 128 * @param guardCmdStr SetGuard:布防,ResetGuard:撤防
127 */ 129 */
128 - @Operation(summary = "布防/撤防命令") 130 + @Operation(summary = "布防/撤防命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
129 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 131 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
130 @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true) 132 @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
131 @GetMapping("/guard/{deviceId}/{guardCmdStr}") 133 @GetMapping("/guard/{deviceId}/{guardCmdStr}")
@@ -170,7 +172,7 @@ public class DeviceControl { @@ -170,7 +172,7 @@ public class DeviceControl {
170 * @param alarmMethod 报警方式(可选) 172 * @param alarmMethod 报警方式(可选)
171 * @param alarmType 报警类型(可选) 173 * @param alarmType 报警类型(可选)
172 */ 174 */
173 - @Operation(summary = "报警复位") 175 + @Operation(summary = "报警复位", security = @SecurityRequirement(name = JwtUtils.HEADER))
174 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 176 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
175 @Parameter(name = "channelId", description = "通道国标编号", required = true) 177 @Parameter(name = "channelId", description = "通道国标编号", required = true)
176 @Parameter(name = "alarmMethod", description = "报警方式") 178 @Parameter(name = "alarmMethod", description = "报警方式")
@@ -217,7 +219,7 @@ public class DeviceControl { @@ -217,7 +219,7 @@ public class DeviceControl {
217 * @param deviceId 设备ID 219 * @param deviceId 设备ID
218 * @param channelId 通道ID 220 * @param channelId 通道ID
219 */ 221 */
220 - @Operation(summary = "强制关键帧") 222 + @Operation(summary = "强制关键帧", security = @SecurityRequirement(name = JwtUtils.HEADER))
221 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 223 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
222 @Parameter(name = "channelId", description = "通道国标编号") 224 @Parameter(name = "channelId", description = "通道国标编号")
223 @GetMapping("/i_frame/{deviceId}") 225 @GetMapping("/i_frame/{deviceId}")
@@ -249,7 +251,7 @@ public class DeviceControl { @@ -249,7 +251,7 @@ public class DeviceControl {
249 * @param presetIndex 调用预置位编号(可选) 251 * @param presetIndex 调用预置位编号(可选)
250 * @param channelId 通道编码(可选) 252 * @param channelId 通道编码(可选)
251 */ 253 */
252 - @Operation(summary = "看守位控制") 254 + @Operation(summary = "看守位控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
253 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 255 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
254 @Parameter(name = "channelId", description = "通道国标编号", required = true) 256 @Parameter(name = "channelId", description = "通道国标编号", required = true)
255 @Parameter(name = "enabled", description = "是否开启看守位 1:开启,0:关闭", required = true) 257 @Parameter(name = "enabled", description = "是否开启看守位 1:开启,0:关闭", required = true)
@@ -309,7 +311,7 @@ public class DeviceControl { @@ -309,7 +311,7 @@ public class DeviceControl {
309 * @param lengthy 拉框宽度像素值 311 * @param lengthy 拉框宽度像素值
310 * @return 312 * @return
311 */ 313 */
312 - @Operation(summary = "拉框放大") 314 + @Operation(summary = "拉框放大", security = @SecurityRequirement(name = JwtUtils.HEADER))
313 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 315 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
314 @Parameter(name = "channelId", description = "通道国标编号", required = true) 316 @Parameter(name = "channelId", description = "通道国标编号", required = true)
315 @Parameter(name = "length", description = "播放窗口长度像素值", required = true) 317 @Parameter(name = "length", description = "播放窗口长度像素值", required = true)
@@ -359,7 +361,7 @@ public class DeviceControl { @@ -359,7 +361,7 @@ public class DeviceControl {
359 * @param lengthy 拉框宽度像素值 361 * @param lengthy 拉框宽度像素值
360 * @return 362 * @return
361 */ 363 */
362 - @Operation(summary = "拉框放大") 364 + @Operation(summary = "拉框缩小", security = @SecurityRequirement(name = JwtUtils.HEADER))
363 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 365 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
364 @Parameter(name = "channelId", description = "通道国标编号") 366 @Parameter(name = "channelId", description = "通道国标编号")
365 @Parameter(name = "length", description = "播放窗口长度像素值", required = true) 367 @Parameter(name = "length", description = "播放窗口长度像素值", required = true)
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device; @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device;
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
4 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
5 import com.genersoft.iot.vmp.conf.exception.ControllerException; 5 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  6 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
6 import com.genersoft.iot.vmp.gb28181.bean.Device; 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
8 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; 9 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
@@ -23,6 +24,7 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult; @@ -23,6 +24,7 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
23 import com.github.pagehelper.PageInfo; 24 import com.github.pagehelper.PageInfo;
24 import io.swagger.v3.oas.annotations.Operation; 25 import io.swagger.v3.oas.annotations.Operation;
25 import io.swagger.v3.oas.annotations.Parameter; 26 import io.swagger.v3.oas.annotations.Parameter;
  27 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
26 import io.swagger.v3.oas.annotations.tags.Tag; 28 import io.swagger.v3.oas.annotations.tags.Tag;
27 import org.apache.commons.compress.utils.IOUtils; 29 import org.apache.commons.compress.utils.IOUtils;
28 import org.apache.ibatis.annotations.Options; 30 import org.apache.ibatis.annotations.Options;
@@ -85,7 +87,7 @@ public class DeviceQuery { @@ -85,7 +87,7 @@ public class DeviceQuery {
85 * @param deviceId 国标ID 87 * @param deviceId 国标ID
86 * @return 国标设备 88 * @return 国标设备
87 */ 89 */
88 - @Operation(summary = "查询国标设备") 90 + @Operation(summary = "查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
89 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 91 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
90 @GetMapping("/devices/{deviceId}") 92 @GetMapping("/devices/{deviceId}")
91 public Device devices(@PathVariable String deviceId){ 93 public Device devices(@PathVariable String deviceId){
@@ -99,7 +101,7 @@ public class DeviceQuery { @@ -99,7 +101,7 @@ public class DeviceQuery {
99 * @param count 每页查询数量 101 * @param count 每页查询数量
100 * @return 分页国标列表 102 * @return 分页国标列表
101 */ 103 */
102 - @Operation(summary = "分页查询国标设备") 104 + @Operation(summary = "分页查询国标设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
103 @Parameter(name = "page", description = "当前页", required = true) 105 @Parameter(name = "page", description = "当前页", required = true)
104 @Parameter(name = "count", description = "每页查询数量", required = true) 106 @Parameter(name = "count", description = "每页查询数量", required = true)
105 @GetMapping("/devices") 107 @GetMapping("/devices")
@@ -123,7 +125,7 @@ public class DeviceQuery { @@ -123,7 +125,7 @@ public class DeviceQuery {
123 * @return 通道列表 125 * @return 通道列表
124 */ 126 */
125 @GetMapping("/devices/{deviceId}/channels") 127 @GetMapping("/devices/{deviceId}/channels")
126 - @Operation(summary = "分页查询通道") 128 + @Operation(summary = "分页查询通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
127 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 129 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
128 @Parameter(name = "page", description = "当前页", required = true) 130 @Parameter(name = "page", description = "当前页", required = true)
129 @Parameter(name = "count", description = "每页查询数量", required = true) 131 @Parameter(name = "count", description = "每页查询数量", required = true)
@@ -149,7 +151,7 @@ public class DeviceQuery { @@ -149,7 +151,7 @@ public class DeviceQuery {
149 * @param deviceId 设备id 151 * @param deviceId 设备id
150 * @return 152 * @return
151 */ 153 */
152 - @Operation(summary = "同步设备通道") 154 + @Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
153 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 155 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
154 @GetMapping("/devices/{deviceId}/sync") 156 @GetMapping("/devices/{deviceId}/sync")
155 public WVPResult<SyncStatus> devicesSync(@PathVariable String deviceId){ 157 public WVPResult<SyncStatus> devicesSync(@PathVariable String deviceId){
@@ -177,7 +179,7 @@ public class DeviceQuery { @@ -177,7 +179,7 @@ public class DeviceQuery {
177 * @param deviceId 设备id 179 * @param deviceId 设备id
178 * @return 180 * @return
179 */ 181 */
180 - @Operation(summary = "移除设备") 182 + @Operation(summary = "移除设备", security = @SecurityRequirement(name = JwtUtils.HEADER))
181 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 183 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
182 @DeleteMapping("/devices/{deviceId}/delete") 184 @DeleteMapping("/devices/{deviceId}/delete")
183 public String delete(@PathVariable String deviceId){ 185 public String delete(@PathVariable String deviceId){
@@ -222,7 +224,7 @@ public class DeviceQuery { @@ -222,7 +224,7 @@ public class DeviceQuery {
222 * @param channelType 通道类型 224 * @param channelType 通道类型
223 * @return 子通道列表 225 * @return 子通道列表
224 */ 226 */
225 - @Operation(summary = "分页查询子目录通道") 227 + @Operation(summary = "分页查询子目录通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
226 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 228 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
227 @Parameter(name = "channelId", description = "通道国标编号", required = true) 229 @Parameter(name = "channelId", description = "通道国标编号", required = true)
228 @Parameter(name = "page", description = "当前页", required = true) 230 @Parameter(name = "page", description = "当前页", required = true)
@@ -254,7 +256,7 @@ public class DeviceQuery { @@ -254,7 +256,7 @@ public class DeviceQuery {
254 * @param channel 通道 256 * @param channel 通道
255 * @return 257 * @return
256 */ 258 */
257 - @Operation(summary = "更新通道信息") 259 + @Operation(summary = "更新通道信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
258 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 260 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
259 @Parameter(name = "channel", description = "通道信息", required = true) 261 @Parameter(name = "channel", description = "通道信息", required = true)
260 @PostMapping("/channel/update/{deviceId}") 262 @PostMapping("/channel/update/{deviceId}")
@@ -268,7 +270,7 @@ public class DeviceQuery { @@ -268,7 +270,7 @@ public class DeviceQuery {
268 * @param streamMode 数据流传输模式 270 * @param streamMode 数据流传输模式
269 * @return 271 * @return
270 */ 272 */
271 - @Operation(summary = "修改数据流传输模式") 273 + @Operation(summary = "修改数据流传输模式", security = @SecurityRequirement(name = JwtUtils.HEADER))
272 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 274 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
273 @Parameter(name = "streamMode", description = "数据流传输模式, 取值:" + 275 @Parameter(name = "streamMode", description = "数据流传输模式, 取值:" +
274 "UDP(udp传输),TCP-ACTIVE(tcp主动模式,暂不支持),TCP-PASSIVE(tcp被动模式)", required = true) 276 "UDP(udp传输),TCP-ACTIVE(tcp主动模式,暂不支持),TCP-PASSIVE(tcp被动模式)", required = true)
@@ -284,7 +286,7 @@ public class DeviceQuery { @@ -284,7 +286,7 @@ public class DeviceQuery {
284 * @param device 设备信息 286 * @param device 设备信息
285 * @return 287 * @return
286 */ 288 */
287 - @Operation(summary = "添加设备信息") 289 + @Operation(summary = "添加设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
288 @Parameter(name = "device", description = "设备", required = true) 290 @Parameter(name = "device", description = "设备", required = true)
289 @PostMapping("/device/add/") 291 @PostMapping("/device/add/")
290 public void addDevice(Device device){ 292 public void addDevice(Device device){
@@ -306,7 +308,7 @@ public class DeviceQuery { @@ -306,7 +308,7 @@ public class DeviceQuery {
306 * @param device 设备信息 308 * @param device 设备信息
307 * @return 309 * @return
308 */ 310 */
309 - @Operation(summary = "更新设备信息") 311 + @Operation(summary = "更新设备信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
310 @Parameter(name = "device", description = "设备", required = true) 312 @Parameter(name = "device", description = "设备", required = true)
311 @PostMapping("/device/update/") 313 @PostMapping("/device/update/")
312 public void updateDevice(Device device){ 314 public void updateDevice(Device device){
@@ -321,7 +323,7 @@ public class DeviceQuery { @@ -321,7 +323,7 @@ public class DeviceQuery {
321 * 323 *
322 * @param deviceId 设备id 324 * @param deviceId 设备id
323 */ 325 */
324 - @Operation(summary = "设备状态查询") 326 + @Operation(summary = "设备状态查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
325 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 327 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
326 @GetMapping("/devices/{deviceId}/status") 328 @GetMapping("/devices/{deviceId}/status")
327 public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) { 329 public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) {
@@ -372,7 +374,7 @@ public class DeviceQuery { @@ -372,7 +374,7 @@ public class DeviceQuery {
372 * @param endTime 报警发生终止时间(可选) 374 * @param endTime 报警发生终止时间(可选)
373 * @return true = 命令发送成功 375 * @return true = 命令发送成功
374 */ 376 */
375 - @Operation(summary = "设备状态查询") 377 + @Operation(summary = "设备报警查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
376 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 378 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
377 @Parameter(name = "startPriority", description = "报警起始级别") 379 @Parameter(name = "startPriority", description = "报警起始级别")
378 @Parameter(name = "endPriority", description = "报警终止级别") 380 @Parameter(name = "endPriority", description = "报警终止级别")
@@ -422,7 +424,7 @@ public class DeviceQuery { @@ -422,7 +424,7 @@ public class DeviceQuery {
422 424
423 425
424 @GetMapping("/{deviceId}/sync_status") 426 @GetMapping("/{deviceId}/sync_status")
425 - @Operation(summary = "获取通道同步进度") 427 + @Operation(summary = "获取通道同步进度", security = @SecurityRequirement(name = JwtUtils.HEADER))
426 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 428 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
427 public WVPResult<SyncStatus> getSyncStatus(@PathVariable String deviceId) { 429 public WVPResult<SyncStatus> getSyncStatus(@PathVariable String deviceId) {
428 SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId); 430 SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
@@ -442,7 +444,7 @@ public class DeviceQuery { @@ -442,7 +444,7 @@ public class DeviceQuery {
442 } 444 }
443 445
444 @GetMapping("/{deviceId}/subscribe_info") 446 @GetMapping("/{deviceId}/subscribe_info")
445 - @Operation(summary = "获取设备的订阅状态") 447 + @Operation(summary = "获取设备的订阅状态", security = @SecurityRequirement(name = JwtUtils.HEADER))
446 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 448 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
447 public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) { 449 public WVPResult<Map<String, Integer>> getSubscribeInfo(@PathVariable String deviceId) {
448 Set<String> allKeys = dynamicTask.getAllKeys(); 450 Set<String> allKeys = dynamicTask.getAllKeys();
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.gbStream; 1 package com.genersoft.iot.vmp.vmanager.gb28181.gbStream;
2 2
3 import com.genersoft.iot.vmp.conf.exception.ControllerException; 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  4 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
4 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 5 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 import com.genersoft.iot.vmp.service.IGbStreamService; 7 import com.genersoft.iot.vmp.service.IGbStreamService;
@@ -11,6 +12,7 @@ import com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean.GbStreamParam; @@ -11,6 +12,7 @@ import com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean.GbStreamParam;
11 import com.github.pagehelper.PageInfo; 12 import com.github.pagehelper.PageInfo;
12 import io.swagger.v3.oas.annotations.Operation; 13 import io.swagger.v3.oas.annotations.Operation;
13 import io.swagger.v3.oas.annotations.Parameter; 14 import io.swagger.v3.oas.annotations.Parameter;
  15 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
14 import io.swagger.v3.oas.annotations.tags.Tag; 16 import io.swagger.v3.oas.annotations.tags.Tag;
15 import org.slf4j.Logger; 17 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
@@ -43,7 +45,7 @@ public class GbStreamController { @@ -43,7 +45,7 @@ public class GbStreamController {
43 * @param platformId 平台ID 45 * @param platformId 平台ID
44 * @return 46 * @return
45 */ 47 */
46 - @Operation(summary = "查询国标通道") 48 + @Operation(summary = "查询国标通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
47 @Parameter(name = "page", description = "当前页", required = true) 49 @Parameter(name = "page", description = "当前页", required = true)
48 @Parameter(name = "count", description = "每页条数", required = true) 50 @Parameter(name = "count", description = "每页条数", required = true)
49 @Parameter(name = "platformId", description = "平台ID", required = true) 51 @Parameter(name = "platformId", description = "平台ID", required = true)
@@ -79,7 +81,7 @@ public class GbStreamController { @@ -79,7 +81,7 @@ public class GbStreamController {
79 * @param gbStreamParam 81 * @param gbStreamParam
80 * @return 82 * @return
81 */ 83 */
82 - @Operation(summary = "移除国标关联") 84 + @Operation(summary = "移除国标关联", security = @SecurityRequirement(name = JwtUtils.HEADER))
83 @DeleteMapping(value = "/del") 85 @DeleteMapping(value = "/del")
84 @ResponseBody 86 @ResponseBody
85 public void del(@RequestBody GbStreamParam gbStreamParam){ 87 public void del(@RequestBody GbStreamParam gbStreamParam){
@@ -99,7 +101,7 @@ public class GbStreamController { @@ -99,7 +101,7 @@ public class GbStreamController {
99 * @param gbStreamParam 101 * @param gbStreamParam
100 * @return 102 * @return
101 */ 103 */
102 - @Operation(summary = "保存国标关联") 104 + @Operation(summary = "保存国标关联", security = @SecurityRequirement(name = JwtUtils.HEADER))
103 @PostMapping(value = "/add") 105 @PostMapping(value = "/add")
104 @ResponseBody 106 @ResponseBody
105 public void add(@RequestBody GbStreamParam gbStreamParam){ 107 public void add(@RequestBody GbStreamParam gbStreamParam){
@@ -118,7 +120,7 @@ public class GbStreamController { @@ -118,7 +120,7 @@ public class GbStreamController {
118 * @param gbId 120 * @param gbId
119 * @return 121 * @return
120 */ 122 */
121 - @Operation(summary = "保存国标关联") 123 + @Operation(summary = "保存国标关联", security = @SecurityRequirement(name = JwtUtils.HEADER))
122 @GetMapping(value = "/addWithGbid") 124 @GetMapping(value = "/addWithGbid")
123 @ResponseBody 125 @ResponseBody
124 public void add(String gbId, String platformGbId, @RequestParam(required = false) String catalogGbId){ 126 public void add(String gbId, String platformGbId, @RequestParam(required = false) String catalogGbId){
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.media; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.media;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
5 import com.genersoft.iot.vmp.conf.security.SecurityUtils; 6 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
6 import com.genersoft.iot.vmp.conf.security.dto.LoginUser; 7 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
7 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; 8 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
@@ -12,6 +13,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -12,6 +13,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
12 import com.genersoft.iot.vmp.vmanager.bean.StreamContent; 13 import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
13 import io.swagger.v3.oas.annotations.Operation; 14 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 15 import io.swagger.v3.oas.annotations.Parameter;
  16 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
15 import io.swagger.v3.oas.annotations.tags.Tag; 17 import io.swagger.v3.oas.annotations.tags.Tag;
16 import org.slf4j.Logger; 18 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory; 19 import org.slf4j.LoggerFactory;
@@ -45,7 +47,7 @@ public class MediaController { @@ -45,7 +47,7 @@ public class MediaController {
45 * @param stream 流id 47 * @param stream 流id
46 * @return 48 * @return
47 */ 49 */
48 - @Operation(summary = "根据应用名和流id获取播放地址") 50 + @Operation(summary = "根据应用名和流id获取播放地址", security = @SecurityRequirement(name = JwtUtils.HEADER))
49 @Parameter(name = "app", description = "应用名", required = true) 51 @Parameter(name = "app", description = "应用名", required = true)
50 @Parameter(name = "stream", description = "流id", required = true) 52 @Parameter(name = "stream", description = "流id", required = true)
51 @Parameter(name = "mediaServerId", description = "媒体服务器id") 53 @Parameter(name = "mediaServerId", description = "媒体服务器id")
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
6 import com.genersoft.iot.vmp.conf.DynamicTask; 6 import com.genersoft.iot.vmp.conf.DynamicTask;
7 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.conf.exception.ControllerException; 8 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  9 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
9 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 10 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
10 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; 11 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
11 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; 12 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
@@ -21,6 +22,7 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam; @@ -21,6 +22,7 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam;
21 import com.github.pagehelper.PageInfo; 22 import com.github.pagehelper.PageInfo;
22 import io.swagger.v3.oas.annotations.Operation; 23 import io.swagger.v3.oas.annotations.Operation;
23 import io.swagger.v3.oas.annotations.Parameter; 24 import io.swagger.v3.oas.annotations.Parameter;
  25 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
24 import io.swagger.v3.oas.annotations.tags.Tag; 26 import io.swagger.v3.oas.annotations.tags.Tag;
25 import org.slf4j.Logger; 27 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory; 28 import org.slf4j.LoggerFactory;
@@ -83,7 +85,7 @@ public class PlatformController { @@ -83,7 +85,7 @@ public class PlatformController {
83 * 85 *
84 * @return 86 * @return
85 */ 87 */
86 - @Operation(summary = "获取国标服务的配置") 88 + @Operation(summary = "获取国标服务的配置", security = @SecurityRequirement(name = JwtUtils.HEADER))
87 @GetMapping("/server_config") 89 @GetMapping("/server_config")
88 public JSONObject serverConfig() { 90 public JSONObject serverConfig() {
89 JSONObject result = new JSONObject(); 91 JSONObject result = new JSONObject();
@@ -99,7 +101,7 @@ public class PlatformController { @@ -99,7 +101,7 @@ public class PlatformController {
99 * 101 *
100 * @return 102 * @return
101 */ 103 */
102 - @Operation(summary = "获取级联服务器信息") 104 + @Operation(summary = "获取级联服务器信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
103 @Parameter(name = "id", description = "平台国标编号", required = true) 105 @Parameter(name = "id", description = "平台国标编号", required = true)
104 @GetMapping("/info/{id}") 106 @GetMapping("/info/{id}")
105 public ParentPlatform getPlatform(@PathVariable String id) { 107 public ParentPlatform getPlatform(@PathVariable String id) {
@@ -119,7 +121,7 @@ public class PlatformController { @@ -119,7 +121,7 @@ public class PlatformController {
119 * @return 121 * @return
120 */ 122 */
121 @GetMapping("/query/{count}/{page}") 123 @GetMapping("/query/{count}/{page}")
122 - @Operation(summary = "分页查询级联平台") 124 + @Operation(summary = "分页查询级联平台", security = @SecurityRequirement(name = JwtUtils.HEADER))
123 @Parameter(name = "page", description = "当前页", required = true) 125 @Parameter(name = "page", description = "当前页", required = true)
124 @Parameter(name = "count", description = "每页条数", required = true) 126 @Parameter(name = "count", description = "每页条数", required = true)
125 public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count) { 127 public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count) {
@@ -140,7 +142,7 @@ public class PlatformController { @@ -140,7 +142,7 @@ public class PlatformController {
140 * @param parentPlatform 142 * @param parentPlatform
141 * @return 143 * @return
142 */ 144 */
143 - @Operation(summary = "添加上级平台信息") 145 + @Operation(summary = "添加上级平台信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
144 @PostMapping("/add") 146 @PostMapping("/add")
145 @ResponseBody 147 @ResponseBody
146 public void addPlatform(@RequestBody ParentPlatform parentPlatform) { 148 public void addPlatform(@RequestBody ParentPlatform parentPlatform) {
@@ -185,7 +187,7 @@ public class PlatformController { @@ -185,7 +187,7 @@ public class PlatformController {
185 * @param parentPlatform 187 * @param parentPlatform
186 * @return 188 * @return
187 */ 189 */
188 - @Operation(summary = "保存上级平台信息") 190 + @Operation(summary = "保存上级平台信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
189 @PostMapping("/save") 191 @PostMapping("/save")
190 @ResponseBody 192 @ResponseBody
191 public void savePlatform(@RequestBody ParentPlatform parentPlatform) { 193 public void savePlatform(@RequestBody ParentPlatform parentPlatform) {
@@ -216,7 +218,7 @@ public class PlatformController { @@ -216,7 +218,7 @@ public class PlatformController {
216 * @param serverGBId 上级平台国标ID 218 * @param serverGBId 上级平台国标ID
217 * @return 219 * @return
218 */ 220 */
219 - @Operation(summary = "删除上级平台") 221 + @Operation(summary = "删除上级平台", security = @SecurityRequirement(name = JwtUtils.HEADER))
220 @Parameter(name = "serverGBId", description = "上级平台的国标编号") 222 @Parameter(name = "serverGBId", description = "上级平台的国标编号")
221 @DeleteMapping("/delete/{serverGBId}") 223 @DeleteMapping("/delete/{serverGBId}")
222 @ResponseBody 224 @ResponseBody
@@ -273,7 +275,7 @@ public class PlatformController { @@ -273,7 +275,7 @@ public class PlatformController {
273 * @param serverGBId 上级平台国标ID 275 * @param serverGBId 上级平台国标ID
274 * @return 276 * @return
275 */ 277 */
276 - @Operation(summary = "查询上级平台是否存在") 278 + @Operation(summary = "查询上级平台是否存在", security = @SecurityRequirement(name = JwtUtils.HEADER))
277 @Parameter(name = "serverGBId", description = "上级平台的国标编号") 279 @Parameter(name = "serverGBId", description = "上级平台的国标编号")
278 @GetMapping("/exit/{serverGBId}") 280 @GetMapping("/exit/{serverGBId}")
279 @ResponseBody 281 @ResponseBody
@@ -294,7 +296,7 @@ public class PlatformController { @@ -294,7 +296,7 @@ public class PlatformController {
294 * @param channelType 通道类型 296 * @param channelType 通道类型
295 * @return 297 * @return
296 */ 298 */
297 - @Operation(summary = "查询上级平台是否存在") 299 + @Operation(summary = "查询上级平台是否存在", security = @SecurityRequirement(name = JwtUtils.HEADER))
298 @Parameter(name = "page", description = "当前页", required = true) 300 @Parameter(name = "page", description = "当前页", required = true)
299 @Parameter(name = "count", description = "每页条数", required = true) 301 @Parameter(name = "count", description = "每页条数", required = true)
300 @Parameter(name = "platformId", description = "上级平台的国标编号") 302 @Parameter(name = "platformId", description = "上级平台的国标编号")
@@ -331,7 +333,7 @@ public class PlatformController { @@ -331,7 +333,7 @@ public class PlatformController {
331 * @param param 通道关联参数 333 * @param param 通道关联参数
332 * @return 334 * @return
333 */ 335 */
334 - @Operation(summary = "向上级平台添加国标通道") 336 + @Operation(summary = "向上级平台添加国标通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
335 @PostMapping("/update_channel_for_gb") 337 @PostMapping("/update_channel_for_gb")
336 @ResponseBody 338 @ResponseBody
337 public void updateChannelForGB(@RequestBody UpdateChannelParam param) { 339 public void updateChannelForGB(@RequestBody UpdateChannelParam param) {
@@ -360,7 +362,7 @@ public class PlatformController { @@ -360,7 +362,7 @@ public class PlatformController {
360 * @param param 通道关联参数 362 * @param param 通道关联参数
361 * @return 363 * @return
362 */ 364 */
363 - @Operation(summary = "从上级平台移除国标通道") 365 + @Operation(summary = "从上级平台移除国标通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
364 @DeleteMapping("/del_channel_for_gb") 366 @DeleteMapping("/del_channel_for_gb")
365 @ResponseBody 367 @ResponseBody
366 public void delChannelForGB(@RequestBody UpdateChannelParam param) { 368 public void delChannelForGB(@RequestBody UpdateChannelParam param) {
@@ -389,7 +391,7 @@ public class PlatformController { @@ -389,7 +391,7 @@ public class PlatformController {
389 * @param parentId 目录父ID 391 * @param parentId 目录父ID
390 * @return 392 * @return
391 */ 393 */
392 - @Operation(summary = "获取目录") 394 + @Operation(summary = "获取目录", security = @SecurityRequirement(name = JwtUtils.HEADER))
393 @Parameter(name = "platformId", description = "上级平台的国标编号", required = true) 395 @Parameter(name = "platformId", description = "上级平台的国标编号", required = true)
394 @Parameter(name = "parentId", description = "父级目录的国标编号", required = true) 396 @Parameter(name = "parentId", description = "父级目录的国标编号", required = true)
395 @GetMapping("/catalog") 397 @GetMapping("/catalog")
@@ -420,7 +422,7 @@ public class PlatformController { @@ -420,7 +422,7 @@ public class PlatformController {
420 * @param platformCatalog 目录 422 * @param platformCatalog 目录
421 * @return 423 * @return
422 */ 424 */
423 - @Operation(summary = "添加目录") 425 + @Operation(summary = "添加目录", security = @SecurityRequirement(name = JwtUtils.HEADER))
424 @PostMapping("/catalog/add") 426 @PostMapping("/catalog/add")
425 @ResponseBody 427 @ResponseBody
426 public void addCatalog(@RequestBody PlatformCatalog platformCatalog) { 428 public void addCatalog(@RequestBody PlatformCatalog platformCatalog) {
@@ -445,7 +447,7 @@ public class PlatformController { @@ -445,7 +447,7 @@ public class PlatformController {
445 * @param platformCatalog 目录 447 * @param platformCatalog 目录
446 * @return 448 * @return
447 */ 449 */
448 - @Operation(summary = "编辑目录") 450 + @Operation(summary = "编辑目录", security = @SecurityRequirement(name = JwtUtils.HEADER))
449 @PostMapping("/catalog/edit") 451 @PostMapping("/catalog/edit")
450 @ResponseBody 452 @ResponseBody
451 public void editCatalog(@RequestBody PlatformCatalog platformCatalog) { 453 public void editCatalog(@RequestBody PlatformCatalog platformCatalog) {
@@ -471,7 +473,7 @@ public class PlatformController { @@ -471,7 +473,7 @@ public class PlatformController {
471 * @param platformId 平台Id 473 * @param platformId 平台Id
472 * @return 474 * @return
473 */ 475 */
474 - @Operation(summary = "删除目录") 476 + @Operation(summary = "删除目录", security = @SecurityRequirement(name = JwtUtils.HEADER))
475 @Parameter(name = "id", description = "目录Id", required = true) 477 @Parameter(name = "id", description = "目录Id", required = true)
476 @Parameter(name = "platformId", description = "平台Id", required = true) 478 @Parameter(name = "platformId", description = "平台Id", required = true)
477 @DeleteMapping("/catalog/del") 479 @DeleteMapping("/catalog/del")
@@ -506,7 +508,7 @@ public class PlatformController { @@ -506,7 +508,7 @@ public class PlatformController {
506 * @param platformCatalog 关联的信息 508 * @param platformCatalog 关联的信息
507 * @return 509 * @return
508 */ 510 */
509 - @Operation(summary = "删除关联") 511 + @Operation(summary = "删除关联", security = @SecurityRequirement(name = JwtUtils.HEADER))
510 @DeleteMapping("/catalog/relation/del") 512 @DeleteMapping("/catalog/relation/del")
511 @ResponseBody 513 @ResponseBody
512 public void delRelation(@RequestBody PlatformCatalog platformCatalog) { 514 public void delRelation(@RequestBody PlatformCatalog platformCatalog) {
@@ -529,7 +531,7 @@ public class PlatformController { @@ -529,7 +531,7 @@ public class PlatformController {
529 * @param catalogId 目录Id 531 * @param catalogId 目录Id
530 * @return 532 * @return
531 */ 533 */
532 - @Operation(summary = "修改默认目录") 534 + @Operation(summary = "修改默认目录", security = @SecurityRequirement(name = JwtUtils.HEADER))
533 @Parameter(name = "catalogId", description = "目录Id", required = true) 535 @Parameter(name = "catalogId", description = "目录Id", required = true)
534 @Parameter(name = "platformId", description = "平台Id", required = true) 536 @Parameter(name = "platformId", description = "平台Id", required = true)
535 @PostMapping("/catalog/default/update") 537 @PostMapping("/catalog/default/update")
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.common.StreamInfo; @@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.common.StreamInfo;
9 import com.genersoft.iot.vmp.conf.UserSetting; 9 import com.genersoft.iot.vmp.conf.UserSetting;
10 import com.genersoft.iot.vmp.conf.exception.ControllerException; 10 import com.genersoft.iot.vmp.conf.exception.ControllerException;
11 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 11 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  12 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
12 import com.genersoft.iot.vmp.gb28181.bean.Device; 13 import com.genersoft.iot.vmp.gb28181.bean.Device;
13 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; 14 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
14 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 15 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -31,6 +32,7 @@ import com.genersoft.iot.vmp.vmanager.bean.StreamContent; @@ -31,6 +32,7 @@ import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
31 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 32 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
32 import io.swagger.v3.oas.annotations.Operation; 33 import io.swagger.v3.oas.annotations.Operation;
33 import io.swagger.v3.oas.annotations.Parameter; 34 import io.swagger.v3.oas.annotations.Parameter;
  35 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
34 import io.swagger.v3.oas.annotations.tags.Tag; 36 import io.swagger.v3.oas.annotations.tags.Tag;
35 import org.slf4j.Logger; 37 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory; 38 import org.slf4j.LoggerFactory;
@@ -92,7 +94,7 @@ public class PlayController { @@ -92,7 +94,7 @@ public class PlayController {
92 @Autowired 94 @Autowired
93 private UserSetting userSetting; 95 private UserSetting userSetting;
94 96
95 - @Operation(summary = "开始点播") 97 + @Operation(summary = "开始点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
96 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 98 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
97 @Parameter(name = "channelId", description = "通道国标编号", required = true) 99 @Parameter(name = "channelId", description = "通道国标编号", required = true)
98 @GetMapping("/start/{deviceId}/{channelId}") 100 @GetMapping("/start/{deviceId}/{channelId}")
@@ -157,7 +159,7 @@ public class PlayController { @@ -157,7 +159,7 @@ public class PlayController {
157 return result; 159 return result;
158 } 160 }
159 161
160 - @Operation(summary = "停止点播") 162 + @Operation(summary = "停止点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
161 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 163 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
162 @Parameter(name = "channelId", description = "通道国标编号", required = true) 164 @Parameter(name = "channelId", description = "通道国标编号", required = true)
163 @Parameter(name = "isSubStream", description = "是否子码流(true-子码流,false-主码流),默认为false", required = true) 165 @Parameter(name = "isSubStream", description = "是否子码流(true-子码流,false-主码流),默认为false", required = true)
@@ -202,7 +204,7 @@ public class PlayController { @@ -202,7 +204,7 @@ public class PlayController {
202 * 将不是h264的视频通过ffmpeg 转码为h264 + aac 204 * 将不是h264的视频通过ffmpeg 转码为h264 + aac
203 * @param streamId 流ID 205 * @param streamId 流ID
204 */ 206 */
205 - @Operation(summary = "将不是h264的视频通过ffmpeg 转码为h264 + aac") 207 + @Operation(summary = "将不是h264的视频通过ffmpeg 转码为h264 + aac", security = @SecurityRequirement(name = JwtUtils.HEADER))
206 @Parameter(name = "streamId", description = "视频流ID", required = true) 208 @Parameter(name = "streamId", description = "视频流ID", required = true)
207 @PostMapping("/convert/{streamId}") 209 @PostMapping("/convert/{streamId}")
208 public JSONObject playConvert(@PathVariable String streamId) { 210 public JSONObject playConvert(@PathVariable String streamId) {
@@ -244,7 +246,7 @@ public class PlayController { @@ -244,7 +246,7 @@ public class PlayController {
244 /** 246 /**
245 * 结束转码 247 * 结束转码
246 */ 248 */
247 - @Operation(summary = "结束转码") 249 + @Operation(summary = "结束转码", security = @SecurityRequirement(name = JwtUtils.HEADER))
248 @Parameter(name = "key", description = "视频流key", required = true) 250 @Parameter(name = "key", description = "视频流key", required = true)
249 @Parameter(name = "mediaServerId", description = "流媒体服务ID", required = true) 251 @Parameter(name = "mediaServerId", description = "流媒体服务ID", required = true)
250 @PostMapping("/convertStop/{key}") 252 @PostMapping("/convertStop/{key}")
@@ -269,7 +271,7 @@ public class PlayController { @@ -269,7 +271,7 @@ public class PlayController {
269 } 271 }
270 } 272 }
271 273
272 - @Operation(summary = "语音广播命令") 274 + @Operation(summary = "语音广播命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
273 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 275 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
274 @Parameter(name = "deviceId", description = "通道国标编号", required = true) 276 @Parameter(name = "deviceId", description = "通道国标编号", required = true)
275 @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true) 277 @Parameter(name = "timeout", description = "推流超时时间(秒)", required = true)
@@ -309,7 +311,7 @@ public class PlayController { @@ -309,7 +311,7 @@ public class PlayController {
309 playService.stopAudioBroadcast(deviceId, channelId); 311 playService.stopAudioBroadcast(deviceId, channelId);
310 } 312 }
311 313
312 - @Operation(summary = "获取所有的ssrc") 314 + @Operation(summary = "获取所有的ssrc", security = @SecurityRequirement(name = JwtUtils.HEADER))
313 @GetMapping("/ssrc") 315 @GetMapping("/ssrc")
314 public JSONObject getSSRC() { 316 public JSONObject getSSRC() {
315 if (logger.isDebugEnabled()) { 317 if (logger.isDebugEnabled()) {
@@ -332,7 +334,7 @@ public class PlayController { @@ -332,7 +334,7 @@ public class PlayController {
332 return jsonObject; 334 return jsonObject;
333 } 335 }
334 336
335 - @Operation(summary = "获取截图") 337 + @Operation(summary = "获取截图", security = @SecurityRequirement(name = JwtUtils.HEADER))
336 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 338 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
337 @Parameter(name = "channelId", description = "通道国标编号", required = true) 339 @Parameter(name = "channelId", description = "通道国标编号", required = true)
338 @Parameter(name = "isSubStream", description = "是否子码流(true-子码流,false-主码流),默认为false", required = true) 340 @Parameter(name = "isSubStream", description = "是否子码流(true-子码流,false-主码流),默认为false", required = true)
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
7 import com.genersoft.iot.vmp.conf.exception.ControllerException; 7 import com.genersoft.iot.vmp.conf.exception.ControllerException;
8 import com.genersoft.iot.vmp.conf.exception.ServiceException; 8 import com.genersoft.iot.vmp.conf.exception.ServiceException;
9 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 9 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  10 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
10 import com.genersoft.iot.vmp.gb28181.bean.Device; 11 import com.genersoft.iot.vmp.gb28181.bean.Device;
11 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 12 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
12 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
@@ -20,6 +21,7 @@ import com.genersoft.iot.vmp.vmanager.bean.StreamContent; @@ -20,6 +21,7 @@ import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
20 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 21 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
21 import io.swagger.v3.oas.annotations.Operation; 22 import io.swagger.v3.oas.annotations.Operation;
22 import io.swagger.v3.oas.annotations.Parameter; 23 import io.swagger.v3.oas.annotations.Parameter;
  24 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
23 import io.swagger.v3.oas.annotations.tags.Tag; 25 import io.swagger.v3.oas.annotations.tags.Tag;
24 import org.slf4j.Logger; 26 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory; 27 import org.slf4j.LoggerFactory;
@@ -68,7 +70,7 @@ public class PlaybackController { @@ -68,7 +70,7 @@ public class PlaybackController {
68 @Autowired 70 @Autowired
69 private UserSetting userSetting; 71 private UserSetting userSetting;
70 72
71 - @Operation(summary = "开始视频回放") 73 + @Operation(summary = "开始视频回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
72 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 74 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
73 @Parameter(name = "channelId", description = "通道国标编号", required = true) 75 @Parameter(name = "channelId", description = "通道国标编号", required = true)
74 @Parameter(name = "startTime", description = "开始时间", required = true) 76 @Parameter(name = "startTime", description = "开始时间", required = true)
@@ -125,7 +127,7 @@ public class PlaybackController { @@ -125,7 +127,7 @@ public class PlaybackController {
125 } 127 }
126 128
127 129
128 - @Operation(summary = "停止视频回放") 130 + @Operation(summary = "停止视频回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
129 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 131 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
130 @Parameter(name = "channelId", description = "通道国标编号", required = true) 132 @Parameter(name = "channelId", description = "通道国标编号", required = true)
131 @Parameter(name = "stream", description = "流ID", required = true) 133 @Parameter(name = "stream", description = "流ID", required = true)
@@ -149,7 +151,7 @@ public class PlaybackController { @@ -149,7 +151,7 @@ public class PlaybackController {
149 } 151 }
150 152
151 153
152 - @Operation(summary = "回放暂停") 154 + @Operation(summary = "回放暂停", security = @SecurityRequirement(name = JwtUtils.HEADER))
153 @Parameter(name = "streamId", description = "回放流ID", required = true) 155 @Parameter(name = "streamId", description = "回放流ID", required = true)
154 @GetMapping("/pause/{streamId}") 156 @GetMapping("/pause/{streamId}")
155 public void playPause(@PathVariable String streamId) { 157 public void playPause(@PathVariable String streamId) {
@@ -165,7 +167,7 @@ public class PlaybackController { @@ -165,7 +167,7 @@ public class PlaybackController {
165 } 167 }
166 168
167 169
168 - @Operation(summary = "回放恢复") 170 + @Operation(summary = "回放恢复", security = @SecurityRequirement(name = JwtUtils.HEADER))
169 @Parameter(name = "streamId", description = "回放流ID", required = true) 171 @Parameter(name = "streamId", description = "回放流ID", required = true)
170 @GetMapping("/resume/{streamId}") 172 @GetMapping("/resume/{streamId}")
171 public void playResume(@PathVariable String streamId) { 173 public void playResume(@PathVariable String streamId) {
@@ -180,7 +182,7 @@ public class PlaybackController { @@ -180,7 +182,7 @@ public class PlaybackController {
180 } 182 }
181 183
182 184
183 - @Operation(summary = "回放拖动播放") 185 + @Operation(summary = "回放拖动播放", security = @SecurityRequirement(name = JwtUtils.HEADER))
184 @Parameter(name = "streamId", description = "回放流ID", required = true) 186 @Parameter(name = "streamId", description = "回放流ID", required = true)
185 @Parameter(name = "seekTime", description = "拖动偏移量,单位s", required = true) 187 @Parameter(name = "seekTime", description = "拖动偏移量,单位s", required = true)
186 @GetMapping("/seek/{streamId}/{seekTime}") 188 @GetMapping("/seek/{streamId}/{seekTime}")
@@ -200,7 +202,7 @@ public class PlaybackController { @@ -200,7 +202,7 @@ public class PlaybackController {
200 } 202 }
201 } 203 }
202 204
203 - @Operation(summary = "回放倍速播放") 205 + @Operation(summary = "回放倍速播放", security = @SecurityRequirement(name = JwtUtils.HEADER))
204 @Parameter(name = "streamId", description = "回放流ID", required = true) 206 @Parameter(name = "streamId", description = "回放流ID", required = true)
205 @Parameter(name = "speed", description = "倍速0.25 0.5 1、2、4", required = true) 207 @Parameter(name = "speed", description = "倍速0.25 0.5 1、2、4", required = true)
206 @GetMapping("/speed/{streamId}/{speed}") 208 @GetMapping("/speed/{streamId}/{speed}")
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.ptz; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.ptz;
2 2
3 3
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
@@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 11 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
11 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.Parameter; 13 import io.swagger.v3.oas.annotations.Parameter;
  14 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
13 import io.swagger.v3.oas.annotations.tags.Tag; 15 import io.swagger.v3.oas.annotations.tags.Tag;
14 import org.slf4j.Logger; 16 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory; 17 import org.slf4j.LoggerFactory;
@@ -50,7 +52,7 @@ public class PtzController { @@ -50,7 +52,7 @@ public class PtzController {
50 * @param zoomSpeed 缩放速度 52 * @param zoomSpeed 缩放速度
51 */ 53 */
52 54
53 - @Operation(summary = "云台控制") 55 + @Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
54 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 56 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
55 @Parameter(name = "channelId", description = "通道国标编号", required = true) 57 @Parameter(name = "channelId", description = "通道国标编号", required = true)
56 @Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true) 58 @Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true)
@@ -113,7 +115,7 @@ public class PtzController { @@ -113,7 +115,7 @@ public class PtzController {
113 } 115 }
114 116
115 117
116 - @Operation(summary = "通用前端控制命令") 118 + @Operation(summary = "通用前端控制命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
117 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 119 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
118 @Parameter(name = "channelId", description = "通道国标编号", required = true) 120 @Parameter(name = "channelId", description = "通道国标编号", required = true)
119 @Parameter(name = "cmdCode", description = "指令码", required = true) 121 @Parameter(name = "cmdCode", description = "指令码", required = true)
@@ -137,7 +139,7 @@ public class PtzController { @@ -137,7 +139,7 @@ public class PtzController {
137 } 139 }
138 140
139 141
140 - @Operation(summary = "预置位查询") 142 + @Operation(summary = "预置位查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
141 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 143 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
142 @Parameter(name = "channelId", description = "通道国标编号", required = true) 144 @Parameter(name = "channelId", description = "通道国标编号", required = true)
143 @GetMapping("/preset/query/{deviceId}/{channelId}") 145 @GetMapping("/preset/query/{deviceId}/{channelId}")
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.record; 1 package com.genersoft.iot.vmp.vmanager.gb28181.record;
2 2
  3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
3 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.conf.exception.ControllerException; 7 import com.genersoft.iot.vmp.conf.exception.ControllerException;
6 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 8 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  9 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
7 import com.genersoft.iot.vmp.gb28181.bean.Device; 10 import com.genersoft.iot.vmp.gb28181.bean.Device;
8 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; 11 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 12 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
10 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
12 import com.genersoft.iot.vmp.service.IDeviceService; 15 import com.genersoft.iot.vmp.service.IDeviceService;
  16 +import com.genersoft.iot.vmp.service.IInviteStreamService;
13 import com.genersoft.iot.vmp.service.IPlayService; 17 import com.genersoft.iot.vmp.service.IPlayService;
  18 +import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
14 import com.genersoft.iot.vmp.service.bean.InviteErrorCode; 19 import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 20 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
16 import com.genersoft.iot.vmp.utils.DateUtil; 21 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -19,10 +24,12 @@ import com.genersoft.iot.vmp.vmanager.bean.StreamContent; @@ -19,10 +24,12 @@ import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
19 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 24 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
20 import io.swagger.v3.oas.annotations.Operation; 25 import io.swagger.v3.oas.annotations.Operation;
21 import io.swagger.v3.oas.annotations.Parameter; 26 import io.swagger.v3.oas.annotations.Parameter;
  27 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
22 import io.swagger.v3.oas.annotations.tags.Tag; 28 import io.swagger.v3.oas.annotations.tags.Tag;
23 import org.slf4j.Logger; 29 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory; 30 import org.slf4j.LoggerFactory;
25 import org.springframework.beans.factory.annotation.Autowired; 31 import org.springframework.beans.factory.annotation.Autowired;
  32 +import org.springframework.util.ObjectUtils;
26 import org.springframework.web.bind.annotation.GetMapping; 33 import org.springframework.web.bind.annotation.GetMapping;
27 import org.springframework.web.bind.annotation.PathVariable; 34 import org.springframework.web.bind.annotation.PathVariable;
28 import org.springframework.web.bind.annotation.RequestMapping; 35 import org.springframework.web.bind.annotation.RequestMapping;
@@ -56,12 +63,15 @@ public class GBRecordController { @@ -56,12 +63,15 @@ public class GBRecordController {
56 private IPlayService playService; 63 private IPlayService playService;
57 64
58 @Autowired 65 @Autowired
  66 + private IInviteStreamService inviteStreamService;
  67 +
  68 + @Autowired
59 private IDeviceService deviceService; 69 private IDeviceService deviceService;
60 70
61 @Autowired 71 @Autowired
62 private UserSetting userSetting; 72 private UserSetting userSetting;
63 73
64 - @Operation(summary = "录像查询") 74 + @Operation(summary = "录像查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
65 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 75 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
66 @Parameter(name = "channelId", description = "通道国标编号", required = true) 76 @Parameter(name = "channelId", description = "通道国标编号", required = true)
67 @Parameter(name = "startTime", description = "开始时间", required = true) 77 @Parameter(name = "startTime", description = "开始时间", required = true)
@@ -115,7 +125,7 @@ public class GBRecordController { @@ -115,7 +125,7 @@ public class GBRecordController {
115 } 125 }
116 126
117 127
118 - @Operation(summary = "开始历史媒体下载") 128 + @Operation(summary = "开始历史媒体下载", security = @SecurityRequirement(name = JwtUtils.HEADER))
119 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 129 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
120 @Parameter(name = "channelId", description = "通道国标编号", required = true) 130 @Parameter(name = "channelId", description = "通道国标编号", required = true)
121 @Parameter(name = "startTime", description = "开始时间", required = true) 131 @Parameter(name = "startTime", description = "开始时间", required = true)
@@ -164,7 +174,7 @@ public class GBRecordController { @@ -164,7 +174,7 @@ public class GBRecordController {
164 return result; 174 return result;
165 } 175 }
166 176
167 - @Operation(summary = "停止历史媒体下载") 177 + @Operation(summary = "停止历史媒体下载", security = @SecurityRequirement(name = JwtUtils.HEADER))
168 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 178 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
169 @Parameter(name = "channelId", description = "通道国标编号", required = true) 179 @Parameter(name = "channelId", description = "通道国标编号", required = true)
170 @Parameter(name = "stream", description = "流ID", required = true) 180 @Parameter(name = "stream", description = "流ID", required = true)
@@ -192,7 +202,7 @@ public class GBRecordController { @@ -192,7 +202,7 @@ public class GBRecordController {
192 } 202 }
193 } 203 }
194 204
195 - @Operation(summary = "获取历史媒体下载进度") 205 + @Operation(summary = "获取历史媒体下载进度", security = @SecurityRequirement(name = JwtUtils.HEADER))
196 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 206 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
197 @Parameter(name = "channelId", description = "通道国标编号", required = true) 207 @Parameter(name = "channelId", description = "通道国标编号", required = true)
198 @Parameter(name = "stream", description = "流ID", required = true) 208 @Parameter(name = "stream", description = "流ID", required = true)
src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.log; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.log;
2 2
3 import com.genersoft.iot.vmp.conf.UserSetting; 3 import com.genersoft.iot.vmp.conf.UserSetting;
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
5 import com.genersoft.iot.vmp.service.ILogService; 6 import com.genersoft.iot.vmp.service.ILogService;
6 import com.genersoft.iot.vmp.storager.dao.dto.LogDto; 7 import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
7 import com.genersoft.iot.vmp.utils.DateUtil; 8 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
9 import com.github.pagehelper.PageInfo; 10 import com.github.pagehelper.PageInfo;
10 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
11 import io.swagger.v3.oas.annotations.Parameter; 12 import io.swagger.v3.oas.annotations.Parameter;
  13 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
12 import io.swagger.v3.oas.annotations.tags.Tag; 14 import io.swagger.v3.oas.annotations.tags.Tag;
13 import org.slf4j.Logger; 15 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 16 import org.slf4j.LoggerFactory;
@@ -42,7 +44,7 @@ public class LogController { @@ -42,7 +44,7 @@ public class LogController {
42 * @return 44 * @return
43 */ 45 */
44 @GetMapping("/all") 46 @GetMapping("/all")
45 - @Operation(summary = "分页查询日志") 47 + @Operation(summary = "分页查询日志", security = @SecurityRequirement(name = JwtUtils.HEADER))
46 @Parameter(name = "query", description = "查询内容", required = true) 48 @Parameter(name = "query", description = "查询内容", required = true)
47 @Parameter(name = "page", description = "当前页", required = true) 49 @Parameter(name = "page", description = "当前页", required = true)
48 @Parameter(name = "count", description = "每页查询数量", required = true) 50 @Parameter(name = "count", description = "每页查询数量", required = true)
@@ -84,7 +86,7 @@ public class LogController { @@ -84,7 +86,7 @@ public class LogController {
84 * 清空日志 86 * 清空日志
85 * 87 *
86 */ 88 */
87 - @Operation(summary = "清空日志") 89 + @Operation(summary = "清空日志", security = @SecurityRequirement(name = JwtUtils.HEADER))
88 @DeleteMapping("/clear") 90 @DeleteMapping("/clear")
89 public void clear() { 91 public void clear() {
90 logService.clear(); 92 logService.clear();
src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
5 import com.genersoft.iot.vmp.conf.DynamicTask; 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
7 import com.genersoft.iot.vmp.conf.exception.ControllerException; 7 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  8 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
8 import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; 9 import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
9 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; 10 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
10 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 11 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
@@ -19,6 +20,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -19,6 +20,7 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
19 import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; 20 import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo;
20 import io.swagger.v3.oas.annotations.Operation; 21 import io.swagger.v3.oas.annotations.Operation;
21 import io.swagger.v3.oas.annotations.Parameter; 22 import io.swagger.v3.oas.annotations.Parameter;
  23 +import io.swagger.v3.oas.annotations.security.SecurityRequirement;
22 import io.swagger.v3.oas.annotations.tags.Tag; 24 import io.swagger.v3.oas.annotations.tags.Tag;
23 import okhttp3.OkHttpClient; 25 import okhttp3.OkHttpClient;
24 import okhttp3.Request; 26 import okhttp3.Request;
@@ -69,7 +71,7 @@ public class PsController { @@ -69,7 +71,7 @@ public class PsController {
69 71
70 @GetMapping(value = "/receive/open") 72 @GetMapping(value = "/receive/open")
71 @ResponseBody 73 @ResponseBody
72 - @Operation(summary = "开启收流和获取发流信息") 74 + @Operation(summary = "开启收流和获取发流信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
73 @Parameter(name = "isSend", description = "是否发送,false时只开启收流, true同时返回推流信息", required = true) 75 @Parameter(name = "isSend", description = "是否发送,false时只开启收流, true同时返回推流信息", required = true)
74 @Parameter(name = "callId", description = "整个过程的唯一标识,为了与后续接口关联", required = true) 76 @Parameter(name = "callId", description = "整个过程的唯一标识,为了与后续接口关联", required = true)
75 @Parameter(name = "ssrc", description = "来源流的SSRC,不传则不校验来源ssrc", required = false) 77 @Parameter(name = "ssrc", description = "来源流的SSRC,不传则不校验来源ssrc", required = false)
@@ -152,7 +154,7 @@ public class PsController { @@ -152,7 +154,7 @@ public class PsController {
152 154
153 @GetMapping(value = "/receive/close") 155 @GetMapping(value = "/receive/close")
154 @ResponseBody 156 @ResponseBody
155 - @Operation(summary = "关闭收流") 157 + @Operation(summary = "关闭收流", security = @SecurityRequirement(name = JwtUtils.HEADER))
156 @Parameter(name = "stream", description = "流的ID", required = true) 158 @Parameter(name = "stream", description = "流的ID", required = true)
157 public void closeRtpServer(String stream) { 159 public void closeRtpServer(String stream) {
158 logger.info("[第三方PS服务对接->关闭收流] stream->{}", stream); 160 logger.info("[第三方PS服务对接->关闭收流] stream->{}", stream);
@@ -170,7 +172,7 @@ public class PsController { @@ -170,7 +172,7 @@ public class PsController {
170 172
171 @GetMapping(value = "/send/start") 173 @GetMapping(value = "/send/start")
172 @ResponseBody 174 @ResponseBody
173 - @Operation(summary = "发送流") 175 + @Operation(summary = "发送流", security = @SecurityRequirement(name = JwtUtils.HEADER))
174 @Parameter(name = "ssrc", description = "发送流的SSRC", required = true) 176 @Parameter(name = "ssrc", description = "发送流的SSRC", required = true)
175 @Parameter(name = "dstIp", description = "目标收流IP", required = true) 177 @Parameter(name = "dstIp", description = "目标收流IP", required = true)
176 @Parameter(name = "dstPort", description = "目标收流端口", required = true) 178 @Parameter(name = "dstPort", description = "目标收流端口", required = true)
src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java deleted 100755 → 0
1 -//package com.genersoft.iot.vmp.vmanager.record;  
2 -//  
3 -//import com.alibaba.fastjson2.JSONObject;  
4 -//import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;  
5 -//import com.genersoft.iot.vmp.service.IRecordInfoServer;  
6 -//import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;  
7 -//import com.genersoft.iot.vmp.vmanager.bean.WVPResult;  
8 -//import com.github.pagehelper.PageInfo;  
9 -//import io.swagger.annotations.Api;  
10 -//import io.swagger.annotations.ApiImplicitParam;  
11 -//import io.swagger.annotations.ApiImplicitParams;  
12 -//import io.swagger.annotations.ApiOperation;  
13 -//import org.springframework.beans.factory.annotation.Autowired;  
14 -//import org.springframework.web.bind.annotation.*;  
15 -//  
16 -//@Tag(name = "云端录像")  
17 -//  
18 -//@RestController  
19 -//@RequestMapping("/api/record")  
20 -//public class RecordController {  
21 -//  
22 -// @Autowired  
23 -// private IRecordInfoServer recordInfoServer;  
24 -//  
25 -// //@ApiOperation("录像列表查询")  
26 -// @ApiImplicitParams({  
27 -// @ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),  
28 -// @ApiImplicitParam(name="count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),  
29 -// @ApiImplicitParam(name="query", value = "查询内容", dataTypeClass = String.class),  
30 -// })  
31 -// @GetMapping(value = "/app/list")  
32 -// @ResponseBody  
33 -// public Object list(@RequestParam(required = false)Integer page,  
34 -// @RequestParam(required = false)Integer count ){  
35 -//  
36 -// PageInfo<RecordInfo> recordList = recordInfoServer.getRecordList(page - 1, page - 1 + count);  
37 -// return recordList;  
38 -// }  
39 -//  
40 -// //@ApiOperation("获取录像详情")  
41 -// @ApiImplicitParams({  
42 -// @ApiImplicitParam(name="recordInfo", value = "录像记录", required = true, dataTypeClass = RecordInfo.class)  
43 -// })  
44 -// @GetMapping(value = "/detail")  
45 -// @ResponseBody  
46 -// public JSONObject list(RecordInfo recordInfo, String time ){  
47 -//  
48 -//  
49 -// return null;  
50 -// }  
51 -//}