ソースを参照

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
#	web_src/src/components/Login.vue
648540858 3 年 前
コミット
ecf4fbb684
100 ファイル変更2052 行追加1950 行削除
  1. 19 21
      pom.xml
  2. 0 2
      src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
  3. 0 1
      src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
  4. 4 0
      src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
  5. 8 9
      src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
  6. 56 0
      src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
  7. 53 0
      src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java
  8. 4 3
      src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
  9. 5 4
      src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
  10. 89 0
      src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java
  11. 0 117
      src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java
  12. 37 0
      src/main/java/com/genersoft/iot/vmp/conf/exception/ControllerException.java
  13. 87 86
      src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
  14. 1 0
      src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
  15. 31 2
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
  16. 18 1
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java
  17. 44 2
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
  18. 15 0
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java
  19. 36 0
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
  20. 14 0
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
  21. 8 0
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java
  22. 7 1
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
  23. 3 3
      src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
  24. 0 81
      src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
  25. 3 2
      src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
  26. 1 5
      src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java
  27. 8 0
      src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java
  28. 19 21
      src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
  29. 0 8
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
  30. 2 3
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
  31. 25 24
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
  32. 3 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
  33. 3 0
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
  34. 41 6
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
  35. 4 3
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
  36. 4 0
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
  37. 5 0
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
  38. 3 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
  39. 1 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java
  40. 22 12
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
  41. 0 88
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
  42. 5 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
  43. 3 0
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
  44. 28 4
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
  45. 77 68
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
  46. 7 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
  47. 28 2
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
  48. 9 6
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
  49. 16 12
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
  50. 8 7
      src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
  51. 2 1
      src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
  52. 2 1
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  53. 3 2
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
  54. 34 3
      src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java
  55. 22 1
      src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java
  56. 21 1
      src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java
  57. 8 0
      src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
  58. 2 2
      src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
  59. 4 4
      src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
  60. 1 5
      src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
  61. 6 0
      src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
  62. 8 4
      src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java
  63. 5 3
      src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
  64. 8 3
      src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
  65. 45 76
      src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
  66. 3 2
      src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
  67. 51 64
      src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
  68. 6 8
      src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java
  69. 83 0
      src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamListMsgListener.java
  70. 0 9
      src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java
  71. 39 36
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
  72. 9 2
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
  73. 6 5
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
  74. 2 1
      src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
  75. 10 0
      src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
  76. 3 0
      src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
  77. 93 97
      src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
  78. 2 1
      src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
  79. 65 72
      src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
  80. 6 0
      src/main/java/com/genersoft/iot/vmp/vmanager/bean/BatchGBStreamParam.java
  81. 31 0
      src/main/java/com/genersoft/iot/vmp/vmanager/bean/ErrorCode.java
  82. 1 1
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java
  83. 12 8
      src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
  84. 26 46
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
  85. 3 9
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java
  86. 81 109
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
  87. 21 25
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
  88. 52 70
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
  89. 87 124
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
  90. 17 27
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
  91. 5 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java
  92. 17 29
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
  93. 119 222
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
  94. 11 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java
  95. 13 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java
  96. 59 125
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
  97. 4 3
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/PlayResult.java
  98. 49 98
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
  99. 31 40
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
  100. 0 0
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java

+ 19 - 21
pom.xml

@@ -6,7 +6,7 @@
 	<parent>
 		<groupId>org.springframework.boot</groupId>
 		<artifactId>spring-boot-starter-parent</artifactId>
-		<version>2.3.5.RELEASE</version>
+		<version>2.7.2</version>
 	</parent>
 
 	<groupId>com.genersoft</groupId>
@@ -47,7 +47,6 @@
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
 		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
-		<jedis-version>3.1.0</jedis-version>
 
 		<!-- 依赖版本 -->
 		<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
@@ -74,7 +73,7 @@
 		<dependency>
 			<groupId>org.mybatis.spring.boot</groupId>
 			<artifactId>mybatis-spring-boot-starter</artifactId>
-			<version>2.1.4</version>
+			<version>2.2.2</version>
 			<exclusions>
 				<exclusion>
 					<groupId>com.zaxxer</groupId>
@@ -91,37 +90,36 @@
 		<dependency>
 			<groupId>com.alibaba</groupId>
 			<artifactId>druid-spring-boot-starter</artifactId>
-			<version>1.1.22</version>
+			<version>1.2.11</version>
 		</dependency>
 
 		<!-- mysql数据库 -->
 		<dependency>
 			<groupId>mysql</groupId>
 			<artifactId>mysql-connector-java</artifactId>
-			<version>8.0.22</version>
+			<version>8.0.30</version>
 		</dependency>
 
 		<!--Mybatis分页插件 -->
 		<dependency>
 			<groupId>com.github.pagehelper</groupId>
 			<artifactId>pagehelper-spring-boot-starter</artifactId>
-			<version>1.4.1</version>
+			<version>1.4.3</version>
 		</dependency>
 
-		<!--Swagger3 -->
 		<!--在线文档 -->
 		<dependency>
-			<groupId>io.springfox</groupId>
-			<artifactId>springfox-boot-starter</artifactId>
-			<version>3.0.0</version>
+			<groupId>org.springdoc</groupId>
+			<artifactId>springdoc-openapi-ui</artifactId>
+			<version>1.6.10</version>
 		</dependency>
+
 		<dependency>
 			<groupId>com.github.xiaoymin</groupId>
-			<artifactId>knife4j-spring-boot-starter</artifactId>
-			<version>3.0.2</version>
+			<artifactId>knife4j-springdoc-ui</artifactId>
+			<version>3.0.3</version>
 		</dependency>
 
-
 		<!--参数校验 -->
 		<dependency>
 			<groupId>javax.validation</groupId>
@@ -145,7 +143,7 @@
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>log4j-over-slf4j</artifactId>
-			<version>1.7.35</version>
+			<version>1.7.36</version>
 		</dependency>
 
 		<!-- xml解析库 -->
@@ -167,14 +165,14 @@
 		<dependency>
 			<groupId>com.squareup.okhttp3</groupId>
 			<artifactId>okhttp</artifactId>
-			<version>4.9.0</version>
+			<version>4.10.0</version>
 		</dependency>
 
 		<!-- okhttp 调试日志 -->
 		<dependency>
 			<groupId>com.squareup.okhttp3</groupId>
 			<artifactId>logging-interceptor</artifactId>
-			<version>4.9.0</version>
+			<version>4.10.0</version>
 		</dependency>
 
 
@@ -183,7 +181,7 @@
 		<dependency>
 			<groupId>io.github.rburgst</groupId>
 			<artifactId>okhttp-digest</artifactId>
-			<version>2.5</version>
+			<version>2.7</version>
 		</dependency>
 
 		<!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
@@ -197,21 +195,21 @@
 		<dependency>
 			<groupId>org.mitre.dsmiley.httpproxy</groupId>
 			<artifactId>smiley-http-proxy-servlet</artifactId>
-			<version>1.12</version>
+			<version>1.12.1</version>
 		</dependency>
 
 		<!--excel解析库-->
 		<dependency>
 			<groupId>com.alibaba</groupId>
 			<artifactId>easyexcel</artifactId>
-			<version>3.0.4</version>
+			<version>3.1.1</version>
 		</dependency>
 
 		<!-- 获取系统信息 -->
 		<dependency>
 			<groupId>com.github.oshi</groupId>
 			<artifactId>oshi-core</artifactId>
-			<version>6.1.0</version>
+			<version>6.2.2</version>
 		</dependency>
 
 		<dependency>
@@ -231,7 +229,7 @@
 		<dependency>
 			<groupId>com.google.guava</groupId>
 			<artifactId>guava</artifactId>
-			<version>31.0.1-jre</version>
+			<version>31.1-jre</version>
 		</dependency>
 
 

+ 0 - 2
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java

@@ -8,7 +8,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.web.servlet.ServletComponentScan;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.scheduling.annotation.EnableScheduling;
-import springfox.documentation.oas.annotations.EnableOpenApi;
 
 /**
  * 启动类
@@ -16,7 +15,6 @@ import springfox.documentation.oas.annotations.EnableOpenApi;
 @ServletComponentScan("com.genersoft.iot.vmp.conf")
 @SpringBootApplication
 @EnableScheduling
-@EnableOpenApi
 @EnableDruidSupport
 public class VManageBootstrap extends LogManager {
 	private static String[] args;

+ 0 - 1
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java

@@ -1,6 +1,5 @@
 package com.genersoft.iot.vmp.common;
 
-import com.alibaba.fastjson.JSONArray;
 
 public class StreamInfo {
 

+ 4 - 0
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java

@@ -91,6 +91,10 @@ public class VideoManagerConstants {
 	 * 接收推流设备的GPS变化通知
 	 */
 	public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
+	/**
+	 * 接收推流设备列表更新变化通知
+	 */
+	public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE";
 
 	/**
 	 * redis 消息通知设备推流到平台

+ 8 - 9
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java

@@ -9,6 +9,7 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
 import java.time.Instant;
 import java.util.Map;
 import java.util.Set;
@@ -25,20 +26,18 @@ public class DynamicTask {
 
     private final Logger logger = LoggerFactory.getLogger(DynamicTask.class);
 
-    @Autowired
     private ThreadPoolTaskScheduler threadPoolTaskScheduler;
 
     private final Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
     private final Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
 
-    @Bean
-    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
-        ThreadPoolTaskScheduler schedulerPool = new ThreadPoolTaskScheduler();
-        schedulerPool.setPoolSize(300);
-        schedulerPool.setWaitForTasksToCompleteOnShutdown(true);
-        schedulerPool.setAwaitTerminationSeconds(10);
-        return schedulerPool;
-
+    @PostConstruct
+    public void DynamicTask() {
+        threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
+        threadPoolTaskScheduler.setPoolSize(300);
+        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
+        threadPoolTaskScheduler.setAwaitTerminationSeconds(10);
+        threadPoolTaskScheduler.initialize();
     }
 
     /**

+ 56 - 0
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java

@@ -0,0 +1,56 @@
+package com.genersoft.iot.vmp.conf;
+
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
+import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
+import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+/**
+ * 全局异常处理
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    private final static Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+    /**
+     * 默认异常处理
+     * @param e 异常
+     * @return 统一返回结果
+     */
+    @ExceptionHandler(Exception.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public WVPResult<String> exceptionHandler(Exception e) {
+        logger.error("[全局异常]: ", e);
+        return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage());
+    }
+
+    /**
+     * 自定义异常处理, 处理controller中返回的错误
+     * @param e 异常
+     * @return 统一返回结果
+     */
+    @ExceptionHandler(ControllerException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public WVPResult<String> exceptionHandler(ControllerException e) {
+        return WVPResult.fail(e.getCode(), e.getMsg());
+    }
+
+    /**
+     * 登陆失败
+     * @param e 异常
+     * @return 统一返回结果
+     */
+    @ExceptionHandler(BadCredentialsException.class)
+    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+    public WVPResult<String> exceptionHandler(BadCredentialsException e) {
+        return WVPResult.fail(ErrorCode.ERROR100.getCode(), e.getMessage());
+    }
+}

+ 53 - 0
src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java

@@ -0,0 +1,53 @@
+package com.genersoft.iot.vmp.conf;
+
+import com.alibaba.fastjson.JSON;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
+import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.core.MethodParameter;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
+
+/**
+ * 全局统一返回结果
+ * @author lin
+ */
+@RestControllerAdvice
+public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
+
+
+    @Override
+    public boolean supports(@NotNull MethodParameter returnType, @NotNull Class<? extends HttpMessageConverter<?>> converterType) {
+        return true;
+    }
+
+    @Override
+    public Object beforeBodyWrite(Object body, @NotNull MethodParameter returnType, @NotNull MediaType selectedContentType, @NotNull Class<? extends HttpMessageConverter<?>> selectedConverterType, @NotNull ServerHttpRequest request, @NotNull ServerHttpResponse response) {
+        // 排除api文档的接口,这个接口不需要统一
+        String[] excludePath = {"/v3/api-docs","/api/v1","/index/hook"};
+        for (String path : excludePath) {
+            if (request.getURI().getPath().startsWith(path)) {
+                return body;
+            }
+        }
+
+        if (body instanceof WVPResult) {
+            return body;
+        }
+
+        if (body instanceof ErrorCode) {
+            ErrorCode errorCode = (ErrorCode) body;
+            return new WVPResult<>(errorCode.getCode(), errorCode.getMsg(), null);
+        }
+
+        if (body instanceof String) {
+            return JSON.toJSONString(WVPResult.success(body));
+        }
+
+        return WVPResult.success(body);
+    }
+}

+ 4 - 3
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java

@@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.net.InetAddress;
@@ -88,7 +89,7 @@ public class MediaConfig{
     }
 
     public String getHookIp() {
-        if (StringUtils.isEmpty(hookIp)){
+        if (ObjectUtils.isEmpty(hookIp)){
             return sipIp;
         }else {
             return hookIp;
@@ -162,7 +163,7 @@ public class MediaConfig{
     }
 
     public String getSdpIp() {
-        if (StringUtils.isEmpty(sdpIp)){
+        if (ObjectUtils.isEmpty(sdpIp)){
             return ip;
         }else {
             if (isValidIPAddress(sdpIp)) {
@@ -181,7 +182,7 @@ public class MediaConfig{
     }
 
     public String getStreamIp() {
-        if (StringUtils.isEmpty(streamIp)){
+        if (ObjectUtils.isEmpty(streamIp)){
             return ip;
         }else {
             return streamIp;

+ 5 - 4
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java

@@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.web.servlet.ServletRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.servlet.ServletException;
@@ -55,7 +56,7 @@ public class ProxyServletConfig {
             String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
             MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
             if (mediaInfo != null) {
-                if (!StringUtils.isEmpty(queryStr)) {
+                if (!ObjectUtils.isEmpty(queryStr)) {
                     queryStr += "&secret=" + mediaInfo.getSecret();
                 }else {
                     queryStr = "secret=" + mediaInfo.getSecret();
@@ -146,7 +147,7 @@ public class ProxyServletConfig {
                 logger.error("[ZLM服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
                 return  url;
             }
-            if (!StringUtils.isEmpty(mediaInfo.getId())) {
+            if (!ObjectUtils.isEmpty(mediaInfo.getId())) {
                 url = url.replace(mediaInfo.getId() + "/", "");
             }
             return url.replace("default/", "");
@@ -173,7 +174,7 @@ public class ProxyServletConfig {
             MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
             String remoteHost = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort());
             if (mediaInfo != null) {
-                if (!StringUtils.isEmpty(queryStr)) {
+                if (!ObjectUtils.isEmpty(queryStr)) {
                     queryStr += "&remoteHost=" + remoteHost;
                 }else {
                     queryStr = "remoteHost=" + remoteHost;
@@ -265,7 +266,7 @@ public class ProxyServletConfig {
                 logger.error("[录像服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
                 return  url;
             }
-            if (!StringUtils.isEmpty(mediaInfo.getId())) {
+            if (!ObjectUtils.isEmpty(mediaInfo.getId())) {
                 url = url.replace(mediaInfo.getId() + "/", "");
             }
             return url.replace("default/", "");

+ 89 - 0
src/main/java/com/genersoft/iot/vmp/conf/SpringDocConfig.java

@@ -0,0 +1,89 @@
+package com.genersoft.iot.vmp.conf;
+
+import io.swagger.v3.oas.models.ExternalDocumentation;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Contact;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.info.License;
+import io.swagger.v3.oas.models.media.StringSchema;
+import io.swagger.v3.oas.models.parameters.HeaderParameter;
+import org.springdoc.core.GroupedOpenApi;
+import org.springdoc.core.SpringDocConfigProperties;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author lin
+ */
+@Configuration
+public class SpringDocConfig {
+
+    @Value("${doc.enabled: true}")
+    private boolean enable;
+
+    @Bean
+    public OpenAPI springShopOpenApi() {
+        Contact contact = new Contact();
+        contact.setName("pan");
+        contact.setEmail("648540858@qq.com");
+        return new OpenAPI()
+                .info(new Info().title("WVP-PRO 接口文档")
+                        .contact(contact)
+                        .description("开箱即用的28181协议视频平台")
+                        .version("v2.0")
+                        .license(new License().name("Apache 2.0").url("http://springdoc.org")));
+    }
+
+    /**
+     * 添加分组
+     * @return
+     */
+    @Bean
+    public GroupedOpenApi publicApi() {
+        return GroupedOpenApi.builder()
+                .group("1. 全部")
+                .packagesToScan("com.genersoft.iot.vmp.vmanager")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi2() {
+        return GroupedOpenApi.builder()
+                .group("2. 国标28181")
+                .packagesToScan("com.genersoft.iot.vmp.vmanager.gb28181")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi3() {
+        return GroupedOpenApi.builder()
+                .group("3. 拉流转发")
+                .packagesToScan("com.genersoft.iot.vmp.vmanager.streamProxy")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi4() {
+        return GroupedOpenApi.builder()
+                .group("4. 推流管理")
+                .packagesToScan("com.genersoft.iot.vmp.vmanager.streamPush")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi5() {
+        return GroupedOpenApi.builder()
+                .group("4. 服务管理")
+                .packagesToScan("com.genersoft.iot.vmp.vmanager.server")
+                .build();
+    }
+
+    @Bean
+    public GroupedOpenApi publicApi6() {
+        return GroupedOpenApi.builder()
+                .group("5. 用户管理")
+                .packagesToScan("com.genersoft.iot.vmp.vmanager.user")
+                .build();
+    }
+}

+ 0 - 117
src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java

@@ -1,117 +0,0 @@
-package com.genersoft.iot.vmp.conf;
-
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.service.Contact;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-
-@Configuration
-public class Swagger3Config {
-
-    @Value("${swagger-ui.enabled: true}")
-    private boolean enable;
-
-    @Bean
-    public Docket createRestApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("1. 全部")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-    @Bean
-    public Docket createRestGBApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("2. 国标28181")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager.gb28181"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-
-    @Bean
-    public Docket createRestONVIFApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("3. ONVIF")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager.onvif"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-
-    @Bean
-    public Docket createRestStreamProxyApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("4. 拉流转发")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager.streamProxy"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-    @Bean
-    public Docket createRestStreamPushApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("5. 推流管理")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager.streamPush"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-
-
-    @Bean
-    public Docket createServerApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("6. 服务管理")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager.server"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-    @Bean
-    public Docket createUserApi() {
-        return new Docket(DocumentationType.OAS_30)
-                .apiInfo(apiInfo())
-                .groupName("7. 用户管理")
-                .select()
-                .apis(RequestHandlerSelectors.basePackage("com.genersoft.iot.vmp.vmanager.user"))
-                .paths(PathSelectors.any())
-                .build()
-                .pathMapping("/")
-                .enable(enable);
-    }
-
-    private ApiInfo apiInfo() {
-        return new ApiInfoBuilder()
-                .title("WVP-PRO 接口文档")
-                .description("更多请咨询服务开发者(https://github.com/648540858/wvp-GB28181-pro)。")
-                .contact(new Contact("648540858", "648540858", "648540858@qq.com"))
-                .version("2.0")
-                .build();
-    }
-}

+ 37 - 0
src/main/java/com/genersoft/iot/vmp/conf/exception/ControllerException.java

@@ -0,0 +1,37 @@
+package com.genersoft.iot.vmp.conf.exception;
+
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
+
+/**
+ * 自定义异常,controller出现错误时直接抛出异常由全局异常捕获并返回结果
+ */
+public class ControllerException extends RuntimeException{
+
+    private int code;
+    private String msg;
+
+    public ControllerException(int code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+    public ControllerException(ErrorCode errorCode) {
+        this.code = errorCode.getCode();
+        this.msg = errorCode.getMsg();
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+}

+ 87 - 86
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java

@@ -1,86 +1,87 @@
-package com.genersoft.iot.vmp.conf;
-
-import com.alibaba.fastjson.parser.ParserConfig;
-import com.genersoft.iot.vmp.common.VideoManagerConstants;
-import com.genersoft.iot.vmp.service.impl.*;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.cache.annotation.CachingConfigurerSupport;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.data.redis.connection.RedisConnectionFactory;
-import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.listener.PatternTopic;
-import org.springframework.data.redis.listener.RedisMessageListenerContainer;
-import org.springframework.data.redis.serializer.StringRedisSerializer;
-
-import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
-
-
-/**
- * @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
- * @author: swwheihei
- * @date: 2019年5月30日 上午10:58:25
- * 
- */
-@Configuration
-public class RedisConfig extends CachingConfigurerSupport {
-
-	@Autowired
-	private RedisGpsMsgListener redisGPSMsgListener;
-
-	@Autowired
-	private RedisAlarmMsgListener redisAlarmMsgListener;
-
-	@Autowired
-	private RedisStreamMsgListener redisStreamMsgListener;
-
-	@Autowired
-	private RedisGbPlayMsgListener redisGbPlayMsgListener;
-
-	@Autowired
-	private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
-
-	@Bean
-	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
-		RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
-		// 使用fastJson序列化
-		FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
-		// value值的序列化采用fastJsonRedisSerializer
-		redisTemplate.setValueSerializer(fastJsonRedisSerializer);
-		redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
-		// 全局开启AutoType,不建议使用
-		 ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
-		// 建议使用这种方式,小范围指定白名单,需要序列化的类
-//		ParserConfig.getGlobalInstance().addAccept("com.avatar");
-		// key的序列化采用StringRedisSerializer
-		redisTemplate.setKeySerializer(new StringRedisSerializer());
-		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
-		redisTemplate.setConnectionFactory(redisConnectionFactory);
-		return redisTemplate;
-	}
-
-
-	/**
-	 * redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
-	 * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
-	 * 
-	 * @param connectionFactory
-	 * @return
-	 */
-	@Bean
-	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
-
-        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
-        container.setConnectionFactory(connectionFactory);
-		container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS));
-		container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
-		container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH"));
-		container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY));
-		container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
-        return container;
-    }
-
-}
+package com.genersoft.iot.vmp.conf.redis;
+
+
+import com.alibaba.fastjson.parser.ParserConfig;
+import com.genersoft.iot.vmp.common.VideoManagerConstants;
+import com.genersoft.iot.vmp.service.impl.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.listener.PatternTopic;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import com.genersoft.iot.vmp.utils.redis.FastJsonRedisSerializer;
+
+
+/**
+ * @description:Redis中间件配置类,使用spring-data-redis集成,自动从application.yml中加载redis配置
+ * @author: swwheihei
+ * @date: 2019年5月30日 上午10:58:25
+ * 
+ */
+@Configuration
+public class RedisConfig extends CachingConfigurerSupport {
+
+	@Autowired
+	private RedisGpsMsgListener redisGPSMsgListener;
+
+	@Autowired
+	private RedisAlarmMsgListener redisAlarmMsgListener;
+
+	@Autowired
+	private RedisStreamMsgListener redisStreamMsgListener;
+
+	@Autowired
+	private RedisGbPlayMsgListener redisGbPlayMsgListener;
+
+	@Autowired
+	private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
+
+	@Autowired
+	private RedisPushStreamListMsgListener redisPushStreamListMsgListener;
+
+	@Bean
+	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+		RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
+		// 使用fastJson序列化
+		FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
+		// value值的序列化采用fastJsonRedisSerializer
+		redisTemplate.setValueSerializer(fastJsonRedisSerializer);
+		redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
+		// 全局开启AutoType,不建议使用
+		 ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
+		// key的序列化采用StringRedisSerializer
+		redisTemplate.setKeySerializer(new StringRedisSerializer());
+		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
+		redisTemplate.setConnectionFactory(redisConnectionFactory);
+		return redisTemplate;
+	}
+
+
+	/**
+	 * redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
+	 * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
+	 * 
+	 * @param connectionFactory
+	 * @return
+	 */
+	@Bean
+	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
+
+        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+        container.setConnectionFactory(connectionFactory);
+		container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS));
+		container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
+		container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH"));
+		container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY));
+		container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
+		container.addMessageListener(redisPushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE));
+        return container;
+    }
+
+}

+ 1 - 0
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java

@@ -91,6 +91,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                     .antMatchers("/webjars/**")
                     .antMatchers("/swagger-resources/**")
                     .antMatchers("/v3/api-docs/**")
+                    .antMatchers("/favicon.ico")
                     .antMatchers("/js/**");
             List<String> interfaceAuthenticationExcludes = userSetting.getInterfaceAuthenticationExcludes();
             for (String interfaceAuthenticationExclude : interfaceAuthenticationExcludes) {

+ 31 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java

@@ -1,41 +1,50 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 /**
  * 国标设备/平台
  * @author lin
  */
+@Schema(description = "国标设备/平台")
 public class Device {
 
 	/**
-	 * 设备Id
+	 * 设备国标编号
 	 */
+	@Schema(description = "设备国标编号")
 	private String deviceId;
 
 	/**
 	 * 设备名
 	 */
+	@Schema(description = "名称")
 	private String name;
 	
 	/**
 	 * 生产厂商
 	 */
+	@Schema(description = "生产厂商")
 	private String manufacturer;
 	
 	/**
 	 * 型号
 	 */
+	@Schema(description = "型号")
 	private String model;
 	
 	/**
 	 * 固件版本
 	 */
+	@Schema(description = "固件版本")
 	private String firmware;
 
 	/**
 	 * 传输协议
 	 * UDP/TCP
 	 */
+	@Schema(description = "传输协议(UDP/TCP)")
 	private String transport;
 
 	/**
@@ -44,103 +53,123 @@ public class Device {
 	 * TCP-ACTIVE:tcp主动模式
 	 * TCP-PASSIVE:tcp被动模式
 	 */
+	@Schema(description = "数据流传输模式")
 	private String streamMode;
 
 	/**
 	 * wan地址_ip
 	 */
+	@Schema(description = "IP")
 	private String  ip;
 
 	/**
 	 * wan地址_port
 	 */
+	@Schema(description = "端口")
 	private int port;
 
 	/**
 	 * wan地址
 	 */
+	@Schema(description = "wan地址")
 	private String  hostAddress;
 	
 	/**
 	 * 在线
 	 */
+	@Schema(description = "是否在线,1为在线,0为离线")
 	private int online;
 
 
 	/**
 	 * 注册时间
 	 */
+	@Schema(description = "注册时间")
 	private String registerTime;
 
 
 	/**
 	 * 心跳时间
 	 */
+	@Schema(description = "心跳时间")
 	private String keepaliveTime;
 
 	/**
 	 * 通道个数
 	 */
+	@Schema(description = "通道个数")
 	private int channelCount;
 
 	/**
 	 * 注册有效期
 	 */
+	@Schema(description = "注册有效期")
 	private int expires;
 
 	/**
 	 * 创建时间
 	 */
+	@Schema(description = "创建时间")
 	private String createTime;
 
 	/**
 	 * 更新时间
 	 */
+	@Schema(description = "更新时间")
 	private String updateTime;
 
 	/**
 	 * 设备使用的媒体id, 默认为null
 	 */
+	@Schema(description = "设备使用的媒体id, 默认为null")
 	private String mediaServerId;
 
 	/**
 	 * 字符集, 支持 UTF-8 与 GB2312
 	 */
+	@Schema(description = "符集, 支持 UTF-8 与 GB2312")
 	private String charset ;
 
 	/**
 	 * 目录订阅周期,0为不订阅
 	 */
+	@Schema(description = "目录订阅周期,0为不订阅")
 	private int subscribeCycleForCatalog;
 
 	/**
 	 * 移动设备位置订阅周期,0为不订阅
 	 */
+	@Schema(description = "移动设备位置订阅周期,0为不订阅")
 	private int subscribeCycleForMobilePosition;
 
 	/**
 	 * 移动设备位置信息上报时间间隔,单位:秒,默认值5
 	 */
+	@Schema(description = "移动设备位置信息上报时间间隔,单位:秒,默认值5")
 	private int mobilePositionSubmissionInterval = 5;
 
 	/**
 	 * 报警订阅周期,0为不订阅
 	 */
+	@Schema(description = "报警心跳时间订阅周期,0为不订阅")
 	private int subscribeCycleForAlarm;
 
 	/**
 	 * 是否开启ssrc校验,默认关闭,开启可以防止串流
 	 */
+	@Schema(description = "是否开启ssrc校验,默认关闭,开启可以防止串流")
 	private boolean ssrcCheck = true;
 
 	/**
-	 * 地理坐标系, 目前支持 WGS84,GCJ02 TODO CGCS2000
+	 * 地理坐标系, 目前支持 WGS84,GCJ02
 	 */
+	@Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02")
 	private String geoCoordSys;
 
 	/**
 	 * 树类型 国标规定了两种树的展现方式 行政区划:CivilCode 和业务分组:BusinessGroup
 	 */
+	@Schema(description = "树类型 国标规定了两种树的展现方式 行政区划:CivilCode 和业务分组:BusinessGroup")
 	private String treeType;
 
 

+ 18 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java

@@ -1,52 +1,67 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
 
+/**
+ * @author lin
+ */
+@Schema(description = "报警信息")
 public class DeviceAlarm {
 
 	/**
 	 * 数据库id
 	 */
+	@Schema(description = "数据库id")
 	private String id;
 
 	/**
 	 * 设备Id
 	 */
+	@Schema(description = "设备的国标编号")
 	private String deviceId;
 
 	/**
 	 * 通道Id
 	 */
+	@Schema(description = "通道的国标编号")
 	private String channelId;
 
 	/**
-	 * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情-
+	 * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情
 	 */
+	@Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情")
 	private String alarmPriority;
 
 	/**
 	 * 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,
 	 * 7其他报警;可以为直接组合如12为电话报警或 设备报警-
 	 */
+	@Schema(description = "报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,\n" +
+			"\t * 7其他报警;可以为直接组合如12为电话报警或设备报警")
 	private String alarmMethod;
 
 	/**
 	 * 报警时间
 	 */
+	@Schema(description = "报警时间")
 	private String alarmTime;
 
 	/**
 	 * 报警内容描述
 	 */
+	@Schema(description = "报警内容描述")
 	private String alarmDescription;
 
 	/**
 	 * 经度
 	 */
+	@Schema(description = "经度")
 	private double longitude;
 
 	/**
 	 * 纬度
 	 */
+	@Schema(description = "纬度")
 	private double latitude;
 
 	/**
@@ -75,8 +90,10 @@ public class DeviceAlarm {
 	 * 		1-存储设备磁盘故障报警;
 	 * 		2-存储设备风扇故障报警。
 	 */
+	@Schema(description = "报警类型")
 	private String alarmType;
 
+	@Schema(description = "创建时间")
 	private String createTime;
 
 

+ 44 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java

@@ -1,136 +1,165 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(description = "通道信息")
 public class DeviceChannel {
 
 
 	/**
 	 * 数据库自增ID
 	 */
+	@Schema(description = "数据库自增ID")
 	private int id;
 
 	/**
-	 * 通道id
+	 * 通道国标编号
 	 */
+	@Schema(description = "通道国标编号")
 	private String channelId;
 
 	/**
-	 * 设备id
+	 * 设备国标编号
 	 */
+	@Schema(description = "设备国标编号")
 	private String deviceId;
 	
 	/**
 	 * 通道名
 	 */
+	@Schema(description = "名称")
 	private String name;
 	
 	/**
 	 * 生产厂商
 	 */
+	@Schema(description = "生产厂商")
 	private String manufacture;
 	
 	/**
 	 * 型号
 	 */
+	@Schema(description = "型号")
 	private String model;
 	
 	/**
 	 * 设备归属
 	 */
+	@Schema(description = "设备归属")
 	private String owner;
 	
 	/**
 	 * 行政区域
 	 */
+	@Schema(description = "行政区域")
 	private String civilCode;
 	
 	/**
 	 * 警区
 	 */
+	@Schema(description = "警区")
 	private String block;
 
 	/**
 	 * 安装地址
 	 */
+	@Schema(description = "安装地址")
 	private String address;
 	
 	/**
 	 * 是否有子设备 1有, 0没有
 	 */
+	@Schema(description = "是否有子设备 1有, 0没有")
 	private int parental;
 	
 	/**
 	 * 父级id
 	 */
+	@Schema(description = "父级id")
 	private String parentId;
 	
 	/**
 	 * 信令安全模式  缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式
 	 */
+	@Schema(description = "信令安全模式  缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式")
 	private int safetyWay;
 	
 	/**
 	 * 注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式
 	 */
+	@Schema(description = "注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式")
 	private int registerWay;
 	
 	/**
 	 * 证书序列号
 	 */
+	@Schema(description = "证书序列号")
 	private String certNum;
 	
 	/**
 	 * 证书有效标识 缺省为0;证书有效标识:0:无效1: 有效
 	 */
+	@Schema(description = "证书有效标识 缺省为0;证书有效标识:0:无效1: 有效")
 	private int certifiable;
 	
 	/**
 	 * 证书无效原因码
 	 */
+	@Schema(description = "证书无效原因码")
 	private int errCode;
 	
 	/**
 	 * 证书终止有效期
 	 */
+	@Schema(description = "证书终止有效期")
 	private String endTime;
 	
 	/**
 	 * 保密属性 缺省为0; 0:不涉密, 1:涉密
 	 */
+	@Schema(description = "保密属性 缺省为0; 0:不涉密, 1:涉密")
 	private String secrecy;
 	
 	/**
 	 * IP地址
 	 */
+	@Schema(description = "IP地址")
 	private String ipAddress;
 	
 	/**
 	 * 端口号
 	 */
+	@Schema(description = "端口号")
 	private int port;
 	
 	/**
 	 * 密码
 	 */
+	@Schema(description = "密码")
 	private String password;
 
 	/**
 	 * 云台类型
 	 */
+	@Schema(description = "云台类型")
 	private int PTZType;
 
 	/**
 	 * 云台类型描述字符串
 	 */
+	@Schema(description = "云台类型描述字符串")
 	private String PTZTypeText;
 
 	/**
 	 * 创建时间
 	 */
+	@Schema(description = "创建时间")
 	private String createTime;
 
 	/**
 	 * 更新时间
 	 */
+	@Schema(description = "更新时间")
 	private String updateTime;
 	
 	/**
@@ -142,66 +171,79 @@ public class DeviceChannel {
 	 * <Status>OFF</Status>
 	 * 遇到过NVR下的IPC下发信令可以推流, 但是 Status 响应 OFF
 	 */
+	@Schema(description = "在线/离线, 1在线,0离线")
 	private int status;
 
 	/**
 	 * 经度
 	 */
+	@Schema(description = "经度")
 	private double longitude;
 	
 	/**
 	 * 纬度
 	 */
+	@Schema(description = "纬度")
 	private double latitude;
 
 	/**
 	 * 经度 GCJ02
 	 */
+	@Schema(description = "GCJ02坐标系经度")
 	private double longitudeGcj02;
 
 	/**
 	 * 纬度 GCJ02
 	 */
+	@Schema(description = "GCJ02坐标系纬度")
 	private double latitudeGcj02;
 
 	/**
 	 * 经度 WGS84
 	 */
+	@Schema(description = "WGS84坐标系经度")
 	private double longitudeWgs84;
 
 	/**
 	 * 纬度 WGS84
 	 */
+	@Schema(description = "WGS84坐标系纬度")
 	private double latitudeWgs84;
 
 	/**
 	 * 子设备数
 	 */
+	@Schema(description = "子设备数")
 	private int subCount;
 
 	/**
 	 * 流唯一编号,存在表示正在直播
 	 */
+	@Schema(description = "流唯一编号,存在表示正在直播")
 	private String  streamId;
 
 	/**
 	 *  是否含有音频
 	 */
+	@Schema(description = "是否含有音频")
 	private boolean hasAudio;
 
 	/**
 	 * 标记通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
 	 */
+	@Schema(description = "标记通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划")
 	private int channelType;
 
 	/**
 	 * 业务分组
 	 */
+	@Schema(description = "业务分组")
 	private String businessGroupId;
 
 	/**
 	 * GPS的更新时间
 	 */
+	@Schema(description = "GPS的更新时间")
 	private String gpsTime;
 
 	public int getId() {

+ 15 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java

@@ -1,21 +1,36 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 /**
  * 直播流关联国标上级平台
+ * @author lin
  */
+@Schema(description = "直播流关联国标上级平台")
 public class GbStream extends PlatformGbStream{
 
+    @Schema(description = "ID")
     private Integer gbStreamId;
+    @Schema(description = "应用名")
     private String app;
+    @Schema(description = "流ID")
     private String stream;
+    @Schema(description = "国标ID")
     private String gbId;
+    @Schema(description = "名称")
     private String name;
+    @Schema(description = "流媒体ID")
     private String mediaServerId;
+    @Schema(description = "经度")
     private double longitude;
+    @Schema(description = "纬度")
     private double latitude;
+    @Schema(description = "流类型(拉流/推流)")
     private String streamType;
+    @Schema(description = "状态")
     private boolean status;
 
+    @Schema(description = "创建时间")
     public String createTime;
 
     @Override

+ 36 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java

@@ -1,157 +1,193 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * @author lin
+ */
+@Schema(description = "平台信息")
 public class ParentPlatform {
 
     /**
      * id
      */
+    @Schema(description = "ID(数据库中)")
     private Integer id;
 
     /**
      * 是否启用
      */
+    @Schema(description = "是否启用")
     private boolean enable;
 
     /**
      * 名称
      */
+    @Schema(description = "名称")
     private String name;
 
     /**
      * SIP服务国标编码
      */
+    @Schema(description = "SIP服务国标编码")
     private String serverGBId;
 
     /**
      * SIP服务国标域
      */
+    @Schema(description = "SIP服务国标域")
     private String serverGBDomain;
 
     /**
      * SIP服务IP
      */
+    @Schema(description = "SIP服务IP")
     private String serverIP;
 
     /**
      * SIP服务端口
      */
+    @Schema(description = "SIP服务端口")
     private int serverPort;
 
     /**
      * 设备国标编号
      */
+    @Schema(description = "11111")
     private String deviceGBId;
 
     /**
      * 设备ip
      */
+    @Schema(description = "设备ip")
     private String deviceIp;
 
     /**
      * 设备端口
      */
+    @Schema(description = "设备端口")
     private String devicePort;
 
     /**
      * SIP认证用户名(默认使用设备国标编号)
      */
+    @Schema(description = "SIP认证用户名(默认使用设备国标编号)")
     private String username;
 
     /**
      * SIP认证密码
      */
+    @Schema(description = "SIP认证密码")
     private String password;
 
     /**
      * 注册周期 (秒)
      */
+    @Schema(description = "注册周期 (秒)")
     private String expires;
 
     /**
      * 心跳周期(秒)
      */
+    @Schema(description = "心跳周期(秒)")
     private String keepTimeout;
 
     /**
      * 传输协议
      * UDP/TCP
      */
+    @Schema(description = "传输协议")
     private String transport;
 
     /**
      * 字符集
      */
+    @Schema(description = "字符集")
     private String characterSet;
 
     /**
      * 允许云台控制
      */
+    @Schema(description = "允许云台控制")
     private boolean ptz;
 
     /**
      * RTCP流保活
      * TODO 预留, 暂不实现
      */
+    @Schema(description = "RTCP流保活")
     private boolean rtcp;
 
     /**
      * 在线状态
      */
+    @Schema(description = "在线状态")
     private boolean status;
 
     /**
      * 在线状态
      */
+    @Schema(description = "在线状态")
     private int channelCount;
 
     /**
      * 默认目录Id,自动添加的通道多放在这个目录下
      */
+    @Schema(description = "默认目录Id,自动添加的通道多放在这个目录下")
     private String catalogId;
 
     /**
      * 已被订阅目录信息
      */
+    @Schema(description = "已被订阅目录信息")
     private boolean catalogSubscribe;
 
     /**
      * 已被订阅报警信息
      */
+    @Schema(description = "已被订阅报警信息")
     private boolean alarmSubscribe;
 
     /**
      * 已被订阅移动位置信息
      */
+    @Schema(description = "已被订阅移动位置信息")
     private boolean mobilePositionSubscribe;
 
     /**
      * 点播未推流的设备时是否使用redis通知拉起
      */
+    @Schema(description = "点播未推流的设备时是否使用redis通知拉起")
     private boolean startOfflinePush;
 
     /**
      * 目录分组-每次向上级发送通道信息时单个包携带的通道数量,取值1,2,4,8
      */
+    @Schema(description = "目录分组-每次向上级发送通道信息时单个包携带的通道数量,取值1,2,4,8")
     private int catalogGroup;
 
     /**
      * 行政区划
      */
+    @Schema(description = "行政区划")
     private String administrativeDivision;
 
     /**
      * 更新时间
      */
+    @Schema(description = "更新时间")
     private String updateTime;
 
     /**
      * 创建时间
      */
+    @Schema(description = "创建时间")
     private String createTime;
 
     /**
      * 树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGroup
      */
+    @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou")
     private String treeType;
 
     public Integer getId() {

+ 14 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java

@@ -1,27 +1,41 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 /**
  * 国标级联-目录
  * @author lin
  */
+@Schema(description = "目录信息")
 public class PlatformCatalog {
+    @Schema(description = "ID")
     private String id;
+
+    @Schema(description = "名称")
     private String name;
+
+    @Schema(description = "平台ID")
     private String platformId;
+
+    @Schema(description = "父级目录ID")
     private String parentId;
 
+    @Schema(description = "行政区划")
     private String civilCode;
 
+    @Schema(description = "目录分组")
     private String businessGroupId;
 
     /**
      * 子节点数
      */
+    @Schema(description = "子节点数")
     private int childrenCount;
 
     /**
      * 0 目录, 1 国标通道, 2 直播流
      */
+    @Schema(description = "类型:0 目录, 1 国标通道, 2 直播流")
     private int type;
 
     public String getId() {

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java

@@ -1,8 +1,16 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 public class PlatformGbStream {
+
+    @Schema(description = "ID")
     private Integer gbStreamId;
+
+    @Schema(description = "平台ID")
     private String platformId;
+
+    @Schema(description = "目录ID")
     private String catalogId;
 
     public Integer getGbStreamId() {

+ 7 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java

@@ -1,14 +1,20 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 /**
  * 摄像机同步状态
  * @author lin
  */
+@Schema(description = "摄像机同步状态")
 public class SyncStatus {
+    @Schema(description = "总数")
     private int total;
+    @Schema(description = "当前更新多少")
     private int current;
+    @Schema(description = "错误描述")
     private String errorMsg;
-
+    @Schema(description = "是否同步中")
     private boolean syncIng;
 
     public int getTotal() {

+ 3 - 3
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java

@@ -37,9 +37,9 @@ public class EventPublisher {
 	 * @param platformGbId
 	 */
 	public void platformKeepaliveExpireEventPublish(String platformGbId){
-		PlatformKeepaliveExpireEvent platformNotRegisterEvent = new PlatformKeepaliveExpireEvent(this);
-		platformNotRegisterEvent.setPlatformGbID(platformGbId);
-        applicationEventPublisher.publishEvent(platformNotRegisterEvent);
+		PlatformKeepaliveExpireEvent platformKeepaliveExpireEvent = new PlatformKeepaliveExpireEvent(this);
+		platformKeepaliveExpireEvent.setPlatformGbID(platformGbId);
+        applicationEventPublisher.publishEvent(platformKeepaliveExpireEvent);
     }
 
 	/**

+ 0 - 81
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java

@@ -1,81 +0,0 @@
-package com.genersoft.iot.vmp.gb28181.event.offline;
-
-import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
-import com.genersoft.iot.vmp.conf.UserSetting;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.connection.Message;
-import org.springframework.data.redis.listener.RedisMessageListenerContainer;
-import org.springframework.stereotype.Component;
-
-import com.genersoft.iot.vmp.common.VideoManagerConstants;
-import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
-
-/**    
- * 设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
- * @author swwheihei
- */
-@Component
-public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener {
-
-    private Logger logger = LoggerFactory.getLogger(KeepaliveTimeoutListenerForPlatform.class);
-
-	@Autowired
-	private EventPublisher publisher;
-
-	@Autowired
-	private UserSetting userSetting;
-
-	@Autowired
-	private SipSubscribe sipSubscribe;
-
-	@Autowired
-	private IVideoManagerStorage storager;
-
-    public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {
-        super(listenerContainer, userSetting);
-    }
-
-
-    /**
-     * 监听失效的key
-     * @param message
-     * @param pattern
-     */
-    @Override
-    public void onMessage(Message message, byte[] pattern) {
-        //  获取失效的key
-        String expiredKey = message.toString();
-        // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线
-        String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_";
-        String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_";
-        String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_";
-        if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {
-            String platformGbId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length());
-            ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId);
-            if (platform != null) {
-                publisher.platformKeepaliveExpireEventPublish(platformGbId);
-            }
-        }else if (expiredKey.startsWith(PLATFORM_REGISTER_PREFIX)) {
-            String platformGbId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length());
-            ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId);
-            if (platform != null) {
-                publisher.platformRegisterCycleEventPublish(platformGbId);
-            }
-        }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) {
-            String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length());
-            if (sipSubscribe.getErrorSubscribe(callId) != null) {
-                SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult();
-                eventResult.callId = callId;
-                eventResult.msg = "注册超时";
-                eventResult.type = "register timeout";
-                sipSubscribe.getErrorSubscribe(callId).response(eventResult);
-            }
-        }
-    }
-}

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java

@@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationListener;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
@@ -58,7 +59,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
         ParentPlatform parentPlatform = null;
 
         Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
-        if (!StringUtils.isEmpty(event.getPlatformId())) {
+        if (!ObjectUtils.isEmpty(event.getPlatformId())) {
             subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
             if (subscribe == null) {
                 return;
@@ -81,7 +82,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
             }else if (event.getGbStreams() != null) {
                 if (platforms.size() > 0) {
                     for (GbStream gbStream : event.getGbStreams()) {
-                        if (gbStream == null || StringUtils.isEmpty(gbStream.getGbId())) {
+                        if (gbStream == null || ObjectUtils.isEmpty(gbStream.getGbId())) {
                             continue;
                         }
                         List<ParentPlatform> parentPlatformsForGB = storager.queryPlatFormListForStreamWithGBId(gbStream.getApp(),gbStream.getStream(), platforms);

+ 1 - 5
src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java

@@ -60,16 +60,12 @@ public class RecordDataCatch {
                 // 处理录像数据, 返回给前端
                 String msgKey = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn();
 
-                WVPResult<RecordInfo> wvpResult = new WVPResult<>();
-                wvpResult.setCode(0);
-                wvpResult.setMsg("success");
                 // 对数据进行排序
                 Collections.sort(recordInfo.getRecordList());
-                wvpResult.setData(recordInfo);
 
                 RequestMessage msg = new RequestMessage();
                 msg.setKey(msgKey);
-                msg.setData(wvpResult);
+                msg.setData(recordInfo);
                 deferredResultHolder.invokeAllResult(msg);
                 data.remove(key);
             }

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java

@@ -1,27 +1,35 @@
 package com.genersoft.iot.vmp.gb28181.session;
 
 import com.genersoft.iot.vmp.utils.ConfigConst;
+import io.swagger.v3.oas.annotations.media.Schema;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 import java.util.Set;
 
+@Schema(description = "ssrc信息")
 public class SsrcConfig {
 
     /**
      * zlm流媒体服务器Id
      */
+    @Schema(description = "流媒体服务器Id")
     private String mediaServerId;
 
+    @Schema(description = "SSRC前缀")
     private String ssrcPrefix;
+
     /**
      * zlm流媒体服务器已用会话句柄
      */
+    @Schema(description = "zlm流媒体服务器已用会话句柄")
     private List<String> isUsed;
+
     /**
      * zlm流媒体服务器可用会话句柄
      */
+    @Schema(description = "zlm流媒体服务器可用会话句柄")
     private List<String> notUsed;
 
     public SsrcConfig() {

+ 19 - 21
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java

@@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import gov.nist.javax.sip.stack.SIPDialog;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 /**    
@@ -24,9 +25,6 @@ import org.springframework.util.StringUtils;
 @Component
 public class VideoStreamSessionManager {
 
-	@Autowired
-	private RedisUtil redisUtil;
-
 	@Autowired
 	private UserSetting userSetting;
 
@@ -58,9 +56,9 @@ public class VideoStreamSessionManager {
 		ssrcTransaction.setMediaServerId(mediaServerId);
 		ssrcTransaction.setType(type);
 
-		redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
+		RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
 				+ "_" +  deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
-		redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
+		RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
 				+ "_" +  deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
 	}
 
@@ -70,7 +68,7 @@ public class VideoStreamSessionManager {
 			byte[] dialogByteArray = SerializeUtils.serialize(dialog);
 			ssrcTransaction.setDialog(dialogByteArray);
 		}
-		redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
+		RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
 				+ "_" +  deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
 				+ ssrcTransaction.getStream(), ssrcTransaction);
 	}
@@ -113,47 +111,47 @@ public class VideoStreamSessionManager {
 
 	public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
 
-		if (StringUtils.isEmpty(deviceId)) {
+		if (ObjectUtils.isEmpty(deviceId)) {
 			deviceId ="*";
 		}
-		if (StringUtils.isEmpty(channelId)) {
+		if (ObjectUtils.isEmpty(channelId)) {
 			channelId ="*";
 		}
-		if (StringUtils.isEmpty(callId)) {
+		if (ObjectUtils.isEmpty(callId)) {
 			callId ="*";
 		}
-		if (StringUtils.isEmpty(stream)) {
+		if (ObjectUtils.isEmpty(stream)) {
 			stream ="*";
 		}
 		String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
-		List<Object> scanResult = redisUtil.scan(key);
+		List<Object> scanResult = RedisUtil.scan(key);
 		if (scanResult.size() == 0) {
 			return null;
 		}
-		return (SsrcTransaction)redisUtil.get((String) scanResult.get(0));
+		return (SsrcTransaction)RedisUtil.get((String) scanResult.get(0));
 	}
 
 	public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
-		if (StringUtils.isEmpty(deviceId)) {
+		if (ObjectUtils.isEmpty(deviceId)) {
 			deviceId ="*";
 		}
-		if (StringUtils.isEmpty(channelId)) {
+		if (ObjectUtils.isEmpty(channelId)) {
 			channelId ="*";
 		}
-		if (StringUtils.isEmpty(callId)) {
+		if (ObjectUtils.isEmpty(callId)) {
 			callId ="*";
 		}
-		if (StringUtils.isEmpty(stream)) {
+		if (ObjectUtils.isEmpty(stream)) {
 			stream ="*";
 		}
 		String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
-		List<Object> scanResult = redisUtil.scan(key);
+		List<Object> scanResult = RedisUtil.scan(key);
 		if (scanResult.size() == 0) {
 			return null;
 		}
 		List<SsrcTransaction> result = new ArrayList<>();
 		for (Object keyObj : scanResult) {
-			result.add((SsrcTransaction)redisUtil.get((String) keyObj));
+			result.add((SsrcTransaction)RedisUtil.get((String) keyObj));
 		}
 		return result;
 	}
@@ -179,17 +177,17 @@ public class VideoStreamSessionManager {
 		if (ssrcTransaction == null) {
 			return;
 		}
-		redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
+		RedisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
 				+  deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
 	}
 
 
 	public List<SsrcTransaction> getAllSsrc() {
-		List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId()));
+		List<Object> ssrcTransactionKeys = RedisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId()));
 		List<SsrcTransaction> result= new ArrayList<>();
 		for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
 			String key = (String)ssrcTransactionKeys.get(i);
-			SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(key);
+			SsrcTransaction ssrcTransaction = (SsrcTransaction)RedisUtil.get(key);
 			result.add(ssrcTransaction);
 		}
 		return result;

+ 0 - 8
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java

@@ -3,8 +3,6 @@ package com.genersoft.iot.vmp.gb28181.transmit;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
-import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor;
-import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.KeepaliveNotifyMessageHandler;
 import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
 import org.slf4j.Logger;
@@ -14,13 +12,10 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 
 import javax.sip.*;
-import javax.sip.address.SipURI;
-import javax.sip.address.URI;
 import javax.sip.header.*;
 import javax.sip.message.Request;
 import javax.sip.message.Response;
 import java.util.Map;
-import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -43,9 +38,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
     @Autowired
     private EventPublisher eventPublisher;
 
-
-
-
     /**
      * 添加 request订阅
      * @param method 方法名

+ 2 - 3
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java

@@ -96,7 +96,7 @@ public class DeferredResultHolder {
 		if (result == null) {
 			return;
 		}
-		result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
+		result.setResult(msg.getData());
 		deferredResultMap.remove(msg.getId());
 		if (deferredResultMap.size() == 0) {
 			map.remove(msg.getKey());
@@ -118,9 +118,8 @@ public class DeferredResultHolder {
 			if (result == null) {
 				return;
 			}
-			result.setResult(ResponseEntity.ok().body(msg.getData()));
+			result.setResult(msg.getData());
 		}
 		map.remove(msg.getKey());
-
 	}
 }

+ 25 - 24
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java

@@ -32,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.annotation.DependsOn;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.*;
@@ -819,7 +820,7 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<Control>\r\n");
 			cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
@@ -922,16 +923,16 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
 			cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n");
-			if (!StringUtils.isEmpty(alarmMethod) || !StringUtils.isEmpty(alarmType)) {
+			if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
 				cmdXml.append("<Info>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmMethod)) {
+			if (!ObjectUtils.isEmpty(alarmMethod)) {
 				cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmType)) {
+			if (!ObjectUtils.isEmpty(alarmType)) {
 				cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmMethod) || !StringUtils.isEmpty(alarmType)) {
+			if (!ObjectUtils.isEmpty(alarmMethod) || !ObjectUtils.isEmpty(alarmType)) {
 				cmdXml.append("</Info>\r\n");
 			}
 			cmdXml.append("</Control>\r\n");
@@ -965,7 +966,7 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<Control>\r\n");
 			cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
@@ -1004,7 +1005,7 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<Control>\r\n");
 			cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
@@ -1073,13 +1074,13 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<Control>\r\n");
 			cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
 			}
 			cmdXml.append("<BasicParam>\r\n");
-			if (!StringUtils.isEmpty(name)) {
+			if (!ObjectUtils.isEmpty(name)) {
 				cmdXml.append("<Name>" + name + "</Name>\r\n");
 			}
 			if (NumericUtil.isInteger(expiration)) {
@@ -1289,22 +1290,22 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
 			cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
-			if (!StringUtils.isEmpty(startPriority)) {
+			if (!ObjectUtils.isEmpty(startPriority)) {
 				cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
 			}
-			if (!StringUtils.isEmpty(endPriority)) {
+			if (!ObjectUtils.isEmpty(endPriority)) {
 				cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmMethod)) {
+			if (!ObjectUtils.isEmpty(alarmMethod)) {
 				cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmType)) {
+			if (!ObjectUtils.isEmpty(alarmType)) {
 				cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
 			}
-			if (!StringUtils.isEmpty(startTime)) {
+			if (!ObjectUtils.isEmpty(startTime)) {
 				cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
 			}
-			if (!StringUtils.isEmpty(endTime)) {
+			if (!ObjectUtils.isEmpty(endTime)) {
 				cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
 			}
 			cmdXml.append("</Query>\r\n");
@@ -1339,7 +1340,7 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<Query>\r\n");
 			cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
@@ -1375,7 +1376,7 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<Query>\r\n");
 			cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
@@ -1506,22 +1507,22 @@ public class SIPCommander implements ISIPCommander {
 			cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
 			cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
 			cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
-			if (!StringUtils.isEmpty(startPriority)) {
+			if (!ObjectUtils.isEmpty(startPriority)) {
 				cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n");
 			}
-			if (!StringUtils.isEmpty(endPriority)) {
+			if (!ObjectUtils.isEmpty(endPriority)) {
 				cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmMethod)) {
+			if (!ObjectUtils.isEmpty(alarmMethod)) {
 				cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n");
 			}
-			if (!StringUtils.isEmpty(alarmType)) {
+			if (!ObjectUtils.isEmpty(alarmType)) {
 				cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n");
 			}
-			if (!StringUtils.isEmpty(startTime)) {
+			if (!ObjectUtils.isEmpty(startTime)) {
 				cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n");
 			}
-			if (!StringUtils.isEmpty(endTime)) {
+			if (!ObjectUtils.isEmpty(endTime)) {
 				cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n");
 			}
 			cmdXml.append("</Query>\r\n");
@@ -1602,7 +1603,7 @@ public class SIPCommander implements ISIPCommander {
 			dragXml.append("<Control>\r\n");
 			dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");
 			dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
-			if (StringUtils.isEmpty(channelId)) {
+			if (ObjectUtils.isEmpty(channelId)) {
 				dragXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
 			} else {
 				dragXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java

@@ -23,6 +23,7 @@ import org.springframework.context.annotation.DependsOn;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.lang.Nullable;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 
@@ -728,10 +729,10 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
                             recordXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n");
                             recordXml.append("<Secrecy>" + recordItem.getSecrecy() + "</Secrecy>\r\n");
                             recordXml.append("<Type>" + recordItem.getType() + "</Type>\r\n");
-                            if (!StringUtils.isEmpty(recordItem.getFileSize())) {
+                            if (!ObjectUtils.isEmpty(recordItem.getFileSize())) {
                                 recordXml.append("<FileSize>" + recordItem.getFileSize() + "</FileSize>\r\n");
                             }
-                            if (!StringUtils.isEmpty(recordItem.getFilePath())) {
+                            if (!ObjectUtils.isEmpty(recordItem.getFilePath())) {
                                 recordXml.append("<FilePath>" + recordItem.getFilePath() + "</FilePath>\r\n");
                             }
                         }

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java

@@ -231,6 +231,9 @@ public abstract class SIPRequestProcessorParent {
 		byte destBye = (byte) despChar;
 		List<Byte> result = new ArrayList<>();
 		byte[] rawContent = request.getRawContent();
+		if (rawContent == null) {
+			return null;
+		}
 		for (int i = 0; i < rawContent.length; i++) {
 			if (rawContent[i] == destBye) {
 				boolean resul = false;

+ 41 - 6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java

@@ -29,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -41,7 +42,7 @@ import java.util.Iterator;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
- * SIP命令类型: NOTIFY请求
+ * SIP命令类型: NOTIFY请求,这是作为上级发送订阅请求后,设备才会响应的
  */
 @Component
 public class NotifyRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor {
@@ -101,6 +102,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 						try {
 							HandlerCatchData take = taskQueue.poll();
 							Element rootElement = getRootElement(take.getEvt());
+							if (rootElement == null) {
+								logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest());
+								continue;
+							}
 							String cmd = XmlUtil.getText(rootElement, "CmdType");
 
 							if (CmdType.CATALOG.equals(cmd)) {
@@ -116,14 +121,17 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 								logger.info("接收到消息:" + cmd);
 							}
 						} catch (DocumentException e) {
-							throw new RuntimeException(e);
+							logger.error("处理NOTIFY消息时错误", e);
+						} finally {
+							taskQueueHandlerRun = false;
 						}
 					}
-				taskQueueHandlerRun = false;
 				});
 			}
 		} catch (SipException | InvalidArgumentException | ParseException e) {
 			e.printStackTrace();
+		} finally {
+			taskQueueHandlerRun = false;
 		}
 	}
 
@@ -139,6 +147,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 
 			// 回复 200 OK
 			Element rootElement = getRootElement(evt);
+			if (rootElement == null) {
+				logger.error("处理MobilePosition移动位置Notify时未获取到消息体,{}", evt.getRequest());
+				return;
+			}
 
 			MobilePosition mobilePosition = new MobilePosition();
 			mobilePosition.setCreateTime(DateUtil.getNow());
@@ -146,7 +158,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 			String channelId = deviceIdElement.getTextTrim().toString();
 			Device device = redisCatchStorage.getDevice(deviceId);
 			if (device != null) {
-				if (!StringUtils.isEmpty(device.getName())) {
+				if (!ObjectUtils.isEmpty(device.getName())) {
 					mobilePosition.setDeviceName(device.getName());
 				}
 			}
@@ -195,6 +207,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 			}
 
 			storager.updateChannelPosition(deviceChannel);
+
 			// 发送redis消息。 通知位置信息的变化
 			JSONObject jsonObject = new JSONObject();
 			jsonObject.put("time", time);
@@ -225,6 +238,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 			String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
 
 			Element rootElement = getRootElement(evt);
+			if (rootElement == null) {
+				logger.error("处理alarm设备报警Notify时未获取到消息体{}", evt.getRequest());
+				return;
+			}
 			Element deviceIdElement = rootElement.element("DeviceID");
 			String channelId = deviceIdElement.getText().toString();
 
@@ -234,6 +251,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 				return;
 			}
 			rootElement = getRootElement(evt, device.getCharset());
+			if (rootElement == null) {
+				logger.warn("[ NotifyAlarm ] content cannot be null, {}", evt.getRequest());
+				return;
+			}
 			DeviceAlarm deviceAlarm = new DeviceAlarm();
 			deviceAlarm.setDeviceId(deviceId);
 			deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
@@ -269,8 +290,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 				mobilePosition.setLatitude(deviceAlarm.getLatitude());
 				mobilePosition.setReportSource("GPS Alarm");
 
-
-
 				// 更新device channel 的经纬度
 				DeviceChannel deviceChannel = new DeviceChannel();
 				deviceChannel.setDeviceId(device.getDeviceId());
@@ -291,6 +310,18 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 				}
 
 				storager.updateChannelPosition(deviceChannel);
+				// 发送redis消息。 通知位置信息的变化
+				JSONObject jsonObject = new JSONObject();
+				jsonObject.put("time", mobilePosition.getTime());
+				jsonObject.put("serial", deviceChannel.getDeviceId());
+				jsonObject.put("code", deviceChannel.getChannelId());
+				jsonObject.put("longitude", mobilePosition.getLongitude());
+				jsonObject.put("latitude", mobilePosition.getLatitude());
+				jsonObject.put("altitude", mobilePosition.getAltitude());
+				jsonObject.put("direction", mobilePosition.getDirection());
+				jsonObject.put("speed", mobilePosition.getSpeed());
+				redisCatchStorage.sendMobilePositionMsg(jsonObject);
+
 			}
 			// TODO: 需要实现存储报警信息、报警分类
 
@@ -319,6 +350,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
 				return;
 			}
 			Element rootElement = getRootElement(evt, device.getCharset());
+			if (rootElement == null) {
+				logger.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest());
+				return;
+			}
 			Element deviceListElement = rootElement.element("DeviceList");
 			if (deviceListElement == null) {
 				return;

+ 4 - 3
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java

@@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -81,7 +82,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
             String deviceId = uri.getUser();
 
             AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
-            if (authHead == null && !StringUtils.isEmpty(sipConfig.getPassword())) {
+            if (authHead == null && !ObjectUtils.isEmpty(sipConfig.getPassword())) {
                 logger.info("[注册请求] 未携带授权头 回复401: {}", requestAddress);
                 response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request);
                 new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain());
@@ -90,7 +91,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
             }
 
             // 校验密码是否正确
-            passwordCorrect = StringUtils.isEmpty(sipConfig.getPassword()) ||
+            passwordCorrect = ObjectUtils.isEmpty(sipConfig.getPassword()) ||
                     new DigestServerAuthenticationHelper().doAuthenticatePlainTextPassword(request, sipConfig.getPassword());
 
             if (!passwordCorrect) {
@@ -132,7 +133,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
             String received = viaHeader.getReceived();
             int rPort = viaHeader.getRPort();
             // 解析本地地址替代
-            if (StringUtils.isEmpty(received) || rPort == -1) {
+            if (ObjectUtils.isEmpty(received) || rPort == -1) {
                 received = viaHeader.getHost();
                 rPort = viaHeader.getPort();
             }

+ 4 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java

@@ -84,6 +84,10 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
 		Request request = evt.getRequest();
 		try {
 			Element rootElement = getRootElement(evt);
+			if (rootElement == null) {
+				logger.error("处理SUBSCRIBE请求  未获取到消息体{}", evt.getRequest());
+				return;
+			}
 			String cmd = XmlUtil.getText(rootElement, "CmdType");
 			if (CmdType.MOBILE_POSITION.equals(cmd)) {
 				processNotifyMobilePosition(evt, rootElement);

+ 5 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java

@@ -108,6 +108,11 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
                 Element rootElement = null;
                 try {
                     rootElement = getRootElement(evt);
+                    if (rootElement == null) {
+                        logger.error("处理MESSAGE请求  未获取到消息体{}", evt.getRequest());
+                        responseAck(evt, Response.BAD_REQUEST, "content is null");
+                        return;
+                    }
                 } catch (DocumentException e) {
                     logger.warn("解析XML消息内容异常", e);
                     // 不存在则回复404

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java

@@ -17,6 +17,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.*;
@@ -64,7 +65,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
         String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();
         String channelId = getText(rootElement, "DeviceID");
         // 远程启动功能
-        if (!StringUtils.isEmpty(getText(rootElement, "TeleBoot"))) {
+        if (!ObjectUtils.isEmpty(getText(rootElement, "TeleBoot"))) {
             if (parentPlatform.getServerGBId().equals(targetGBId)) {
                 // 远程启动本平台:需要在重新启动程序后先对SipStack解绑
                 logger.info("执行远程启动本平台命令");
@@ -101,7 +102,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
             }
         }
         // 云台/前端控制命令
-        if (!StringUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) {
+        if (!ObjectUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) {
             String cmdString = getText(rootElement,"PTZCmd");
             Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
             if (deviceForPlatform == null) {

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java

@@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 /**
- * 命令类型: 通知命令
+ * 命令类型: 通知命令, 参看 A.2.5 通知命令
  * 命令类型: 状态信息(心跳)报送, 报警通知, 媒体通知, 移动设备位置数据,语音广播通知(TODO), 设备预置位(TODO)
  * @author lin
  */

+ 22 - 12
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java

@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
 
+import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
@@ -21,6 +22,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -32,6 +34,9 @@ import java.text.ParseException;
 
 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
 
+/**
+ * 报警事件的处理,参考:9.4
+ */
 @Component
 public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
@@ -73,12 +78,8 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
         // 回复200 OK
         try {
             responseAck(evt, Response.OK);
-        } catch (SipException e) {
-            throw new RuntimeException(e);
-        } catch (InvalidArgumentException e) {
-            throw new RuntimeException(e);
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
+        } catch (SipException | InvalidArgumentException | ParseException e) {
+            logger.error("[收到报警通知], 回复200OK失败", e);
         }
 
         Element deviceIdElement = rootElement.element("DeviceID");
@@ -114,7 +115,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
             deviceAlarm.setLatitude(0.00);
         }
 
-        if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
+        if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
             if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) {
                 MobilePosition mobilePosition = new MobilePosition();
                 mobilePosition.setCreateTime(DateUtil.getNow());
@@ -124,7 +125,6 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
                 mobilePosition.setLatitude(deviceAlarm.getLatitude());
                 mobilePosition.setReportSource("GPS Alarm");
 
-
                 // 更新device channel 的经纬度
                 DeviceChannel deviceChannel = new DeviceChannel();
                 deviceChannel.setDeviceId(device.getDeviceId());
@@ -144,9 +144,21 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
                     storager.insertMobilePosition(mobilePosition);
                 }
                 storager.updateChannelPosition(deviceChannel);
+
+                // 发送redis消息。 通知位置信息的变化
+                JSONObject jsonObject = new JSONObject();
+                jsonObject.put("time", mobilePosition.getTime());
+                jsonObject.put("serial", deviceChannel.getDeviceId());
+                jsonObject.put("code", deviceChannel.getChannelId());
+                jsonObject.put("longitude", mobilePosition.getLongitude());
+                jsonObject.put("latitude", mobilePosition.getLatitude());
+                jsonObject.put("altitude", mobilePosition.getAltitude());
+                jsonObject.put("direction", mobilePosition.getDirection());
+                jsonObject.put("speed", mobilePosition.getSpeed());
+                redisCatchStorage.sendMobilePositionMsg(jsonObject);
             }
         }
-        if (!StringUtils.isEmpty(deviceAlarm.getDeviceId())) {
+        if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) {
             if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) {
                 deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));
             }
@@ -159,7 +171,6 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
             alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
             alarmChannelMessage.setGbId(channelId);
             redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
-
             return;
         }
 
@@ -169,7 +180,6 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
             deviceAlarmService.add(deviceAlarm);
         }
 
-
         if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) {
             publisher.deviceAlarmEventPublish(deviceAlarm);
         }
@@ -222,7 +232,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
             deviceAlarm.setLatitude(0.00);
         }
 
-        if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
+        if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) {
 
             if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) {
                 deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType"));

+ 0 - 88
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java

@@ -1,88 +0,0 @@
-package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
-
-import com.genersoft.iot.vmp.gb28181.bean.*;
-import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
-import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
-import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
-import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
-import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
-import org.dom4j.Element;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import javax.sip.InvalidArgumentException;
-import javax.sip.RequestEvent;
-import javax.sip.SipException;
-import javax.sip.header.FromHeader;
-import javax.sip.message.Response;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.List;
-
-@Component
-public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
-
-    private final String cmdType = "Catalog";
-
-    @Autowired
-    private NotifyMessageHandler notifyMessageHandler;
-
-    @Autowired
-    private IVideoManagerStorage storage;
-
-    @Autowired
-    private SIPCommanderFroPlatform cmderFroPlatform;
-
-    @Override
-    public void afterPropertiesSet() throws Exception {
-        notifyMessageHandler.addHandler(cmdType, this);
-    }
-
-    @Override
-    public void handForDevice(RequestEvent evt, Device device, Element element) {
-
-    }
-
-    @Override
-    public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
-
-        String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + parentPlatform.getServerGBId();
-        FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
-        try {
-            // 回复200 OK
-            responseAck(evt, Response.OK);
-            Element snElement = rootElement.element("SN");
-            String sn = snElement.getText();
-            // 准备回复通道信息
-            List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
-            // 查询关联的直播通道
-            List<DeviceChannel> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
-            // 回复目录信息
-            List<DeviceChannel> catalogs =  storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
-
-            List<DeviceChannel> allChannels = new ArrayList<>();
-            if (catalogs.size() > 0) {
-                allChannels.addAll(catalogs);
-            }
-            // 回复级联的通道
-            if (deviceChannels.size() > 0) {
-                allChannels.addAll(deviceChannels);
-            }
-            // 回复直播的通道
-            if (gbStreams.size() > 0) {
-                allChannels.addAll(gbStreams);
-            }
-            if (allChannels.size() > 0) {
-                cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
-            }else {
-                // 回复无通道
-                cmderFroPlatform.catalogQuery(null, parentPlatform, sn, fromHeader.getTag(), 0);
-            }
-        } catch (SipException | InvalidArgumentException | ParseException e) {
-            e.printStackTrace();
-        }
-
-    }
-}

+ 5 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java

@@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -25,6 +26,9 @@ import javax.sip.header.ViaHeader;
 import javax.sip.message.Response;
 import java.text.ParseException;
 
+/**
+ * 状态信息(心跳)报送
+ */
 @Component
 public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
@@ -55,7 +59,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
             String received = viaHeader.getReceived();
             int rPort = viaHeader.getRPort();
             // 解析本地地址替代
-            if (StringUtils.isEmpty(received) || rPort == -1) {
+            if (ObjectUtils.isEmpty(received) || rPort == -1) {
                 received = viaHeader.getHost();
                 rPort = viaHeader.getPort();
             }

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java

@@ -29,6 +29,9 @@ import java.text.ParseException;
 
 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
 
+/**
+ * 媒体通知
+ */
 @Component
 public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 

+ 28 - 4
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java

@@ -1,16 +1,16 @@
 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
 
+import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
-import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
 import com.genersoft.iot.vmp.service.IDeviceChannelService;
+import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
-import com.genersoft.iot.vmp.utils.GpsUtil;
 import org.dom4j.DocumentException;
 import org.dom4j.Element;
 import org.slf4j.Logger;
@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -28,6 +29,9 @@ import java.text.ParseException;
 
 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
 
+/**
+ * 移动设备位置数据通知,设备主动发起,不需要上级订阅
+ */
 @Component
 public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
@@ -43,6 +47,9 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
     @Autowired
     private IVideoManagerStorage storager;
 
+    @Autowired
+    private IRedisCatchStorage redisCatchStorage;
+
     @Autowired
     private IDeviceChannelService deviceChannelService;
 
@@ -56,10 +63,14 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
 
         try {
             rootElement = getRootElement(evt, device.getCharset());
-
+            if (rootElement == null) {
+                logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest());
+                responseAck(evt, Response.BAD_REQUEST);
+                return;
+            }
             MobilePosition mobilePosition = new MobilePosition();
             mobilePosition.setCreateTime(DateUtil.getNow());
-            if (!StringUtils.isEmpty(device.getName())) {
+            if (!ObjectUtils.isEmpty(device.getName())) {
                 mobilePosition.setDeviceName(device.getName());
             }
             mobilePosition.setDeviceId(device.getDeviceId());
@@ -106,6 +117,19 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
             storager.updateChannelPosition(deviceChannel);
             //回复 200 OK
             responseAck(evt, Response.OK);
+
+            // 发送redis消息。 通知位置信息的变化
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("time", mobilePosition.getTime());
+            jsonObject.put("serial", deviceChannel.getDeviceId());
+            jsonObject.put("code", deviceChannel.getChannelId());
+            jsonObject.put("longitude", mobilePosition.getLongitude());
+            jsonObject.put("latitude", mobilePosition.getLatitude());
+            jsonObject.put("altitude", mobilePosition.getAltitude());
+            jsonObject.put("direction", mobilePosition.getDirection());
+            jsonObject.put("speed", mobilePosition.getSpeed());
+            redisCatchStorage.sendMobilePositionMsg(jsonObject);
+
         } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
             e.printStackTrace();
         }

+ 77 - 68
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java

@@ -35,6 +35,9 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
+/**
+ * 目录查询的回复
+ */
 @Component
 public class CatalogResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
@@ -85,82 +88,88 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
         // 回复200 OK
         try {
             responseAck(evt, Response.OK);
+            if (!taskQueueHandlerRun) {
+                taskQueueHandlerRun = true;
+                taskExecutor.execute(()-> {
+                    while (!taskQueue.isEmpty()) {
+                        HandlerCatchData take = taskQueue.poll();
+                        try {
+                            Element rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
+                            if (rootElement == null) {
+                                logger.warn("[ 收到通道 ] content cannot be null, {}", evt.getRequest());
+                                continue;
+                            }
+                            Element deviceListElement = rootElement.element("DeviceList");
+                            Element sumNumElement = rootElement.element("SumNum");
+                            Element snElement = rootElement.element("SN");
+                            if (snElement == null || sumNumElement == null || deviceListElement == null) {
+                                responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error");
+                                continue;
+                            }
+                            int sumNum = Integer.parseInt(sumNumElement.getText());
+
+                            if (sumNum == 0) {
+                                logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
+                                // 数据已经完整接收
+                                storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
+                                catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
+                            }else {
+                                Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
+                                if (deviceListIterator != null) {
+                                    List<DeviceChannel> channelList = new ArrayList<>();
+                                    // 遍历DeviceList
+                                    while (deviceListIterator.hasNext()) {
+                                        Element itemDevice = deviceListIterator.next();
+                                        Element channelDeviceElement = itemDevice.element("DeviceID");
+                                        if (channelDeviceElement == null) {
+                                            continue;
+                                        }
+                                        DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
+                                        deviceChannel.setDeviceId(take.getDevice().getDeviceId());
+
+                                        channelList.add(deviceChannel);
+                                    }
+                                    int sn = Integer.parseInt(snElement.getText());
+                                    catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
+                                    logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
+                                    if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
+                                        // 数据已经完整接收, 此时可能存在某个设备离线变上线的情况,但是考虑到性能,此处不做处理,
+                                        // 目前支持设备通道上线通知时和设备上线时向上级通知
+                                        boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
+                                        if (!resetChannelsResult) {
+                                            String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "条";
+                                            catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
+                                        }else {
+                                            catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
+                                        }
+                                    }
+                                }
+
+                            }
+                        } catch (DocumentException e) {
+                            e.printStackTrace();
+                        } catch (InvalidArgumentException e) {
+                            e.printStackTrace();
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        } catch (SipException e) {
+                            e.printStackTrace();
+                        } finally {
+                            taskQueueHandlerRun = false;
+                        }
+                    }
+                });
+            }
         } catch (SipException e) {
             throw new RuntimeException(e);
         } catch (InvalidArgumentException e) {
             throw new RuntimeException(e);
         } catch (ParseException e) {
             throw new RuntimeException(e);
+        } finally {
+            taskQueueHandlerRun = false;
         }
-        if (!taskQueueHandlerRun) {
-            taskQueueHandlerRun = true;
-            taskExecutor.execute(()-> {
-                while (!taskQueue.isEmpty()) {
-                    HandlerCatchData take = taskQueue.poll();
-                    String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + take.getDevice().getDeviceId();
-                    Element rootElement = null;
-                    try {
-                        rootElement = getRootElement(take.getEvt(), take.getDevice().getCharset());
-                        Element deviceListElement = rootElement.element("DeviceList");
-                        Element sumNumElement = rootElement.element("SumNum");
-                        Element snElement = rootElement.element("SN");
-                        if (snElement == null || sumNumElement == null || deviceListElement == null) {
-                            responseAck(take.getEvt(), Response.BAD_REQUEST, "xml error");
-                            return;
-                        }
-                        int sumNum = Integer.parseInt(sumNumElement.getText());
-
-                        if (sumNum == 0) {
-                            logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
-                            // 数据已经完整接收
-                            storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
-                            catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
-                        }else {
-                            Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
-                            if (deviceListIterator != null) {
-                                List<DeviceChannel> channelList = new ArrayList<>();
-                                // 遍历DeviceList
-                                while (deviceListIterator.hasNext()) {
-                                    Element itemDevice = deviceListIterator.next();
-                                    Element channelDeviceElement = itemDevice.element("DeviceID");
-                                    if (channelDeviceElement == null) {
-                                        continue;
-                                    }
-                                    DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
-                                    deviceChannel.setDeviceId(take.getDevice().getDeviceId());
-
-                                    channelList.add(deviceChannel);
-                                }
-                                int sn = Integer.parseInt(snElement.getText());
-                                catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
-                                logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
-                                if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
-                                    // 数据已经完整接收
-                                    boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
-                                    if (!resetChannelsResult) {
-                                        String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(take.getDevice().getDeviceId()).size() + "条";
-                                        catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), errorMsg);
-                                    }else {
-                                        catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
-                                    }
-                                }
-                            }
 
-                        }
-                    } catch (DocumentException e) {
-                        e.printStackTrace();
-                    } catch (InvalidArgumentException e) {
-                        e.printStackTrace();
-                    } catch (ParseException e) {
-                        e.printStackTrace();
-                    } catch (SipException e) {
-                        e.printStackTrace();
-                    }
-                }
-                taskQueueHandlerRun = false;
-            });
-
-        }
     }
 
     @Override

+ 7 - 1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java

@@ -20,6 +20,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -75,6 +76,11 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
         }
         try {
             rootElement = getRootElement(evt, device.getCharset());
+            if (rootElement == null) {
+                logger.warn("[ 接收到DeviceInfo应答消息 ] content cannot be null, {}", evt.getRequest());
+                responseAck(evt, Response.BAD_REQUEST);
+                return;
+            }
             Element deviceIdElement = rootElement.element("DeviceID");
             String channelId = deviceIdElement.getTextTrim();
             String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + device.getDeviceId() + channelId;
@@ -83,7 +89,7 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
             device.setManufacturer(getText(rootElement, "Manufacturer"));
             device.setModel(getText(rootElement, "Model"));
             device.setFirmware(getText(rootElement, "Firmware"));
-            if (StringUtils.isEmpty(device.getStreamMode())) {
+            if (ObjectUtils.isEmpty(device.getStreamMode())) {
                 device.setStreamMode("UDP");
             }
             deviceService.updateDevice(device);

+ 28 - 2
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java

@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
 
+import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@@ -8,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respons
 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
 import com.genersoft.iot.vmp.service.IDeviceChannelService;
+import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.utils.GpsUtil;
@@ -18,6 +20,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -28,6 +31,10 @@ import java.text.ParseException;
 
 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
 
+/**
+ * 移动设备位置数据查询回复
+ * @author lin
+ */
 @Component
 public class MobilePositionResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
@@ -43,6 +50,9 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
     @Autowired
     private IVideoManagerStorage storager;
 
+    @Autowired
+    private IRedisCatchStorage redisCatchStorage;
+
     @Autowired
     private IDeviceChannelService deviceChannelService;
 
@@ -56,10 +66,14 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
 
         try {
             rootElement = getRootElement(evt, device.getCharset());
-
+            if (rootElement == null) {
+                logger.warn("[ 移动设备位置数据查询回复 ] content cannot be null, {}", evt.getRequest());
+                responseAck(evt, Response.BAD_REQUEST);
+                return;
+            }
             MobilePosition mobilePosition = new MobilePosition();
             mobilePosition.setCreateTime(DateUtil.getNow());
-            if (!StringUtils.isEmpty(device.getName())) {
+            if (!ObjectUtils.isEmpty(device.getName())) {
                 mobilePosition.setDeviceName(device.getName());
             }
             mobilePosition.setDeviceId(device.getDeviceId());
@@ -103,6 +117,18 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
                 storager.insertMobilePosition(mobilePosition);
             }
             storager.updateChannelPosition(deviceChannel);
+
+            // 发送redis消息。 通知位置信息的变化
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("time", mobilePosition.getTime());
+            jsonObject.put("serial", deviceChannel.getDeviceId());
+            jsonObject.put("code", deviceChannel.getChannelId());
+            jsonObject.put("longitude", mobilePosition.getLongitude());
+            jsonObject.put("latitude", mobilePosition.getLatitude());
+            jsonObject.put("altitude", mobilePosition.getAltitude());
+            jsonObject.put("direction", mobilePosition.getDirection());
+            jsonObject.put("speed", mobilePosition.getSpeed());
+            redisCatchStorage.sendMobilePositionMsg(jsonObject);
             //回复 200 OK
             responseAck(evt, Response.OK);
         } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {

+ 9 - 6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java

@@ -26,6 +26,9 @@ import java.util.List;
 
 import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
 
+/**
+ * 设备预置位查询应答
+ */
 @Component
 public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
@@ -49,7 +52,11 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
         Element rootElement = null;
         try {
             rootElement = getRootElement(evt, device.getCharset());
-
+            if (rootElement == null) {
+                logger.warn("[ 设备预置位查询应答 ] content cannot be null, {}", evt.getRequest());
+                responseAck(evt, Response.BAD_REQUEST);
+                return;
+            }
             Element presetListNumElement = rootElement.element("PresetList");
             Element snElement = rootElement.element("SN");
             //该字段可能为通道或则设备的id
@@ -61,11 +68,7 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
             }
             int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
             List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>();
-            if (sumNum == 0) {
-                // 数据无预置位信息
-
-
-            }else {
+            if (sumNum > 0) {
                 for (Iterator<Element> presetIterator =  presetListNumElement.elementIterator();presetIterator.hasNext();){
                     Element itemListElement = presetIterator.next();
                     PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq();

+ 16 - 12
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java

@@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.InvalidArgumentException;
@@ -39,7 +40,7 @@ import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
 @Component
 public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
 
-    private Logger logger = LoggerFactory.getLogger(RecordInfoResponseMessageHandler.class);
+    private final Logger logger = LoggerFactory.getLogger(RecordInfoResponseMessageHandler.class);
     private final String cmdType = "RecordInfo";
 
     private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
@@ -76,10 +77,14 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
             if (!taskQueueHandlerRun) {
                 taskQueueHandlerRun = true;
                 taskExecutor.execute(()->{
-                    try {
-                        while (!taskQueue.isEmpty()) {
+                    while (!taskQueue.isEmpty()) {
+                        try {
                             HandlerCatchData take = taskQueue.poll();
                             Element rootElementForCharset = getRootElement(take.getEvt(), take.getDevice().getCharset());
+                            if (rootElement == null) {
+                                logger.warn("[ 国标录像 ] content cannot be null, {}", evt.getRequest());
+                                continue;
+                            }
                             String sn = getText(rootElementForCharset, "SN");
                             String channelId = getText(rootElementForCharset, "DeviceID");
                             RecordInfo recordInfo = new RecordInfo();
@@ -89,7 +94,7 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
                             recordInfo.setName(getText(rootElementForCharset, "Name"));
                             String sumNumStr = getText(rootElementForCharset, "SumNum");
                             int sumNum = 0;
-                            if (!StringUtils.isEmpty(sumNumStr)) {
+                            if (!ObjectUtils.isEmpty(sumNumStr)) {
                                 sumNum = Integer.parseInt(sumNumStr);
                             }
                             recordInfo.setSumNum(sumNum);
@@ -141,10 +146,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
                                     releaseRequest(take.getDevice().getDeviceId(), sn);
                                 }
                             }
+                        } catch (DocumentException e) {
+                            throw new RuntimeException(e);
+                        } finally {
+                            taskQueueHandlerRun = false;
                         }
-                        taskQueueHandlerRun = false;
-                    }catch (DocumentException e) {
-                        throw new RuntimeException(e);
                     }
                 });
             }
@@ -155,6 +161,8 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
             e.printStackTrace();
         } catch (ParseException e) {
             e.printStackTrace();
+        }finally {
+            taskQueueHandlerRun = false;
         }
     }
 
@@ -165,16 +173,12 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
 
     public void releaseRequest(String deviceId, String sn){
         String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
-        WVPResult<RecordInfo> wvpResult = new WVPResult<>();
-        wvpResult.setCode(0);
-        wvpResult.setMsg("success");
         // 对数据进行排序
         Collections.sort(recordDataCatch.getRecordInfo(deviceId, sn).getRecordList());
-        wvpResult.setData(recordDataCatch.getRecordInfo(deviceId, sn));
 
         RequestMessage msg = new RequestMessage();
         msg.setKey(key);
-        msg.setData(wvpResult);
+        msg.setData(recordDataCatch.getRecordInfo(deviceId, sn));
         deferredResultHolder.invokeAllResult(msg);
         recordDataCatch.remove(deviceId, sn);
     }

+ 8 - 7
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java

@@ -14,6 +14,7 @@ import org.dom4j.Element;
 import org.dom4j.io.SAXReader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import javax.sip.RequestEvent;
@@ -118,12 +119,12 @@ public class XmlUtil {
         // 如果是属性
         for (Object o : element.attributes()) {
             Attribute attr = (Attribute) o;
-            if (!StringUtils.isEmpty(attr.getValue())) {
+            if (!ObjectUtils.isEmpty(attr.getValue())) {
                 json.put("@" + attr.getName(), attr.getValue());
             }
         }
         List<Element> chdEl = element.elements();
-        if (chdEl.isEmpty() && !StringUtils.isEmpty(element.getText())) {// 如果没有子元素,只有一个值
+        if (chdEl.isEmpty() && !ObjectUtils.isEmpty(element.getText())) {// 如果没有子元素,只有一个值
             json.put(element.getName(), element.getText());
         }
 
@@ -154,7 +155,7 @@ public class XmlUtil {
             } else { // 子元素没有子元素
                 for (Object o : element.attributes()) {
                     Attribute attr = (Attribute) o;
-                    if (!StringUtils.isEmpty(attr.getValue())) {
+                    if (!ObjectUtils.isEmpty(attr.getValue())) {
                         json.put("@" + attr.getName(), attr.getValue());
                     }
                 }
@@ -197,7 +198,7 @@ public class XmlUtil {
             return null;
         }
         String channelId = channdelIdElement.getTextTrim();
-        if (StringUtils.isEmpty(channelId)) {
+        if (ObjectUtils.isEmpty(channelId)) {
             logger.warn("解析Catalog消息时发现缺少 DeviceID");
             return null;
         }
@@ -316,7 +317,7 @@ public class XmlUtil {
         // 识别自带的目录标识
         String parental = XmlUtil.getText(itemDevice, "Parental");
         // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
-        if (!StringUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
+        if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
             deviceChannel.setParental(0);
         }else {
             deviceChannel.setParental(1);
@@ -332,14 +333,14 @@ public class XmlUtil {
         deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
 
         String safetyWay = XmlUtil.getText(itemDevice, "SafetyWay");
-        if (StringUtils.isEmpty(safetyWay)) {
+        if (ObjectUtils.isEmpty(safetyWay)) {
             deviceChannel.setSafetyWay(0);
         } else {
             deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
         }
 
         String registerWay = XmlUtil.getText(itemDevice, "RegisterWay");
-        if (StringUtils.isEmpty(registerWay)) {
+        if (ObjectUtils.isEmpty(registerWay)) {
             deviceChannel.setRegisterWay(1);
         } else {
             deviceChannel.setRegisterWay(Integer.parseInt(registerWay));

+ 2 - 1
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java

@@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.io.File;
@@ -49,7 +50,7 @@ public class AssistRESTfulUtils {
         if (mediaServerItem == null) {
             return null;
         }
-        if (StringUtils.isEmpty(mediaServerItem.getRecordAssistPort())) {
+        if (ObjectUtils.isEmpty(mediaServerItem.getRecordAssistPort())) {
             logger.warn("未启用Assist服务");
             return null;
         }

+ 2 - 1
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -633,7 +634,7 @@ public class ZLMHttpHookListener {
 
 	private Map<String, String> urlParamToMap(String params) {
 		HashMap<String, String> map = new HashMap<>();
-		if (StringUtils.isEmpty(params)) {
+		if (ObjectUtils.isEmpty(params)) {
 			return map;
 		}
 		String[] paramsArray = params.split("&");

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java

@@ -9,6 +9,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
@@ -187,7 +188,7 @@ public class ZLMRTPServerFactory {
 
         // 使用RTPServer 功能找一个可用的端口
         String sendRtpPortRange = serverItem.getSendRtpPortRange();
-        if (StringUtils.isEmpty(sendRtpPortRange)) {
+        if (ObjectUtils.isEmpty(sendRtpPortRange)) {
             return null;
         }
         String[] portRangeStrArray = serverItem.getSendRtpPortRange().split(",");
@@ -229,7 +230,7 @@ public class ZLMRTPServerFactory {
     public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
         // 使用RTPServer 功能找一个可用的端口
         String sendRtpPortRange = serverItem.getSendRtpPortRange();
-        if (StringUtils.isEmpty(sendRtpPortRange)) {
+        if (ObjectUtils.isEmpty(sendRtpPortRange)) {
             return null;
         }
         String[] portRangeStrArray = serverItem.getSendRtpPortRange().split(",");

+ 34 - 3
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java

@@ -3,64 +3,94 @@ package com.genersoft.iot.vmp.media.zlm.dto;
 
 import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
+import io.swagger.v3.oas.annotations.media.Schema;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.HashMap;
 
+@Schema(description = "流媒体服务信息")
 public class MediaServerItem{
 
+    @Schema(description = "ID")
     private String id;
 
+    @Schema(description = "IP")
     private String ip;
 
+    @Schema(description = "hook使用的IP(zlm访问WVP使用的IP)")
     private String hookIp;
 
+    @Schema(description = "SDP IP")
     private String sdpIp;
 
+    @Schema(description = "流IP")
     private String streamIp;
 
+    @Schema(description = "HTTP端口")
     private int httpPort;
 
+    @Schema(description = "HTTPS端口")
     private int httpSSlPort;
 
+    @Schema(description = "RTMP端口")
     private int rtmpPort;
 
+    @Schema(description = "RTMPS端口")
     private int rtmpSSlPort;
 
+    @Schema(description = "RTP收流端口(单端口模式有用)")
     private int rtpProxyPort;
 
+    @Schema(description = "RTSP端口")
     private int rtspPort;
 
+    @Schema(description = "RTSPS端口")
     private int rtspSSLPort;
 
+    @Schema(description = "是否开启自动配置ZLM")
     private boolean autoConfig;
 
+    @Schema(description = "ZLM鉴权参数")
     private String secret;
 
+    @Schema(description = "某个流无人观看时,触发hook.on_stream_none_reader事件的最大等待时间,单位毫秒")
     private int streamNoneReaderDelayMS;
 
+    @Schema(description = "keepalive hook触发间隔,单位秒")
     private int hookAliveInterval;
 
+    @Schema(description = "是否使用多端口模式")
     private boolean rtpEnable;
 
+    @Schema(description = "状态")
     private boolean status;
 
+    @Schema(description = "多端口RTP收流端口范围")
     private String rtpPortRange;
 
+    @Schema(description = "RTP发流端口范围")
     private String sendRtpPortRange;
 
+    @Schema(description = "assist服务端口")
     private int recordAssistPort;
 
+    @Schema(description = "创建时间")
     private String createTime;
 
+    @Schema(description = "更新时间")
     private String updateTime;
 
+    @Schema(description = "上次心跳时间")
     private String lastKeepaliveTime;
 
+    @Schema(description = "是否是默认ZLM")
     private boolean defaultServer;
 
+    @Schema(description = "SSRC信息")
     private SsrcConfig ssrcConfig;
 
+    @Schema(description = "当前使用到的端口")
     private int currentPort;
 
 
@@ -68,6 +98,7 @@ public class MediaServerItem{
      * 每一台ZLM都有一套独立的SSRC列表
      * 在ApplicationCheckRunner里对mediaServerSsrcMap进行初始化
      */
+    @Schema(description = "ID")
     private HashMap<String, SsrcConfig> mediaServerSsrcMap;
 
     public MediaServerItem() {
@@ -76,9 +107,9 @@ public class MediaServerItem{
     public MediaServerItem(ZLMServerConfig zlmServerConfig, String sipIp) {
         id = zlmServerConfig.getGeneralMediaServerId();
         ip = zlmServerConfig.getIp();
-        hookIp = StringUtils.isEmpty(zlmServerConfig.getHookIp())? sipIp: zlmServerConfig.getHookIp();
-        sdpIp = StringUtils.isEmpty(zlmServerConfig.getSdpIp())? zlmServerConfig.getIp(): zlmServerConfig.getSdpIp();
-        streamIp = StringUtils.isEmpty(zlmServerConfig.getStreamIp())? zlmServerConfig.getIp(): zlmServerConfig.getStreamIp();
+        hookIp = ObjectUtils.isEmpty(zlmServerConfig.getHookIp())? sipIp: zlmServerConfig.getHookIp();
+        sdpIp = ObjectUtils.isEmpty(zlmServerConfig.getSdpIp())? zlmServerConfig.getIp(): zlmServerConfig.getSdpIp();
+        streamIp = ObjectUtils.isEmpty(zlmServerConfig.getStreamIp())? zlmServerConfig.getIp(): zlmServerConfig.getStreamIp();
         httpPort = zlmServerConfig.getHttpPort();
         httpSSlPort = zlmServerConfig.getHttpSSLport();
         rtmpPort = zlmServerConfig.getRtmpPort();

+ 22 - 1
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java

@@ -1,24 +1,45 @@
 package com.genersoft.iot.vmp.media.zlm.dto;
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import io.swagger.v3.oas.annotations.media.Schema;
 
+/**
+ * @author lin
+ */
+@Schema(description = "拉流代理的信息")
 public class StreamProxyItem extends GbStream {
 
+    @Schema(description = "类型")
     private String type;
+    @Schema(description = "应用名")
     private String app;
+    @Schema(description = "流ID")
     private String stream;
+    @Schema(description = "流媒体服务ID")
     private String mediaServerId;
+    @Schema(description = "拉流地址")
     private String url;
+    @Schema(description = "拉流地址")
     private String src_url;
+    @Schema(description = "目标地址")
     private String dst_url;
+    @Schema(description = "超时时间")
     private int timeout_ms;
+    @Schema(description = "ffmpeg模板KEY")
     private String ffmpeg_cmd_key;
+    @Schema(description = "rtsp拉流时,拉流方式,0:tcp,1:udp,2:组播")
     private String rtp_type;
+    @Schema(description = "是否启用")
     private boolean enable;
+    @Schema(description = "是否启用HLS")
     private boolean enable_hls;
+    @Schema(description = "是否启用MP4")
     private boolean enable_mp4;
-    private boolean enable_remove_none_reader; // 无人观看时删除
+    @Schema(description = "是否 无人观看时删除")
+    private boolean enable_remove_none_reader;
+    @Schema(description = "上级平台国标ID")
     private String platformGbId;
+    @Schema(description = "创建时间")
     private String createTime;
 
     public String getType() {

+ 21 - 1
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java

@@ -2,37 +2,43 @@ package com.genersoft.iot.vmp.media.zlm.dto;
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.utils.DateUtil;
+import io.swagger.v3.oas.annotations.media.Schema;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.util.unit.DataUnit;
 
 import java.util.List;
 
-
+@Schema(description = "推流信息")
 public class StreamPushItem extends GbStream implements Comparable<StreamPushItem>{
 
     /**
      * id
      */
+    @Schema(description = "id")
     private Integer id;
 
     /**
      * 应用名
      */
+    @Schema(description = "应用名")
     private String app;
 
     /**
      * 流id
      */
+    @Schema(description = "流id")
     private String stream;
 
     /**
      * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
      */
+    @Schema(description = "观看总人数")
     private String totalReaderCount;
 
     /**
      * 协议 包括hls/rtsp/rtmp/http-flv/ws-flv
      */
+    @Schema(description = "协议 包括hls/rtsp/rtmp/http-flv/ws-flv")
     private List<MediaSchema> schemas;
 
     /**
@@ -46,71 +52,85 @@ public class StreamPushItem extends GbStream implements Comparable<StreamPushIte
      * mp4_vod=6,
      * device_chn=7
      */
+    @Schema(description = "产生源类型")
     private int originType;
 
     /**
      * 客户端和服务器网络信息,可能为null类型
      */
+    @Schema(description = "客户端和服务器网络信息,可能为null类型")
     private MediaItem.OriginSock originSock;
 
     /**
      * 产生源类型的字符串描述
      */
+    @Schema(description = "产生源类型的字符串描述")
     private String originTypeStr;
 
     /**
      * 产生源的url
      */
+    @Schema(description = "产生源的url")
     private String originUrl;
 
     /**
      * 存活时间,单位秒
      */
+    @Schema(description = "存活时间,单位秒")
     private Long aliveSecond;
 
     /**
      * 音视频轨道
      */
+    @Schema(description = "音视频轨道")
     private List<MediaItem.MediaTrack> tracks;
 
     /**
      * 音视频轨道
      */
+    @Schema(description = "音视频轨道")
     private String vhost;
 
     /**
      * 使用的流媒体ID
      */
+    @Schema(description = "使用的流媒体ID")
     private String mediaServerId;
 
     /**
      * 使用的服务ID
      */
+    @Schema(description = "使用的服务ID")
     private String serverId;
 
     /**
      * 推流时间
      */
+    @Schema(description = "推流时间")
     private String pushTime;
 
     /**
      * 更新时间
      */
+    @Schema(description = "更新时间")
     private String updateTime;
 
     /**
      * 创建时间
      */
+    @Schema(description = "创建时间")
     private String createTime;
 
     /**
      * 是否正在推流
      */
+    @Schema(description = "是否正在推流")
     private boolean pushIng;
 
     /**
      * 是否自己平台的推流
      */
+    @Schema(description = "是否自己平台的推流")
     private boolean self;
 
 

+ 8 - 0
src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java

@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.github.pagehelper.PageInfo;
 
 import java.util.List;
@@ -45,4 +46,11 @@ public interface IGbStreamService {
 
     void sendCatalogMsg(GbStream gbStream, String type);
     void sendCatalogMsgs(List<GbStream> gbStreams, String type);
+
+    /**
+     * 修改gbId或name
+     * @param streamPushItemForUpdate
+     * @return
+     */
+    int updateGbIdOrName(List<StreamPushItem> streamPushItemForUpdate);
 }

+ 2 - 2
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java

@@ -63,7 +63,7 @@ public interface IMediaServerService {
 
     void clearMediaServerForOnline();
 
-    WVPResult<String> add(MediaServerItem mediaSerItem);
+    void add(MediaServerItem mediaSerItem);
 
     int addToDatabase(MediaServerItem mediaSerItem);
 
@@ -71,7 +71,7 @@ public interface IMediaServerService {
 
     void resetOnlineServerItem(MediaServerItem serverItem);
 
-    WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret);
+    MediaServerItem checkMediaServer(String ip, int port, String secret);
 
     boolean checkMediaRecordServer(String ip, int port);
 

+ 4 - 4
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java

@@ -32,13 +32,13 @@ public interface IPlayService {
 
     void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString);
 
-    DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
-    DeferredResult<ResponseEntity<String>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
+    DeferredResult<String> playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
+    DeferredResult<String> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
 
     void zlmServerOffline(String mediaServerId);
 
-    DeferredResult<ResponseEntity<String>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
-    DeferredResult<ResponseEntity<String>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId,  String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
+    DeferredResult<String> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
+    DeferredResult<String> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId,  String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
 
     StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
 

+ 1 - 5
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java

@@ -2,12 +2,8 @@ package com.genersoft.iot.vmp.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
-import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
-import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
 
 public interface IStreamProxyService {
@@ -16,7 +12,7 @@ public interface IStreamProxyService {
      * 保存视频代理
      * @param param
      */
-    WVPResult<StreamInfo> save(StreamProxyItem param);
+    StreamInfo save(StreamProxyItem param);
 
     /**
      * 添加视频代理到zlm

+ 6 - 0
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java

@@ -100,4 +100,10 @@ public interface IStreamPushService {
      * 增加推流
      */
     boolean add(StreamPushItem stream);
+
+    /**
+     * 获取全部的app+Streanm 用于判断推流列表是新增还是修改
+     * @return
+     */
+    List<String> getAllAppAndStream();
 }

+ 8 - 4
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java

@@ -4,14 +4,18 @@ import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 
-import javax.sip.RequestEvent;
+import java.util.EventObject;
 
+
+/**
+ * @author lin
+ */
 public class PlayBackResult<T> {
     private int code;
     private T data;
     private MediaServerItem mediaServerItem;
     private JSONObject response;
-    private SipSubscribe.EventResult event;
+    private SipSubscribe.EventResult<EventObject> event;
 
     public int getCode() {
         return code;
@@ -45,11 +49,11 @@ public class PlayBackResult<T> {
         this.response = response;
     }
 
-    public SipSubscribe.EventResult getEvent() {
+    public SipSubscribe.EventResult<EventObject> getEvent() {
         return event;
     }
 
-    public void setEvent(SipSubscribe.EventResult event) {
+    public void setEvent(SipSubscribe.EventResult<EventObject> event) {
         this.event = event;
     }
 }

+ 5 - 3
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java

@@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.support.incrementer.AbstractIdentityColumnMaxValueIncrementer;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.time.Instant;
@@ -105,6 +106,7 @@ public class DeviceServiceImpl implements IDeviceService {
                 redisCatchStorage.updateDevice(device);
                 commander.deviceInfoQuery(device);
                 sync(device);
+                // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
             }else {
                 deviceMapper.update(device);
                 redisCatchStorage.updateDevice(device);
@@ -281,13 +283,13 @@ public class DeviceServiceImpl implements IDeviceService {
             logger.warn("更新设备时未找到设备信息");
             return;
         }
-        if (!StringUtils.isEmpty(device.getName())) {
+        if (!ObjectUtils.isEmpty(device.getName())) {
             deviceInStore.setName(device.getName());
         }
-        if (!StringUtils.isEmpty(device.getCharset())) {
+        if (!ObjectUtils.isEmpty(device.getCharset())) {
             deviceInStore.setCharset(device.getCharset());
         }
-        if (!StringUtils.isEmpty(device.getMediaServerId())) {
+        if (!ObjectUtils.isEmpty(device.getMediaServerId())) {
             deviceInStore.setMediaServerId(device.getMediaServerId());
         }
 

+ 8 - 3
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java

@@ -1,10 +1,9 @@
 package com.genersoft.iot.vmp.service.impl;
 
-import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
-import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
 import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
@@ -19,6 +18,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.ArrayList;
@@ -169,7 +169,7 @@ public class GbStreamServiceImpl implements IGbStreamService {
     public void sendCatalogMsgs(List<GbStream> gbStreams, String type) {
         if (gbStreams.size() > 0) {
             for (GbStream gs : gbStreams) {
-                if (StringUtils.isEmpty(gs.getGbId())){
+                if (ObjectUtils.isEmpty(gs.getGbId())){
                     continue;
                 }
                 List<ParentPlatform> parentPlatforms = platformGbStreamMapper.selectByAppAndStream(gs.getApp(), gs.getStream());
@@ -183,4 +183,9 @@ public class GbStreamServiceImpl implements IGbStreamService {
             }
         }
     }
+
+    @Override
+    public int updateGbIdOrName(List<StreamPushItem> streamPushItemForUpdate) {
+        return gbStreamMapper.updateGbIdOrName(streamPushItemForUpdate);
+    }
 }

+ 45 - 76
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java

@@ -11,6 +11,8 @@ import java.util.Set;
 import com.genersoft.iot.vmp.media.zlm.ZLMRunner;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +21,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import com.alibaba.fastjson.JSON;
@@ -58,9 +61,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Autowired
     private SipConfig sipConfig;
 
-    @Autowired
-    private ZLMRunner zlmRunner;
-
     @Value("${server.ssl.enabled:false}")
     private boolean sslEnabled;
 
@@ -88,8 +88,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Autowired
     private ZLMRTPServerFactory zlmrtpServerFactory;
 
-    @Autowired
-    private RedisUtil redisUtil;
 
     @Autowired
     private IVideoManagerStorage storager;
@@ -107,19 +105,19 @@ public class MediaServerServiceImpl implements IMediaServerService {
     public void updateVmServer(List<MediaServerItem>  mediaServerItemList) {
         logger.info("[zlm] 缓存初始化 ");
         for (MediaServerItem mediaServerItem : mediaServerItemList) {
-            if (StringUtils.isEmpty(mediaServerItem.getId())) {
+            if (ObjectUtils.isEmpty(mediaServerItem.getId())) {
                 continue;
             }
             // 更新
             if (mediaServerItem.getSsrcConfig() == null) {
                 SsrcConfig ssrcConfig = new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain());
                 mediaServerItem.setSsrcConfig(ssrcConfig);
-                redisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem);
+                RedisUtil.set(VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(), mediaServerItem);
             }
             // 查询redis是否存在此mediaServer
             String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
-            if (!redisUtil.hasKey(key)) {
-                redisUtil.set(key, mediaServerItem);
+            if (!RedisUtil.hasKey(key)) {
+                RedisUtil.set(key, mediaServerItem);
             }
 
         }
@@ -161,7 +159,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
             if (mediaServerItem.isRtpEnable()) {
                 rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
             }
-            redisUtil.set(key, mediaServerItem);
+            RedisUtil.set(key, mediaServerItem);
             return new SSRCInfo(rtpServerPort, ssrc, streamId);
         }
     }
@@ -194,7 +192,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
         ssrcConfig.releaseSsrc(ssrc);
         mediaServerItem.setSsrcConfig(ssrcConfig);
         String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
-        redisUtil.set(key, mediaServerItem);
+        RedisUtil.set(key, mediaServerItem);
     }
 
     /**
@@ -203,7 +201,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Override
     public void clearRTPServer(MediaServerItem mediaServerItem) {
         mediaServerItem.setSsrcConfig(new SsrcConfig(mediaServerItem.getId(), null, sipConfig.getDomain()));
-        redisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0);
+        RedisUtil.zAdd(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), mediaServerItem.getId(), 0);
 
     }
 
@@ -225,19 +223,19 @@ public class MediaServerServiceImpl implements IMediaServerService {
             );
         }
         String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId();
-        redisUtil.set(key, mediaServerItemInDataBase);
+        RedisUtil.set(key, mediaServerItemInDataBase);
     }
 
     @Override
     public List<MediaServerItem> getAll() {
         List<MediaServerItem> result = new ArrayList<>();
-        List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetting.getServerId() + "_" ));
+        List<Object> mediaServerKeys = RedisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetting.getServerId() + "_" ));
         String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
         for (Object mediaServerKey : mediaServerKeys) {
             String key = (String) mediaServerKey;
-            MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key);
+            MediaServerItem mediaServerItem = (MediaServerItem) RedisUtil.get(key);
             // 检查状态
-            Double aDouble = redisUtil.zScore(onlineKey, mediaServerItem.getId());
+            Double aDouble = RedisUtil.zScore(onlineKey, mediaServerItem.getId());
             if (aDouble != null) {
                 mediaServerItem.setStatus(true);
             }
@@ -263,13 +261,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Override
     public List<MediaServerItem> getAllOnline() {
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
-        Set<String> mediaServerIdSet = redisUtil.zRevRange(key, 0, -1);
+        Set<String> mediaServerIdSet = RedisUtil.zRevRange(key, 0, -1);
 
         List<MediaServerItem> result = new ArrayList<>();
         if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) {
             for (String mediaServerId : mediaServerIdSet) {
                 String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
-                result.add((MediaServerItem) redisUtil.get(serverKey));
+                result.add((MediaServerItem) RedisUtil.get(serverKey));
             }
         }
         Collections.reverse(result);
@@ -287,7 +285,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
             return null;
         }
         String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
-        return (MediaServerItem)redisUtil.get(key);
+        return (MediaServerItem)RedisUtil.get(key);
     }
 
     @Override
@@ -299,12 +297,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
     @Override
     public void clearMediaServerForOnline() {
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
-        redisUtil.del(key);
+        RedisUtil.del(key);
     }
 
     @Override
-    public WVPResult<String> add(MediaServerItem mediaServerItem) {
-        WVPResult<String> result = new WVPResult<>();
+    public void add(MediaServerItem mediaServerItem) {
         mediaServerItem.setCreateTime(DateUtil.getNow());
         mediaServerItem.setUpdateTime(DateUtil.getNow());
         mediaServerItem.setHookAliveInterval(120);
@@ -314,26 +311,19 @@ public class MediaServerServiceImpl implements IMediaServerService {
             if (data != null && data.size() > 0) {
                 ZLMServerConfig zlmServerConfig= JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
                 if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) {
-                    result.setCode(-1);
-                    result.setMsg("保存失败,媒体服务ID [ " + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
-                    return result;
+                    throw new ControllerException(ErrorCode.ERROR100.getCode(),"保存失败,媒体服务ID [ " + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
                 }
                 mediaServerItem.setId(zlmServerConfig.getGeneralMediaServerId());
                 zlmServerConfig.setIp(mediaServerItem.getIp());
                 mediaServerMapper.add(mediaServerItem);
                 zlmServerOnline(zlmServerConfig);
-                result.setCode(0);
-                result.setMsg("success");
             }else {
-                result.setCode(-1);
-                result.setMsg("连接失败");
+                throw new ControllerException(ErrorCode.ERROR100.getCode(),"连接失败");
             }
 
         }else {
-            result.setCode(-1);
-            result.setMsg("连接失败");
+            throw new ControllerException(ErrorCode.ERROR100.getCode(),"连接失败");
         }
-       return result;
     }
 
     @Override
@@ -401,20 +391,20 @@ public class MediaServerServiceImpl implements IMediaServerService {
         }
         serverItem.setStatus(true);
 
-        if (StringUtils.isEmpty(serverItem.getId())) {
+        if (ObjectUtils.isEmpty(serverItem.getId())) {
             logger.warn("[未注册的zlm] serverItem缺少ID, 无法接入:{}:{}", zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
             return;
         }
         mediaServerMapper.update(serverItem);
         String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId();
-        if (redisUtil.get(key) == null) {
+        if (RedisUtil.get(key) == null) {
             SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain());
             serverItem.setSsrcConfig(ssrcConfig);
         }else {
-            MediaServerItem mediaServerItemInRedis = (MediaServerItem)redisUtil.get(key);
+            MediaServerItem mediaServerItemInRedis = (MediaServerItem)RedisUtil.get(key);
             serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig());
         }
-        redisUtil.set(key, serverItem);
+        RedisUtil.set(key, serverItem);
         resetOnlineServerItem(serverItem);
         if (serverItem.isAutoConfig()) {
             setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
@@ -435,15 +425,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
         // 更新缓存
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
         // 使用zset的分数作为当前并发量, 默认值设置为0
-        if (redisUtil.zScore(key, serverItem.getId()) == null) {  // 不存在则设置默认值 已存在则重置
-            redisUtil.zAdd(key, serverItem.getId(), 0L);
+        if (RedisUtil.zScore(key, serverItem.getId()) == null) {  // 不存在则设置默认值 已存在则重置
+            RedisUtil.zAdd(key, serverItem.getId(), 0L);
             // 查询服务流数量
             zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{
                 Integer code = mediaList.getInteger("code");
                 if (code == 0) {
                     JSONArray data = mediaList.getJSONArray("data");
                     if (data != null) {
-                        redisUtil.zAdd(key, serverItem.getId(), data.size());
+                        RedisUtil.zAdd(key, serverItem.getId(), data.size());
                     }
                 }
             }));
@@ -460,14 +450,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
             return;
         }
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
-        redisUtil.zIncrScore(key, mediaServerId, 1);
+        RedisUtil.zIncrScore(key, mediaServerId, 1);
 
     }
 
     @Override
     public void removeCount(String mediaServerId) {
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
-        redisUtil.zIncrScore(key, mediaServerId, - 1);
+        RedisUtil.zIncrScore(key, mediaServerId, - 1);
     }
 
     /**
@@ -478,15 +468,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
     public MediaServerItem getMediaServerForMinimumLoad() {
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
 
-        if (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
-            if (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
+        if (RedisUtil.zSize(key)  == null || RedisUtil.zSize(key) == 0) {
+            if (RedisUtil.zSize(key)  == null || RedisUtil.zSize(key) == 0) {
                 logger.info("获取负载最低的节点时无在线节点");
                 return null;
             }
         }
 
         // 获取分数最低的,及并发最低的
-        Set<Object> objects = redisUtil.ZRange(key, 0, -1);
+        Set<Object> objects = RedisUtil.ZRange(key, 0, -1);
         ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects);
 
         String mediaServerId = (String)mediaServerObjectS.get(0);
@@ -536,7 +526,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
         // 最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track, 设置此选项优化那些音频错误的不规范流,
         // 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项
 //        param.put("general.wait_track_ready_ms", "3000" );
-        if (mediaServerItem.isRtpEnable() && !StringUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
+        if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
             param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
         }
 
@@ -563,12 +553,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
 
 
     @Override
-    public WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret) {
-        WVPResult<MediaServerItem> result = new WVPResult<>();
+    public MediaServerItem checkMediaServer(String ip, int port, String secret) {
         if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) {
-            result.setCode(-1);
-            result.setMsg("此连接已存在");
-            return result;
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "此连接已存在");
         }
         MediaServerItem mediaServerItem = new MediaServerItem();
         mediaServerItem.setIp(ip);
@@ -576,21 +563,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
         mediaServerItem.setSecret(secret);
         JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
         if (responseJSON == null) {
-            result.setCode(-1);
-            result.setMsg("连接失败");
-            return result;
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接失败");
         }
         JSONArray data = responseJSON.getJSONArray("data");
         ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
         if (zlmServerConfig == null) {
-            result.setCode(-1);
-            result.setMsg("读取配置失败");
-            return result;
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "读取配置失败");
         }
         if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) {
-            result.setCode(-1);
-            result.setMsg("媒体服务ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
-            return result;
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "媒体服务ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
         }
         mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort());
         mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort());
@@ -602,10 +583,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
         mediaServerItem.setHookIp(sipConfig.getIp());
         mediaServerItem.setSdpIp(ip);
         mediaServerItem.setStreamNoneReaderDelayMS(zlmServerConfig.getGeneralStreamNoneReaderDelayMS());
-        result.setCode(0);
-        result.setMsg("成功");
-        result.setData(mediaServerItem);
-        return result;
+        return mediaServerItem;
     }
 
     @Override
@@ -629,9 +607,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
 
     @Override
     public void delete(String id) {
-        redisUtil.zRemove(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), id);
+        RedisUtil.zRemove(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), id);
         String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + id;
-        redisUtil.del(key);
+        RedisUtil.del(key);
     }
     @Override
     public void deleteDb(String id){
@@ -650,7 +628,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
             }
             // zlm连接重试
             logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息,尝试重连zlm");
-            reloadZlm();
+//            reloadZlm();
             mediaServerItem = getOne(mediaServerId);
             if (mediaServerItem == null) {
                 // zlm连接重试
@@ -660,7 +638,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
         }
         String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
         int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2;
-        redisUtil.set(key, data, hookAliveInterval);
+        RedisUtil.set(key, data, hookAliveInterval);
     }
 
     private MediaServerItem getOneFromDatabase(String mediaServerId) {
@@ -682,13 +660,4 @@ public class MediaServerServiceImpl implements IMediaServerService {
             }
         }
     }
-
-    public void reloadZlm(){
-        try {
-            zlmRunner.run();
-            Thread.sleep(500);//延迟0.5秒缓冲时间
-        } catch (Exception e) {
-            logger.warn("尝试重连zlm失败!",e);
-        }
-    }
 }

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java

@@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.service.IMediaService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 @Service
@@ -94,7 +95,7 @@ public class MediaServiceImpl implements IMediaService {
         }
         streamInfoResult.setIp(addr);
         streamInfoResult.setMediaServerId(mediaInfo.getId());
-        String callIdParam = StringUtils.isEmpty(callId)?"":"?callId=" + callId;
+        String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId;
         streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s%s", addr, mediaInfo.getRtmpPort(), app,  stream, callIdParam));
         if (mediaInfo.getRtmpSSlPort() != 0) {
             streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s%s", addr, mediaInfo.getRtmpSSlPort(), app,  stream, callIdParam));
@@ -121,7 +122,7 @@ public class MediaServiceImpl implements IMediaService {
             streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
             streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
             streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
-            streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=%s%s", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app,  stream, isPlay?"play":"push", StringUtils.isEmpty(callId)?"":"&callId=" + callId));
+            streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=%s%s", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app,  stream, isPlay?"play":"push", ObjectUtils.isEmpty(callId)?"":"&callId=" + callId));
         }
 
         streamInfoResult.setTracks(tracks);

+ 51 - 64
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java

@@ -7,12 +7,12 @@ import java.util.*;
 import javax.sip.ResponseEvent;
 
 import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.web.context.request.async.DeferredResult;
@@ -34,7 +34,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
-import com.genersoft.iot.vmp.media.zlm.dto.HookType;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -141,6 +140,9 @@ public class PlayServiceImpl implements IPlayService {
     public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId,
                            ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
                            Runnable timeoutCallback) {
+        if (mediaServerItem == null) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
+        }
         PlayResult playResult = new PlayResult();
         RequestMessage msg = new RequestMessage();
         String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
@@ -148,18 +150,11 @@ public class PlayServiceImpl implements IPlayService {
         String uuid = UUID.randomUUID().toString();
         msg.setId(uuid);
         playResult.setUuid(uuid);
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
+        DeferredResult<WVPResult<String>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
         playResult.setResult(result);
         // 录像查询以channelId作为deviceId查询
         resultHolder.put(key, uuid, result);
-        if (mediaServerItem == null) {
-            WVPResult wvpResult = new WVPResult();
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("未找到可用的zlm");
-            msg.setData(wvpResult);
-            resultHolder.invokeResult(msg);
-            return playResult;
-        }
+
         Device device = redisCatchStorage.getDevice(deviceId);
         StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
         playResult.setDevice(device);
@@ -170,17 +165,14 @@ public class PlayServiceImpl implements IPlayService {
                 // TODO 应该在上流时调用更好,结束也可能是错误结束
                 String path =  "snap";
                 String fileName =  deviceId + "_" + channelId + ".jpg";
-                ResponseEntity responseEntity =  (ResponseEntity)result.getResult();
-                if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
-                    WVPResult wvpResult = (WVPResult)responseEntity.getBody();
-                    if (Objects.requireNonNull(wvpResult).getCode() == 0) {
-                        StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
-                        MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
-                        String streamUrl = streamInfoForSuccess.getFmp4();
-                        // 请求截图
-                        logger.info("[请求截图]: " + fileName);
-                        zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
-                    }
+                WVPResult wvpResult =  (WVPResult)result.getResult();
+                if (Objects.requireNonNull(wvpResult).getCode() == 0) {
+                    StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData();
+                    MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
+                    String streamUrl = streamInfoForSuccess.getFmp4();
+                    // 请求截图
+                    logger.info("[请求截图]: " + fileName);
+                    zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
                 }
             });
         });
@@ -188,7 +180,7 @@ public class PlayServiceImpl implements IPlayService {
             String streamId = streamInfo.getStream();
             if (streamId == null) {
                 WVPResult wvpResult = new WVPResult();
-                wvpResult.setCode(-1);
+                wvpResult.setCode(ErrorCode.ERROR100.getCode());
                 wvpResult.setMsg("点播失败, redis缓存streamId等于null");
                 msg.setData(wvpResult);
                 resultHolder.invokeAllResult(msg);
@@ -202,8 +194,8 @@ public class PlayServiceImpl implements IPlayService {
                 if (rtpInfo.getBoolean("exist")) {
 
                     WVPResult wvpResult = new WVPResult();
-                    wvpResult.setCode(0);
-                    wvpResult.setMsg("success");
+                    wvpResult.setCode(ErrorCode.SUCCESS.getCode());
+                    wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
                     wvpResult.setData(streamInfo);
                     msg.setData(wvpResult);
 
@@ -236,7 +228,7 @@ public class PlayServiceImpl implements IPlayService {
             }, event -> {
                 // sip error错误
                 WVPResult wvpResult = new WVPResult();
-                wvpResult.setCode(-1);
+                wvpResult.setCode(ErrorCode.ERROR100.getCode());
                 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
                 msg.setData(wvpResult);
                 resultHolder.invokeAllResult(msg);
@@ -246,7 +238,7 @@ public class PlayServiceImpl implements IPlayService {
             }, (code, msgStr)->{
                 // invite点播超时
                 WVPResult wvpResult = new WVPResult();
-                wvpResult.setCode(-1);
+                wvpResult.setCode(ErrorCode.ERROR100.getCode());
                 if (code == 0) {
                     wvpResult.setMsg("点播超时,请稍候重试");
                 }else if (code == 1) {
@@ -386,15 +378,15 @@ public class PlayServiceImpl implements IPlayService {
             redisCatchStorage.startPlay(streamInfo);
 
             WVPResult wvpResult = new WVPResult();
-            wvpResult.setCode(0);
-            wvpResult.setMsg("success");
+            wvpResult.setCode(ErrorCode.SUCCESS.getCode());
+            wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
             wvpResult.setData(streamInfo);
             msg.setData(wvpResult);
 
             resultHolder.invokeAllResult(msg);
         } else {
             logger.warn("设备预览API调用失败!");
-            msg.setData("设备预览API调用失败!");
+            msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "设备预览API调用失败!"));
             resultHolder.invokeAllResult(msg);
         }
     }
@@ -418,7 +410,7 @@ public class PlayServiceImpl implements IPlayService {
     }
 
     @Override
-    public DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime,
+    public DeferredResult<String> playBack(String deviceId, String channelId, String startTime,
                                                            String endTime,InviteStreamCallback inviteStreamCallback,
                                                            PlayBackCallback callback) {
         Device device = storager.queryVideoDevice(deviceId);
@@ -432,7 +424,7 @@ public class PlayServiceImpl implements IPlayService {
     }
 
     @Override
-    public DeferredResult<ResponseEntity<String>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
+    public DeferredResult<String> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
                                                            String deviceId, String channelId, String startTime,
                                                            String endTime, InviteStreamCallback infoCallBack,
                                                            PlayBackCallback playBackCallback) {
@@ -441,24 +433,21 @@ public class PlayServiceImpl implements IPlayService {
         }
         String uuid = UUID.randomUUID().toString();
         String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(30000L);
         Device device = storager.queryVideoDevice(deviceId);
         if (device == null) {
-            result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
-            return result;
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在");
         }
-
+        DeferredResult<String> result = new DeferredResult<>(30000L);
         resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result);
-        RequestMessage msg = new RequestMessage();
-        msg.setId(uuid);
-        msg.setKey(key);
+        RequestMessage requestMessage = new RequestMessage();
+        requestMessage.setId(uuid);
+        requestMessage.setKey(key);
         PlayBackResult<RequestMessage> playBackResult = new PlayBackResult<>();
-        String  playBackTimeOutTaskKey = UUID.randomUUID().toString();
+        String playBackTimeOutTaskKey = UUID.randomUUID().toString();
         dynamicTask.startDelay(playBackTimeOutTaskKey, ()->{
             logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
             playBackResult.setCode(-1);
-            playBackResult.setData(msg);
-            playBackCallback.call(playBackResult);
+            playBackResult.setData(requestMessage);
             SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
             // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
             if (dialog != null) {
@@ -481,24 +470,23 @@ public class PlayServiceImpl implements IPlayService {
                     StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
                     if (streamInfo == null) {
                         logger.warn("设备回放API调用失败!");
-                        msg.setData("设备回放API调用失败!");
                         playBackResult.setCode(-1);
-                        playBackResult.setData(msg);
                         playBackCallback.call(playBackResult);
                         return;
                     }
                     redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());
-                    msg.setData(JSON.toJSONString(streamInfo));
+                    WVPResult<StreamInfo> success = WVPResult.success(streamInfo);
+                    requestMessage.setData(success);
                     playBackResult.setCode(0);
-                    playBackResult.setData(msg);
+                    playBackResult.setData(requestMessage);
                     playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
                     playBackResult.setResponse(inviteStreamInfo.getResponse());
                     playBackCallback.call(playBackResult);
                 }, event -> {
                     dynamicTask.stop(playBackTimeOutTaskKey);
-                    msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
+                    requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)));
                     playBackResult.setCode(-1);
-                    playBackResult.setData(msg);
+                    playBackResult.setData(requestMessage);
                     playBackResult.setEvent(event);
                     playBackCallback.call(playBackResult);
                     streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
@@ -507,7 +495,7 @@ public class PlayServiceImpl implements IPlayService {
     }
 
     @Override
-    public DeferredResult<ResponseEntity<String>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
+    public DeferredResult<String> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
         Device device = storager.queryVideoDevice(deviceId);
         if (device == null) {
             return null;
@@ -519,32 +507,31 @@ public class PlayServiceImpl implements IPlayService {
     }
 
     @Override
-    public DeferredResult<ResponseEntity<String>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
+    public DeferredResult<String> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
         if (mediaServerItem == null || ssrcInfo == null) {
             return null;
         }
         String uuid = UUID.randomUUID().toString();
         String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(30000L);
+        DeferredResult<String> result = new DeferredResult<>(30000L);
         Device device = storager.queryVideoDevice(deviceId);
         if (device == null) {
-            result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
-            return result;
+            throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在");
         }
 
         resultHolder.put(key, uuid, result);
-        RequestMessage msg = new RequestMessage();
-        msg.setId(uuid);
-        msg.setKey(key);
+        RequestMessage requestMessage = new RequestMessage();
+        requestMessage.setId(uuid);
+        requestMessage.setKey(key);
         WVPResult<StreamInfo> wvpResult = new WVPResult<>();
-        msg.setData(wvpResult);
+        requestMessage.setData(wvpResult);
         PlayBackResult<RequestMessage> downloadResult = new PlayBackResult<>();
-        downloadResult.setData(msg);
+        downloadResult.setData(requestMessage);
 
         String downLoadTimeOutTaskKey = UUID.randomUUID().toString();
         dynamicTask.startDelay(downLoadTimeOutTaskKey, ()->{
             logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId));
-            wvpResult.setCode(-1);
+            wvpResult.setCode(ErrorCode.ERROR100.getCode());
             wvpResult.setMsg("录像下载请求超时");
             downloadResult.setCode(-1);
             hookCallBack.call(downloadResult);
@@ -578,8 +565,8 @@ public class PlayServiceImpl implements IPlayService {
                         return ;
                     }
                     redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
-                    wvpResult.setCode(0);
-                    wvpResult.setMsg("success");
+                    wvpResult.setCode(ErrorCode.SUCCESS.getCode());
+                    wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
                     wvpResult.setData(streamInfo);
                     downloadResult.setCode(0);
                     downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
@@ -588,7 +575,7 @@ public class PlayServiceImpl implements IPlayService {
                 }, event -> {
                     dynamicTask.stop(downLoadTimeOutTaskKey);
                     downloadResult.setCode(-1);
-                    wvpResult.setCode(-1);
+                    wvpResult.setCode(ErrorCode.ERROR100.getCode());
                     wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));
                     downloadResult.setEvent(event);
                     hookCallBack.call(downloadResult);
@@ -649,7 +636,7 @@ public class PlayServiceImpl implements IPlayService {
             resultHolder.invokeResult(msg);
         } else {
             logger.warn("设备预览API调用失败!");
-            msg.setData("设备预览API调用失败!");
+            msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "设备预览API调用失败!"));
             resultHolder.invokeResult(msg);
         }
     }

+ 6 - 8
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java

@@ -66,8 +66,6 @@ public class RedisGbPlayMsgListener implements MessageListener {
     @Autowired
     private UserSetting userSetting;
 
-    @Autowired
-    private RedisUtil redis;
 
     @Autowired
     private ZLMMediaListManager zlmMediaListManager;
@@ -227,7 +225,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
         WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId,
                 WvpRedisMsgCmd.REQUEST_PUSH_STREAM, serial, result);
         JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
-        redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
+        RedisUtil.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
     }
 
     /**
@@ -246,7 +244,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
                     WvpRedisMsgCmd.GET_SEND_ITEM, serial, result);
 
             JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
-            redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
+            RedisUtil.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
             return;
         }
         // 确定流是否在线
@@ -269,7 +267,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
                         userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result
                 );
                 JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
-                redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
+                RedisUtil.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
             }, userSetting.getPlatformPlayTimeout());
 
             // 添加订阅
@@ -308,7 +306,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
                 userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result
         );
         JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
-        redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
+        RedisUtil.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
     }
 
     /**
@@ -345,7 +343,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
             wvpResult.setMsg("timeout");
             errorCallback.handler(wvpResult);
         }, userSetting.getPlatformPlayTimeout());
-        redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
+        RedisUtil.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
     }
 
     /**
@@ -370,6 +368,6 @@ public class RedisGbPlayMsgListener implements MessageListener {
             callbacksForStartSendRtpStream.remove(key);
             callbacksForError.remove(key);
         });
-        redis.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
+        RedisUtil.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
     }
 }

+ 83 - 0
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamListMsgListener.java

@@ -0,0 +1,83 @@
+package com.genersoft.iot.vmp.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
+import com.genersoft.iot.vmp.service.IGbStreamService;
+import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.IStreamPushService;
+import com.genersoft.iot.vmp.utils.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * @Auther: JiangFeng
+ * @Date: 2022/8/16 11:32
+ * @Description: 接收redis发送的推流设备列表更新通知
+ */
+@Component
+public class RedisPushStreamListMsgListener implements MessageListener {
+
+    private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamListMsgListener.class);
+    @Resource
+    private IMediaServerService mediaServerService;
+
+    @Resource
+    private IStreamPushService streamPushService;
+    @Resource
+    private IGbStreamService gbStreamService;
+
+    @Override
+    public void onMessage(Message message, byte[] bytes) {
+        //
+        logger.warn("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody()));
+        List<StreamPushItem> streamPushItems = JSON.parseArray(new String(message.getBody()), StreamPushItem.class);
+        //查询全部的app+stream 用于判断是添加还是修改
+        List<String> allAppAndStream = streamPushService.getAllAppAndStream();
+
+        /**
+         * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表
+         */
+        List<StreamPushItem> streamPushItemForSave = new ArrayList<>();
+        List<StreamPushItem> streamPushItemForUpdate = new ArrayList<>();
+        for (StreamPushItem streamPushItem : streamPushItems) {
+            String app = streamPushItem.getApp();
+            String stream = streamPushItem.getStream();
+            boolean contains = allAppAndStream.contains(app + stream);
+            //不存在就添加
+            if (!contains) {
+                streamPushItem.setStatus(false);
+                streamPushItem.setStreamType("push");
+                streamPushItem.setCreateTime(DateUtil.getNow());
+                streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId());
+                streamPushItem.setOriginType(2);
+                streamPushItem.setOriginTypeStr("rtsp_push");
+                streamPushItem.setTotalReaderCount("0");
+                streamPushItemForSave.add(streamPushItem);
+            } else {
+                //存在就只修改 name和gbId
+                streamPushItemForUpdate.add(streamPushItem);
+            }
+        }
+        if (streamPushItemForSave.size() > 0) {
+
+            logger.info("添加{}条",streamPushItemForSave.size());
+            logger.info(JSONObject.toJSONString(streamPushItemForSave));
+            streamPushService.batchAdd(streamPushItemForSave);
+
+        }
+        if(streamPushItemForUpdate.size()>0){
+            logger.info("修改{}条",streamPushItemForUpdate.size());
+            logger.info(JSONObject.toJSONString(streamPushItemForUpdate));
+            gbStreamService.updateGbIdOrName(streamPushItemForUpdate);
+        }
+
+    }
+}

+ 0 - 9
src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java

@@ -26,15 +26,6 @@ public class RedisStreamMsgListener implements MessageListener {
 
     private final static Logger logger = LoggerFactory.getLogger(RedisStreamMsgListener.class);
 
-    @Autowired
-    private ISIPCommander commander;
-
-    @Autowired
-    private ISIPCommanderForPlatform commanderForPlatform;
-
-    @Autowired
-    private IVideoManagerStorage storage;
-
     @Autowired
     private UserSetting userSetting;
 

+ 39 - 36
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.TreeType;
@@ -24,6 +25,7 @@ import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.utils.DateUtil;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
 import org.slf4j.Logger;
@@ -33,6 +35,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.net.InetAddress;
@@ -93,10 +96,8 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
 
 
     @Override
-    public WVPResult<StreamInfo> save(StreamProxyItem param) {
+    public StreamInfo save(StreamProxyItem param) {
         MediaServerItem mediaInfo;
-        WVPResult<StreamInfo> wvpResult = new WVPResult<>();
-        wvpResult.setCode(0);
         if (param.getMediaServerId() == null || "auto".equals(param.getMediaServerId())){
             mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
         }else {
@@ -104,14 +105,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
         }
         if (mediaInfo == null) {
             logger.warn("保存代理未找到在线的ZLM...");
-            wvpResult.setMsg("保存失败");
-            return wvpResult;
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "保存代理未找到在线的ZLM");
         }
-
         String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
                 param.getStream() );
         param.setDst_url(dstUrl);
-        StringBuffer result = new StringBuffer();
+        StringBuffer resultMsg = new StringBuffer();
         boolean streamLive = false;
         param.setMediaServerId(mediaInfo.getId());
         boolean saveResult;
@@ -121,43 +120,47 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
         }else { // 新增
             saveResult = addStreamProxy(param);
         }
-        if (saveResult) {
-            result.append("保存成功");
-            if (param.isEnable()) {
-                JSONObject jsonObject = addStreamProxyToZlm(param);
-                if (jsonObject == null || jsonObject.getInteger("code") != 0) {
-                    streamLive = false;
-                    result.append(", 但是启用失败,请检查流地址是否可用");
-                    param.setEnable(false);
-                    // 直接移除
-                    if (param.isEnable_remove_none_reader()) {
-                        del(param.getApp(), param.getStream());
-                    }else {
-                        updateStreamProxy(param);
-                    }
-
+        if (!saveResult) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(),"保存失败");
+        }
+        StreamInfo resultForStreamInfo = null;
+        resultMsg.append("保存成功");
+        if (param.isEnable()) {
+            JSONObject jsonObject = addStreamProxyToZlm(param);
+            if (jsonObject == null || jsonObject.getInteger("code") != 0) {
+                streamLive = false;
+                resultMsg.append(", 但是启用失败,请检查流地址是否可用");
+                param.setEnable(false);
+                // 直接移除
+                if (param.isEnable_remove_none_reader()) {
+                    del(param.getApp(), param.getStream());
                 }else {
-                    streamLive = true;
-                    StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
-                            mediaInfo, param.getApp(), param.getStream(), null, null);
-                    wvpResult.setData(streamInfo);
-
+                    updateStreamProxy(param);
                 }
+
+
+            }else {
+                streamLive = true;
+                resultForStreamInfo = mediaService.getStreamInfoByAppAndStream(
+                        mediaInfo, param.getApp(), param.getStream(), null, null);
+
             }
-        }else {
-            result.append("保存失败");
         }
-        if ( !StringUtils.isEmpty(param.getPlatformGbId()) && streamLive) {
+        if ( !ObjectUtils.isEmpty(param.getPlatformGbId()) && streamLive) {
             List<GbStream> gbStreams = new ArrayList<>();
             gbStreams.add(param);
             if (gbStreamService.addPlatformInfo(gbStreams, param.getPlatformGbId(), param.getCatalogId())){
-                result.append(",  关联国标平台[ " + param.getPlatformGbId() + " ]成功");
+                return resultForStreamInfo;
             }else {
-                result.append(",  关联国标平台[ " + param.getPlatformGbId() + " ]失败");
+                resultMsg.append(",  关联国标平台[ " + param.getPlatformGbId() + " ]失败");
+                throw new ControllerException(ErrorCode.ERROR100.getCode(), resultMsg.toString());
+            }
+        }else {
+            if (!streamLive) {
+                throw new ControllerException(ErrorCode.ERROR100.getCode(), resultMsg.toString());
             }
         }
-        wvpResult.setMsg(result.toString());
-        return wvpResult;
+        return resultForStreamInfo;
     }
 
     /**
@@ -174,7 +177,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
         streamProxyItem.setCreateTime(now);
         try {
             if (streamProxyMapper.add(streamProxyItem) > 0) {
-                if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
+                if (!ObjectUtils.isEmpty(streamProxyItem.getGbId())) {
                     if (gbStreamMapper.add(streamProxyItem) < 0) {
                         //事务回滚
                         dataSourceTransactionManager.rollback(transactionStatus);
@@ -209,7 +212,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
         streamProxyItem.setStreamType("proxy");
         try {
             if (streamProxyMapper.update(streamProxyItem) > 0) {
-                if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
+                if (!ObjectUtils.isEmpty(streamProxyItem.getGbId())) {
                     if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
                         //事务回滚
                         dataSourceTransactionManager.rollback(transactionStatus);

+ 9 - 2
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java

@@ -27,6 +27,7 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
@@ -208,7 +209,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
         Map<String, MediaItem> streamInfoPushItemMap = new HashMap<>();
         if (pushList.size() > 0) {
             for (StreamPushItem streamPushItem : pushList) {
-                if (StringUtils.isEmpty(streamPushItem.getGbId())) {
+                if (ObjectUtils.isEmpty(streamPushItem.getGbId())) {
                     pushItemMap.put(streamPushItem.getApp() + streamPushItem.getStream(), streamPushItem);
                 }
             }
@@ -340,6 +341,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
         gbStreamMapper.batchAdd(streamPushItems);
     }
 
+
     @Override
     public void batchAddForUpload(List<StreamPushItem> streamPushItems, Map<String, List<String[]>> streamPushItemsForAll ) {
         // 存储数据到stream_push表
@@ -491,7 +493,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
         TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
         try {
             int addStreamResult = streamPushMapper.add(stream);
-            if (!StringUtils.isEmpty(stream.getGbId())) {
+            if (!ObjectUtils.isEmpty(stream.getGbId())) {
                 stream.setStreamType("push");
                 gbStreamMapper.add(stream);
             }
@@ -503,4 +505,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
         }
         return result;
     }
+
+    @Override
+    public List<String> getAllAppAndStream() {
+        return streamPushMapper.getAllAppAndStream();
+    }
 }

+ 6 - 5
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java

@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
@@ -82,9 +83,9 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPus
 
     @Override
     public void invoke(StreamPushExcelDto streamPushExcelDto, AnalysisContext analysisContext) {
-        if (StringUtils.isEmpty(streamPushExcelDto.getApp())
-                || StringUtils.isEmpty(streamPushExcelDto.getStream())
-                || StringUtils.isEmpty(streamPushExcelDto.getGbId())) {
+        if (ObjectUtils.isEmpty(streamPushExcelDto.getApp())
+                || ObjectUtils.isEmpty(streamPushExcelDto.getStream())
+                || ObjectUtils.isEmpty(streamPushExcelDto.getGbId())) {
             return;
         }
 
@@ -130,7 +131,7 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPus
         streamPushItems.add(streamPushItem);
         streamPushItemForSave.put(streamPushItem.getApp() + streamPushItem.getStream(), streamPushItem);
 
-        if (!StringUtils.isEmpty(streamPushExcelDto.getPlatformId())) {
+        if (!ObjectUtils.isEmpty(streamPushExcelDto.getPlatformId())) {
             List<String[]> platformList = streamPushItemsForPlatform.get(streamPushItem.getApp() + streamPushItem.getStream());
             if (platformList == null) {
                 platformList = new ArrayList<>();
@@ -138,7 +139,7 @@ public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPus
             }
             String platformId = streamPushExcelDto.getPlatformId();
             String catalogId = streamPushExcelDto.getCatalogId();
-            if (StringUtils.isEmpty(streamPushExcelDto.getCatalogId())) {
+            if (ObjectUtils.isEmpty(streamPushExcelDto.getCatalogId())) {
                 catalogId = null;
             }
             String[] platFormInfoArray = new String[]{platformId, catalogId};

+ 2 - 1
src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java

@@ -7,6 +7,7 @@ import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.List;
@@ -60,7 +61,7 @@ public class UserServiceImpl implements IUserService {
 
     @Override
     public boolean checkPushAuthority(String callId, String sign) {
-        if (StringUtils.isEmpty(callId)) {
+        if (ObjectUtils.isEmpty(callId)) {
             return userMapper.checkPushAuthorityByCallId(sign).size() > 0;
         }else {
             return userMapper.checkPushAuthorityByCallIdAndSign(callId, sign).size() > 0;

+ 10 - 0
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java

@@ -148,4 +148,14 @@ public interface GbStreamMapper {
             "SET mediaServerId=#{mediaServerId}" +
             "WHERE app=#{app} AND stream=#{stream}")
     void updateMediaServer(String app, String stream, String mediaServerId);
+
+    @Update("<script> "+
+                " <foreach collection='list' item='item' index='index' separator=';'>"+
+                    "UPDATE gb_stream " +
+                    " SET name=#{item.name},"+
+                    " gbId=#{item.gbId}"+
+                    " WHERE app=#{item.app} and stream=#{item.stream}"+
+                "</foreach>"+
+            "</script>")
+    int updateGbIdOrName(List<StreamPushItem> streamPushItemForUpdate);
 }

+ 3 - 0
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java

@@ -168,4 +168,7 @@ public interface StreamPushMapper {
 
     @Update("UPDATE stream_push SET status=0")
     void setAllStreamOffline();
+
+    @Select("SELECT CONCAT(app,stream) FROM gb_stream")
+    List<String> getAllAppAndStream();
 }

+ 93 - 97
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java

@@ -22,7 +22,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
 
 import java.util.*;
 
@@ -32,9 +31,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
 
     private final Logger logger = LoggerFactory.getLogger(RedisCatchStorageImpl.class);
 
-    @Autowired
-	private RedisUtil redis;
-
     @Autowired
     private DeviceChannelMapper deviceChannelMapper;
 
@@ -45,9 +41,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     public Long getCSEQ() {
         String key = VideoManagerConstants.SIP_CSEQ_PREFIX  + userSetting.getServerId();
 
-        long result =  redis.incr(key, 1L);
+        long result =  RedisUtil.incr(key, 1L);
         if (result > Integer.MAX_VALUE) {
-            redis.set(key, 1);
+            RedisUtil.set(key, 1);
             result = 1;
         }
         return result;
@@ -57,9 +53,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     public Long getSN(String method) {
         String key = VideoManagerConstants.SIP_SN_PREFIX  + userSetting.getServerId() + "_" +  method;
 
-        long result =  redis.incr(key, 1L);
+        long result =  RedisUtil.incr(key, 1L);
         if (result > Integer.MAX_VALUE) {
-            redis.set(key, 1);
+            RedisUtil.set(key, 1);
             result = 1;
         }
         return result;
@@ -68,20 +64,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public void resetAllCSEQ() {
         String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX  + userSetting.getServerId() + "_*";
-        List<Object> keys = redis.scan(scanKey);
+        List<Object> keys = RedisUtil.scan(scanKey);
         for (Object o : keys) {
             String key = (String) o;
-            redis.set(key, 1);
+            RedisUtil.set(key, 1);
         }
     }
 
     @Override
     public void resetAllSN() {
         String scanKey = VideoManagerConstants.SIP_SN_PREFIX  + userSetting.getServerId() + "_*";
-        List<Object> keys = redis.scan(scanKey);
+        List<Object> keys = RedisUtil.scan(scanKey);
         for (Object o : keys) {
             String key = (String) o;
-            redis.set(key, 1);
+            RedisUtil.set(key, 1);
         }
     }
 
@@ -92,7 +88,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
      */
     @Override
     public boolean startPlay(StreamInfo stream) {
-        return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(),
+        return RedisUtil.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(),
                         stream.getStream(), stream.getDeviceID(), stream.getChannelId()),
                 stream);
     }
@@ -107,7 +103,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         if (streamInfo == null) {
             return false;
         }
-        return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
+        return RedisUtil.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
                 userSetting.getServerId(),
                 streamInfo.getStream(),
                 streamInfo.getDeviceID(),
@@ -120,7 +116,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
      */
     @Override
     public StreamInfo queryPlay(StreamInfo streamInfo) {
-        return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s",
+        return (StreamInfo)RedisUtil.get(String.format("%S_%s_%s_%s_%s",
                 VideoManagerConstants.PLAYER_PREFIX,
                 userSetting.getServerId(),
                 streamInfo.getStream(),
@@ -129,36 +125,36 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     }
     @Override
     public StreamInfo queryPlayByStreamId(String streamId) {
-        List<Object> playLeys = redis.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId));
+        List<Object> playLeys = RedisUtil.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId));
         if (playLeys == null || playLeys.size() == 0) {
             return null;
         }
-        return (StreamInfo)redis.get(playLeys.get(0).toString());
+        return (StreamInfo)RedisUtil.get(playLeys.get(0).toString());
     }
 
     @Override
     public StreamInfo queryPlayByDevice(String deviceId, String channelId) {
-        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
+        List<Object> playLeys = RedisUtil.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
                 userSetting.getServerId(),
                 deviceId,
                 channelId));
         if (playLeys == null || playLeys.size() == 0) {
             return null;
         }
-        return (StreamInfo)redis.get(playLeys.get(0).toString());
+        return (StreamInfo)RedisUtil.get(playLeys.get(0).toString());
     }
 
     @Override
     public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) {
         Map<String, StreamInfo> streamInfos = new HashMap<>();
-//		List<Object> playLeys = redis.keys(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
-        List<Object> players = redis.scan(String.format("%S_%s_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(),deviceId));
+//		List<Object> playLeys = RedisUtil.keys(String.format("%S_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, deviceId));
+        List<Object> players = RedisUtil.scan(String.format("%S_%s_*_%S_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(),deviceId));
         if (players.size() == 0) {
             return streamInfos;
         }
         for (Object player : players) {
             String key = (String) player;
-            StreamInfo streamInfo = (StreamInfo) redis.get(key);
+            StreamInfo streamInfo = (StreamInfo) RedisUtil.get(key);
             streamInfos.put(streamInfo.getDeviceID() + "_" + streamInfo.getChannelId(), streamInfo);
         }
         return streamInfos;
@@ -167,7 +163,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
 
     @Override
     public boolean startPlayback(StreamInfo stream, String callId) {
-        return redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
+        return RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
                 userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);
     }
 
@@ -175,10 +171,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     public boolean startDownload(StreamInfo stream, String callId) {
         boolean result;
         if (stream.getProgress() == 1) {
-            result = redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
+            result = RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
                     userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);
         }else {
-            result = redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
+            result = RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
                     userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream, 60*60);
         }
         return result;
@@ -210,10 +206,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
                 stream,
                 callId
         );
-        List<Object> scan = redis.scan(key);
+        List<Object> scan = RedisUtil.scan(key);
         if (scan.size() > 0) {
             for (Object keyObj : scan) {
-                redis.del((String) keyObj);
+                RedisUtil.del((String) keyObj);
             }
         }
         return true;
@@ -246,10 +242,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
                 stream,
                 callId
         );
-        List<Object> scan = redis.scan(key);
+        List<Object> scan = RedisUtil.scan(key);
         if (scan.size() > 0) {
             for (Object keyObj : scan) {
-                redis.del((String) keyObj);
+                RedisUtil.del((String) keyObj);
             }
         }
         return true;
@@ -279,9 +275,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
                 stream,
                 callId
         );
-        List<Object> streamInfoScan = redis.scan(key);
+        List<Object> streamInfoScan = RedisUtil.scan(key);
         if (streamInfoScan.size() > 0) {
-            return (StreamInfo) redis.get((String) streamInfoScan.get(0));
+            return (StreamInfo) RedisUtil.get((String) streamInfoScan.get(0));
         }else {
             return null;
         }
@@ -290,64 +286,64 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) {
         String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX  + userSetting.getServerId() + "_" +  parentPlatformCatch.getId();
-        redis.set(key, parentPlatformCatch);
+        RedisUtil.set(key, parentPlatformCatch);
     }
 
     @Override
     public void updatePlatformKeepalive(ParentPlatform parentPlatform) {
         String key = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX  + userSetting.getServerId() + "_" + parentPlatform.getServerGBId();
-        redis.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
+        RedisUtil.set(key, "", Integer.parseInt(parentPlatform.getKeepTimeout()));
     }
 
     @Override
     public void updatePlatformRegister(ParentPlatform parentPlatform) {
         String key = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_" + parentPlatform.getServerGBId();
-        redis.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
+        RedisUtil.set(key, "", Integer.parseInt(parentPlatform.getExpires()));
     }
 
     @Override
     public ParentPlatformCatch queryPlatformCatchInfo(String platformGbId) {
-        return (ParentPlatformCatch)redis.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
+        return (ParentPlatformCatch)RedisUtil.get(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
     }
 
     @Override
     public void delPlatformCatchInfo(String platformGbId) {
-        redis.del(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
+        RedisUtil.del(VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + platformGbId);
     }
 
     @Override
     public void delPlatformKeepalive(String platformGbId) {
-        redis.del(VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + platformGbId);
+        RedisUtil.del(VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + platformGbId);
     }
 
     @Override
     public void delPlatformRegister(String platformGbId) {
-        redis.del(VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_" + platformGbId);
+        RedisUtil.del(VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_" + platformGbId);
     }
 
 
     @Override
     public void updatePlatformRegisterInfo(String callId, String platformGbId) {
         String key = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId;
-        redis.set(key, platformGbId, 30);
+        RedisUtil.set(key, platformGbId, 30);
     }
 
 
     @Override
     public String queryPlatformRegisterInfo(String callId) {
-        return (String)redis.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
+        return (String)RedisUtil.get(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
     }
 
     @Override
     public void delPlatformRegisterInfo(String callId) {
-        redis.del(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
+        RedisUtil.del(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + callId);
     }
 
     @Override
     public void cleanPlatformRegisterInfos() {
-        List regInfos = redis.scan(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + "*");
+        List regInfos = RedisUtil.scan(VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + "*");
         for (Object key : regInfos) {
-            redis.del(key.toString());
+            RedisUtil.del(key.toString());
         }
     }
 
@@ -356,7 +352,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_"
                 + sendRtpItem.getPlatformId() + "_" + sendRtpItem.getChannelId() + "_"
                 + sendRtpItem.getStreamId() + "_" + sendRtpItem.getCallId();
-        redis.set(key, sendRtpItem);
+        RedisUtil.set(key, sendRtpItem);
     }
 
     @Override
@@ -375,9 +371,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         }
         String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_" + platformGbId
                 + "_" + channelId + "_" + streamId + "_" + callId;
-        List<Object> scan = redis.scan(key);
+        List<Object> scan = RedisUtil.scan(key);
         if (scan.size() > 0) {
-            return (SendRtpItem)redis.get((String)scan.get(0));
+            return (SendRtpItem)RedisUtil.get((String)scan.get(0));
         }else {
             return null;
         }
@@ -389,12 +385,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
             platformGbId = "*";
         }
         String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_" + platformGbId + "_*" + "_*" + "_*";
-        List<Object> queryResult = redis.scan(key);
+        List<Object> queryResult = RedisUtil.scan(key);
         List<SendRtpItem> result= new ArrayList<>();
 
         for (Object o : queryResult) {
             String keyItem = (String) o;
-            result.add((SendRtpItem) redis.get(keyItem));
+            result.add((SendRtpItem) RedisUtil.get(keyItem));
         }
 
         return result;
@@ -415,10 +411,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         }
         String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_" + platformGbId
                 + "_" + channelId + "_" + streamId + "_" + callId;
-        List<Object> scan = redis.scan(key);
+        List<Object> scan = RedisUtil.scan(key);
         if (scan.size() > 0) {
             for (Object keyStr : scan) {
-                redis.del((String)keyStr);
+                RedisUtil.del((String)keyStr);
             }
         }
     }
@@ -432,7 +428,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public boolean isChannelSendingRTP(String channelId) {
         String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_" + "*_" + channelId + "*_" + "*_";
-        List<Object> RtpStreams = redis.scan(key);
+        List<Object> RtpStreams = RedisUtil.scan(key);
         if (RtpStreams.size() > 0) {
             return true;
         } else {
@@ -442,30 +438,30 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
 
     @Override
     public void clearCatchByDeviceId(String deviceId) {
-        List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX,
+        List<Object> playLeys = RedisUtil.scan(String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX,
                 userSetting.getServerId(),
                 deviceId));
         if (playLeys.size() > 0) {
             for (Object key : playLeys) {
-                redis.del(key.toString());
+                RedisUtil.del(key.toString());
             }
         }
 
-        List<Object> playBackers = redis.scan(String.format("%S_%s_%s_*_*_*", VideoManagerConstants.PLAY_BLACK_PREFIX,
+        List<Object> playBackers = RedisUtil.scan(String.format("%S_%s_%s_*_*_*", VideoManagerConstants.PLAY_BLACK_PREFIX,
                 userSetting.getServerId(),
                 deviceId));
         if (playBackers.size() > 0) {
             for (Object key : playBackers) {
-                redis.del(key.toString());
+                RedisUtil.del(key.toString());
             }
         }
 
-        List<Object> deviceCache = redis.scan(String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX,
+        List<Object> deviceCache = RedisUtil.scan(String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX,
                 userSetting.getServerId(),
                 deviceId));
         if (deviceCache.size() > 0) {
             for (Object key : deviceCache) {
-                redis.del(key.toString());
+                RedisUtil.del(key.toString());
             }
         }
     }
@@ -473,14 +469,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public void updateWVPInfo(JSONObject jsonObject, int time) {
         String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId();
-        redis.set(key, jsonObject, time);
+        RedisUtil.set(key, jsonObject, time);
     }
 
     @Override
     public void sendStreamChangeMsg(String type, JSONObject jsonObject) {
         String key = VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + type;
         logger.info("[redis 流变化事件] {}: {}", key, jsonObject.toString());
-        redis.convertAndSend(key, jsonObject);
+        RedisUtil.convertAndSend(key, jsonObject);
     }
 
     @Override
@@ -491,13 +487,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         if (streamAuthorityInfo != null) {
             mediaItem.setCallId(streamAuthorityInfo.getCallId());
         }
-        redis.set(key, mediaItem);
+        RedisUtil.set(key, mediaItem);
     }
 
     @Override
     public void removeStream(String mediaServerId, String type, String app, String streamId) {
         String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_"  + app + "_" + streamId + "_" + mediaServerId;
-        redis.del(key);
+        RedisUtil.del(key);
     }
 
     @Override
@@ -524,9 +520,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
                 stream,
                 callId
         );
-        List<Object> streamInfoScan = redis.scan(key);
+        List<Object> streamInfoScan = RedisUtil.scan(key);
         if (streamInfoScan.size() > 0) {
-            return (StreamInfo) redis.get((String) streamInfoScan.get(0));
+            return (StreamInfo) RedisUtil.get((String) streamInfoScan.get(0));
         }else {
             return null;
         }
@@ -535,16 +531,16 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public ThirdPartyGB queryMemberNoGBId(String queryKey) {
         String key = VideoManagerConstants.WVP_STREAM_GB_ID_PREFIX + queryKey;
-        JSONObject jsonObject = (JSONObject)redis.get(key);
+        JSONObject jsonObject = (JSONObject)RedisUtil.get(key);
         return  JSONObject.toJavaObject(jsonObject, ThirdPartyGB.class);
     }
 
     @Override
     public void removeStream(String mediaServerId, String type) {
         String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_*_*_" + mediaServerId;
-        List<Object> streams = redis.scan(key);
+        List<Object> streams = RedisUtil.scan(key);
         for (Object stream : streams) {
-            redis.del((String) stream);
+            RedisUtil.del((String) stream);
         }
     }
 
@@ -552,9 +548,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     public List<MediaItem> getStreams(String mediaServerId, String type) {
         List<MediaItem> result = new ArrayList<>();
         String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_*_*_" + mediaServerId;
-        List<Object> streams = redis.scan(key);
+        List<Object> streams = RedisUtil.scan(key);
         for (Object stream : streams) {
-            MediaItem mediaItem = (MediaItem)redis.get((String) stream);
+            MediaItem mediaItem = (MediaItem)RedisUtil.get((String) stream);
             result.add(mediaItem);
         }
         return result;
@@ -563,43 +559,43 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public void updateDevice(Device device) {
         String key = VideoManagerConstants.DEVICE_PREFIX + userSetting.getServerId() + "_" + device.getDeviceId();
-        redis.set(key, device);
+        RedisUtil.set(key, device);
     }
 
     @Override
     public void removeDevice(String deviceId) {
         String key = VideoManagerConstants.DEVICE_PREFIX + userSetting.getServerId() + "_" + deviceId;
-        redis.del(key);
+        RedisUtil.del(key);
     }
 
     @Override
     public Device getDevice(String deviceId) {
         String key = VideoManagerConstants.DEVICE_PREFIX + userSetting.getServerId() + "_" + deviceId;
-        return (Device)redis.get(key);
+        return (Device)RedisUtil.get(key);
     }
 
     @Override
     public void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo) {
         String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_" + gpsMsgInfo.getId();
-        redis.set(key, gpsMsgInfo, 60); // 默认GPS消息保存1分钟
+        RedisUtil.set(key, gpsMsgInfo, 60); // 默认GPS消息保存1分钟
     }
 
     @Override
     public GPSMsgInfo getGpsMsgInfo(String gbId) {
         String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_" + gbId;
-        return (GPSMsgInfo)redis.get(key);
+        return (GPSMsgInfo)RedisUtil.get(key);
     }
 
     @Override
     public List<GPSMsgInfo> getAllGpsMsgInfo() {
         String scanKey = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetting.getServerId() + "_*";
         List<GPSMsgInfo> result = new ArrayList<>();
-        List<Object> keys = redis.scan(scanKey);
+        List<Object> keys = RedisUtil.scan(scanKey);
         for (Object o : keys) {
             String key = (String) o;
-            GPSMsgInfo gpsMsgInfo = (GPSMsgInfo) redis.get(key);
+            GPSMsgInfo gpsMsgInfo = (GPSMsgInfo) RedisUtil.get(key);
             if (!gpsMsgInfo.isStored()) { // 只取没有存过得
-                result.add((GPSMsgInfo) redis.get(key));
+                result.add((GPSMsgInfo) RedisUtil.get(key));
             }
         }
 
@@ -609,19 +605,19 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     @Override
     public void updateStreamAuthorityInfo(String app, String stream, StreamAuthorityInfo streamAuthorityInfo) {
         String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream;
-        redis.set(key, streamAuthorityInfo);
+        RedisUtil.set(key, streamAuthorityInfo);
     }
 
     @Override
     public void removeStreamAuthorityInfo(String app, String stream) {
         String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
-        redis.del(key);
+        RedisUtil.del(key);
     }
 
     @Override
     public StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream) {
         String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
-        return (StreamAuthorityInfo) redis.get(key);
+        return (StreamAuthorityInfo) RedisUtil.get(key);
 
     }
 
@@ -631,10 +627,10 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + userSetting.getServerId() + "_*_" + app + "_" + streamId + "_" + mediaServerId;
 
         MediaItem result = null;
-        List<Object> keys = redis.scan(scanKey);
+        List<Object> keys = RedisUtil.scan(scanKey);
         if (keys.size() > 0) {
             String key = (String) keys.get(0);
-            result = (MediaItem)redis.get(key);
+            result = (MediaItem)RedisUtil.get(key);
         }
 
         return result;
@@ -646,11 +642,11 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>();
         systemInfoDto.setTime(DateUtil.getNow());
         systemInfoDto.setData(cpuInfo);
-        redis.lSet(key, systemInfoDto);
+        RedisUtil.lSet(key, systemInfoDto);
         // 每秒一个,最多只存30个
-        if (redis.lGetListSize(key) > 30) {
-            for (int i = 0; i < redis.lGetListSize(key) - 30; i++) {
-                redis.lLeftPop(key);
+        if (RedisUtil.lGetListSize(key) > 30) {
+            for (int i = 0; i < RedisUtil.lGetListSize(key) - 30; i++) {
+                RedisUtil.lLeftPop(key);
             }
         }
     }
@@ -661,11 +657,11 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         SystemInfoDto<Double> systemInfoDto = new SystemInfoDto<>();
         systemInfoDto.setTime(DateUtil.getNow());
         systemInfoDto.setData(memInfo);
-        redis.lSet(key, systemInfoDto);
+        RedisUtil.lSet(key, systemInfoDto);
         // 每秒一个,最多只存30个
-        if (redis.lGetListSize(key) > 30) {
-            for (int i = 0; i < redis.lGetListSize(key) - 30; i++) {
-                redis.lLeftPop(key);
+        if (RedisUtil.lGetListSize(key) > 30) {
+            for (int i = 0; i < RedisUtil.lGetListSize(key) - 30; i++) {
+                RedisUtil.lLeftPop(key);
             }
         }
     }
@@ -676,11 +672,11 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         SystemInfoDto<Map<String, String>> systemInfoDto = new SystemInfoDto<>();
         systemInfoDto.setTime(DateUtil.getNow());
         systemInfoDto.setData(networkInterfaces);
-        redis.lSet(key, systemInfoDto);
+        RedisUtil.lSet(key, systemInfoDto);
         // 每秒一个,最多只存30个
-        if (redis.lGetListSize(key) > 30) {
-            for (int i = 0; i < redis.lGetListSize(key) - 30; i++) {
-                redis.lLeftPop(key);
+        if (RedisUtil.lGetListSize(key) > 30) {
+            for (int i = 0; i < RedisUtil.lGetListSize(key) - 30; i++) {
+                RedisUtil.lLeftPop(key);
             }
         }
     }
@@ -689,21 +685,21 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
     public void sendMobilePositionMsg(JSONObject jsonObject) {
         String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
         logger.info("[redis发送通知]移动位置 {}: {}", key, jsonObject.toString());
-        redis.convertAndSend(key, jsonObject);
+        RedisUtil.convertAndSend(key, jsonObject);
     }
 
     @Override
     public void sendStreamPushRequestedMsg(MessageForPushChannel msg) {
         String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
         logger.info("[redis发送通知]推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
-        redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
+        RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
     }
 
     @Override
     public void sendAlarmMsg(AlarmChannelMessage msg) {
         String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM;
         logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg));
-        redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
+        RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
     }
 
     @Override
@@ -718,6 +714,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
         logger.info("[redis通知]获取所有推流设备的状态");
         JSONObject jsonObject = new JSONObject();
         jsonObject.put(key, key);
-        redis.convertAndSend(key, jsonObject);
+        RedisUtil.convertAndSend(key, jsonObject);
     }
 }

+ 2 - 1
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java

@@ -26,6 +26,7 @@ import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
@@ -132,7 +133,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 						deviceChannel.setStreamId(allChannelMapInPlay.get(deviceChannel.getChannelId()).getStreamId());
 					}
 					channels.add(deviceChannel);
-					if (!StringUtils.isEmpty(deviceChannel.getParentId())) {
+					if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
 						if (subContMap.get(deviceChannel.getParentId()) == null) {
 							subContMap.put(deviceChannel.getParentId(), 1);
 						}else {

+ 65 - 72
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java

@@ -4,6 +4,7 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.utils.SpringBeanFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.*;
 import org.springframework.stereotype.Component;
@@ -14,12 +15,14 @@ import org.springframework.util.CollectionUtils;
  * @author: swwheihei
  * @date:   2020年5月6日 下午8:27:29     
  */
-@Component
 @SuppressWarnings(value = {"rawtypes", "unchecked"})
 public class RedisUtil {
 
-	@Autowired
-    private RedisTemplate redisTemplate;
+    private static RedisTemplate redisTemplate;
+
+    static {
+        redisTemplate = (RedisTemplate)SpringBeanFactory.getBean("redisTemplate");
+    }
 	
 	/**
      * 指定缓存失效时间
@@ -27,7 +30,7 @@ public class RedisUtil {
      * @param time 时间(秒)
      * @return true / false
      */
-    public boolean expire(String key, long time) {
+    public static boolean expire(String key, long time) {
         try {
             if (time > 0) {
                 redisTemplate.expire(key, time, TimeUnit.SECONDS);
@@ -44,7 +47,7 @@ public class RedisUtil {
      * @param key 键
      * @return
      */
-    public long getExpire(String key) {
+    public static long getExpire(String key) {
         return redisTemplate.getExpire(key, TimeUnit.SECONDS);
     }
 
@@ -53,7 +56,7 @@ public class RedisUtil {
      * @param key 键
      * @return true / false
      */
-    public boolean hasKey(String key) {
+    public static boolean hasKey(String key) {
         try {
             return redisTemplate.hasKey(key);
         } catch (Exception e) {
@@ -67,7 +70,7 @@ public class RedisUtil {
      * @SuppressWarnings("unchecked") 忽略类型转换警告
      * @param key 键(一个或者多个)
      */
-    public boolean del(String... key) {
+    public static boolean del(String... key) {
     	try {
     		if (key != null && key.length > 0) {
                 if (key.length == 1) {
@@ -91,7 +94,7 @@ public class RedisUtil {
      * @param key 键
      * @return 值
      */
-    public Object get(String key) {
+    public static Object get(String key) {
         return key == null ? null : redisTemplate.opsForValue().get(key);
     }
 
@@ -101,7 +104,7 @@ public class RedisUtil {
      * @param value 值
      * @return true / false
      */
-    public boolean set(String key, Object value) {
+    public static boolean set(String key, Object value) {
         try {
             redisTemplate.opsForValue().set(key, value);
             return true;
@@ -118,7 +121,7 @@ public class RedisUtil {
      * @param time 时间(秒),如果 time < 0 则设置无限时间
      * @return true / false
      */
-    public boolean set(String key, Object value, long time) {
+    public static boolean set(String key, Object value, long time) {
         try {
             if (time > 0) {
                 redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
@@ -138,7 +141,7 @@ public class RedisUtil {
      * @param delta 递增大小
      * @return
      */
-    public long incr(String key, long delta) {
+    public static long incr(String key, long delta) {
         if (delta < 0) {
             throw new RuntimeException("递增因子必须大于 0");
         }
@@ -151,7 +154,7 @@ public class RedisUtil {
      * @param delta 递减大小
      * @return
      */
-    public long decr(String key, long delta) {
+    public static long decr(String key, long delta) {
         if (delta < 0) {
             throw new RuntimeException("递减因子必须大于 0");
         }
@@ -166,7 +169,7 @@ public class RedisUtil {
      * @param item 项(no null)
      * @return 值
      */
-    public Object hget(String key, String item) {
+    public static Object hget(String key, String item) {
         return redisTemplate.opsForHash().get(key, item);
     }
 
@@ -175,7 +178,7 @@ public class RedisUtil {
      * @param key 键(no null)
      * @return 对应的多个键值
      */
-    public Map<Object, Object> hmget(String key) {
+    public static Map<Object, Object> hmget(String key) {
         return redisTemplate.opsForHash().entries(key);
     }
 
@@ -185,7 +188,7 @@ public class RedisUtil {
      * @param map 值
      * @return true / false
      */
-    public boolean hmset(String key, Map<Object, Object> map) {
+    public static boolean hmset(String key, Map<Object, Object> map) {
         try {
             redisTemplate.opsForHash().putAll(key, map);
             return true;
@@ -202,7 +205,7 @@ public class RedisUtil {
      * @param time 时间
      * @return true / false
      */
-    public boolean hmset(String key, Map<Object, Object> map, long time) {
+    public static boolean hmset(String key, Map<Object, Object> map, long time) {
         try {
             redisTemplate.opsForHash().putAll(key, map);
             if (time > 0) {
@@ -222,7 +225,7 @@ public class RedisUtil {
      * @param value 值
      * @return true / false
      */
-    public boolean hset(String key, String item, Object value) {
+    public static boolean hset(String key, String item, Object value) {
         try {
             redisTemplate.opsForHash().put(key, item, value);
             return true;
@@ -240,7 +243,7 @@ public class RedisUtil {
      * @param time 时间(如果原来的 Hash表 设置了时间,这里会覆盖)
      * @return true / false
      */
-    public boolean hset(String key, String item, Object value, long time) {
+    public static boolean hset(String key, String item, Object value, long time) {
         try {
             redisTemplate.opsForHash().put(key, item, value);
             if (time > 0) {
@@ -258,7 +261,7 @@ public class RedisUtil {
      * @param key 键
      * @param item 项(可以多个,no null)
      */
-    public void hdel(String key, Object... item) {
+    public static void hdel(String key, Object... item) {
         redisTemplate.opsForHash().delete(key, item);
     }
 
@@ -268,7 +271,7 @@ public class RedisUtil {
      * @param item 值(no null)
      * @return true / false
      */
-    public boolean hHasKey(String key, String item) {
+    public static boolean hHasKey(String key, String item) {
         return redisTemplate.opsForHash().hasKey(key, item);
     }
 
@@ -279,7 +282,7 @@ public class RedisUtil {
      * @param by 递增大小 > 0
      * @return
      */
-    public Double hincr(String key, String item, Double by) {
+    public static Double hincr(String key, String item, Double by) {
         return redisTemplate.opsForHash().increment(key, item, by);
     }
 
@@ -290,7 +293,7 @@ public class RedisUtil {
      * @param by 递减大小
      * @return
      */
-    public Double hdecr(String key, String item, Double by) {
+    public static Double hdecr(String key, String item, Double by) {
         return redisTemplate.opsForHash().increment(key, item, -by);
     }
 
@@ -301,7 +304,7 @@ public class RedisUtil {
      * @param key 键
      * @return 值
      */
-    public Set<Object> sGet(String key) {
+    public static Set<Object> sGet(String key) {
         try {
             return redisTemplate.opsForSet().members(key);
         } catch (Exception e) {
@@ -316,7 +319,7 @@ public class RedisUtil {
      * @param value 值
      * @return true / false
      */
-    public boolean sHasKey(String key, Object value) {
+    public static boolean sHasKey(String key, Object value) {
         try {
             return redisTemplate.opsForSet().isMember(key, value);
         } catch (Exception e) {
@@ -331,7 +334,7 @@ public class RedisUtil {
      * @param values 值(可以多个)
      * @return 成功个数
      */
-    public long sSet(String key, Object... values) {
+    public static long sSet(String key, Object... values) {
         try {
             return redisTemplate.opsForSet().add(key, values);
         } catch (Exception e) {
@@ -347,7 +350,7 @@ public class RedisUtil {
      * @param values 值(可以多个)
      * @return 成功放入个数
      */
-    public long sSet(String key, long time, Object... values) {
+    public static long sSet(String key, long time, Object... values) {
         try {
             long count = redisTemplate.opsForSet().add(key, values);
             if (time > 0) {
@@ -365,7 +368,7 @@ public class RedisUtil {
      * @param key 键
      * @return 长度
      */
-    public long sGetSetSize(String key) {
+    public static long sGetSetSize(String key) {
         try {
             return redisTemplate.opsForSet().size(key);
         } catch (Exception e) {
@@ -380,7 +383,7 @@ public class RedisUtil {
      * @param values 值
      * @return 成功移除个数
      */
-    public long setRemove(String key, Object... values) {
+    public static long setRemove(String key, Object... values) {
         try {
             return redisTemplate.opsForSet().remove(key, values);
         } catch (Exception e) {
@@ -397,7 +400,7 @@ public class RedisUtil {
      * @param value
      * @param score
      */
-    public void zAdd(Object key, Object value, double score) {
+    public static void zAdd(Object key, Object value, double score) {
         redisTemplate.opsForZSet().add(key, value, score);
     }
 
@@ -407,7 +410,7 @@ public class RedisUtil {
      * @param key
      * @param value
      */
-    public void zRemove(Object key, Object value) {
+    public static void zRemove(Object key, Object value) {
         redisTemplate.opsForZSet().remove(key, value);
     }
 
@@ -418,7 +421,7 @@ public class RedisUtil {
      * @param value
      * @param delta -1 表示减 1 表示加1
      */
-    public Double zIncrScore(Object key, Object value, double delta) {
+    public static Double zIncrScore(Object key, Object value, double delta) {
         return redisTemplate.opsForZSet().incrementScore(key, value, delta);
     }
 
@@ -429,7 +432,7 @@ public class RedisUtil {
      * @param value
      * @return
      */
-    public Double zScore(Object key, Object value) {
+    public static Double zScore(Object key, Object value) {
         return redisTemplate.opsForZSet().score(key, value);
     }
 
@@ -440,7 +443,7 @@ public class RedisUtil {
      * @param value
      * @return
      */
-    public Long zRank(Object key, Object value) {
+    public static Long zRank(Object key, Object value) {
         return redisTemplate.opsForZSet().rank(key, value);
     }
 
@@ -450,7 +453,7 @@ public class RedisUtil {
      * @param key
      * @return
      */
-    public Long zSize(Object key) {
+    public static Long zSize(Object key) {
         return redisTemplate.opsForZSet().zCard(key);
     }
 
@@ -464,7 +467,7 @@ public class RedisUtil {
      * @param end
      * @return
      */
-    public Set<Object> ZRange(Object key, int start, int end) {
+    public static Set<Object> ZRange(Object key, int start, int end) {
         return redisTemplate.opsForZSet().range(key, start, end);
     }
     /**
@@ -475,7 +478,7 @@ public class RedisUtil {
      * @param end
      * @return
      */
-    public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) {
+    public static Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) {
         return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
     }
     /**
@@ -488,7 +491,7 @@ public class RedisUtil {
      * @param end
      * @return
      */
-    public Set<String> zRevRange(Object key, int start, int end) {
+    public static Set<String> zRevRange(Object key, int start, int end) {
         return redisTemplate.opsForZSet().reverseRange(key, start, end);
     }
     /**
@@ -499,7 +502,7 @@ public class RedisUtil {
      * @param max
      * @return
      */
-    public Set<String> zSortRange(Object key, int min, int max) {
+    public static Set<String> zSortRange(Object key, int min, int max) {
         return redisTemplate.opsForZSet().rangeByScore(key, min, max);
     }
 
@@ -513,7 +516,7 @@ public class RedisUtil {
      * @param end 结束(0 到 -1 代表所有值)
      * @return
      */
-    public List<Object> lGet(String key, long start, long end) {
+    public static List<Object> lGet(String key, long start, long end) {
         try {
             return redisTemplate.opsForList().range(key, start, end);
         } catch (Exception e) {
@@ -527,7 +530,7 @@ public class RedisUtil {
      * @param key 键
      * @return 长度
      */
-    public long lGetListSize(String key) {
+    public static long lGetListSize(String key) {
         try {
             return redisTemplate.opsForList().size(key);
         } catch (Exception e) {
@@ -544,7 +547,7 @@ public class RedisUtil {
      *              当 index < 0 时 {-1:表尾, -2:倒数第二个元素}
      * @return 值
      */
-    public Object lGetIndex(String key, long index) {
+    public static Object lGetIndex(String key, long index) {
         try {
             return redisTemplate.opsForList().index(key, index);
         } catch (Exception e) {
@@ -559,7 +562,7 @@ public class RedisUtil {
      * @param value 值
      * @return true / false
      */
-    public boolean lSet(String key, Object value) {
+    public static boolean lSet(String key, Object value) {
         try {
             redisTemplate.opsForList().rightPush(key, value);
             return true;
@@ -576,7 +579,7 @@ public class RedisUtil {
      * @param time 时间
      * @return true / false
      */
-    public boolean lSet(String key, Object value, long time) {
+    public static boolean lSet(String key, Object value, long time) {
         try {
             redisTemplate.opsForList().rightPush(key, value);
             if (time > 0) {
@@ -595,7 +598,7 @@ public class RedisUtil {
      * @param values 值
      * @return true / false
      */
-    public boolean lSetList(String key, List<Object> values) {
+    public static boolean lSetList(String key, List<Object> values) {
         try {
             redisTemplate.opsForList().rightPushAll(key, values);
             return true;
@@ -612,7 +615,7 @@ public class RedisUtil {
      * @param time 时间
      * @return true / false
      */
-    public boolean lSetList(String key, List<Object> values, long time) {
+    public static boolean lSetList(String key, List<Object> values, long time) {
         try {
             redisTemplate.opsForList().rightPushAll(key, values);
             if (time > 0) {
@@ -632,7 +635,7 @@ public class RedisUtil {
      * @param value 值
      * @return true / false
      */
-    public boolean lUpdateIndex(String key, long index, Object value) {
+    public static boolean lUpdateIndex(String key, long index, Object value) {
         try {
             redisTemplate.opsForList().set(key, index, value);
             return true;
@@ -651,7 +654,7 @@ public class RedisUtil {
      * @param value
      * @return
      */
-    public long lRemove(String key, long count, Object value) {
+    public static long lRemove(String key, long count, Object value) {
         try {
             return redisTemplate.opsForList().remove(key, count, value);
         } catch (Exception e) {
@@ -665,7 +668,7 @@ public class RedisUtil {
      * @param key 键
      * @return
      */
-    public Object lLeftPop(String key) {
+    public static Object lLeftPop(String key) {
         return redisTemplate.opsForList().leftPop(key);
     }
 
@@ -674,7 +677,7 @@ public class RedisUtil {
      * @param key 键
      * @return
      */
-    public Object lrightPop(String key) {
+    public static Object lrightPop(String key) {
         return redisTemplate.opsForList().rightPop(key);
     }
 
@@ -683,7 +686,7 @@ public class RedisUtil {
      * @param key 键
      * @return true / false
      */
-    public List<Object> keys(String key) {
+    public static List<Object> keys(String key) {
         try {
             Set<String> set = redisTemplate.keys(key);
             return new ArrayList<>(set);
@@ -699,7 +702,7 @@ public class RedisUtil {
      * @param query 查询参数
      * @return
      */
-//    public List<Object> scan(String query) {
+//    public static List<Object> scan(String query) {
 //        List<Object> result = new ArrayList<>();
 //        try {
 //            Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("field",
@@ -723,33 +726,23 @@ public class RedisUtil {
      * @param query 查询参数
      * @return
      */
-    public List<Object> scan(String query) {
-        Set<String> keys = (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
-            Set<String> keysTmp = new HashSet<>();
-            Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(query).count(1000).build());
-            while (cursor.hasNext()) {
-                keysTmp.add(new String(cursor.next()));
+    public static List<Object> scan(String query) {
+        Set<String> resultKeys = (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
+            ScanOptions scanOptions = ScanOptions.scanOptions().match("*" + query + "*").count(1000).build();
+            Cursor<byte[]> scan = connection.scan(scanOptions);
+            Set<String> keys = new HashSet<>();
+            while (scan.hasNext()) {
+                byte[] next = scan.next();
+                keys.add(new String(next));
             }
-            return keysTmp;
+            return keys;
         });
-//        Set<String> keys = (Set<String>) redisTemplate.execute(new RedisCallback<Set<String>>(){
-//
-//            @Override
-//            public Set<String> doInRedis(RedisConnection connection) throws DataAccessException {
-//                Set<String> keysTmp = new HashSet<>();
-//                Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(query).count(1000).build());
-//                while (cursor.hasNext()) {
-//                    keysTmp.add(new String(cursor.next()));
-//                }
-//            return keysTmp;
-//            }
-//        });
 
-        return new ArrayList<>(keys);
+        return new ArrayList<>(resultKeys);
     }
 
     //    ============================== 消息发送与订阅 ==============================
-    public void convertAndSend(String channel, JSONObject msg) {
+    public static void convertAndSend(String channel, JSONObject msg) {
 //        redisTemplate.convertAndSend(channel, msg);
         redisTemplate.convertAndSend(channel, msg);
 

+ 6 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/bean/BatchGBStreamParam.java

@@ -1,10 +1,16 @@
 package com.genersoft.iot.vmp.vmanager.bean;
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import io.swagger.v3.oas.annotations.media.Schema;
 
 import java.util.List;
 
+/**
+ * @author lin
+ */
+@Schema(description = "多个推流信息")
 public class BatchGBStreamParam {
+    @Schema(description = "推流信息列表")
     private List<GbStream> gbStreams;
 
     public List<GbStream> getGbStreams() {

+ 31 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/bean/ErrorCode.java

@@ -0,0 +1,31 @@
+package com.genersoft.iot.vmp.vmanager.bean;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+/**
+ * 全局错误码
+ */
+public enum ErrorCode {
+    SUCCESS(0, "成功"),
+    ERROR100(100, "失败"),
+    ERROR400(400, "参数不全或者错误"),
+    ERROR403(403, "无权限操作"),
+    ERROR401(401, "请登录后重新请求"),
+    ERROR500(500, "系统异常");
+
+    private final int code;
+    private final String msg;
+
+    ErrorCode(int code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 1 - 1
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/session/PlayTypeEnum.java

@@ -1,4 +1,4 @@
-package com.genersoft.iot.vmp.vmanager.gb28181.session;
+package com.genersoft.iot.vmp.vmanager.bean;
 
 public enum PlayTypeEnum {
 

+ 12 - 8
src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java

@@ -1,6 +1,9 @@
 package com.genersoft.iot.vmp.vmanager.bean;
 
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(description = "统一返回结果")
 public class WVPResult<T> {
 
     public WVPResult() {
@@ -13,27 +16,28 @@ public class WVPResult<T> {
     }
 
 
+    @Schema(description = "错误码,0为成功")
     private int code;
+    @Schema(description = "描述,错误时描述错误原因")
     private String msg;
+    @Schema(description = "数据")
     private T data;
 
-    private static final Integer SUCCESS = 200;
-    private static final Integer FAILED = 400;
 
-    public static <T> WVPResult<T> Data(T t, String msg) {
-        return new WVPResult<>(SUCCESS, msg, t);
+    public static <T> WVPResult<T> success(T t, String msg) {
+        return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t);
     }
 
-    public static <T> WVPResult<T> Data(T t) {
-        return Data(t, "成功");
+    public static <T> WVPResult<T> success(T t) {
+        return success(t, ErrorCode.SUCCESS.getMsg());
     }
 
     public static <T> WVPResult<T> fail(int code, String msg) {
         return new WVPResult<>(code, msg, null);
     }
 
-    public static <T> WVPResult<T> fail(String msg) {
-        return fail(FAILED, msg);
+    public static <T> WVPResult<T> fail(ErrorCode errorCode) {
+        return fail(errorCode.getCode(), errorCode.getMsg());
     }
 
     public int getCode() {

+ 26 - 46
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java

@@ -13,10 +13,9 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.util.StringUtil;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -33,7 +32,7 @@ import org.springframework.web.context.request.async.DeferredResult;
 /**
  *  位置信息管理
  */
-@Api(tags = "位置信息管理")
+@Tag(name  = "位置信息管理")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/position")
@@ -54,27 +53,22 @@ public class MobilePositionController {
 	private IDeviceService deviceService;
 
     /**
-     *  查询历史轨迹
+     * 查询历史轨迹
      * @param deviceId 设备ID
      * @param start 开始时间
      * @param end 结束时间
      * @return
      */
-    @ApiOperation("查询历史轨迹")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-            @ApiImplicitParam(name = "channelId", value = "通道ID", required = false, dataTypeClass = String.class),
-            @ApiImplicitParam(name = "start", value = "开始时间", required = false, dataTypeClass = String.class),
-            @ApiImplicitParam(name = "end", value = "结束时间", required = false, dataTypeClass = String.class),
-    })
+    @Operation(summary = "查询历史轨迹")
+    @Parameter(name = "deviceId", description = "设备国标编号", required = true)
+    @Parameter(name = "channelId", description = "通道国标编号")
+    @Parameter(name = "start", description = "开始时间")
+    @Parameter(name = "end", description = "结束时间")
     @GetMapping("/history/{deviceId}")
-    public ResponseEntity<WVPResult<List<MobilePosition>>> positions(@PathVariable String deviceId,
+    public List<MobilePosition> positions(@PathVariable String deviceId,
                                                                      @RequestParam(required = false) String channelId,
                                                                      @RequestParam(required = false) String start,
                                                                      @RequestParam(required = false) String end) {
-//        if (logger.isDebugEnabled()) {
-//            logger.debug("查询设备" + deviceId + "的历史轨迹");
-//        }
 
         if (StringUtil.isEmpty(start)) {
             start = null;
@@ -82,11 +76,7 @@ public class MobilePositionController {
         if (StringUtil.isEmpty(end)) {
             end = null;
         }
-        WVPResult<List<MobilePosition>> wvpResult = new WVPResult<>();
-        wvpResult.setCode(0);
-        List<MobilePosition> result = storager.queryMobilePositions(deviceId, channelId, start, end);
-        wvpResult.setData(result);
-        return new ResponseEntity<>(wvpResult, HttpStatus.OK);
+        return storager.queryMobilePositions(deviceId, channelId, start, end);
     }
 
     /**
@@ -94,17 +84,11 @@ public class MobilePositionController {
      * @param deviceId 设备ID
      * @return
      */
-    @ApiOperation("查询设备最新位置")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-    })
+    @Operation(summary = "查询设备最新位置")
+    @Parameter(name = "deviceId", description = "设备国标编号", required = true)
     @GetMapping("/latest/{deviceId}")
-    public ResponseEntity<MobilePosition> latestPosition(@PathVariable String deviceId) {
-//        if (logger.isDebugEnabled()) {
-//            logger.debug("查询设备" + deviceId + "的最新位置");
-//        }
-        MobilePosition result = storager.queryLatestPosition(deviceId);
-        return new ResponseEntity<>(result, HttpStatus.OK);
+    public MobilePosition latestPosition(@PathVariable String deviceId) {
+        return storager.queryLatestPosition(deviceId);
     }
 
     /**
@@ -112,12 +96,10 @@ public class MobilePositionController {
      * @param deviceId 设备ID
      * @return
      */
-    @ApiOperation("获取移动位置信息")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-    })
+    @Operation(summary = "获取移动位置信息")
+    @Parameter(name = "deviceId", description = "设备国标编号", required = true)
     @GetMapping("/realtime/{deviceId}")
-    public DeferredResult<ResponseEntity<MobilePosition>> realTimePosition(@PathVariable String deviceId) {
+    public DeferredResult<MobilePosition> realTimePosition(@PathVariable String deviceId) {
         Device device = storager.queryVideoDevice(deviceId);
         String uuid = UUID.randomUUID().toString();
         String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
@@ -128,7 +110,7 @@ public class MobilePositionController {
 			msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", event.statusCode, event.msg));
 			resultHolder.invokeResult(msg);
 		});
-        DeferredResult<ResponseEntity<MobilePosition>> result = new DeferredResult<ResponseEntity<MobilePosition>>(5*1000L);
+        DeferredResult<MobilePosition> result = new DeferredResult<MobilePosition>(5*1000L);
 		result.onTimeout(()->{
 			logger.warn(String.format("获取移动位置信息超时"));
 			// 释放rtpserver
@@ -149,14 +131,12 @@ public class MobilePositionController {
      * @param interval 上报时间间隔
      * @return true = 命令发送成功
      */
-    @ApiOperation("订阅位置信息")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-            @ApiImplicitParam(name = "expires", value = "订阅超时时间", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "interval", value = "上报时间间隔", dataTypeClass = String.class),
-    })
+    @Operation(summary = "订阅位置信息")
+    @Parameter(name = "deviceId", description = "设备国标编号", required = true)
+    @Parameter(name = "expires", description = "订阅超时时间", required = true)
+    @Parameter(name = "interval", description = "上报时间间隔", required = true)
     @GetMapping("/subscribe/{deviceId}")
-    public ResponseEntity<String> positionSubscribe(@PathVariable String deviceId,
+    public String positionSubscribe(@PathVariable String deviceId,
                                                     @RequestParam String expires,
                                                     @RequestParam String interval) {
         String msg = ((expires.equals("0")) ? "取消" : "") + "订阅设备" + deviceId + "的移动位置";
@@ -178,6 +158,6 @@ public class MobilePositionController {
             result += ",失败";
         }
 
-        return new ResponseEntity<>(result, HttpStatus.OK);
+        return result;
     }
 }

+ 3 - 9
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java

@@ -1,10 +1,8 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.SseController;
 
 import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEventListener;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.CrossOrigin;
@@ -18,7 +16,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  * @author: lawrencehj
  * @data: 2021-01-20
  */
-@Api(tags = "SSE推送")
+@Tag(name  = "SSE推送")
 @CrossOrigin
 @Controller
 @RequestMapping("/api")
@@ -26,10 +24,6 @@ public class SseController {
     @Autowired
     AlarmEventListener alarmEventListener;
 
-    @ApiOperation("浏览器推送")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "browserId", value = "浏览器ID", dataTypeClass = String.class),
-    })
     @GetMapping("/emit")
     public SseEmitter emit(@RequestParam String browserId) {
         final SseEmitter sseEmitter = new SseEmitter(0L);

+ 81 - 109
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java

@@ -1,34 +1,33 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.alarm;
 
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
-import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
-import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.models.auth.In;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
-import java.text.ParseException;
 import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.List;
 
-@Api(tags = "报警信息管理")
+@Tag(name = "报警信息管理")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/alarm")
@@ -46,68 +45,6 @@ public class AlarmController {
     @Autowired
     private IVideoManagerStorage storage;
 
-    /**
-     *  分页查询报警
-     *
-     * @param deviceId 设备id
-     * @param page 当前页
-     * @param count 每页查询数量
-     * @param alarmPriority  报警级别
-     * @param alarmMethod 报警方式
-     * @param alarmType  报警类型
-     * @param startTime  开始时间
-     * @param endTime 结束时间
-     * @return
-     */
-    @ApiOperation("分页查询报警")
-    @GetMapping("/all")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name="deviceId", value = "设备id", dataTypeClass = String.class),
-            @ApiImplicitParam(name="page", value = "当前页", required = true ,dataTypeClass = Integer.class),
-            @ApiImplicitParam(name="count", value = "每页查询数量", required = true ,dataTypeClass = Integer.class),
-            @ApiImplicitParam(name="alarmPriority", value = "查询内容" ,dataTypeClass = String.class),
-            @ApiImplicitParam(name="alarmMethod", value = "查询内容" ,dataTypeClass = String.class),
-            @ApiImplicitParam(name="alarmMethod", value = "查询内容" ,dataTypeClass = String.class),
-            @ApiImplicitParam(name="alarmType", value = "查询内容" ,dataTypeClass = String.class),
-            @ApiImplicitParam(name="startTime", value = "开始时间" ,dataTypeClass = String.class),
-            @ApiImplicitParam(name="endTime", value = "结束时间" ,dataTypeClass = String.class),
-    })
-    public ResponseEntity<PageInfo<DeviceAlarm>> getAll(
-                                             @RequestParam int page,
-                                             @RequestParam int count,
-                                             @RequestParam(required = false)  String deviceId,
-                                             @RequestParam(required = false) String alarmPriority,
-                                             @RequestParam(required = false) String alarmMethod,
-                                             @RequestParam(required = false) String alarmType,
-                                             @RequestParam(required = false) String startTime,
-                                             @RequestParam(required = false) String endTime
-                                             ) {
-        if (StringUtils.isEmpty(alarmPriority)) {
-            alarmPriority = null;
-        }
-        if (StringUtils.isEmpty(alarmMethod)) {
-            alarmMethod = null;
-        }
-        if (StringUtils.isEmpty(alarmType)) {
-            alarmType = null;
-        }
-        if (StringUtils.isEmpty(startTime)) {
-            startTime = null;
-        }
-        if (StringUtils.isEmpty(endTime)) {
-            endTime = null;
-        }
-
-
-        if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){
-            return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
-        }
-
-        PageInfo<DeviceAlarm> allAlarm = deviceAlarmService.getAllAlarm(page, count, deviceId, alarmPriority, alarmMethod,
-                alarmType, startTime, endTime);
-        return new ResponseEntity<>(allAlarm, HttpStatus.OK);
-    }
-
 
     /**
      *  删除报警
@@ -117,29 +54,27 @@ public class AlarmController {
      * @param time 结束时间(这个时间之前的报警会被删除)
      * @return
      */
-    @ApiOperation("删除报警")
     @DeleteMapping("/delete")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name="id", value = "ID", required = false ,dataTypeClass = Integer.class),
-            @ApiImplicitParam(name="deviceIds", value = "多个设备id,逗号分隔", required = false ,dataTypeClass = String.class),
-            @ApiImplicitParam(name="time", value = "结束时间", required = false ,dataTypeClass = String.class),
-    })
-    public ResponseEntity<WVPResult<String>> delete(
-                                              @RequestParam(required = false) Integer id,
-                                              @RequestParam(required = false) String deviceIds,
-                                              @RequestParam(required = false) String time
+    @Operation(summary = "删除报警")
+    @Parameter(name = "id", description = "ID")
+    @Parameter(name = "deviceIds", description = "多个设备id,逗号分隔")
+    @Parameter(name = "time", description = "结束时间")
+    public Integer delete(
+            @RequestParam(required = false) Integer id,
+            @RequestParam(required = false) String deviceIds,
+            @RequestParam(required = false) String time
     ) {
-        if (StringUtils.isEmpty(id)) {
+        if (ObjectUtils.isEmpty(id)) {
             id = null;
         }
-        if (StringUtils.isEmpty(deviceIds)) {
+        if (ObjectUtils.isEmpty(deviceIds)) {
             deviceIds = null;
         }
-        if (StringUtils.isEmpty(time)) {
+        if (ObjectUtils.isEmpty(time)) {
             time = null;
         }
         if (!DateUtil.verification(time, DateUtil.formatter) ){
-            return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
+            return null;
         }
         List<String> deviceIdList = null;
         if (deviceIds != null) {
@@ -147,12 +82,7 @@ public class AlarmController {
             deviceIdList = Arrays.asList(deviceIdArray);
         }
 
-        int count = deviceAlarmService.clearAlarmBeforeTime(id, deviceIdList, time);
-        WVPResult wvpResult = new WVPResult();
-        wvpResult.setCode(0);
-        wvpResult.setMsg("success");
-        wvpResult.setData(count);
-        return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
+        return deviceAlarmService.clearAlarmBeforeTime(id, deviceIdList, time);
     }
 
     /**
@@ -161,17 +91,10 @@ public class AlarmController {
      * @param deviceId 报警id
      * @return
      */
-    @ApiOperation("测试向上级/设备发送模拟报警通知")
     @GetMapping("/test/notify/alarm")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name="deviceId", value = "deviceId", required = true ,dataTypeClass = Integer.class)
-    })
-    public ResponseEntity<WVPResult<String>> delete(
-            @RequestParam(required = false) String deviceId
-    ) {
-        if (StringUtils.isEmpty(deviceId)) {
-            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
-        }
+    @Operation(summary = "测试向上级/设备发送模拟报警通知")
+    @Parameter(name = "deviceId", description = "设备国标编号")
+    public void delete(@RequestParam String deviceId) {
         Device device = storage.queryVideoDevice(deviceId);
         ParentPlatform platform = storage.queryParentPlatByServerGBId(deviceId);
         DeviceAlarm deviceAlarm = new DeviceAlarm();
@@ -189,17 +112,66 @@ public class AlarmController {
         }else if (device == null && platform != null){
             commanderForPlatform.sendAlarmMessage(platform, deviceAlarm);
         }else {
-            WVPResult wvpResult = new WVPResult();
-            wvpResult.setCode(0);
-            wvpResult.setMsg("无法确定" + deviceId + "是平台还是设备");
-            return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(),"无法确定" + deviceId + "是平台还是设备");
         }
 
-        WVPResult wvpResult = new WVPResult();
-        wvpResult.setCode(0);
-        wvpResult.setMsg("success");
-        return new ResponseEntity<WVPResult<String>>(wvpResult, HttpStatus.OK);
     }
 
+    /**
+     *  分页查询报警
+     *
+     * @param deviceId 设备id
+     * @param page 当前页
+     * @param count 每页查询数量
+     * @param alarmPriority  报警级别
+     * @param alarmMethod 报警方式
+     * @param alarmType  报警类型
+     * @param startTime  开始时间
+     * @param endTime 结束时间
+     * @return
+     */
+    @Operation(summary = "分页查询报警")
+    @Parameter(name = "page",description = "当前页",required = true)
+    @Parameter(name = "count",description = "每页查询数量",required = true)
+    @Parameter(name = "deviceId",description = "设备id")
+    @Parameter(name = "alarmPriority",description = "查询内容")
+    @Parameter(name = "alarmMethod",description = "查询内容")
+    @Parameter(name = "alarmType",description = "每页查询数量")
+    @Parameter(name = "startTime",description = "开始时间")
+    @Parameter(name = "endTime",description = "结束时间")
+    @GetMapping("/all")
+    public PageInfo<DeviceAlarm> getAll(
+            @RequestParam int page,
+            @RequestParam int count,
+            @RequestParam(required = false)  String deviceId,
+            @RequestParam(required = false) String alarmPriority,
+            @RequestParam(required = false) String alarmMethod,
+            @RequestParam(required = false) String alarmType,
+            @RequestParam(required = false) String startTime,
+            @RequestParam(required = false) String endTime
+    ) {
+        if (ObjectUtils.isEmpty(alarmPriority)) {
+            alarmPriority = null;
+        }
+        if (ObjectUtils.isEmpty(alarmMethod)) {
+            alarmMethod = null;
+        }
+        if (ObjectUtils.isEmpty(alarmType)) {
+            alarmType = null;
+        }
+        if (ObjectUtils.isEmpty(startTime)) {
+            startTime = null;
+        }
+        if (ObjectUtils.isEmpty(endTime)) {
+            endTime = null;
+        }
+
+
+        if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间或结束时间格式有误");
+        }
 
+        return deviceAlarmService.getAllAlarm(page, count, deviceId, alarmPriority, alarmMethod,
+                alarmType, startTime, endTime);
+    }
 }

+ 21 - 25
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java

@@ -14,21 +14,21 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
 
 import java.util.UUID;
 
-@Api(tags = "国标设备配置")
+@Tag(name = "国标设备配置")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/device/config")
@@ -55,17 +55,15 @@ public class DeviceConfig {
 	 * @param heartBeatCount 心跳计数
 	 * @return
 	 */
-	@ApiOperation("基本配置设置命令")
 	@GetMapping("/basicParam/{deviceId}")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value ="设备ID" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道ID",dataTypeClass = String.class ),
-			@ApiImplicitParam(name = "name", value ="名称" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "expiration", value ="到期时间" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "heartBeatInterval", value ="心跳间隔" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "heartBeatCount", value ="心跳计数" ,dataTypeClass = String.class),
-	})
-	public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
+	@Operation(summary = "基本配置设置命令")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "name", description = "名称")
+	@Parameter(name = "expiration", description = "到期时间")
+	@Parameter(name = "heartBeatInterval", description = "心跳间隔")
+	@Parameter(name = "heartBeatCount", description = "心跳计数")
+	public DeferredResult<String> homePositionApi(@PathVariable String deviceId,
                                                                	String channelId,
                                                                 @RequestParam(required = false) String name,
 																@RequestParam(required = false) String expiration,
@@ -84,7 +82,7 @@ public class DeviceConfig {
 			msg.setData(String.format("设备配置操作失败,错误码: %s, %s", event.statusCode, event.msg));
 			resultHolder.invokeResult(msg);
 		});
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
+        DeferredResult<String> result = new DeferredResult<String>(3 * 1000L);
 		result.onTimeout(() -> {
 			logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
 			// 释放rtpserver
@@ -109,20 +107,18 @@ public class DeviceConfig {
 	 * @param channelId 通道ID
 	 * @return
 	 */
-	@ApiOperation("设备配置查询请求")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value ="设备ID" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道ID" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "configType", value ="配置类型" ,dataTypeClass = String.class),
-	})
+	@Operation(summary = "设备配置查询请求")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "configType", description = "配置类型")
 	@GetMapping("/query/{deviceId}/{configType}")
-    public DeferredResult<ResponseEntity<String>> configDownloadApi(@PathVariable String deviceId, 
+    public DeferredResult<String> configDownloadApi(@PathVariable String deviceId,
                                                                 @PathVariable String configType,
                                                                 @RequestParam(required = false) String channelId) {
 		if (logger.isDebugEnabled()) {
 			logger.debug("设备状态查询API调用");
 		}
-		String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
+		String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
 		String uuid = UUID.randomUUID().toString();
 		Device device = storager.queryVideoDevice(deviceId);
 		cmder.deviceConfigQuery(device, channelId, configType, event -> {
@@ -132,7 +128,7 @@ public class DeviceConfig {
 			msg.setData(String.format("获取设备配置失败,错误码: %s, %s", event.statusCode, event.msg));
 			resultHolder.invokeResult(msg);
 		});
-        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
+        DeferredResult<String> result = new DeferredResult<String > (3 * 1000L);
 		result.onTimeout(()->{
 			logger.warn(String.format("获取设备配置超时"));
 			// 释放rtpserver

+ 52 - 70
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java

@@ -8,28 +8,30 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.device;
 
 import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
 
 import java.util.UUID;
 
-@Api(tags = "国标设备控制")
+@Tag(name  = "国标设备控制")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/device/control")
@@ -51,12 +53,10 @@ public class DeviceControl {
      * 
      * @param deviceId 设备ID
      */
-	@ApiOperation("远程启动控制命令")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value ="设备ID", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "远程启动控制命令")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
     @GetMapping("/teleboot/{deviceId}")
-    public ResponseEntity<String> teleBootApi(@PathVariable String deviceId) {
+    public String teleBootApi(@PathVariable String deviceId) {
         if (logger.isDebugEnabled()) {
             logger.debug("设备远程启动API调用");
         }
@@ -66,10 +66,10 @@ public class DeviceControl {
             JSONObject json = new JSONObject();
             json.put("DeviceID", deviceId);
             json.put("Result", "OK");
-            return new ResponseEntity<>(json.toJSONString(), HttpStatus.OK);
+            return json.toJSONString();
         } else {
             logger.warn("设备远程启动API调用失败!");
-            return new ResponseEntity<String>("设备远程启动API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备远程启动API调用失败!");
         }
     }
 
@@ -80,13 +80,10 @@ public class DeviceControl {
      * @param recordCmdStr  Record:手动录像,StopRecord:停止手动录像
      * @param channelId     通道编码(可选)
      */
-    @ApiOperation("录像控制命令")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value ="设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "recordCmdStr", value ="命令, 可选值:Record(手动录像),StopRecord(停止手动录像)",
-					required = true ,dataTypeClass = String.class),
-	})
+	@Operation(summary = "录像控制")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "recordCmdStr", description = "命令, 可选值:Record(手动录像),StopRecord(停止手动录像)", required = true)
     @GetMapping("/record/{deviceId}/{recordCmdStr}")
     public DeferredResult<ResponseEntity<String>> recordApi(@PathVariable String deviceId,
             @PathVariable String recordCmdStr, String channelId) {
@@ -127,13 +124,10 @@ public class DeviceControl {
 	 * @param	deviceId 设备ID
 	 * @param	guardCmdStr SetGuard:布防,ResetGuard:撤防
 	 */
-	@ApiOperation("布防/撤防命令")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "guardCmdStr", value ="命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true,
-					dataTypeClass = String.class)
-	})
+	@Operation(summary = "布防/撤防命令")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
 	@GetMapping("/guard/{deviceId}/{guardCmdStr}")
 	public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
 		if (logger.isDebugEnabled()) {
@@ -171,13 +165,11 @@ public class DeviceControl {
 	 * @param	alarmMethod 报警方式(可选)
 	 * @param	alarmType   报警类型(可选)
 	 */
-	@ApiOperation("报警复位")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "alarmMethod", value ="报警方式", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "alarmType", value ="报警类型", dataTypeClass = String.class),
-	})
+	@Operation(summary = "报警复位")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "alarmMethod", description = "报警方式")
+	@Parameter(name = "alarmType", description = "报警类型")
 	@GetMapping("/reset_alarm/{deviceId}")
 	public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId, String channelId,
 																@RequestParam(required = false) String alarmMethod,
@@ -215,11 +207,9 @@ public class DeviceControl {
 	 * @param	deviceId 设备ID
 	 * @param	channelId  通道ID
 	 */
-	@ApiOperation("强制关键帧")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道ID", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "强制关键帧")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号")
 	@GetMapping("/i_frame/{deviceId}")
 	public ResponseEntity<String> iFrame(@PathVariable String deviceId,
 										@RequestParam(required = false) String channelId) {
@@ -249,15 +239,12 @@ public class DeviceControl {
      * @param presetIndex   调用预置位编号(可选)
      * @param channelId     通道编码(可选)
 	 */
-	@ApiOperation("看守位控制")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name = "enabled", value = "是否开启看守位 1:开启,0:关闭", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "resetTime", value = "自动归位时间间隔", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "presetIndex", value = "调用预置位编号", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value ="通道ID", dataTypeClass = String.class),
-	})
+	@Operation(summary = "看守位控制")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "enabled", description = "是否开启看守位 1:开启,0:关闭", required = true)
+	@Parameter(name = "presetIndex", description = "调用预置位编号")
+	@Parameter(name = "resetTime", description = "自动归位时间间隔")
 	@GetMapping("/home_position/{deviceId}/{enabled}")
 	public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
 																@PathVariable String enabled,
@@ -267,7 +254,7 @@ public class DeviceControl {
         if (logger.isDebugEnabled()) {
 			logger.debug("报警复位API调用");
 		}
-		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
+		String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
 		String uuid = UUID.randomUUID().toString();
 		Device device = storager.queryVideoDevice(deviceId);
 		cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
@@ -307,17 +294,14 @@ public class DeviceControl {
 	 * @param lengthy 拉框宽度像素值
 	 * @return
 	 */
-	@ApiOperation("拉框放大")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "length", value = "播放窗口长度像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "width", value = "播放窗口宽度像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "midpointx", value = "拉框中心的横轴坐标像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "midpointy", value = "拉框中心的纵轴坐标像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "lengthx", value = "拉框长度像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "lengthy", value = "拉框宽度像素值", required = true, dataTypeClass = Integer.class),
-	})
+	@Operation(summary = "拉框放大")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "length", description = "播放窗口长度像素值", required = true)
+	@Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true)
+	@Parameter(name = "midpointy", description = "拉框中心的纵轴坐标像素值", required = true)
+	@Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
+	@Parameter(name = "lengthy", description = "lengthy", required = true)
 	@GetMapping("drag_zoom/zoom_in")
 	public ResponseEntity<String> dragZoomIn(@RequestParam String deviceId,
 											 @RequestParam(required = false) String channelId,
@@ -356,17 +340,15 @@ public class DeviceControl {
 	 * @param lengthy 拉框宽度像素值
 	 * @return
 	 */
-	@ApiOperation("拉框缩小")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "length", value = "播放窗口长度像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "width", value = "播放窗口宽度像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "midpointx", value = "拉框中心的横轴坐标像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "midpointy", value = "拉框中心的纵轴坐标像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "lengthx", value = "拉框长度像素值", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "lengthy", value = "拉框宽度像素值", required = true, dataTypeClass = Integer.class),
-	})
+	@Operation(summary = "拉框放大")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号")
+	@Parameter(name = "length", description = "播放窗口长度像素值", required = true)
+	@Parameter(name = "width", description = "拉框中心的横轴坐标像素值", required = true)
+	@Parameter(name = "midpointx", description = "拉框中心的横轴坐标像素值", required = true)
+	@Parameter(name = "midpointy", description = "拉框中心的纵轴坐标像素值", required = true)
+	@Parameter(name = "lengthx", description = "拉框长度像素值", required = true)
+	@Parameter(name = "lengthy", description = "拉框宽度像素值", required = true)
 	@GetMapping("/drag_zoom/zoom_out")
 	public ResponseEntity<String> dragZoomOut(@RequestParam String deviceId,
 											  @RequestParam(required = false) String channelId,

+ 87 - 124
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java

@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.device;
 
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
@@ -17,12 +18,12 @@ import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.apache.commons.compress.utils.IOUtils;
 import org.apache.http.HttpResponse;
 import org.slf4j.Logger;
@@ -31,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
@@ -41,7 +43,7 @@ import java.io.*;
 import java.nio.file.Files;
 import java.util.*;
 
-@Api(tags = "国标设备查询", value = "国标设备查询")
+@Tag(name  = "国标设备查询", description = "国标设备查询")
 @SuppressWarnings("rawtypes")
 @CrossOrigin
 @RestController
@@ -79,19 +81,12 @@ public class DeviceQuery {
 	 * @param deviceId 国标ID
 	 * @return 国标设备
 	 */
-	@ApiOperation("使用ID查询国标设备")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "查询国标设备")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	@GetMapping("/devices/{deviceId}")
-	public ResponseEntity<Device> devices(@PathVariable String deviceId){
+	public Device devices(@PathVariable String deviceId){
 		
-//		if (logger.isDebugEnabled()) {
-//			logger.debug("查询视频设备API调用,deviceId:" + deviceId);
-//		}
-		
-		Device device = storager.queryVideoDevice(deviceId);
-		return new ResponseEntity<>(device,HttpStatus.OK);
+		return storager.queryVideoDevice(deviceId);
 	}
 
 	/**
@@ -100,18 +95,12 @@ public class DeviceQuery {
 	 * @param count 每页查询数量
 	 * @return 分页国标列表
 	 */
-	@ApiOperation("分页查询国标设备")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "page", value = "当前页", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),
-	})
+	@Operation(summary = "分页查询国标设备")
+	@Parameter(name = "page", description = "当前页", required = true)
+	@Parameter(name = "count", description = "每页查询数量", required = true)
 	@GetMapping("/devices")
 	public PageInfo<Device> devices(int page, int count){
 		
-//		if (logger.isDebugEnabled()) {
-//			logger.debug("查询所有视频设备API调用");
-//		}
-		
 		return storager.queryVideoDeviceList(page, count);
 	}
 
@@ -124,34 +113,29 @@ public class DeviceQuery {
 	 * @param query 查询内容
 	 * @param online 是否在线  在线 true / 离线 false
 	 * @param channelType 设备 false/子目录 true
+	 * @param catalogUnderDevice 是否直属与设备的目录
 	 * @return 通道列表
 	 */
-	@ApiOperation("分页查询通道")
 	@GetMapping("/devices/{deviceId}/channels")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name="deviceId", value = "设备id", required = true ,dataTypeClass = String.class),
-			@ApiImplicitParam(name="page", value = "当前页", required = true ,dataTypeClass = Integer.class),
-			@ApiImplicitParam(name="count", value = "每页查询数量", required = true ,dataTypeClass = Integer.class),
-			@ApiImplicitParam(name="query", value = "查询内容" ,dataTypeClass = String.class),
-			@ApiImplicitParam(name="online", value = "是否在线"  ,dataTypeClass = Boolean.class),
-			@ApiImplicitParam(name="channelType", value = "设备/子目录-> false/true" ,dataTypeClass = Boolean.class),
-			@ApiImplicitParam(name="catalogUnderDevice", value = "是否直属与设备的目录" ,dataTypeClass = Boolean.class),
-	})
-	public ResponseEntity<PageInfo> channels(@PathVariable String deviceId,
+	@Operation(summary = "分页查询通道")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "page", description = "当前页", required = true)
+	@Parameter(name = "count", description = "每页查询数量", required = true)
+	@Parameter(name = "query", description = "查询内容")
+	@Parameter(name = "online", description = "是否在线")
+	@Parameter(name = "channelType", description = "设备/子目录-> false/true")
+	@Parameter(name = "catalogUnderDevice", description = "是否直属与设备的目录")
+	public PageInfo channels(@PathVariable String deviceId,
 											   int page, int count,
 											   @RequestParam(required = false) String query,
 											   @RequestParam(required = false) Boolean online,
 											   @RequestParam(required = false) Boolean channelType,
 											   @RequestParam(required = false) Boolean catalogUnderDevice) {
-//		if (logger.isDebugEnabled()) {
-//			logger.debug("查询视频设备通道API调用");
-//		}
-		if (StringUtils.isEmpty(query)) {
+		if (ObjectUtils.isEmpty(query)) {
 			query = null;
 		}
 
-		PageInfo pageResult = storager.queryChannelsByDeviceId(deviceId, query, channelType, online, catalogUnderDevice, page, count);
-		return new ResponseEntity<>(pageResult,HttpStatus.OK);
+		return storager.queryChannelsByDeviceId(deviceId, query, channelType, online, catalogUnderDevice, page, count);
 	}
 
 	/**
@@ -159,10 +143,8 @@ public class DeviceQuery {
 	 * @param deviceId 设备id
 	 * @return
 	 */
-	@ApiOperation("同步设备通道")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name="deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "同步设备通道")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	@PostMapping("/devices/{deviceId}/sync")
 	public WVPResult<SyncStatus> devicesSync(@PathVariable String deviceId){
 		
@@ -173,11 +155,8 @@ public class DeviceQuery {
 		boolean status = deviceService.isSyncRunning(deviceId);
 		// 已存在则返回进度
 		if (status) {
-			WVPResult<SyncStatus> wvpResult = new WVPResult<>();
-			wvpResult.setCode(0);
 			SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
-			wvpResult.setData(channelSyncStatus);
-			return wvpResult;
+			return WVPResult.success(channelSyncStatus);
 		}
 		deviceService.sync(device);
 
@@ -192,12 +171,10 @@ public class DeviceQuery {
 	 * @param deviceId 设备id
 	 * @return
 	 */
-	@ApiOperation("移除设备")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name="deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "移除设备")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	@DeleteMapping("/devices/{deviceId}/delete")
-	public ResponseEntity<String> delete(@PathVariable String deviceId){
+	public String delete(@PathVariable String deviceId){
 		
 		if (logger.isDebugEnabled()) {
 			logger.debug("设备信息删除API调用,deviceId:" + deviceId);
@@ -221,10 +198,10 @@ public class DeviceQuery {
 			}
 			JSONObject json = new JSONObject();
 			json.put("deviceId", deviceId);
-			return new ResponseEntity<>(json.toString(),HttpStatus.OK);
+			return json.toString();
 		} else {
 			logger.warn("设备信息删除API调用失败!");
-			return new ResponseEntity<String>("设备信息删除API调用失败!", HttpStatus.INTERNAL_SERVER_ERROR);
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备信息删除API调用失败!");
 		}
 	}
 
@@ -239,16 +216,14 @@ public class DeviceQuery {
 	 * @param channelType 通道类型
 	 * @return 子通道列表
 	 */
-	@ApiOperation("分页查询子目录通道")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name="deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name="channelId", value = "通道id", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name="count", value = "每页条数", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name="query", value = "查询内容", dataTypeClass = String.class),
-			@ApiImplicitParam(name="online", value = "是否在线", dataTypeClass = Boolean.class),
-			@ApiImplicitParam(name="channelType", value = "通道类型, 子目录", dataTypeClass = Boolean.class),
-	})
+	@Operation(summary = "分页查询子目录通道")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "page", description = "当前页", required = true)
+	@Parameter(name = "count", description = "每页查询数量", required = true)
+	@Parameter(name = "query", description = "查询内容")
+	@Parameter(name = "online", description = "是否在线")
+	@Parameter(name = "channelType", description = "设备/子目录-> false/true")
 	@GetMapping("/sub_channels/{deviceId}/{channelId}/channels")
 	public ResponseEntity<PageInfo> subChannels(@PathVariable String deviceId,
 												  @PathVariable String channelId,
@@ -258,9 +233,6 @@ public class DeviceQuery {
 												  @RequestParam(required = false) Boolean online,
 												  @RequestParam(required = false) Boolean channelType){
 
-//		if (logger.isDebugEnabled()) {
-//			logger.debug("查询所有视频通道API调用");
-//		}
 		DeviceChannel deviceChannel = storager.queryChannel(deviceId,channelId);
 		if (deviceChannel == null) {
 			PageInfo<DeviceChannel> deviceChannelPageResult = new PageInfo<>();
@@ -277,13 +249,11 @@ public class DeviceQuery {
 	 * @param channel 通道
 	 * @return
 	 */
-	@ApiOperation("更新通道信息")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name="deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name="channel", value = "通道", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "更新通道信息")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channel", description = "通道信息", required = true)
 	@PostMapping("/channel/update/{deviceId}")
-	public ResponseEntity<PageInfo> updateChannel(@PathVariable String deviceId,DeviceChannel channel){
+	public ResponseEntity updateChannel(@PathVariable String deviceId,DeviceChannel channel){
 		deviceChannelService.updateChannel(deviceId, channel);
 		return new ResponseEntity<>(null,HttpStatus.OK);
 	}
@@ -294,17 +264,14 @@ public class DeviceQuery {
 	 * @param streamMode 数据流传输模式
 	 * @return
 	 */
-	@ApiOperation("修改数据流传输模式")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "streamMode", value = "数据流传输模式, 取值:" +
-					"UDP(udp传输),TCP-ACTIVE(tcp主动模式,暂不支持),TCP-PASSIVE(tcp被动模式)", dataTypeClass = String.class),
-	})
+	@Operation(summary = "修改数据流传输模式")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "streamMode", description = "数据流传输模式, 取值:" +
+			"UDP(udp传输),TCP-ACTIVE(tcp主动模式,暂不支持),TCP-PASSIVE(tcp被动模式)", required = true)
 	@PostMapping("/transport/{deviceId}/{streamMode}")
-	public ResponseEntity<PageInfo> updateTransport(@PathVariable String deviceId, @PathVariable String streamMode){
+	public ResponseEntity updateTransport(@PathVariable String deviceId, @PathVariable String streamMode){
 		Device device = storager.queryVideoDevice(deviceId);
 		device.setStreamMode(streamMode);
-//		storager.updateDevice(device);
 		deviceService.updateDevice(device);
 		return new ResponseEntity<>(null,HttpStatus.OK);
 	}
@@ -314,10 +281,8 @@ public class DeviceQuery {
 	 * @param device 设备信息
 	 * @return
 	 */
-	@ApiOperation("更新设备信息")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "device", value = "设备信息", required = true, dataTypeClass = Device.class)
-	})
+	@Operation(summary = "更新设备信息")
+	@Parameter(name = "device", description = "设备", required = true)
 	@PostMapping("/device/update/")
 	public ResponseEntity<WVPResult<String>> updateDevice(Device device){
 
@@ -335,10 +300,8 @@ public class DeviceQuery {
 	 * 
 	 * @param deviceId 设备id
 	 */
-	@ApiOperation("设备状态查询")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-	})
+	@Operation(summary = "设备状态查询")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	@GetMapping("/devices/{deviceId}/status")
 	public DeferredResult<ResponseEntity<String>> deviceStatusApi(@PathVariable String deviceId) {
 		if (logger.isDebugEnabled()) {
@@ -383,16 +346,14 @@ public class DeviceQuery {
 	 * @param endTime		报警发生终止时间(可选)
 	 * @return				true = 命令发送成功
 	 */
-	@ApiOperation("设备报警查询")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备id", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "startPriority", value = "报警起始级别", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "endPriority", value = "报警终止级别", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "alarmMethod", value = "报警方式条件", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "alarmType", value = "报警类型", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "startTime", value = "报警发生起始时间", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "endTime", value = "报警发生终止时间", dataTypeClass = String.class),
-	})
+	@Operation(summary = "设备状态查询")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "startPriority", description = "报警起始级别")
+	@Parameter(name = "endPriority", description = "报警终止级别")
+	@Parameter(name = "alarmMethod", description = "报警方式条件")
+	@Parameter(name = "alarmType", description = "报警类型")
+	@Parameter(name = "startTime", description = "报警发生起始时间")
+	@Parameter(name = "endTime", description = "报警发生终止时间")
 	@GetMapping("/alarm/{deviceId}")
 	public DeferredResult<ResponseEntity<String>> alarmApi(@PathVariable String deviceId,
 														@RequestParam(required = false) String startPriority, 
@@ -430,7 +391,8 @@ public class DeviceQuery {
 
 
 	@GetMapping("/{deviceId}/sync_status")
-	@ApiOperation(value = "获取通道同步进度", notes = "获取通道同步进度")
+	@Operation(summary = "获取通道同步进度")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	public WVPResult<SyncStatus> getSyncStatus(@PathVariable String deviceId) {
 		SyncStatus channelSyncStatus = deviceService.getChannelSyncStatus(deviceId);
 		WVPResult<SyncStatus> wvpResult = new WVPResult<>();
@@ -438,7 +400,8 @@ public class DeviceQuery {
 			wvpResult.setCode(-1);
 			wvpResult.setMsg("同步尚未开始");
 		}else {
-			wvpResult.setCode(0);
+			wvpResult.setCode(ErrorCode.SUCCESS.getCode());
+			wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
 			wvpResult.setData(channelSyncStatus);
 			if (channelSyncStatus.getErrorMsg() != null) {
 				wvpResult.setMsg(channelSyncStatus.getErrorMsg());
@@ -448,7 +411,8 @@ public class DeviceQuery {
 	}
 
 	@GetMapping("/{deviceId}/subscribe_info")
-	@ApiOperation(value = "获取设备的订阅状态", notes = "获取设备的订阅状态")
+	@Operation(summary = "获取设备的订阅状态")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
 	public WVPResult<Map<String, String>> getSubscribeInfo(@PathVariable String deviceId) {
 		Set<String> allKeys = dynamicTask.getAllKeys();
 		Map<String, String> dialogStateMap = new HashMap<>();
@@ -473,7 +437,9 @@ public class DeviceQuery {
 	}
 
 	@GetMapping("/snap/{deviceId}/{channelId}")
-	@ApiOperation(value = "请求截图", notes = "请求截图")
+	@Operation(summary = "请求截图")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
 	public void getSnap(HttpServletResponse resp, @PathVariable String deviceId, @PathVariable String channelId) {
 
 		try {
@@ -493,16 +459,17 @@ public class DeviceQuery {
 	 * @param count 每页条数
 	 * @return 国标设备
 	 */
-	@ApiOperation("查询国标树")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "parentId", value = "父ID", required = false, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "onlyCatalog", value = "只获取目录", required = false, dataTypeClass = Boolean.class),
-			@ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name="count", value = "每页条数", required = true, dataTypeClass = Integer.class),
-	})
+	@Operation(summary = "查询国标树")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "parentId", description = "父级国标编号")
+	@Parameter(name = "onlyCatalog", description = "只获取目录")
+	@Parameter(name = "page", description = "当前页", required = true)
+	@Parameter(name = "count", description = "每页条数", required = true)
 	@GetMapping("/tree/{deviceId}")
-	public ResponseEntity<PageInfo> getTree(@PathVariable String deviceId, @RequestParam(required = false) String parentId, @RequestParam(required = false) Boolean onlyCatalog, int page, int count){
+	public ResponseEntity<PageInfo> getTree(@PathVariable String deviceId,
+											@RequestParam(required = false) String parentId,
+											@RequestParam(required = false) Boolean onlyCatalog,
+											int page, int count){
 
 
 		if (page <= 0) {
@@ -534,7 +501,6 @@ public class DeviceQuery {
 		return new ResponseEntity<>(pageInfo,HttpStatus.OK);
 	}
 
-
 	/**
 	 * 查询国标树下的通道
 	 * @param deviceId 设备ID
@@ -543,17 +509,14 @@ public class DeviceQuery {
 	 * @param count 每页条数
 	 * @return 国标设备
 	 */
-	@ApiOperation("查询国标树下的通道")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
-			@ApiImplicitParam(name = "parentId", value = "父ID", required = false, dataTypeClass = String.class),
-			@ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
-			@ApiImplicitParam(name="count", value = "每页条数", required = true, dataTypeClass = Integer.class),
-	})
+	@Operation(summary = "查询国标树下的通道")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "parentId", description = "父级国标编号")
+	@Parameter(name = "page", description = "当前页", required = true)
+	@Parameter(name = "count", description = "每页条数", required = true)
 	@GetMapping("/tree/channel/{deviceId}")
 	public ResponseEntity<PageInfo> getChannelInTreeNode(@PathVariable String deviceId, @RequestParam(required = false) String parentId, int page, int count){
 
-
 		if (page <= 0) {
 			page = 1;
 		}

+ 17 - 27
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java

@@ -5,17 +5,17 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean.GbStreamParam;
 import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.github.pagehelper.PageInfo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
-@Api(tags = "视频流关联到级联平台")
+@Tag(name  = "视频流关联到级联平台")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/gbStream")
@@ -37,16 +37,13 @@ public class GbStreamController {
      * @param platformId 平台ID
      * @return
      */
-    @ApiOperation("查询国标通道")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "page", value = "当前页", required = true , dataTypeClass = Integer.class),
-            @ApiImplicitParam(name = "count", value = "每页条数", required = true , dataTypeClass = Integer.class),
-            @ApiImplicitParam(name = "platformId", value = "平台ID", required = true , dataTypeClass = String.class),
-            @ApiImplicitParam(name = "catalogId", value = "目录ID", required = false , dataTypeClass = String.class),
-            @ApiImplicitParam(name="query", value = "查询内容", required = false , dataTypeClass = String.class),
-            @ApiImplicitParam(name="mediaServerId", value = "流媒体ID", required = false , dataTypeClass = String.class),
-
-    })
+    @Operation(summary = "查询国标通道")
+    @Parameter(name = "page", description = "当前页", required = true)
+    @Parameter(name = "count", description = "每页条数", required = true)
+    @Parameter(name = "platformId", description = "平台ID", required = true)
+    @Parameter(name = "catalogId", description = "目录ID")
+    @Parameter(name = "query", description = "查询内容")
+    @Parameter(name = "mediaServerId", description = "流媒体ID")
     @GetMapping(value = "/list")
     @ResponseBody
     public PageInfo<GbStream> list(@RequestParam(required = true)Integer page,
@@ -55,13 +52,13 @@ public class GbStreamController {
                                    @RequestParam(required = false)String catalogId,
                                    @RequestParam(required = false)String query,
                                    @RequestParam(required = false)String mediaServerId){
-        if (StringUtils.isEmpty(catalogId)) {
+        if (ObjectUtils.isEmpty(catalogId)) {
             catalogId = null;
         }
-        if (StringUtils.isEmpty(query)) {
+        if (ObjectUtils.isEmpty(query)) {
             query = null;
         }
-        if (StringUtils.isEmpty(mediaServerId)) {
+        if (ObjectUtils.isEmpty(mediaServerId)) {
             mediaServerId = null;
         }
 
@@ -76,11 +73,7 @@ public class GbStreamController {
      * @param gbStreamParam
      * @return
      */
-    @ApiOperation("移除国标关联")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "gbStreamParam", value = "GbStreamParam", required = true,
-                    dataTypeClass = GbStreamParam.class),
-    })
+    @Operation(summary = "移除国标关联")
     @DeleteMapping(value = "/del")
     @ResponseBody
     public Object del(@RequestBody GbStreamParam gbStreamParam){
@@ -97,10 +90,7 @@ public class GbStreamController {
      * @param gbStreamParam
      * @return
      */
-    @ApiOperation("保存国标关联")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "gbStreamParam", value = "GbStreamParam", required = true, dataTypeClass = GbStreamParam.class),
-    })
+    @Operation(summary = "保存国标关联")
     @PostMapping(value = "/add")
     @ResponseBody
     public Object add(@RequestBody GbStreamParam gbStreamParam){

+ 5 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java

@@ -1,15 +1,20 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.gbStream.bean;
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import io.swagger.v3.oas.annotations.media.Schema;
 
 import java.util.List;
 
+@Schema(description = "国标关联参数")
 public class GbStreamParam {
 
+    @Schema(description = "平台ID")
     private String platformId;
 
+    @Schema(description = "目录ID")
     private String catalogId;
 
+    @Schema(description = "流国标信息列表")
     private List<GbStream> gbStreams;
 
     public String getPlatformId() {

+ 17 - 29
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java

@@ -1,21 +1,18 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.media;
 
 import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
-import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
-import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
-import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -25,7 +22,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletRequest;
 
 
-@Api(tags = "媒体流相关")
+@Tag(name  = "媒体流相关")
 @Controller
 @CrossOrigin
 @RequestMapping(value = "/api/media")
@@ -48,15 +45,15 @@ public class MediaController {
      * @param stream 流id
      * @return
      */
-    @ApiOperation("根据应用名和流id获取播放地址")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "app", value = "应用名", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "stream", value = "流id", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "mediaServerId", value = "媒体服务器id", dataTypeClass = String.class, required = false),
-    })
+    @Operation(summary = "根据应用名和流id获取播放地址")
+    @Parameter(name = "app", description = "应用名", required = true)
+    @Parameter(name = "stream", description = "流id", required = true)
+    @Parameter(name = "mediaServerId", description = "媒体服务器id")
+    @Parameter(name = "callId", description = "推流时携带的自定义鉴权ID")
+    @Parameter(name = "useSourceIpAsStreamIp", description = "是否使用请求IP作为返回的地址IP")
     @GetMapping(value = "/stream_info_by_app_and_stream")
     @ResponseBody
-    public WVPResult<StreamInfo> getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
+    public StreamInfo getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
                                                              @RequestParam String stream,
                                                              @RequestParam(required = false) String mediaServerId,
                                                              @RequestParam(required = false) String callId,
@@ -68,10 +65,7 @@ public class MediaController {
             if (streamAuthorityInfo.getCallId().equals(callId)) {
                 authority = true;
             }else {
-                WVPResult<StreamInfo> result = new WVPResult<>();
-                result.setCode(401);
-                result.setMsg("fail");
-                return result;
+                throw new ControllerException(ErrorCode.ERROR400);
             }
         }else {
             // 是否登陆用户, 登陆用户返回完整信息
@@ -94,9 +88,7 @@ public class MediaController {
 
         WVPResult<StreamInfo> result = new WVPResult<>();
         if (streamInfo != null){
-            result.setCode(0);
-            result.setMsg("scccess");
-            result.setData(streamInfo);
+            return  streamInfo;
         }else {
             //获取流失败,重启拉流后重试一次
             streamProxyService.stop(app,stream);
@@ -115,14 +107,10 @@ public class MediaController {
                 streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
             }
             if (streamInfo != null){
-                result.setCode(0);
-                result.setMsg("scccess");
-                result.setData(streamInfo);
+                return  streamInfo;
             }else {
-                result.setCode(-1);
-                result.setMsg("fail");
+                throw new ControllerException(ErrorCode.ERROR100);
             }
         }
-        return result;
     }
 }

+ 119 - 222
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.VideoManagerConstants;
 import com.genersoft.iot.vmp.conf.DynamicTask;
 import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
@@ -14,19 +15,20 @@ import com.genersoft.iot.vmp.service.IPlatformChannelService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam;
 import com.github.pagehelper.PageInfo;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -36,7 +38,7 @@ import java.util.List;
 /**
  * 级联平台管理
  */
-@Api(tags = "级联平台管理")
+@Tag(name  = "级联平台管理")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/platform")
@@ -73,15 +75,15 @@ public class PlatformController {
      *
      * @return
      */
-    @ApiOperation("获取国标服务的配置")
+    @Operation(summary = "获取国标服务的配置")
     @GetMapping("/server_config")
-    public ResponseEntity<JSONObject> serverConfig() {
+    public JSONObject serverConfig() {
         JSONObject result = new JSONObject();
         result.put("deviceIp", sipConfig.getIp());
         result.put("devicePort", sipConfig.getPort());
         result.put("username", sipConfig.getId());
         result.put("password", sipConfig.getPassword());
-        return new ResponseEntity<>(result, HttpStatus.OK);
+        return result;
     }
 
     /**
@@ -89,20 +91,17 @@ public class PlatformController {
      *
      * @return
      */
-    @ApiOperation("获取国标服务的配置")
+    @Operation(summary = "获取级联服务器信息")
+    @Parameter(name = "id", description = "平台国标编号", required = true)
     @GetMapping("/info/{id}")
-    public ResponseEntity<WVPResult<ParentPlatform>> getPlatform(@PathVariable String id) {
+    public ParentPlatform getPlatform(@PathVariable String id) {
         ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(id);
         WVPResult<ParentPlatform> wvpResult = new WVPResult<>();
         if (parentPlatform != null) {
-            wvpResult.setCode(0);
-            wvpResult.setMsg("success");
-            wvpResult.setData(parentPlatform);
+            return  parentPlatform;
         } else {
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("未查询到此平台");
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未查询到此平台");
         }
-        return new ResponseEntity<>(wvpResult, HttpStatus.OK);
     }
 
     /**
@@ -112,12 +111,10 @@ public class PlatformController {
      * @param count 每页条数
      * @return
      */
-    @ApiOperation("分页查询级联平台")
     @GetMapping("/query/{count}/{page}")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "page", value = "当前页", dataTypeClass = Integer.class),
-            @ApiImplicitParam(name = "count", value = "每页条数", dataTypeClass = Integer.class),
-    })
+    @Operation(summary = "分页查询级联平台")
+    @Parameter(name = "page", description = "当前页", required = true)
+    @Parameter(name = "count", description = "每页条数", required = true)
     public PageInfo<ParentPlatform> platforms(@PathVariable int page, @PathVariable int count) {
 
         PageInfo<ParentPlatform> parentPlatformPageInfo = storager.queryParentPlatformList(page, count);
@@ -136,44 +133,34 @@ public class PlatformController {
      * @param parentPlatform
      * @return
      */
-    @ApiOperation("添加上级平台信息")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "parentPlatform", value = "上级平台信息", dataTypeClass = ParentPlatform.class),
-    })
+    @Operation(summary = "添加上级平台信息")
     @PostMapping("/add")
     @ResponseBody
-    public ResponseEntity<WVPResult<String>> addPlatform(@RequestBody ParentPlatform parentPlatform) {
+    public String addPlatform(@RequestBody ParentPlatform parentPlatform) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("保存上级平台信息API调用");
         }
-        WVPResult<String> wvpResult = new WVPResult<>();
-        if (StringUtils.isEmpty(parentPlatform.getName())
-                || StringUtils.isEmpty(parentPlatform.getServerGBId())
-                || StringUtils.isEmpty(parentPlatform.getServerGBDomain())
-                || StringUtils.isEmpty(parentPlatform.getServerIP())
-                || StringUtils.isEmpty(parentPlatform.getServerPort())
-                || StringUtils.isEmpty(parentPlatform.getDeviceGBId())
-                || StringUtils.isEmpty(parentPlatform.getExpires())
-                || StringUtils.isEmpty(parentPlatform.getKeepTimeout())
-                || StringUtils.isEmpty(parentPlatform.getTransport())
-                || StringUtils.isEmpty(parentPlatform.getCharacterSet())
+        if (ObjectUtils.isEmpty(parentPlatform.getName())
+                || ObjectUtils.isEmpty(parentPlatform.getServerGBId())
+                || ObjectUtils.isEmpty(parentPlatform.getServerGBDomain())
+                || ObjectUtils.isEmpty(parentPlatform.getServerIP())
+                || ObjectUtils.isEmpty(parentPlatform.getServerPort())
+                || ObjectUtils.isEmpty(parentPlatform.getDeviceGBId())
+                || ObjectUtils.isEmpty(parentPlatform.getExpires())
+                || ObjectUtils.isEmpty(parentPlatform.getKeepTimeout())
+                || ObjectUtils.isEmpty(parentPlatform.getTransport())
+                || ObjectUtils.isEmpty(parentPlatform.getCharacterSet())
         ) {
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("missing parameters");
-            return new ResponseEntity<>(wvpResult, HttpStatus.BAD_REQUEST);
+            throw new ControllerException(ErrorCode.ERROR400);
         }
         if (parentPlatform.getServerPort() < 0 || parentPlatform.getServerPort() > 65535) {
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("error severPort");
-            return new ResponseEntity<>(wvpResult, HttpStatus.BAD_REQUEST);
+            throw new ControllerException(ErrorCode.ERROR400.getCode(), "error severPort");
         }
 
         ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
         if (parentPlatformOld != null) {
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("平台 " + parentPlatform.getServerGBId() + " 已存在");
-            return new ResponseEntity<>(wvpResult, HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台 " + parentPlatform.getServerGBId() + " 已存在");
         }
         parentPlatform.setCreateTime(DateUtil.getNow());
         parentPlatform.setUpdateTime(DateUtil.getNow());
@@ -195,13 +182,9 @@ public class PlatformController {
             } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
                 commanderForPlatform.unregister(parentPlatform, null, null);
             }
-            wvpResult.setCode(0);
-            wvpResult.setMsg("success");
-            return new ResponseEntity<>(wvpResult, HttpStatus.OK);
+            return null;
         } else {
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("写入数据库失败");
-            return new ResponseEntity<>(wvpResult, HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败");
         }
     }
 
@@ -211,32 +194,26 @@ public class PlatformController {
      * @param parentPlatform
      * @return
      */
-    @ApiOperation("保存上级平台信息")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "parentPlatform", value = "上级平台信息", dataTypeClass = ParentPlatform.class),
-    })
+    @Operation(summary = "保存上级平台信息")
     @PostMapping("/save")
     @ResponseBody
-    public ResponseEntity<WVPResult<String>> savePlatform(@RequestBody ParentPlatform parentPlatform) {
+    public String savePlatform(@RequestBody ParentPlatform parentPlatform) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("保存上级平台信息API调用");
         }
-        WVPResult<String> wvpResult = new WVPResult<>();
-        if (StringUtils.isEmpty(parentPlatform.getName())
-                || StringUtils.isEmpty(parentPlatform.getServerGBId())
-                || StringUtils.isEmpty(parentPlatform.getServerGBDomain())
-                || StringUtils.isEmpty(parentPlatform.getServerIP())
-                || StringUtils.isEmpty(parentPlatform.getServerPort())
-                || StringUtils.isEmpty(parentPlatform.getDeviceGBId())
-                || StringUtils.isEmpty(parentPlatform.getExpires())
-                || StringUtils.isEmpty(parentPlatform.getKeepTimeout())
-                || StringUtils.isEmpty(parentPlatform.getTransport())
-                || StringUtils.isEmpty(parentPlatform.getCharacterSet())
+        if (ObjectUtils.isEmpty(parentPlatform.getName())
+                || ObjectUtils.isEmpty(parentPlatform.getServerGBId())
+                || ObjectUtils.isEmpty(parentPlatform.getServerGBDomain())
+                || ObjectUtils.isEmpty(parentPlatform.getServerIP())
+                || ObjectUtils.isEmpty(parentPlatform.getServerPort())
+                || ObjectUtils.isEmpty(parentPlatform.getDeviceGBId())
+                || ObjectUtils.isEmpty(parentPlatform.getExpires())
+                || ObjectUtils.isEmpty(parentPlatform.getKeepTimeout())
+                || ObjectUtils.isEmpty(parentPlatform.getTransport())
+                || ObjectUtils.isEmpty(parentPlatform.getCharacterSet())
         ) {
-            wvpResult.setCode(-1);
-            wvpResult.setMsg("missing parameters");
-            return new ResponseEntity<>(wvpResult, HttpStatus.BAD_REQUEST);
+            throw new ControllerException(ErrorCode.ERROR400);
         }
         parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase());
         ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
@@ -270,13 +247,9 @@ public class PlatformController {
                 // 停止订阅相关的定时任务
                 subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
             }
-            wvpResult.setCode(0);
-            wvpResult.setMsg("success");
-            return new ResponseEntity<>(wvpResult, HttpStatus.OK);
+            return null;
         } else {
-            wvpResult.setCode(0);
-            wvpResult.setMsg("写入数据库失败");
-            return new ResponseEntity<>(wvpResult, HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败");
         }
     }
 
@@ -286,24 +259,22 @@ public class PlatformController {
      * @param serverGBId 上级平台国标ID
      * @return
      */
-    @ApiOperation("删除上级平台")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "serverGBId", value = "上级平台国标ID", dataTypeClass = String.class),
-    })
+    @Operation(summary = "删除上级平台")
+    @Parameter(name = "serverGBId", description = "上级平台的国标编号")
     @DeleteMapping("/delete/{serverGBId}")
     @ResponseBody
-    public ResponseEntity<String> deletePlatform(@PathVariable String serverGBId) {
+    public String deletePlatform(@PathVariable String serverGBId) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("删除上级平台API调用");
         }
-        if (StringUtils.isEmpty(serverGBId)
+        if (ObjectUtils.isEmpty(serverGBId)
         ) {
-            return new ResponseEntity<>("missing parameters", HttpStatus.BAD_REQUEST);
+            throw new ControllerException(ErrorCode.ERROR400);
         }
         ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId);
         if (parentPlatform == null) {
-            return new ResponseEntity<>("fail", HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在");
         }
         // 发送离线消息,无论是否成功都删除缓存
         commanderForPlatform.unregister(parentPlatform, (event -> {
@@ -327,9 +298,9 @@ public class PlatformController {
         // 删除缓存的订阅信息
         subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
         if (deleteResult) {
-            return new ResponseEntity<>("success", HttpStatus.OK);
+            return null;
         } else {
-            return new ResponseEntity<>("fail", HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100);
         }
     }
 
@@ -339,19 +310,14 @@ public class PlatformController {
      * @param serverGBId 上级平台国标ID
      * @return
      */
-    @ApiOperation("查询上级平台是否存在")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "serverGBId", value = "上级平台国标ID", dataTypeClass = String.class),
-    })
+    @Operation(summary = "查询上级平台是否存在")
+    @Parameter(name = "serverGBId", description = "上级平台的国标编号")
     @GetMapping("/exit/{serverGBId}")
     @ResponseBody
-    public ResponseEntity<String> exitPlatform(@PathVariable String serverGBId) {
+    public Boolean exitPlatform(@PathVariable String serverGBId) {
 
-//        if (logger.isDebugEnabled()) {
-//            logger.debug("查询上级平台是否存在API调用:" + serverGBId);
-//        }
         ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId);
-        return new ResponseEntity<>(String.valueOf(parentPlatform != null), HttpStatus.OK);
+        return parentPlatform != null;
     }
 
     /**
@@ -365,16 +331,14 @@ public class PlatformController {
      * @param channelType 通道类型
      * @return
      */
-    @ApiOperation("分页查询级联平台的所有所有通道")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "page", value = "当前页", dataTypeClass = Integer.class),
-            @ApiImplicitParam(name = "count", value = "每页条数", dataTypeClass = Integer.class),
-            @ApiImplicitParam(name = "platformId", value = "上级平台ID", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "catalogId", value = "目录ID", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "query", value = "查询内容", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "online", value = "是否在线", dataTypeClass = Boolean.class),
-            @ApiImplicitParam(name = "channelType", value = "通道类型", dataTypeClass = Boolean.class),
-    })
+    @Operation(summary = "查询上级平台是否存在")
+    @Parameter(name = "page", description = "当前页", required = true)
+    @Parameter(name = "count", description = "每页条数", required = true)
+    @Parameter(name = "platformId", description = "上级平台的国标编号")
+    @Parameter(name = "catalogId", description = "目录ID")
+    @Parameter(name = "query", description = "查询内容")
+    @Parameter(name = "online", description = "是否在线")
+    @Parameter(name = "channelType", description = "通道类型")
     @GetMapping("/channel_list")
     @ResponseBody
     public PageInfo<ChannelReduce> channelList(int page, int count,
@@ -384,16 +348,13 @@ public class PlatformController {
                                                @RequestParam(required = false) Boolean online,
                                                @RequestParam(required = false) Boolean channelType) {
 
-//        if (logger.isDebugEnabled()) {
-//            logger.debug("查询所有所有通道API调用");
-//        }
-        if (StringUtils.isEmpty(platformId)) {
+        if (ObjectUtils.isEmpty(platformId)) {
             platformId = null;
         }
-        if (StringUtils.isEmpty(query)) {
+        if (ObjectUtils.isEmpty(query)) {
             query = null;
         }
-        if (StringUtils.isEmpty(platformId) || StringUtils.isEmpty(catalogId)) {
+        if (ObjectUtils.isEmpty(platformId) || ObjectUtils.isEmpty(catalogId)) {
             catalogId = null;
         }
         PageInfo<ChannelReduce> channelReduces = storager.queryAllChannelList(page, count, query, online, channelType, platformId, catalogId);
@@ -407,20 +368,18 @@ public class PlatformController {
      * @param param 通道关联参数
      * @return
      */
-    @ApiOperation("向上级平台添加国标通道")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "param", value = "通道关联参数", dataTypeClass = UpdateChannelParam.class),
-    })
+    @Operation(summary = "向上级平台添加国标通道")
     @PostMapping("/update_channel_for_gb")
     @ResponseBody
-    public ResponseEntity<String> updateChannelForGB(@RequestBody UpdateChannelParam param) {
+    public void updateChannelForGB(@RequestBody UpdateChannelParam param) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("给上级平台添加国标通道API调用");
         }
         int result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
-
-        return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
+        if (result <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100);
+        }
     }
 
     /**
@@ -429,20 +388,19 @@ public class PlatformController {
      * @param param 通道关联参数
      * @return
      */
-    @ApiOperation("从上级平台移除国标通道")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "param", value = "通道关联参数", dataTypeClass = UpdateChannelParam.class),
-    })
+    @Operation(summary = "从上级平台移除国标通道")
     @DeleteMapping("/del_channel_for_gb")
     @ResponseBody
-    public ResponseEntity<String> delChannelForGB(@RequestBody UpdateChannelParam param) {
+    public void delChannelForGB(@RequestBody UpdateChannelParam param) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("给上级平台删除国标通道API调用");
         }
         int result = storager.delChannelForGB(param.getPlatformId(), param.getChannelReduces());
 
-        return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
+        if (result <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100);
+        }
     }
 
     /**
@@ -452,37 +410,25 @@ public class PlatformController {
      * @param parentId   目录父ID
      * @return
      */
-    @ApiOperation("获取目录")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "platformId", value = "平台ID", dataTypeClass = String.class, required = true),
-            @ApiImplicitParam(name = "parentId", value = "目录父ID", dataTypeClass = String.class, required = true),
-    })
+    @Operation(summary = "获取目录")
+    @Parameter(name = "platformId", description = "上级平台的国标编号", required = true)
+    @Parameter(name = "parentId", description = "父级目录的国标编号", required = true)
     @GetMapping("/catalog")
     @ResponseBody
-    public ResponseEntity<WVPResult<List<PlatformCatalog>>> getCatalogByPlatform(String platformId, String parentId) {
+    public List<PlatformCatalog> getCatalogByPlatform(String platformId, String parentId) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("查询目录,platformId: {}, parentId: {}", platformId, parentId);
         }
         ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
         if (platform == null) {
-            return new ResponseEntity<>(new WVPResult<>(400, "平台未找到", null), HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台未找到");
         }
         if (platformId.equals(parentId)) {
             parentId = platform.getDeviceGBId();
         }
-        List<PlatformCatalog> platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
-//        if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
-//            platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
-//        }else {
-//
-//        }
-
-        WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
-        result.setCode(0);
-        result.setMsg("success");
-        result.setData(platformCatalogList);
-        return new ResponseEntity<>(result, HttpStatus.OK);
+
+        return storager.getChildrenCatalogByPlatform(platformId, parentId);
     }
 
     /**
@@ -491,34 +437,22 @@ public class PlatformController {
      * @param platformCatalog 目录
      * @return
      */
-    @ApiOperation("添加目录")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "platformCatalog", value = "目录信息", dataTypeClass = PlatformCatalog.class, required = true),
-    })
+    @Operation(summary = "添加目录")
     @PostMapping("/catalog/add")
     @ResponseBody
-    public ResponseEntity<WVPResult<List<PlatformCatalog>>> addCatalog(@RequestBody PlatformCatalog platformCatalog) {
+    public void addCatalog(@RequestBody PlatformCatalog platformCatalog) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("添加目录,{}", JSON.toJSONString(platformCatalog));
         }
         PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
-        WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
 
         if (platformCatalogInStore != null) {
-            result.setCode(-1);
-            result.setMsg(platformCatalog.getId() + " already exists");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), platformCatalog.getId() + " already exists");
         }
         int addResult = storager.addCatalog(platformCatalog);
-        if (addResult > 0) {
-            result.setCode(0);
-            result.setMsg("success");
-            return new ResponseEntity<>(result, HttpStatus.OK);
-        } else {
-            result.setCode(-500);
-            result.setMsg("save error");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+        if (addResult <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100);
         }
     }
 
@@ -528,32 +462,22 @@ public class PlatformController {
      * @param platformCatalog 目录
      * @return
      */
-    @ApiOperation("编辑目录")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "platformCatalog", value = "目录信息", dataTypeClass = PlatformCatalog.class, required = true),
-    })
+    @Operation(summary = "编辑目录")
     @PostMapping("/catalog/edit")
     @ResponseBody
-    public ResponseEntity<WVPResult<List<PlatformCatalog>>> editCatalog(@RequestBody PlatformCatalog platformCatalog) {
+    public void editCatalog(@RequestBody PlatformCatalog platformCatalog) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("编辑目录,{}", JSON.toJSONString(platformCatalog));
         }
         PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
-        WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
-        result.setCode(0);
 
         if (platformCatalogInStore == null) {
-            result.setMsg(platformCatalog.getId() + " not exists");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), platformCatalog.getId() + " not exists");
         }
         int addResult = storager.updateCatalog(platformCatalog);
-        if (addResult > 0) {
-            result.setMsg("success");
-            return new ResponseEntity<>(result, HttpStatus.OK);
-        } else {
-            result.setMsg("save error");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+        if (addResult <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "写入数据库失败");
         }
     }
 
@@ -561,27 +485,23 @@ public class PlatformController {
      * 删除目录
      *
      * @param id 目录Id
+     * @param platformId 平台Id
      * @return
      */
-    @ApiOperation("删除目录")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "id", value = "目录Id", dataTypeClass = String.class, required = true),
-    })
+    @Operation(summary = "删除目录")
+    @Parameter(name = "id", description = "目录Id", required = true)
+    @Parameter(name = "platformId", description = "平台Id", required = true)
     @DeleteMapping("/catalog/del")
     @ResponseBody
-    public ResponseEntity<WVPResult<String>> delCatalog(String id, String platformId) {
+    public void delCatalog(String id, String platformId) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("删除目录,{}", id);
         }
-        WVPResult<String> result = new WVPResult<>();
 
-        if (StringUtils.isEmpty(id) || StringUtils.isEmpty(platformId)) {
-            result.setCode(-1);
-            result.setMsg("param error");
-            return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
+        if (ObjectUtils.isEmpty(id) || ObjectUtils.isEmpty(platformId)) {
+            throw new ControllerException(ErrorCode.ERROR400);
         }
-        result.setCode(0);
 
         int delResult = storager.delCatalog(id);
         // 如果删除的是默认目录则根目录设置为默认目录
@@ -590,16 +510,10 @@ public class PlatformController {
         // 默认节点被移除
         if (parentPlatform == null) {
             storager.setDefaultCatalog(platformId, platformId);
-            result.setData(platformId);
         }
 
-
-        if (delResult > 0) {
-            result.setMsg("success");
-            return new ResponseEntity<>(result, HttpStatus.OK);
-        } else {
-            result.setMsg("save error");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+        if (delResult <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "写入数据库失败");
         }
     }
 
@@ -609,27 +523,18 @@ public class PlatformController {
      * @param platformCatalog 关联的信息
      * @return
      */
-    @ApiOperation("删除关联")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "platformCatalog", value = "关联的信息", dataTypeClass = PlatformCatalog.class, required = true),
-    })
+    @Operation(summary = "删除关联")
     @DeleteMapping("/catalog/relation/del")
     @ResponseBody
-    public ResponseEntity<WVPResult<List<PlatformCatalog>>> delRelation(@RequestBody PlatformCatalog platformCatalog) {
+    public void delRelation(@RequestBody PlatformCatalog platformCatalog) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("删除关联,{}", JSON.toJSONString(platformCatalog));
         }
         int delResult = storager.delRelation(platformCatalog);
-        WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
-        result.setCode(0);
 
-        if (delResult > 0) {
-            result.setMsg("success");
-            return new ResponseEntity<>(result, HttpStatus.OK);
-        } else {
-            result.setMsg("save error");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+        if (delResult <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "写入数据库失败");
         }
     }
 
@@ -641,28 +546,20 @@ public class PlatformController {
      * @param catalogId  目录Id
      * @return
      */
-    @ApiOperation("修改默认目录")
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "platformId", value = "平台Id", dataTypeClass = String.class, required = true),
-            @ApiImplicitParam(name = "catalogId", value = "目录Id", dataTypeClass = String.class, required = true),
-    })
+    @Operation(summary = "修改默认目录")
+    @Parameter(name = "catalogId", description = "目录Id", required = true)
+    @Parameter(name = "platformId", description = "平台Id", required = true)
     @PostMapping("/catalog/default/update")
     @ResponseBody
-    public ResponseEntity<WVPResult<String>> setDefaultCatalog(String platformId, String catalogId) {
+    public void setDefaultCatalog(String platformId, String catalogId) {
 
         if (logger.isDebugEnabled()) {
             logger.debug("修改默认目录,{},{}", platformId, catalogId);
         }
         int updateResult = storager.setDefaultCatalog(platformId, catalogId);
-        WVPResult<String> result = new WVPResult<>();
-        result.setCode(0);
 
-        if (updateResult > 0) {
-            result.setMsg("success");
-            return new ResponseEntity<>(result, HttpStatus.OK);
-        } else {
-            result.setMsg("save error");
-            return new ResponseEntity<>(result, HttpStatus.OK);
+        if (updateResult <= 0) {
+            throw new ControllerException(ErrorCode.ERROR100.getCode(), "写入数据库失败");
         }
     }
 

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java

@@ -1,55 +1,66 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.platform.bean;
 
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+import io.swagger.v3.oas.annotations.media.Schema;
 
 /**
  * 精简的channel信息展示,主要是选择通道的时候展示列表使用
  */
+@Schema(description = "精简的channel信息展示")
 public class ChannelReduce {
 
     /**
      * deviceChannel的数据库自增ID
      */
+    @Schema(description = "deviceChannel的数据库自增ID")
     private int id;
 
     /**
      * 通道id
      */
+    @Schema(description = "通道国标编号")
     private String channelId;
 
     /**
      * 设备id
      */
+    @Schema(description = "设备国标编号")
     private String deviceId;
 
     /**
      * 通道名
      */
+    @Schema(description = "通道名")
     private String name;
 
     /**
      * 生产厂商
      */
+    @Schema(description = "生产厂商")
     private String manufacturer;
 
     /**
      * wan地址
      */
+    @Schema(description = "wan地址")
     private String  hostAddress;
 
     /**
      * 子节点数
      */
+    @Schema(description = "子节点数")
     private int  subCount;
 
     /**
      * 平台Id
      */
+    @Schema(description = "平台上级国标编号")
     private String  platformId;
 
     /**
      * 目录Id
      */
+    @Schema(description = "目录国标编号")
     private String  catalogId;
 
     public int getId() {

+ 13 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java

@@ -1,10 +1,23 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.platform.bean;
 
+import io.swagger.v3.oas.annotations.media.Schema;
+
 import java.util.List;
 
+/**
+ * 通道关联参数
+ * @author lin
+ */
+@Schema(description = "通道关联参数")
 public class UpdateChannelParam {
+
+    @Schema(description = "上级平台的国标编号")
     private String platformId;
+
+    @Schema(description = "目录的国标编号")
     private String catalogId;
+
+    @Schema(description = "")
     private List<ChannelReduce> channelReduces;
 
     public String getPlatformId() {

+ 59 - 125
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java

@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.vmanager.gb28181.play;
 
 import com.alibaba.fastjson.JSONArray;
 import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
@@ -12,19 +13,18 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
 import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.service.IPlayService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -40,10 +40,11 @@ import org.springframework.web.context.request.async.DeferredResult;
 import java.util.List;
 import java.util.UUID;
 
+
 /**
  * @author lin
  */
-@Api(tags = "国标设备点播")
+@Tag(name  = "国标设备点播")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/play")
@@ -78,13 +79,11 @@ public class PlayController {
 	@Autowired
 	private IMediaServerService mediaServerService;
 
-	@ApiOperation("开始点播")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-	})
+	@Operation(summary = "开始点播")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
 	@GetMapping("/start/{deviceId}/{channelId}")
-	public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId,
+	public DeferredResult<WVPResult<String>> play(@PathVariable String deviceId,
 													   @PathVariable String channelId) {
 
 		// 获取可用的zlm
@@ -95,174 +94,112 @@ public class PlayController {
 		return playResult.getResult();
 	}
 
-	@ApiOperation("停止点播")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-	})
+
+	@Operation(summary = "停止点播")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
 	@GetMapping("/stop/{deviceId}/{channelId}")
-	public DeferredResult<ResponseEntity<String>> playStop(@PathVariable String deviceId, @PathVariable String channelId) {
+	public JSONObject playStop(@PathVariable String deviceId, @PathVariable String channelId) {
 
 		logger.debug(String.format("设备预览/回放停止API调用,streamId:%s_%s", deviceId, channelId ));
 
-		String uuid = UUID.randomUUID().toString();
-		DeferredResult<ResponseEntity<String>> result = new DeferredResult<>();
+		if (deviceId == null || channelId == null) {
+			throw new ControllerException(ErrorCode.ERROR400);
+		}
 
-		// 录像查询以channelId作为deviceId查询
-		String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId;
-		resultHolder.put(key, uuid, result);
 		StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
 		if (streamInfo == null) {
-			RequestMessage msg = new RequestMessage();
-			msg.setId(uuid);
-			msg.setKey(key);
-			msg.setData("点播未找到");
-			resultHolder.invokeAllResult(msg);
-			storager.stopPlay(deviceId, channelId);
-			return result;
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "点播未找到");
 		}
-		cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, eventResult -> {
-			redisCatchStorage.stopPlay(streamInfo);
-			storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
-			RequestMessage msgForSuccess = new RequestMessage();
-			msgForSuccess.setId(uuid);
-			msgForSuccess.setKey(key);
-			msgForSuccess.setData("success");
-			resultHolder.invokeAllResult(msgForSuccess);
-		});
 
-		if (deviceId != null || channelId != null) {
-			JSONObject json = new JSONObject();
-			json.put("deviceId", deviceId);
-			json.put("channelId", channelId);
-			RequestMessage msg = new RequestMessage();
-			msg.setId(uuid);
-			msg.setKey(key);
-			msg.setData(json.toString());
-			resultHolder.invokeAllResult(msg);
-		} else {
-			logger.warn("设备预览/回放停止API调用失败!");
-			RequestMessage msg = new RequestMessage();
-			msg.setId(uuid);
-			msg.setKey(key);
-			msg.setData("streamId null");
-			resultHolder.invokeAllResult(msg);
-		}
+		cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), null, null);
+		redisCatchStorage.stopPlay(streamInfo);
+
+		storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
+		JSONObject json = new JSONObject();
+		json.put("deviceId", deviceId);
+		json.put("channelId", channelId);
+		return json;
 
-		// 超时处理
-		result.onTimeout(()->{
-			logger.warn(String.format("设备预览/回放停止超时,deviceId/channelId:%s_%s ", deviceId, channelId));
-			redisCatchStorage.stopPlay(streamInfo);
-			storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
-			RequestMessage msg = new RequestMessage();
-			msg.setId(uuid);
-			msg.setKey(key);
-			msg.setData("Timeout");
-			resultHolder.invokeAllResult(msg);
-		});
-		return result;
 	}
 
 	/**
 	 * 将不是h264的视频通过ffmpeg 转码为h264 + aac
 	 * @param streamId 流ID
-	 * @return
 	 */
-	@ApiOperation("将不是h264的视频通过ffmpeg 转码为h264 + aac")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "streamId", value = "视频流ID", dataTypeClass = String.class),
-	})
+	@Operation(summary = "将不是h264的视频通过ffmpeg 转码为h264 + aac")
+	@Parameter(name = "streamId", description = "视频流ID", required = true)
 	@PostMapping("/convert/{streamId}")
-	public ResponseEntity<String> playConvert(@PathVariable String streamId) {
+	public JSONObject playConvert(@PathVariable String streamId) {
 		StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
 		if (streamInfo == null) {
 			streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
 		}
 		if (streamInfo == null) {
 			logger.warn("视频转码API调用失败!, 视频流已经停止!");
-			return new ResponseEntity<String>("未找到视频流信息, 视频流可能已经停止", HttpStatus.OK);
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到视频流信息, 视频流可能已经停止");
 		}
 		MediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId());
 		JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
 		if (!rtpInfo.getBoolean("exist")) {
 			logger.warn("视频转码API调用失败!, 视频流已停止推流!");
-			return new ResponseEntity<String>("推流信息在流媒体中不存在, 视频流可能已停止推流", HttpStatus.OK);
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到视频流信息, 视频流可能已停止推流");
 		} else {
 			String dstUrl = String.format("rtmp://%s:%s/convert/%s", "127.0.0.1", mediaInfo.getRtmpPort(),
 					streamId );
 			String srcUrl = String.format("rtsp://%s:%s/rtp/%s", "127.0.0.1", mediaInfo.getRtspPort(), streamId);
 			JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(mediaInfo, srcUrl, dstUrl, "1000000", true, false, null);
 			logger.info(jsonObject.toJSONString());
-			JSONObject result = new JSONObject();
 			if (jsonObject != null && jsonObject.getInteger("code") == 0) {
-				   result.put("code", 0);
 				JSONObject data = jsonObject.getJSONObject("data");
 				if (data != null) {
-				   	result.put("key", data.getString("key"));
+					JSONObject result = new JSONObject();
+					result.put("key", data.getString("key"));
 					StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId(), false);
-					result.put("data", streamInfoResult);
+					result.put("StreamInfo", streamInfoResult);
+					return result;
+				}else {
+					throw new ControllerException(ErrorCode.ERROR100.getCode(), "转码失败");
 				}
 			}else {
-				result.put("code", 1);
-				result.put("msg", "cover fail");
+				throw new ControllerException(ErrorCode.ERROR100.getCode(), "转码失败");
 			}
-			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK);
 		}
 	}
 
 	/**
 	 * 结束转码
-	 * @param key
-	 * @return
 	 */
-	@ApiOperation("结束转码")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "key", value = "视频流key", dataTypeClass = String.class),
-	})
+	@Operation(summary = "结束转码")
+	@Parameter(name = "key", description = "视频流key", required = true)
+	@Parameter(name = "mediaServerId", description = "流媒体服务ID", required = true)
 	@PostMapping("/convertStop/{key}")
-	public ResponseEntity<String> playConvertStop(@PathVariable String key, String mediaServerId) {
-		JSONObject result = new JSONObject();
+	public void playConvertStop(@PathVariable String key, String mediaServerId) {
 		if (mediaServerId == null) {
-			result.put("code", 400);
-			result.put("msg", "mediaServerId is null");
-			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST);
+			throw new ControllerException(ErrorCode.ERROR400.getCode(), "流媒体:" + mediaServerId + "不存在" );
 		}
 		MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 		if (mediaInfo == null) {
-			result.put("code", 0);
-			result.put("msg", "使用的流媒体已经停止运行");
-			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK);
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "使用的流媒体已经停止运行" );
 		}else {
 			JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(mediaInfo, key);
 			logger.info(jsonObject.toJSONString());
 			if (jsonObject != null && jsonObject.getInteger("code") == 0) {
-				result.put("code", 0);
 				JSONObject data = jsonObject.getJSONObject("data");
-				if (data != null && data.getBoolean("flag")) {
-					result.put("code", "0");
-					result.put("msg", "success");
-				}else {
-
+				if (data == null || data.getBoolean("flag") == null || !data.getBoolean("flag")) {
+					throw new ControllerException(ErrorCode.ERROR100 );
 				}
 			}else {
-				result.put("code", 1);
-				result.put("msg", "delFFmpegSource fail");
+				throw new ControllerException(ErrorCode.ERROR100 );
 			}
-			return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK);
 		}
-
-
 	}
 
-	@ApiOperation("语音广播命令")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备Id", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道Id", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "timeout", value = "推流超时时间(秒)", dataTypeClass = Integer.class),
-	})
-    @GetMapping("/broadcast/{deviceId}/{channelId}")
-    @PostMapping("/broadcast/{deviceId}/{channelId}")
-    public DeferredResult<WVPResult<AudioBroadcastResult>> broadcastApi(@PathVariable String deviceId, @PathVariable String channelId,  Integer timeout) {
+	@Operation(summary = "语音广播命令")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+    @GetMapping("/broadcast/{deviceId}")
+    @PostMapping("/broadcast/{deviceId}")
+    public DeferredResult<WVPResult<AudioBroadcastResult>> broadcastApi(@PathVariable String deviceId) {
         if (logger.isDebugEnabled()) {
             logger.debug("语音广播API调用");
         }
@@ -321,6 +258,7 @@ public class PlayController {
 		return result;
 	}
 
+	@Operation(summary = "获取所有的ssrc")
 
 	@ApiOperation("停止语音广播")
 	@ApiImplicitParams({
@@ -337,9 +275,9 @@ public class PlayController {
 		return new WVPResult<>(0, "success", null);
 	}
 
-	@ApiOperation("获取所有的ssrc")
+	@Operation(summary = "获取所有的ssrc")
 	@GetMapping("/ssrc")
-	public WVPResult<JSONObject> getSsrc() {
+	public JSONObject getSSRC() {
 		if (logger.isDebugEnabled()) {
 			logger.debug("获取所有的ssrc");
 		}
@@ -354,14 +292,10 @@ public class PlayController {
 			objects.add(jsonObject);
 		}
 
-		WVPResult<JSONObject> result = new WVPResult<>();
-		result.setCode(0);
-		result.setMsg("success");
 		JSONObject jsonObject = new JSONObject();
 		jsonObject.put("data", objects);
 		jsonObject.put("count", objects.size());
-		result.setData(jsonObject);
-		return result;
+		return jsonObject;
 	}
 
 }

+ 4 - 3
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/bean/PlayResult.java

@@ -1,21 +1,22 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.play.bean;
 
 import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.context.request.async.DeferredResult;
 
 public class PlayResult {
 
-    private DeferredResult<ResponseEntity<String>> result;
+    private DeferredResult<WVPResult<String>> result;
     private String uuid;
 
     private Device device;
 
-    public DeferredResult<ResponseEntity<String>> getResult() {
+    public DeferredResult<WVPResult<String>> getResult() {
         return result;
     }
 
-    public void setResult(DeferredResult<ResponseEntity<String>> result) {
+    public void setResult(DeferredResult<WVPResult<String>> result) {
         this.result = result;
     }
 

+ 49 - 98
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java

@@ -1,21 +1,18 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.playback;
 
 import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
-//import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
-import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.service.IPlayService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.util.StringUtils;
+import org.springframework.util.ObjectUtils;
 import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -28,7 +25,10 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import org.springframework.web.context.request.async.DeferredResult;
 
-@Api(tags = "视频回放")
+/**
+ * @author lin
+ */
+@Tag(name = "视频回放")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/playback")
@@ -45,157 +45,108 @@ public class PlaybackController {
 	@Autowired
 	private IRedisCatchStorage redisCatchStorage;
 
-	// @Autowired
-	// private ZLMRESTfulUtils zlmresTfulUtils;
-
 	@Autowired
 	private IPlayService playService;
 
 	@Autowired
 	private DeferredResultHolder resultHolder;
 
-	@Autowired
-	private IMediaServerService mediaServerService;
-
-	@ApiOperation("开始视频回放")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "startTime", value = "开始时间", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "endTime", value = "结束时间", dataTypeClass = String.class),
-	})
+	@Operation(summary = "开始视频回放")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "startTime", description = "开始时间", required = true)
+	@Parameter(name = "endTime", description = "结束时间", required = true)
 	@GetMapping("/start/{deviceId}/{channelId}")
-	public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId, @PathVariable String channelId,
+	public DeferredResult<String> play(@PathVariable String deviceId, @PathVariable String channelId,
 													   String startTime,String endTime) {
 
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
 		}
 
-		DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, null, wvpResult->{
-			resultHolder.invokeResult(wvpResult.getData());
-		});
 
-		return result;
+		return playService.playBack(deviceId, channelId, startTime, endTime, null,
+				playBackResult->resultHolder.invokeResult(playBackResult.getData()));
 	}
 
-	@ApiOperation("停止视频回放")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class),
-	})
+
+	@Operation(summary = "停止视频回放")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "stream", description = "流ID", required = true)
 	@GetMapping("/stop/{deviceId}/{channelId}/{stream}")
-	public ResponseEntity<String> playStop(
+	public void playStop(
 			@PathVariable String deviceId,
 			@PathVariable String channelId,
 			@PathVariable String stream) {
-
-		cmder.streamByeCmd(deviceId, channelId, stream, null);
-
-		if (logger.isDebugEnabled()) {
-			logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId));
-		}
-		if (StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(channelId) || StringUtils.isEmpty(stream)) {
-			return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
-		}
-
-		if (deviceId != null && channelId != null) {
-			JSONObject json = new JSONObject();
-			json.put("deviceId", deviceId);
-			json.put("channelId", channelId);
-			return new ResponseEntity<>(json.toString(), HttpStatus.OK);
-		} else {
-			logger.warn("设备录像回放停止API调用失败!");
-			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
+		if (ObjectUtils.isEmpty(deviceId) || ObjectUtils.isEmpty(channelId) || ObjectUtils.isEmpty(stream)) {
+			throw new ControllerException(ErrorCode.ERROR400);
 		}
+		cmder.streamByeCmd(deviceId, channelId, stream, null);
 	}
 
-	@ApiOperation("回放暂停")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "streamId", value = "回放流ID", dataTypeClass = String.class),
-	})
+
+	@Operation(summary = "回放暂停")
+	@Parameter(name = "streamId", description = "回放流ID", required = true)
 	@GetMapping("/pause/{streamId}")
-	public ResponseEntity<String> playPause(@PathVariable String streamId) {
+	public void playPause(@PathVariable String streamId) {
 		logger.info("playPause: "+streamId);
-		JSONObject json = new JSONObject();
 		StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
 		if (null == streamInfo) {
-			json.put("msg", "streamId不存在");
 			logger.warn("streamId不存在!");
-			return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
+			throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
 		}
 		Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
 		cmder.playPauseCmd(device, streamInfo);
-		json.put("msg", "ok");
-		return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
 	}
 
-	@ApiOperation("回放恢复")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "streamId", value = "回放流ID", dataTypeClass = String.class),
-	})
+
+	@Operation(summary = "回放恢复")
+	@Parameter(name = "streamId", description = "回放流ID", required = true)
 	@GetMapping("/resume/{streamId}")
-	public ResponseEntity<String> playResume(@PathVariable String streamId) {
+	public void playResume(@PathVariable String streamId) {
 		logger.info("playResume: "+streamId);
-		JSONObject json = new JSONObject();
 		StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
 		if (null == streamInfo) {
-			json.put("msg", "streamId不存在");
 			logger.warn("streamId不存在!");
-			return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
+			throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
 		}
 		Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
 		cmder.playResumeCmd(device, streamInfo);
-		json.put("msg", "ok");
-		return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
 	}
 
-	@ApiOperation("回放拖动播放")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "streamId", value = "回放流ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "seekTime", value = "拖动偏移量,单位s", dataTypeClass = Long.class),
-	})
+
+	@Operation(summary = "回放拖动播放")
+	@Parameter(name = "streamId", description = "回放流ID", required = true)
+	@Parameter(name = "seekTime", description = "拖动偏移量,单位s", required = true)
 	@GetMapping("/seek/{streamId}/{seekTime}")
-	public ResponseEntity<String> playSeek(@PathVariable String streamId, @PathVariable long seekTime) {
+	public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) {
 		logger.info("playSeek: "+streamId+", "+seekTime);
-		JSONObject json = new JSONObject();
 		StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
 		if (null == streamInfo) {
-			json.put("msg", "streamId不存在");
 			logger.warn("streamId不存在!");
-			return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
+			throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
 		}
 		Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
 		cmder.playSeekCmd(device, streamInfo, seekTime);
-		json.put("msg", "ok");
-		return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
 	}
 
-	@ApiOperation("回放倍速播放")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "streamId", value = "回放流ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "speed", value = "倍速0.25 0.5 1、2、4", dataTypeClass = Double.class),
-	})
+	@Operation(summary = "回放倍速播放")
+	@Parameter(name = "streamId", description = "回放流ID", required = true)
+	@Parameter(name = "speed", description = "倍速0.25 0.5 1、2、4", required = true)
 	@GetMapping("/speed/{streamId}/{speed}")
-	public ResponseEntity<String> playSpeed(@PathVariable String streamId, @PathVariable Double speed) {
+	public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) {
 		logger.info("playSpeed: "+streamId+", "+speed);
-		JSONObject json = new JSONObject();
 		StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
 		if (null == streamInfo) {
-			json.put("msg", "streamId不存在");
 			logger.warn("streamId不存在!");
-			return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
+			throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
 		}
 		if(speed != 0.25 && speed != 0.5 && speed != 1 && speed != 2.0 && speed != 4.0) {
-			json.put("msg", "不支持的speed(0.25 0.5 1、2、4)");
 			logger.warn("不支持的speed: " + speed);
-			return new ResponseEntity<String>(json.toString(), HttpStatus.BAD_REQUEST);
+			throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)");
 		}
 		Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
 		cmder.playSpeedCmd(device, streamInfo, speed);
-		json.put("msg", "ok");
-		return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
 	}
-
 }

+ 31 - 40
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java

@@ -1,14 +1,13 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.ptz;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
+ 
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
+import org.springframework.util.ObjectUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.async.DeferredResult;
@@ -21,7 +20,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 
 import java.util.UUID;
 
-@Api(tags = "云台控制")
+@Tag(name  = "云台控制")
 @CrossOrigin
 @RestController
 @RequestMapping("/api/ptz")
@@ -46,19 +45,17 @@ public class PtzController {
 	 * @param horizonSpeed	水平移动速度
 	 * @param verticalSpeed	垂直移动速度
 	 * @param zoomSpeed	    缩放速度
-	 * @return String 控制结果
 	 */
-	@ApiOperation("云台控制")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "command", value = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "horizonSpeed", value = "水平速度", dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "verticalSpeed", value = "垂直速度", dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "zoomSpeed", value = "缩放速度", dataTypeClass = Integer.class),
-	})
+
+	@Operation(summary = "云台控制")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true)
+	@Parameter(name = "horizonSpeed", description = "水平速度", required = true)
+	@Parameter(name = "verticalSpeed", description = "垂直速度", required = true)
+	@Parameter(name = "zoomSpeed", description = "缩放速度", required = true)
 	@PostMapping("/control/{deviceId}/{channelId}")
-	public ResponseEntity<String> ptz(@PathVariable String deviceId,@PathVariable String channelId, String command, int horizonSpeed, int verticalSpeed, int zoomSpeed){
+	public void ptz(@PathVariable String deviceId,@PathVariable String channelId, String command, int horizonSpeed, int verticalSpeed, int zoomSpeed){
 
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,command:%s ,horizonSpeed:%d ,verticalSpeed:%d ,zoomSpeed:%d",deviceId, channelId, command, horizonSpeed, verticalSpeed, zoomSpeed));
@@ -97,26 +94,23 @@ public class PtzController {
 				cmdCode = 32;
 				break;
 			case "stop":
-				cmdCode = 0;
 				break;
 			default:
 				break;
 		}
 		cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
-		return new ResponseEntity<String>("success",HttpStatus.OK);
 	}
 
-	@ApiOperation("通用前端控制命令")
-	@ApiImplicitParams({
-			@ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-			@ApiImplicitParam(name = "cmdCode", value = "指令码", dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "parameter1", value = "数据一", dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "parameter2", value = "数据二", dataTypeClass = Integer.class),
-			@ApiImplicitParam(name = "combindCode2", value = "组合码二", dataTypeClass = Integer.class),
-	})
+
+	@Operation(summary = "通用前端控制命令")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
+	@Parameter(name = "cmdCode", description = "指令码", required = true)
+	@Parameter(name = "parameter1", description = "数据一", required = true)
+	@Parameter(name = "parameter2", description = "数据二", required = true)
+	@Parameter(name = "combindCode2", description = "组合码二", required = true)
 	@PostMapping("/front_end_command/{deviceId}/{channelId}")
-	public ResponseEntity<String> frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
+	public void frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
 
 		if (logger.isDebugEnabled()) {
 			logger.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,cmdCode:%d parameter1:%d parameter2:%d",deviceId, channelId, cmdCode, parameter1, parameter2));
@@ -124,23 +118,21 @@ public class PtzController {
 		Device device = storager.queryVideoDevice(deviceId);
 
 		cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
-		return new ResponseEntity<String>("success",HttpStatus.OK);
 	}
 
-	@ApiOperation("预置位查询")
-	@ApiImplicitParams({
-            @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
-            @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
-	})
+
+	@Operation(summary = "预置位查询")
+	@Parameter(name = "deviceId", description = "设备国标编号", required = true)
+	@Parameter(name = "channelId", description = "通道国标编号", required = true)
 	@GetMapping("/preset/query/{deviceId}/{channelId}")
-	public DeferredResult<ResponseEntity<String>> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) {
+	public DeferredResult<String> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) {
 		if (logger.isDebugEnabled()) {
 			logger.debug("设备预置位查询API调用");
 		}
 		Device device = storager.queryVideoDevice(deviceId);
 		String uuid =  UUID.randomUUID().toString();
-		String key =  DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
-		DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
+		String key =  DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(channelId) ? deviceId : channelId);
+		DeferredResult<String> result = new DeferredResult<String> (3 * 1000L);
 		result.onTimeout(()->{
 			logger.warn(String.format("获取设备预置位超时"));
 			// 释放rtpserver
@@ -161,7 +153,6 @@ public class PtzController {
 			msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
 			resultHolder.invokeResult(msg);
 		});
-
 		return result;
 	}
 }

+ 0 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません