Commit b4048fbe80dba8e7756ae557a15ab60b4f80a44b
合并开源主线
Showing
100 changed files
with
1881 additions
and
660 deletions
Too many changes to show.
To preserve performance only 100 of 165 files are displayed.
README.md
| @@ -99,15 +99,16 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git | @@ -99,15 +99,16 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git | ||
| 99 | - [X] 支持接口鉴权 | 99 | - [X] 支持接口鉴权 |
| 100 | - [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载 | 100 | - [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载 |
| 101 | - [X] 支持打包可执行jar和war | 101 | - [X] 支持打包可执行jar和war |
| 102 | +- [X] 支持跨域请求,支持前后端分离部署 | ||
| 102 | 103 | ||
| 103 | 104 | ||
| 104 | # 遇到问题如何解决 | 105 | # 遇到问题如何解决 |
| 105 | 国标最麻烦的地方在于设备的兼容性,所以需要大量的设备来测试,目前作者手里的设备有限,再加上作者水平有限,所以遇到问题在所难免; | 106 | 国标最麻烦的地方在于设备的兼容性,所以需要大量的设备来测试,目前作者手里的设备有限,再加上作者水平有限,所以遇到问题在所难免; |
| 106 | -1. 查看wiki,仔细的阅读可以帮你避免几乎所有的问题 | 107 | +1. 查看文档网站,仔细的阅读可以帮你避免几乎所有的问题 |
| 107 | 2. 搜索issues,这里有大部分的答案 | 108 | 2. 搜索issues,这里有大部分的答案 |
| 108 | 3. 加QQ群(901799015),这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。 | 109 | 3. 加QQ群(901799015),这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。 |
| 109 | 4. 你可以请作者为你解答,但是我不是免费的。 | 110 | 4. 你可以请作者为你解答,但是我不是免费的。 |
| 110 | -5. 你可以把遇到问题的设备寄给我,可以更容易的复现问题。 | 111 | +5. 你可以把遇到问题的设备寄给我,可以更容易的兼容设备和解决问题。 |
| 111 | 112 | ||
| 112 | # 使用帮助 | 113 | # 使用帮助 |
| 113 | QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) | 114 | QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) |
doc/_content/ability/gis.md
| @@ -14,7 +14,7 @@ WVP提供了简单的电子地图用于设备的定位以及移动设备的轨 | @@ -14,7 +14,7 @@ WVP提供了简单的电子地图用于设备的定位以及移动设备的轨 | ||
| 14 | PS: 目前的底图仅用用作演示和学习,商用情况请自行购买授权使用。 | 14 | PS: 目前的底图仅用用作演示和学习,商用情况请自行购买授权使用。 |
| 15 | 15 | ||
| 16 | ### 更换底图以及底图配置 | 16 | ### 更换底图以及底图配置 |
| 17 | -目前WVP支持使用了更换底图,配置文件在web_src/static/js/mapConfig.js,请修改后重新编译前端文件。 | 17 | +目前WVP支持使用了更换底图,配置文件在web_src/static/js/config.js,请修改后重新编译前端文件。 |
| 18 | ```javascript | 18 | ```javascript |
| 19 | window.mapParam = { | 19 | window.mapParam = { |
| 20 | // 开启/关闭地图功能 | 20 | // 开启/关闭地图功能 |
doc/_content/introduction/deployment.md
| @@ -27,13 +27,32 @@ | @@ -27,13 +27,32 @@ | ||
| 27 | ```shell | 27 | ```shell |
| 28 | nohup java -jar wvp-pro-*.jar & | 28 | nohup java -jar wvp-pro-*.jar & |
| 29 | ``` | 29 | ``` |
| 30 | -war包: | 30 | +**war包:** |
| 31 | 下载Tomcat后将war包放入webapps中,启动Tomcat以解压war包,停止Tomcat后,删除ROOT目录以及war包,将解压后的war包目录重命名为ROOT,将配置文件中的Server.port配置为与Tomcat端口一致 | 31 | 下载Tomcat后将war包放入webapps中,启动Tomcat以解压war包,停止Tomcat后,删除ROOT目录以及war包,将解压后的war包目录重命名为ROOT,将配置文件中的Server.port配置为与Tomcat端口一致 |
| 32 | 然后启动Tomcat。 | 32 | 然后启动Tomcat。 |
| 33 | **启动ZLM** | 33 | **启动ZLM** |
| 34 | ```shell | 34 | ```shell |
| 35 | nohup ./MediaServer -d -m 3 & | 35 | nohup ./MediaServer -d -m 3 & |
| 36 | ``` | 36 | ``` |
| 37 | - | 37 | +### 前后端分离部署 |
| 38 | +前后端部署目前在最新的版本已经支持,请使用3月15日之后的版本部署 | ||
| 39 | +前端编译后的文件在`src/main/resources/static`中,将此目录下的文件部署。 | ||
| 40 | +前后端分离部署最大的问题是跨域的解决,之前版本使用cookie完成登录流程,而cookie是不可以在复杂跨域中使用的。所以当前版本使用JWT生成的TOKEN作为认证凭据, | ||
| 41 | +部署前端后需要在wvp中配置前端访问的地址以完成跨域流程。 | ||
| 42 | +**配置前端服务器** | ||
| 43 | +1. 假如你的服务有公网域名为xxx.com,公网IP为11.11.11.11, 那么你可以在wvp中这样配置: | ||
| 44 | +```yaml | ||
| 45 | +user-settings: | ||
| 46 | + # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个 | ||
| 47 | + allowed-origins: | ||
| 48 | + - http://xxx.com:8008 | ||
| 49 | + - http://11.11.11.11:8008 | ||
| 50 | +``` | ||
| 51 | +配置不是必须的,你使用哪个ip/域名访问就配置哪个即可。修改配置后重启wvp以使配置生效。 | ||
| 52 | +2. 在`src/main/resources/static/static/js/config.js`下配置服务器的地址,也就是wvp服务的地址 | ||
| 53 | +```javascript | ||
| 54 | +window.baseUrl = "http://xxx.com:18080" | ||
| 55 | +``` | ||
| 56 | +`这里的地址是需要客户电脑能访问到的,因为请求是客户端电脑发起,与代理不同` | ||
| 38 | [接入设备](./_content/ability/device.md) | 57 | [接入设备](./_content/ability/device.md) |
| 39 | 58 |
pom.xml
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | 11 | ||
| 12 | <groupId>com.genersoft</groupId> | 12 | <groupId>com.genersoft</groupId> |
| 13 | <artifactId>wvp-pro</artifactId> | 13 | <artifactId>wvp-pro</artifactId> |
| 14 | - <version>2.6.7</version> | 14 | + <version>2.6.8</version> |
| 15 | <name>web video platform</name> | 15 | <name>web video platform</name> |
| 16 | <description>国标28181视频平台</description> | 16 | <description>国标28181视频平台</description> |
| 17 | <packaging>${project.packaging}</packaging> | 17 | <packaging>${project.packaging}</packaging> |
| @@ -123,11 +123,9 @@ | @@ -123,11 +123,9 @@ | ||
| 123 | <artifactId>spring-boot-starter-security</artifactId> | 123 | <artifactId>spring-boot-starter-security</artifactId> |
| 124 | </dependency> | 124 | </dependency> |
| 125 | 125 | ||
| 126 | - <!-- druid数据库连接池 --> | ||
| 127 | <dependency> | 126 | <dependency> |
| 128 | - <groupId>com.alibaba</groupId> | ||
| 129 | - <artifactId>druid-spring-boot-starter</artifactId> | ||
| 130 | - <version>1.2.11</version> | 127 | + <groupId>org.springframework.boot</groupId> |
| 128 | + <artifactId>spring-boot-starter-jdbc</artifactId> | ||
| 131 | </dependency> | 129 | </dependency> |
| 132 | 130 | ||
| 133 | <!-- mysql数据库 --> | 131 | <!-- mysql数据库 --> |
| @@ -216,8 +214,6 @@ | @@ -216,8 +214,6 @@ | ||
| 216 | <version>4.10.0</version> | 214 | <version>4.10.0</version> |
| 217 | </dependency> | 215 | </dependency> |
| 218 | 216 | ||
| 219 | - | ||
| 220 | - | ||
| 221 | <!-- okhttp-digest --> | 217 | <!-- okhttp-digest --> |
| 222 | <dependency> | 218 | <dependency> |
| 223 | <groupId>io.github.rburgst</groupId> | 219 | <groupId>io.github.rburgst</groupId> |
| @@ -226,10 +222,17 @@ | @@ -226,10 +222,17 @@ | ||
| 226 | </dependency> | 222 | </dependency> |
| 227 | 223 | ||
| 228 | <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> | 224 | <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> |
| 225 | +<!-- <dependency>--> | ||
| 226 | +<!-- <groupId>net.sf.kxml</groupId>--> | ||
| 227 | +<!-- <artifactId>kxml2</artifactId>--> | ||
| 228 | +<!-- <version>2.3.0</version>--> | ||
| 229 | +<!-- </dependency>--> | ||
| 230 | + | ||
| 231 | + <!-- jwt实现 --> | ||
| 229 | <dependency> | 232 | <dependency> |
| 230 | - <groupId>net.sf.kxml</groupId> | ||
| 231 | - <artifactId>kxml2</artifactId> | ||
| 232 | - <version>2.3.0</version> | 233 | + <groupId>org.bitbucket.b_c</groupId> |
| 234 | + <artifactId>jose4j</artifactId> | ||
| 235 | + <version>0.9.3</version> | ||
| 233 | </dependency> | 236 | </dependency> |
| 234 | 237 | ||
| 235 | <!--反向代理--> | 238 | <!--反向代理--> |
| @@ -289,7 +292,7 @@ | @@ -289,7 +292,7 @@ | ||
| 289 | <plugin> | 292 | <plugin> |
| 290 | <groupId>org.springframework.boot</groupId> | 293 | <groupId>org.springframework.boot</groupId> |
| 291 | <artifactId>spring-boot-maven-plugin</artifactId> | 294 | <artifactId>spring-boot-maven-plugin</artifactId> |
| 292 | - <version>2.3.5.RELEASE</version> | 295 | + <version>2.7.2</version> |
| 293 | <configuration> | 296 | <configuration> |
| 294 | <includeSystemScope>true</includeSystemScope> | 297 | <includeSystemScope>true</includeSystemScope> |
| 295 | </configuration> | 298 | </configuration> |
sql/2.6.6-2.6.7更新.sql
0 → 100755
src/main/resources/db/migration/V2.6.7_20230201__初始化.sql renamed to sql/初始化.sql
| @@ -32,6 +32,7 @@ CREATE TABLE `device` ( | @@ -32,6 +32,7 @@ CREATE TABLE `device` ( | ||
| 32 | `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 32 | `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| 33 | `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 33 | `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| 34 | `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 34 | `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| 35 | + `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | ||
| 35 | `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 36 | `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| 36 | `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 37 | `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| 37 | `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 38 | `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| @@ -47,6 +48,7 @@ CREATE TABLE `device` ( | @@ -47,6 +48,7 @@ CREATE TABLE `device` ( | ||
| 47 | `mobilePositionSubmissionInterval` int DEFAULT '5', | 48 | `mobilePositionSubmissionInterval` int DEFAULT '5', |
| 48 | `subscribeCycleForAlarm` int DEFAULT NULL, | 49 | `subscribeCycleForAlarm` int DEFAULT NULL, |
| 49 | `ssrcCheck` int DEFAULT '0', | 50 | `ssrcCheck` int DEFAULT '0', |
| 51 | + `asMessageChannel` int DEFAULT '0', | ||
| 50 | `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | 52 | `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, |
| 51 | `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | 53 | `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, |
| 52 | `custom_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, | 54 | `custom_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, |
| @@ -329,6 +331,7 @@ CREATE TABLE `parent_platform` ( | @@ -329,6 +331,7 @@ CREATE TABLE `parent_platform` ( | ||
| 329 | `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | 331 | `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, |
| 330 | `ptz` int DEFAULT NULL, | 332 | `ptz` int DEFAULT NULL, |
| 331 | `rtcp` int DEFAULT NULL, | 333 | `rtcp` int DEFAULT NULL, |
| 334 | + `asMessageChannel` int DEFAULT '0', | ||
| 332 | `status` bit(1) DEFAULT NULL, | 335 | `status` bit(1) DEFAULT NULL, |
| 333 | `startOfflinePush` int DEFAULT '0', | 336 | `startOfflinePush` int DEFAULT '0', |
| 334 | `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, | 337 | `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, |
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
| 1 | package com.genersoft.iot.vmp; | 1 | package com.genersoft.iot.vmp; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport; | ||
| 4 | import com.genersoft.iot.vmp.utils.GitUtil; | 3 | import com.genersoft.iot.vmp.utils.GitUtil; |
| 5 | import com.genersoft.iot.vmp.utils.SpringBeanFactory; | 4 | import com.genersoft.iot.vmp.utils.SpringBeanFactory; |
| 6 | import org.slf4j.Logger; | 5 | import org.slf4j.Logger; |
| @@ -25,7 +24,6 @@ import java.util.Collections; | @@ -25,7 +24,6 @@ import java.util.Collections; | ||
| 25 | @ServletComponentScan("com.genersoft.iot.vmp.conf") | 24 | @ServletComponentScan("com.genersoft.iot.vmp.conf") |
| 26 | @SpringBootApplication | 25 | @SpringBootApplication |
| 27 | @EnableScheduling | 26 | @EnableScheduling |
| 28 | -@EnableDruidSupport | ||
| 29 | public class VManageBootstrap extends SpringBootServletInitializer { | 27 | public class VManageBootstrap extends SpringBootServletInitializer { |
| 30 | 28 | ||
| 31 | private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class); | 29 | private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class); |
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
| @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.common; | @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.common; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | ||
| 5 | import java.io.Serializable; | 5 | import java.io.Serializable; |
| 6 | +import java.util.Objects; | ||
| 6 | 7 | ||
| 7 | @Schema(description = "流信息") | 8 | @Schema(description = "流信息") |
| 8 | public class StreamInfo implements Serializable, Cloneable{ | 9 | public class StreamInfo implements Serializable, Cloneable{ |
| @@ -168,7 +169,7 @@ public class StreamInfo implements Serializable, Cloneable{ | @@ -168,7 +169,7 @@ public class StreamInfo implements Serializable, Cloneable{ | ||
| 168 | } | 169 | } |
| 169 | 170 | ||
| 170 | public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) { | 171 | public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) { |
| 171 | - String file = String.format("%s/%s/%s", app, stream, callIdParam); | 172 | + String file = String.format("%s/%s%s", app, stream, callIdParam); |
| 172 | if (port > 0) { | 173 | if (port > 0) { |
| 173 | this.rtmp = new StreamURL("rtmp", host, port, file); | 174 | this.rtmp = new StreamURL("rtmp", host, port, file); |
| 174 | } | 175 | } |
| @@ -178,7 +179,7 @@ public class StreamInfo implements Serializable, Cloneable{ | @@ -178,7 +179,7 @@ public class StreamInfo implements Serializable, Cloneable{ | ||
| 178 | } | 179 | } |
| 179 | 180 | ||
| 180 | public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) { | 181 | public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) { |
| 181 | - String file = String.format("%s/%s/%s", app, stream, callIdParam); | 182 | + String file = String.format("%s/%s%s", app, stream, callIdParam); |
| 182 | if (port > 0) { | 183 | if (port > 0) { |
| 183 | this.rtsp = new StreamURL("rtsp", host, port, file); | 184 | this.rtsp = new StreamURL("rtsp", host, port, file); |
| 184 | } | 185 | } |
| @@ -236,8 +237,11 @@ public class StreamInfo implements Serializable, Cloneable{ | @@ -236,8 +237,11 @@ public class StreamInfo implements Serializable, Cloneable{ | ||
| 236 | } | 237 | } |
| 237 | } | 238 | } |
| 238 | 239 | ||
| 239 | - public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam, boolean isPlay) { | ||
| 240 | - String file = String.format("index/api/webrtc?app=%s&stream=%s&type=%s%s", app, stream, isPlay?"play":"push", callIdParam); | 240 | + public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam) { |
| 241 | + if (callIdParam != null) { | ||
| 242 | + callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&"); | ||
| 243 | + } | ||
| 244 | + String file = String.format("index/api/webrtc?app=%s&stream=%s&type=play%s", app, stream, callIdParam); | ||
| 241 | if (port > 0) { | 245 | if (port > 0) { |
| 242 | this.rtc = new StreamURL("http", host, port, file); | 246 | this.rtc = new StreamURL("http", host, port, file); |
| 243 | } | 247 | } |
src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
| @@ -66,9 +66,7 @@ public class ApiAccessFilter extends OncePerRequestFilter { | @@ -66,9 +66,7 @@ public class ApiAccessFilter extends OncePerRequestFilter { | ||
| 66 | logDto.setUri(servletRequest.getRequestURI()); | 66 | logDto.setUri(servletRequest.getRequestURI()); |
| 67 | logDto.setCreateTime(DateUtil.getNow()); | 67 | logDto.setCreateTime(DateUtil.getNow()); |
| 68 | logService.add(logDto); | 68 | logService.add(logDto); |
| 69 | -// logger.warn("[Api Access] [{}] [{}] [{}] [{}] [{}] {}ms", | ||
| 70 | -// uriName, servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getRemoteAddr(), HttpStatus.valueOf(servletResponse.getStatus()), | ||
| 71 | -// System.currentTimeMillis() - start); | 69 | + |
| 72 | 70 | ||
| 73 | } | 71 | } |
| 74 | } | 72 | } |
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
| @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; | @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; | ||
| 8 | import org.springframework.http.HttpStatus; | 8 | import org.springframework.http.HttpStatus; |
| 9 | import org.springframework.http.ResponseEntity; | 9 | import org.springframework.http.ResponseEntity; |
| 10 | import org.springframework.security.authentication.BadCredentialsException; | 10 | import org.springframework.security.authentication.BadCredentialsException; |
| 11 | +import org.springframework.web.HttpRequestMethodNotSupportedException; | ||
| 11 | import org.springframework.web.bind.annotation.ExceptionHandler; | 12 | import org.springframework.web.bind.annotation.ExceptionHandler; |
| 12 | import org.springframework.web.bind.annotation.ResponseStatus; | 13 | import org.springframework.web.bind.annotation.ResponseStatus; |
| 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; | 14 | import org.springframework.web.bind.annotation.RestControllerAdvice; |
| @@ -32,6 +33,28 @@ public class GlobalExceptionHandler { | @@ -32,6 +33,28 @@ public class GlobalExceptionHandler { | ||
| 32 | return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage()); | 33 | return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage()); |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 36 | + /** | ||
| 37 | + * 默认异常处理 | ||
| 38 | + * @param e 异常 | ||
| 39 | + * @return 统一返回结果 | ||
| 40 | + */ | ||
| 41 | + @ExceptionHandler(IllegalStateException.class) | ||
| 42 | + @ResponseStatus(HttpStatus.BAD_REQUEST) | ||
| 43 | + public WVPResult<String> exceptionHandler(IllegalStateException e) { | ||
| 44 | + return WVPResult.fail(ErrorCode.ERROR400); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * 默认异常处理 | ||
| 49 | + * @param e 异常 | ||
| 50 | + * @return 统一返回结果 | ||
| 51 | + */ | ||
| 52 | + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) | ||
| 53 | + @ResponseStatus(HttpStatus.BAD_REQUEST) | ||
| 54 | + public WVPResult<String> exceptionHandler(HttpRequestMethodNotSupportedException e) { | ||
| 55 | + return WVPResult.fail(ErrorCode.ERROR400); | ||
| 56 | + } | ||
| 57 | + | ||
| 35 | 58 | ||
| 36 | /** | 59 | /** |
| 37 | * 自定义异常处理, 处理controller中返回的错误 | 60 | * 自定义异常处理, 处理controller中返回的错误 |
src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java
| @@ -10,14 +10,11 @@ import org.springframework.context.annotation.Bean; | @@ -10,14 +10,11 @@ import org.springframework.context.annotation.Bean; | ||
| 10 | import org.springframework.core.MethodParameter; | 10 | import org.springframework.core.MethodParameter; |
| 11 | import org.springframework.http.MediaType; | 11 | import org.springframework.http.MediaType; |
| 12 | import org.springframework.http.converter.HttpMessageConverter; | 12 | import org.springframework.http.converter.HttpMessageConverter; |
| 13 | -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | ||
| 14 | import org.springframework.http.server.ServerHttpRequest; | 13 | import org.springframework.http.server.ServerHttpRequest; |
| 15 | import org.springframework.http.server.ServerHttpResponse; | 14 | import org.springframework.http.server.ServerHttpResponse; |
| 16 | import org.springframework.web.bind.annotation.RestControllerAdvice; | 15 | import org.springframework.web.bind.annotation.RestControllerAdvice; |
| 17 | import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; | 16 | import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; |
| 18 | 17 | ||
| 19 | -import java.util.List; | ||
| 20 | - | ||
| 21 | /** | 18 | /** |
| 22 | * 全局统一返回结果 | 19 | * 全局统一返回结果 |
| 23 | * @author lin | 20 | * @author lin |
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
| @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.conf; | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.conf; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 3 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 4 | import com.genersoft.iot.vmp.service.IMediaServerService; | 4 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 5 | +import org.apache.catalina.connector.ClientAbortException; | ||
| 5 | import org.apache.http.HttpHost; | 6 | import org.apache.http.HttpHost; |
| 6 | import org.apache.http.HttpRequest; | 7 | import org.apache.http.HttpRequest; |
| 7 | import org.apache.http.HttpResponse; | 8 | import org.apache.http.HttpResponse; |
| @@ -169,13 +170,14 @@ public class ProxyServletConfig { | @@ -169,13 +170,14 @@ public class ProxyServletConfig { | ||
| 169 | protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { | 170 | protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { |
| 170 | String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); | 171 | String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); |
| 171 | MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); | 172 | MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); |
| 172 | - String remoteHost = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort()); | ||
| 173 | - if (mediaInfo != null) { | ||
| 174 | - if (!ObjectUtils.isEmpty(queryStr)) { | ||
| 175 | - queryStr += "&remoteHost=" + remoteHost; | ||
| 176 | - }else { | ||
| 177 | - queryStr = "remoteHost=" + remoteHost; | ||
| 178 | - } | 173 | + if (mediaInfo == null) { |
| 174 | + return null; | ||
| 175 | + } | ||
| 176 | + String remoteHost = String.format("http://%s:%s", mediaInfo.getStreamIp(), mediaInfo.getRecordAssistPort()); | ||
| 177 | + if (!ObjectUtils.isEmpty(queryStr)) { | ||
| 178 | + queryStr += "&remoteHost=" + remoteHost; | ||
| 179 | + }else { | ||
| 180 | + queryStr = "remoteHost=" + remoteHost; | ||
| 179 | } | 181 | } |
| 180 | return queryStr; | 182 | return queryStr; |
| 181 | } | 183 | } |
| @@ -192,6 +194,12 @@ public class ProxyServletConfig { | @@ -192,6 +194,12 @@ public class ProxyServletConfig { | ||
| 192 | } catch (IOException ioException) { | 194 | } catch (IOException ioException) { |
| 193 | if (ioException instanceof ConnectException) { | 195 | if (ioException instanceof ConnectException) { |
| 194 | logger.error("录像服务 连接失败"); | 196 | logger.error("录像服务 连接失败"); |
| 197 | + }else if (ioException instanceof ClientAbortException) { | ||
| 198 | + /** | ||
| 199 | + * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常, | ||
| 200 | + * TODO 暂时去除异常处理。后续使用其他代理框架修改测试 | ||
| 201 | + */ | ||
| 202 | + | ||
| 195 | }else { | 203 | }else { |
| 196 | logger.error("录像服务 代理失败: ", e); | 204 | logger.error("录像服务 代理失败: ", e); |
| 197 | } | 205 | } |
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
| @@ -4,7 +4,6 @@ package com.genersoft.iot.vmp.conf; | @@ -4,7 +4,6 @@ package com.genersoft.iot.vmp.conf; | ||
| 4 | import org.junit.jupiter.api.Order; | 4 | import org.junit.jupiter.api.Order; |
| 5 | import org.springframework.boot.context.properties.ConfigurationProperties; | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; |
| 6 | import org.springframework.stereotype.Component; | 6 | import org.springframework.stereotype.Component; |
| 7 | -import org.springframework.util.ObjectUtils; | ||
| 8 | 7 | ||
| 9 | @Component | 8 | @Component |
| 10 | @ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true) | 9 | @ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true) |
| @@ -13,6 +12,8 @@ public class SipConfig { | @@ -13,6 +12,8 @@ public class SipConfig { | ||
| 13 | 12 | ||
| 14 | private String ip; | 13 | private String ip; |
| 15 | 14 | ||
| 15 | + private String showIp; | ||
| 16 | + | ||
| 16 | private Integer port; | 17 | private Integer port; |
| 17 | 18 | ||
| 18 | private String domain; | 19 | private String domain; |
| @@ -96,4 +97,14 @@ public class SipConfig { | @@ -96,4 +97,14 @@ public class SipConfig { | ||
| 96 | this.alarm = alarm; | 97 | this.alarm = alarm; |
| 97 | } | 98 | } |
| 98 | 99 | ||
| 100 | + public String getShowIp() { | ||
| 101 | + if (this.showIp == null) { | ||
| 102 | + return this.ip; | ||
| 103 | + } | ||
| 104 | + return showIp; | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + public void setShowIp(String showIp) { | ||
| 108 | + this.showIp = showIp; | ||
| 109 | + } | ||
| 99 | } | 110 | } |
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
| @@ -40,17 +40,20 @@ public class SipPlatformRunner implements CommandLineRunner { | @@ -40,17 +40,20 @@ public class SipPlatformRunner implements CommandLineRunner { | ||
| 40 | List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true); | 40 | List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true); |
| 41 | 41 | ||
| 42 | for (ParentPlatform parentPlatform : parentPlatforms) { | 42 | for (ParentPlatform parentPlatform : parentPlatforms) { |
| 43 | + | ||
| 44 | + ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | ||
| 45 | + | ||
| 43 | // 更新缓存 | 46 | // 更新缓存 |
| 44 | ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); | 47 | ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); |
| 45 | parentPlatformCatch.setParentPlatform(parentPlatform); | 48 | parentPlatformCatch.setParentPlatform(parentPlatform); |
| 46 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); | 49 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); |
| 47 | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | 50 | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); |
| 48 | - // 设置所有平台离线 | ||
| 49 | - platformService.offline(parentPlatform, true); | ||
| 50 | // 取消订阅 | 51 | // 取消订阅 |
| 51 | - sipCommanderForPlatform.unregister(parentPlatform, null, (eventResult)->{ | 52 | + sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{ |
| 52 | platformService.login(parentPlatform); | 53 | platformService.login(parentPlatform); |
| 53 | }); | 54 | }); |
| 55 | + // 设置所有平台离线 | ||
| 56 | + platformService.offline(parentPlatform, true); | ||
| 54 | } | 57 | } |
| 55 | } | 58 | } |
| 56 | } | 59 | } |
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
| @@ -50,15 +50,22 @@ public class UserSetting { | @@ -50,15 +50,22 @@ public class UserSetting { | ||
| 50 | private Boolean pushStreamAfterAck = Boolean.FALSE; | 50 | private Boolean pushStreamAfterAck = Boolean.FALSE; |
| 51 | 51 | ||
| 52 | private Boolean sipLog = Boolean.FALSE; | 52 | private Boolean sipLog = Boolean.FALSE; |
| 53 | + private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE; | ||
| 54 | + | ||
| 55 | + private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE; | ||
| 53 | 56 | ||
| 54 | private String serverId = "000000"; | 57 | private String serverId = "000000"; |
| 55 | 58 | ||
| 59 | + private String recordPath = null; | ||
| 60 | + | ||
| 56 | private String thirdPartyGBIdReg = "[\\s\\S]*"; | 61 | private String thirdPartyGBIdReg = "[\\s\\S]*"; |
| 57 | 62 | ||
| 58 | private String broadcastForPlatform = "UDP"; | 63 | private String broadcastForPlatform = "UDP"; |
| 59 | 64 | ||
| 60 | private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); | 65 | private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); |
| 61 | 66 | ||
| 67 | + private List<String> allowedOrigins = new ArrayList<>(); | ||
| 68 | + | ||
| 62 | public Boolean getSavePositionHistory() { | 69 | public Boolean getSavePositionHistory() { |
| 63 | return savePositionHistory; | 70 | return savePositionHistory; |
| 64 | } | 71 | } |
| @@ -238,4 +245,36 @@ public class UserSetting { | @@ -238,4 +245,36 @@ public class UserSetting { | ||
| 238 | public void setSipLog(Boolean sipLog) { | 245 | public void setSipLog(Boolean sipLog) { |
| 239 | this.sipLog = sipLog; | 246 | this.sipLog = sipLog; |
| 240 | } | 247 | } |
| 248 | + | ||
| 249 | + public List<String> getAllowedOrigins() { | ||
| 250 | + return allowedOrigins; | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + public void setAllowedOrigins(List<String> allowedOrigins) { | ||
| 254 | + this.allowedOrigins = allowedOrigins; | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + public Boolean getSendToPlatformsWhenIdLost() { | ||
| 258 | + return sendToPlatformsWhenIdLost; | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + public void setSendToPlatformsWhenIdLost(Boolean sendToPlatformsWhenIdLost) { | ||
| 262 | + this.sendToPlatformsWhenIdLost = sendToPlatformsWhenIdLost; | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + public Boolean getRefuseChannelStatusChannelFormNotify() { | ||
| 266 | + return refuseChannelStatusChannelFormNotify; | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + public void setRefuseChannelStatusChannelFormNotify(Boolean refuseChannelStatusChannelFormNotify) { | ||
| 270 | + this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify; | ||
| 271 | + } | ||
| 272 | + | ||
| 273 | + public String getRecordPath() { | ||
| 274 | + return recordPath; | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + public void setRecordPath(String recordPath) { | ||
| 278 | + this.recordPath = recordPath; | ||
| 279 | + } | ||
| 241 | } | 280 | } |
src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.conf.druid; | ||
| 2 | - | ||
| 3 | -import com.alibaba.druid.support.http.StatViewServlet; | ||
| 4 | -import com.alibaba.druid.support.http.WebStatFilter; | ||
| 5 | -import org.springframework.beans.factory.annotation.Value; | ||
| 6 | -import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
| 7 | -import org.springframework.boot.web.servlet.ServletRegistrationBean; | ||
| 8 | -import org.springframework.context.annotation.Bean; | ||
| 9 | - | ||
| 10 | -import javax.servlet.Filter; | ||
| 11 | -import javax.servlet.Servlet; | ||
| 12 | - | ||
| 13 | -/** | ||
| 14 | - * druid监控配置 | ||
| 15 | - * @author | ||
| 16 | - */ | ||
| 17 | -public class DruidConfiguration { | ||
| 18 | - | ||
| 19 | - @Value("${rj-druid-manage.allow:127.0.0.1}") | ||
| 20 | - private String allow; | ||
| 21 | - | ||
| 22 | - @Value("${rj-druid-manage.deny:}") | ||
| 23 | - private String deny; | ||
| 24 | - | ||
| 25 | - @Value("${rj-druid-manage.loginUsername:admin}") | ||
| 26 | - private String loginUsername; | ||
| 27 | - | ||
| 28 | - @Value("${rj-druid-manage.loginPassword:admin}") | ||
| 29 | - private String loginPassword; | ||
| 30 | - | ||
| 31 | - @Value("${rj-druid-manage.resetEnable:false}") | ||
| 32 | - private String resetEnable; | ||
| 33 | - | ||
| 34 | - /** | ||
| 35 | - * druid监控页面开启 | ||
| 36 | - */ | ||
| 37 | - @Bean | ||
| 38 | - public ServletRegistrationBean druidServlet() { | ||
| 39 | - ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); | ||
| 40 | - // IP白名单 | ||
| 41 | - servletRegistrationBean.addInitParameter("allow", allow); | ||
| 42 | - // IP黑名单(共同存在时,deny优先于allow) | ||
| 43 | - servletRegistrationBean.addInitParameter("deny", deny); | ||
| 44 | - //控制台管理用户 | ||
| 45 | - servletRegistrationBean.addInitParameter("loginUsername", loginUsername); | ||
| 46 | - servletRegistrationBean.addInitParameter("loginPassword", loginPassword); | ||
| 47 | - //是否能够重置数据 禁用HTML页面上的“Reset All”功能 | ||
| 48 | - servletRegistrationBean.addInitParameter("resetEnable", resetEnable); | ||
| 49 | - return servletRegistrationBean; | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | - /** | ||
| 53 | - * druid url监控配置 | ||
| 54 | - */ | ||
| 55 | - @Bean | ||
| 56 | - public FilterRegistrationBean filterRegistrationBean() { | ||
| 57 | - FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new WebStatFilter()); | ||
| 58 | - filterRegistrationBean.addUrlPatterns("/*"); | ||
| 59 | - filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); | ||
| 60 | - return filterRegistrationBean; | ||
| 61 | - } | ||
| 62 | - | ||
| 63 | - | ||
| 64 | -} | ||
| 65 | \ No newline at end of file | 0 | \ No newline at end of file |
src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.conf.druid; | ||
| 2 | - | ||
| 3 | -import org.springframework.boot.web.servlet.ServletComponentScan; | ||
| 4 | -import org.springframework.context.annotation.Import; | ||
| 5 | - | ||
| 6 | -import java.lang.annotation.*; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * druid监控支持注解 | ||
| 10 | - * | ||
| 11 | - * @author | ||
| 12 | - * {@link DruidConfiguration} druid监控页面安全配置支持 | ||
| 13 | - * {@link ServletComponentScan} druid监控页面需要扫描servlet | ||
| 14 | - */ | ||
| 15 | -@Target(ElementType.TYPE) | ||
| 16 | -@Retention(RetentionPolicy.RUNTIME) | ||
| 17 | -@Documented | ||
| 18 | -@Inherited | ||
| 19 | -@Import({ | ||
| 20 | - DruidConfiguration.class, | ||
| 21 | -}) | ||
| 22 | -@ServletComponentScan | ||
| 23 | -public @interface EnableDruidSupport { | ||
| 24 | -} |
src/main/java/com/genersoft/iot/vmp/conf/security/AnonymousAuthenticationEntryPoint.java
| 1 | package com.genersoft.iot.vmp.conf.security; | 1 | package com.genersoft.iot.vmp.conf.security; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | +import com.genersoft.iot.vmp.conf.security.dto.JwtUser; | ||
| 4 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 5 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 5 | -import org.apache.poi.hssf.eventmodel.ERFListener; | ||
| 6 | -import org.slf4j.Logger; | ||
| 7 | -import org.slf4j.LoggerFactory; | 6 | +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| 8 | import org.springframework.security.core.AuthenticationException; | 7 | import org.springframework.security.core.AuthenticationException; |
| 8 | +import org.springframework.security.core.context.SecurityContextHolder; | ||
| 9 | import org.springframework.security.web.AuthenticationEntryPoint; | 9 | import org.springframework.security.web.AuthenticationEntryPoint; |
| 10 | import org.springframework.stereotype.Component; | 10 | import org.springframework.stereotype.Component; |
| 11 | 11 | ||
| @@ -18,17 +18,15 @@ import java.io.IOException; | @@ -18,17 +18,15 @@ import java.io.IOException; | ||
| 18 | * @author lin | 18 | * @author lin |
| 19 | */ | 19 | */ |
| 20 | @Component | 20 | @Component |
| 21 | -public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint { | ||
| 22 | - | ||
| 23 | - private final static Logger logger = LoggerFactory.getLogger(DefaultUserDetailsServiceImpl.class); | 21 | +public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint { |
| 24 | 22 | ||
| 25 | @Override | 23 | @Override |
| 26 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { | 24 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { |
| 27 | - // 允许跨域 | ||
| 28 | - response.setHeader("Access-Control-Allow-Origin", "*"); | ||
| 29 | - // 允许自定义请求头token(允许head跨域) | ||
| 30 | - response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified"); | ||
| 31 | - response.setHeader("Content-type", "application/json;charset=UTF-8"); | 25 | + String jwt = request.getHeader(JwtUtils.getHeader()); |
| 26 | + JwtUser jwtUser = JwtUtils.verifyToken(jwt); | ||
| 27 | + String username = jwtUser.getUserName(); | ||
| 28 | + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() ); | ||
| 29 | + SecurityContextHolder.getContext().setAuthentication(token); | ||
| 32 | JSONObject jsonObject = new JSONObject(); | 30 | JSONObject jsonObject = new JSONObject(); |
| 33 | jsonObject.put("code", ErrorCode.ERROR401.getCode()); | 31 | jsonObject.put("code", ErrorCode.ERROR401.getCode()); |
| 34 | jsonObject.put("msg", ErrorCode.ERROR401.getMsg()); | 32 | jsonObject.put("msg", ErrorCode.ERROR401.getMsg()); |
src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
| 1 | package com.genersoft.iot.vmp.conf.security; | 1 | package com.genersoft.iot.vmp.conf.security; |
| 2 | 2 | ||
| 3 | -import java.time.LocalDateTime; | ||
| 4 | - | 3 | +import com.alibaba.excel.util.StringUtils; |
| 4 | +import com.genersoft.iot.vmp.conf.security.dto.LoginUser; | ||
| 5 | +import com.genersoft.iot.vmp.service.IUserService; | ||
| 6 | +import com.genersoft.iot.vmp.storager.dao.dto.User; | ||
| 5 | import org.slf4j.Logger; | 7 | import org.slf4j.Logger; |
| 6 | import org.slf4j.LoggerFactory; | 8 | import org.slf4j.LoggerFactory; |
| 7 | import org.springframework.beans.factory.annotation.Autowired; | 9 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -10,10 +12,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; | @@ -10,10 +12,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; | ||
| 10 | import org.springframework.security.core.userdetails.UsernameNotFoundException; | 12 | import org.springframework.security.core.userdetails.UsernameNotFoundException; |
| 11 | import org.springframework.stereotype.Component; | 13 | import org.springframework.stereotype.Component; |
| 12 | 14 | ||
| 13 | -import com.alibaba.excel.util.StringUtils; | ||
| 14 | -import com.genersoft.iot.vmp.conf.security.dto.LoginUser; | ||
| 15 | -import com.genersoft.iot.vmp.service.IUserService; | ||
| 16 | -import com.genersoft.iot.vmp.storager.dao.dto.User; | 15 | +import java.time.LocalDateTime; |
| 17 | 16 | ||
| 18 | /** | 17 | /** |
| 19 | * 用户登录认证逻辑 | 18 | * 用户登录认证逻辑 |
| @@ -45,4 +44,8 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService { | @@ -45,4 +44,8 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService { | ||
| 45 | } | 44 | } |
| 46 | 45 | ||
| 47 | 46 | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + | ||
| 50 | + | ||
| 48 | } | 51 | } |
src/main/java/com/genersoft/iot/vmp/conf/security/InvalidSessionHandler.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.conf.security; | ||
| 2 | - | ||
| 3 | -import org.slf4j.Logger; | ||
| 4 | -import org.slf4j.LoggerFactory; | ||
| 5 | -import org.springframework.security.web.session.InvalidSessionStrategy; | ||
| 6 | - | ||
| 7 | -import javax.servlet.ServletException; | ||
| 8 | -import javax.servlet.http.HttpServletRequest; | ||
| 9 | -import javax.servlet.http.HttpServletResponse; | ||
| 10 | -import java.io.IOException; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * 登录超时的处理 | ||
| 14 | - */ | ||
| 15 | -public class InvalidSessionHandler implements InvalidSessionStrategy { | ||
| 16 | - | ||
| 17 | - private final static Logger logger = LoggerFactory.getLogger(InvalidSessionHandler.class); | ||
| 18 | - | ||
| 19 | - @Override | ||
| 20 | - public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse httpServletResponse) throws IOException, ServletException { | ||
| 21 | - String username = request.getParameter("username"); | ||
| 22 | - logger.info("[登录超时] - [{}]", username); | ||
| 23 | - } | ||
| 24 | -} |
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 4 | +import com.genersoft.iot.vmp.conf.security.dto.JwtUser; | ||
| 5 | +import org.apache.commons.lang3.StringUtils; | ||
| 6 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 7 | +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
| 8 | +import org.springframework.security.core.context.SecurityContextHolder; | ||
| 9 | +import org.springframework.stereotype.Component; | ||
| 10 | +import org.springframework.web.filter.OncePerRequestFilter; | ||
| 11 | + | ||
| 12 | +import javax.servlet.FilterChain; | ||
| 13 | +import javax.servlet.ServletException; | ||
| 14 | +import javax.servlet.http.HttpServletRequest; | ||
| 15 | +import javax.servlet.http.HttpServletResponse; | ||
| 16 | +import java.io.IOException; | ||
| 17 | +import java.util.ArrayList; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * jwt token 过滤器 | ||
| 21 | + */ | ||
| 22 | + | ||
| 23 | +@Component | ||
| 24 | +public class JwtAuthenticationFilter extends OncePerRequestFilter { | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + @Autowired | ||
| 28 | + private UserSetting userSetting; | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { | ||
| 33 | + | ||
| 34 | + // 忽略登录请求的token验证 | ||
| 35 | + String requestURI = request.getRequestURI(); | ||
| 36 | + if (requestURI.equalsIgnoreCase("/api/user/login")) { | ||
| 37 | + chain.doFilter(request, response); | ||
| 38 | + return; | ||
| 39 | + } | ||
| 40 | + if (!userSetting.isInterfaceAuthentication()) { | ||
| 41 | + // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录 | ||
| 42 | + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() ); | ||
| 43 | + SecurityContextHolder.getContext().setAuthentication(token); | ||
| 44 | + chain.doFilter(request, response); | ||
| 45 | + return; | ||
| 46 | + } | ||
| 47 | + String jwt = request.getHeader(JwtUtils.getHeader()); | ||
| 48 | + // 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的 | ||
| 49 | + // 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口 | ||
| 50 | + if (StringUtils.isBlank(jwt)) { | ||
| 51 | + jwt = request.getParameter(JwtUtils.getHeader()); | ||
| 52 | + if (StringUtils.isBlank(jwt)) { | ||
| 53 | + chain.doFilter(request, response); | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + JwtUser jwtUser = JwtUtils.verifyToken(jwt); | ||
| 59 | + String username = jwtUser.getUserName(); | ||
| 60 | + // TODO 处理各个状态 | ||
| 61 | + switch (jwtUser.getStatus()){ | ||
| 62 | + case EXPIRED: | ||
| 63 | + response.setStatus(400); | ||
| 64 | + chain.doFilter(request, response); | ||
| 65 | + // 异常 | ||
| 66 | + return; | ||
| 67 | + case EXCEPTION: | ||
| 68 | + // 过期 | ||
| 69 | + response.setStatus(400); | ||
| 70 | + chain.doFilter(request, response); | ||
| 71 | + return; | ||
| 72 | + case EXPIRING_SOON: | ||
| 73 | + // 即将过期 | ||
| 74 | +// return; | ||
| 75 | + default: | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录 | ||
| 79 | + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword(), new ArrayList<>() ); | ||
| 80 | + SecurityContextHolder.getContext().setAuthentication(token); | ||
| 81 | + chain.doFilter(request, response); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.security.dto.JwtUser; | ||
| 4 | +import org.jose4j.json.JsonUtil; | ||
| 5 | +import org.jose4j.jwk.RsaJsonWebKey; | ||
| 6 | +import org.jose4j.jws.AlgorithmIdentifiers; | ||
| 7 | +import org.jose4j.jws.JsonWebSignature; | ||
| 8 | +import org.jose4j.jwt.JwtClaims; | ||
| 9 | +import org.jose4j.jwt.NumericDate; | ||
| 10 | +import org.jose4j.jwt.consumer.ErrorCodes; | ||
| 11 | +import org.jose4j.jwt.consumer.InvalidJwtException; | ||
| 12 | +import org.jose4j.jwt.consumer.JwtConsumer; | ||
| 13 | +import org.jose4j.jwt.consumer.JwtConsumerBuilder; | ||
| 14 | +import org.jose4j.lang.JoseException; | ||
| 15 | +import org.slf4j.Logger; | ||
| 16 | +import org.slf4j.LoggerFactory; | ||
| 17 | + | ||
| 18 | +import java.security.PrivateKey; | ||
| 19 | +import java.time.LocalDateTime; | ||
| 20 | +import java.time.ZoneOffset; | ||
| 21 | + | ||
| 22 | +public class JwtUtils { | ||
| 23 | + | ||
| 24 | + private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); | ||
| 25 | + | ||
| 26 | + private static final String HEADER = "access-token"; | ||
| 27 | + private static final String AUDIENCE = "Audience"; | ||
| 28 | + | ||
| 29 | + private static final long EXPIRED_THRESHOLD = 10 * 60; | ||
| 30 | + | ||
| 31 | + private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae"; | ||
| 32 | + private static final String privateKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\",\"d\":\"ed7U_k3rJ4yTk70JtRSIfjKGiEb67BO1TabcymnljKO7RU8nage84zZYuSu_XpQsHk6P1f0Gzxkicghm_Er-FrfVn2pp70Xu52z3yRd6BJUgWLDFk97ngScIyw5OiULKU9SrZk2frDpftNCSUcIgb50F8m0QAnBa_CdPsQKbuuhLv8V8tBAV7F_lAwvSBgu56wRo3hPz5dWH8YeXM7XBfQ9viFMNEKd21sP_j5C7ueUnXT66nBxe3ZJEU3iuMYM6D6dB_KW2GfZC6WmTgvGhhxJD0h7aYmfjkD99MDleB7SkpbvoODOqiQ5Epb7Nyh6kv5u4KUv2CJYtATLZkUeMkQ\",\"p\":\"uBUjWPWtlGksmOqsqCNWksfqJvMcnP_8TDYN7e4-WnHL4N-9HjRuPDnp6kHvCIEi9SEfxm7gNxlRcWegvNQr3IZCz7TnCTexXc5NOklB9OavWFla6u-s3Thn6Tz45-EUjpJr0VJMxhO-KxGmuTwUXBBp4vN6K2qV6rQNFmgkWzk\",\"q\":\"tW_i7cCec56bHkhITL_79dXHz_PLC_f7xlynmlZJGU_d6mqOKmLBNBbTMLnYW8uAFiFzWxDeDHh1o5uF0mSQR-Z1Fg35OftnpbWpy0Cbc2la5WgXQjOwtG1eLYIY2BD3-wQ1VYDBCvowr4FDi-sngxwLqvwmrJ0xjhi99O-Gzcs\",\"dp\":\"q1d5jE85Hz_6M-eTh_lEluEf0NtPEc-vvhw-QO4V-cecNpbrCBdTWBmr4dE3NdpFeJc5ZVFEv-SACyei1MBEh0ItI_pFZi4BmMfy2ELh8ptaMMkTOESYyVy8U7veDq9RnBcr5i1Nqr0rsBkA77-9T6gzdvycBZdzLYAkAmwzEvk\",\"dq\":\"q29A2K08Crs-jmp2Bi8Q_8QzvIX6wSBbwZ4ir24AO-5_HNP56IrPS0yV2GCB0pqCOGb6_Hz_koDvhtuYoqdqvMVAtMoXR3YJBUaVXPt65p4RyNmFwIPe31zHs_BNUTsXVRMw4c16mci03-Af1sEm4HdLfxAp6sfM3xr5wcnhcek\",\"qi\":\"rHPgVTyHUHuYzcxfouyBfb1XAY8nshwn0ddo81o1BccD4Z7zo5It6SefDHjxCAbcmbiCcXBSooLcY-NF5FMv3fg19UE21VyLQltHcVjRRp2tRs4OHcM8yaXIU2x6N6Z6BP2tOksHb9MOBY1wAQzFOAKg_G4Sxev6-_6ud6RISuc\"}"; | ||
| 33 | + private static final String publicKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\"}"; | ||
| 34 | + | ||
| 35 | + /** | ||
| 36 | + * token过期时间(分钟) | ||
| 37 | + */ | ||
| 38 | + public static final long expirationTime = 30; | ||
| 39 | + | ||
| 40 | + public static String createToken(String username, String password) { | ||
| 41 | + try { | ||
| 42 | + /** | ||
| 43 | + * “iss” (issuer) 发行人 | ||
| 44 | + * | ||
| 45 | + * “sub” (subject) 主题 | ||
| 46 | + * | ||
| 47 | + * “aud” (audience) 接收方 用户 | ||
| 48 | + * | ||
| 49 | + * “exp” (expiration time) 到期时间 | ||
| 50 | + * | ||
| 51 | + * “nbf” (not before) 在此之前不可用 | ||
| 52 | + * | ||
| 53 | + * “iat” (issued at) jwt的签发时间 | ||
| 54 | + */ | ||
| 55 | + //Payload | ||
| 56 | + JwtClaims claims = new JwtClaims(); | ||
| 57 | + claims.setGeneratedJwtId(); | ||
| 58 | + claims.setIssuedAtToNow(); | ||
| 59 | + // 令牌将过期的时间 分钟 | ||
| 60 | + claims.setExpirationTimeMinutesInTheFuture(expirationTime); | ||
| 61 | + claims.setNotBeforeMinutesInThePast(0); | ||
| 62 | + claims.setSubject("login"); | ||
| 63 | + claims.setAudience(AUDIENCE); | ||
| 64 | + //添加自定义参数,必须是字符串类型 | ||
| 65 | + claims.setClaim("username", username); | ||
| 66 | + claims.setClaim("password", password); | ||
| 67 | + | ||
| 68 | + //jws | ||
| 69 | + JsonWebSignature jws = new JsonWebSignature(); | ||
| 70 | + //签名算法RS256 | ||
| 71 | + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256); | ||
| 72 | + jws.setKeyIdHeaderValue(keyId); | ||
| 73 | + jws.setPayload(claims.toJson()); | ||
| 74 | + | ||
| 75 | + PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyStr)).getPrivateKey(); | ||
| 76 | + jws.setKey(privateKey); | ||
| 77 | + | ||
| 78 | + //get token | ||
| 79 | + String idToken = jws.getCompactSerialization(); | ||
| 80 | + return idToken; | ||
| 81 | + } catch (JoseException e) { | ||
| 82 | + logger.error("[Token生成失败]: {}", e.getMessage()); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + return null; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + public static String getHeader() { | ||
| 89 | + return HEADER; | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + | ||
| 93 | + public static JwtUser verifyToken(String token) { | ||
| 94 | + | ||
| 95 | + JwtUser jwtUser = new JwtUser(); | ||
| 96 | + | ||
| 97 | + try { | ||
| 98 | + JwtConsumer consumer = new JwtConsumerBuilder() | ||
| 99 | + .setRequireExpirationTime() | ||
| 100 | + .setMaxFutureValidityInMinutes(5256000) | ||
| 101 | + .setAllowedClockSkewInSeconds(30) | ||
| 102 | + .setRequireSubject() | ||
| 103 | + //.setExpectedIssuer("") | ||
| 104 | + .setExpectedAudience(AUDIENCE) | ||
| 105 | + .setVerificationKey(new RsaJsonWebKey(JsonUtil.parseJson(publicKeyStr)).getPublicKey()) | ||
| 106 | + .build(); | ||
| 107 | + | ||
| 108 | + JwtClaims claims = consumer.processToClaims(token); | ||
| 109 | + NumericDate expirationTime = claims.getExpirationTime(); | ||
| 110 | + // 判断是否即将过期, 默认剩余时间小于5分钟未即将过期 | ||
| 111 | + // 剩余时间 (秒) | ||
| 112 | + long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue(); | ||
| 113 | + if (timeRemaining < 5 * 60) { | ||
| 114 | + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON); | ||
| 115 | + }else { | ||
| 116 | + jwtUser.setStatus(JwtUser.TokenStatus.NORMAL); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + String username = (String) claims.getClaimValue("username"); | ||
| 120 | + String password = (String) claims.getClaimValue("password"); | ||
| 121 | + jwtUser.setUserName(username); | ||
| 122 | + jwtUser.setPassword(password); | ||
| 123 | + | ||
| 124 | + return jwtUser; | ||
| 125 | + } catch (InvalidJwtException e) { | ||
| 126 | + if (e.hasErrorCode(ErrorCodes.EXPIRED)) { | ||
| 127 | + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED); | ||
| 128 | + }else { | ||
| 129 | + jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION); | ||
| 130 | + } | ||
| 131 | + return jwtUser; | ||
| 132 | + }catch (Exception e) { | ||
| 133 | + logger.error("[Token解析失败]: {}", e.getMessage()); | ||
| 134 | + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED); | ||
| 135 | + return jwtUser; | ||
| 136 | + } | ||
| 137 | + } | ||
| 138 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java
| @@ -21,7 +21,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler { | @@ -21,7 +21,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler { | ||
| 21 | 21 | ||
| 22 | @Override | 22 | @Override |
| 23 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { | 23 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { |
| 24 | - String username = request.getParameter("username"); | ||
| 25 | - logger.info("[登录成功] - [{}]", username); | 24 | +// String username = request.getParameter("username"); |
| 25 | +// httpServletResponse.setContentType("application/json;charset=UTF-8"); | ||
| 26 | +// // 生成JWT,并放置到请求头中 | ||
| 27 | +// String jwt = JwtUtils.createToken(authentication.getName(), ); | ||
| 28 | +// httpServletResponse.setHeader(JwtUtils.getHeader(), jwt); | ||
| 29 | +// ServletOutputStream outputStream = httpServletResponse.getOutputStream(); | ||
| 30 | +// outputStream.write(JSON.toJSONString(ErrorCode.SUCCESS).getBytes(StandardCharsets.UTF_8)); | ||
| 31 | +// outputStream.flush(); | ||
| 32 | +// outputStream.close(); | ||
| 33 | + | ||
| 34 | +// logger.info("[登录成功] - [{}]", username); | ||
| 26 | } | 35 | } |
| 27 | } | 36 | } |
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.java
| 1 | package com.genersoft.iot.vmp.conf.security; | 1 | package com.genersoft.iot.vmp.conf.security; |
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.conf.security.dto.LoginUser; | 3 | import com.genersoft.iot.vmp.conf.security.dto.LoginUser; |
| 4 | +import com.genersoft.iot.vmp.storager.dao.dto.User; | ||
| 4 | import org.springframework.security.authentication.AuthenticationManager; | 5 | import org.springframework.security.authentication.AuthenticationManager; |
| 5 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | 6 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| 6 | import org.springframework.security.core.Authentication; | 7 | import org.springframework.security.core.Authentication; |
| @@ -9,6 +10,7 @@ import org.springframework.security.core.context.SecurityContextHolder; | @@ -9,6 +10,7 @@ import org.springframework.security.core.context.SecurityContextHolder; | ||
| 9 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | 10 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
| 10 | 11 | ||
| 11 | import javax.security.sasl.AuthenticationException; | 12 | import javax.security.sasl.AuthenticationException; |
| 13 | +import java.time.LocalDateTime; | ||
| 12 | 14 | ||
| 13 | public class SecurityUtils { | 15 | public class SecurityUtils { |
| 14 | 16 | ||
| @@ -25,9 +27,12 @@ public class SecurityUtils { | @@ -25,9 +27,12 @@ public class SecurityUtils { | ||
| 25 | public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException { | 27 | public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException { |
| 26 | //使用security框架自带的验证token生成器 也可以自定义。 | 28 | //使用security框架自带的验证token生成器 也可以自定义。 |
| 27 | UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password); | 29 | UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password); |
| 30 | + //认证 如果失败,这里会自动异常后返回,所以这里不需要判断返回值是否为空,确定是否登录成功 | ||
| 28 | Authentication authenticate = authenticationManager.authenticate(token); | 31 | Authentication authenticate = authenticationManager.authenticate(token); |
| 29 | - SecurityContextHolder.getContext().setAuthentication(authenticate); | ||
| 30 | LoginUser user = (LoginUser) authenticate.getPrincipal(); | 32 | LoginUser user = (LoginUser) authenticate.getPrincipal(); |
| 33 | + | ||
| 34 | + SecurityContextHolder.getContext().setAuthentication(token); | ||
| 35 | + | ||
| 31 | return user; | 36 | return user; |
| 32 | } | 37 | } |
| 33 | 38 | ||
| @@ -49,8 +54,13 @@ public class SecurityUtils { | @@ -49,8 +54,13 @@ public class SecurityUtils { | ||
| 49 | if(authentication!=null){ | 54 | if(authentication!=null){ |
| 50 | Object principal = authentication.getPrincipal(); | 55 | Object principal = authentication.getPrincipal(); |
| 51 | if(principal!=null && !"anonymousUser".equals(principal)){ | 56 | if(principal!=null && !"anonymousUser".equals(principal)){ |
| 52 | - LoginUser user = (LoginUser) authentication.getPrincipal(); | ||
| 53 | - return user; | 57 | +// LoginUser user = (LoginUser) authentication.getPrincipal(); |
| 58 | + | ||
| 59 | + String username = (String) principal; | ||
| 60 | + User user = new User(); | ||
| 61 | + user.setUsername(username); | ||
| 62 | + LoginUser loginUser = new LoginUser(user, LocalDateTime.now()); | ||
| 63 | + return loginUser; | ||
| 54 | } | 64 | } |
| 55 | } | 65 | } |
| 56 | return null; | 66 | return null; |
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
| @@ -15,9 +15,16 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; | @@ -15,9 +15,16 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| 15 | import org.springframework.security.config.annotation.web.builders.WebSecurity; | 15 | import org.springframework.security.config.annotation.web.builders.WebSecurity; |
| 16 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | 16 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
| 17 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | 17 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
| 18 | +import org.springframework.security.config.http.SessionCreationPolicy; | ||
| 18 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | 19 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; |
| 20 | +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
| 21 | +import org.springframework.web.cors.CorsConfiguration; | ||
| 22 | +import org.springframework.web.cors.CorsConfigurationSource; | ||
| 23 | +import org.springframework.web.cors.CorsUtils; | ||
| 24 | +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
| 19 | 25 | ||
| 20 | -import java.util.List; | 26 | +import java.util.ArrayList; |
| 27 | +import java.util.Arrays; | ||
| 21 | 28 | ||
| 22 | /** | 29 | /** |
| 23 | * 配置Spring Security | 30 | * 配置Spring Security |
| @@ -56,22 +63,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -56,22 +63,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
| 56 | */ | 63 | */ |
| 57 | @Autowired | 64 | @Autowired |
| 58 | private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint; | 65 | private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint; |
| 59 | -// /** | ||
| 60 | -// * 超时处理 | ||
| 61 | -// */ | ||
| 62 | -// @Autowired | ||
| 63 | -// private InvalidSessionHandler invalidSessionHandler; | ||
| 64 | - | ||
| 65 | -// /** | ||
| 66 | -// * 顶号处理 | ||
| 67 | -// */ | ||
| 68 | -// @Autowired | ||
| 69 | -// private SessionInformationExpiredHandler sessionInformationExpiredHandler; | ||
| 70 | -// /** | ||
| 71 | -// * 登录用户没有权限访问资源 | ||
| 72 | -// */ | ||
| 73 | -// @Autowired | ||
| 74 | -// private LoginUserAccessDeniedHandler accessDeniedHandler; | 66 | + @Autowired |
| 67 | + private JwtAuthenticationFilter jwtAuthenticationFilter; | ||
| 75 | 68 | ||
| 76 | 69 | ||
| 77 | /** | 70 | /** |
| @@ -80,31 +73,21 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -80,31 +73,21 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
| 80 | @Override | 73 | @Override |
| 81 | public void configure(WebSecurity web) { | 74 | public void configure(WebSecurity web) { |
| 82 | 75 | ||
| 83 | - if (!userSetting.isInterfaceAuthentication()) { | ||
| 84 | - web.ignoring().antMatchers("**"); | ||
| 85 | - }else { | ||
| 86 | - // 可以直接访问的静态数据 | ||
| 87 | - web.ignoring() | ||
| 88 | - .antMatchers("/") | ||
| 89 | - .antMatchers("/#/**") | ||
| 90 | - .antMatchers("/static/**") | ||
| 91 | - .antMatchers("/index.html") | ||
| 92 | - .antMatchers("/doc.html") // "/webjars/**", "/swagger-resources/**", "/v3/api-docs/**" | ||
| 93 | - .antMatchers("/webjars/**") | ||
| 94 | - .antMatchers("/swagger-resources/**") | ||
| 95 | - .antMatchers("/v3/api-docs/**") | ||
| 96 | - .antMatchers("/favicon.ico") | ||
| 97 | - .antMatchers("/js/**"); | ||
| 98 | - List<String> interfaceAuthenticationExcludes = userSetting.getInterfaceAuthenticationExcludes(); | ||
| 99 | - for (String interfaceAuthenticationExclude : interfaceAuthenticationExcludes) { | ||
| 100 | - if (interfaceAuthenticationExclude.split("/").length < 4 ) { | ||
| 101 | - logger.warn("{}不满足两级目录,已忽略", interfaceAuthenticationExclude); | ||
| 102 | - }else { | ||
| 103 | - web.ignoring().antMatchers(interfaceAuthenticationExclude); | ||
| 104 | - } | ||
| 105 | - | ||
| 106 | - } | ||
| 107 | - } | 76 | + ArrayList<String> matchers = new ArrayList<>(); |
| 77 | + matchers.add("/"); | ||
| 78 | + matchers.add("/#/**"); | ||
| 79 | + matchers.add("/static/**"); | ||
| 80 | + matchers.add("/index.html"); | ||
| 81 | + matchers.add("/doc.html"); | ||
| 82 | + matchers.add("/webjars/**"); | ||
| 83 | + matchers.add("/swagger-resources/**"); | ||
| 84 | + matchers.add("/v3/api-docs/**"); | ||
| 85 | + matchers.add("/js/**"); | ||
| 86 | + matchers.add("/api/device/query/snap/**"); | ||
| 87 | + matchers.add("/record_proxy/*/**"); | ||
| 88 | + matchers.addAll(userSetting.getInterfaceAuthenticationExcludes()); | ||
| 89 | + // 可以直接访问的静态数据 | ||
| 90 | + web.ignoring().antMatchers(matchers.toArray(new String[0])); | ||
| 108 | } | 91 | } |
| 109 | 92 | ||
| 110 | /** | 93 | /** |
| @@ -126,36 +109,43 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | @@ -126,36 +109,43 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | ||
| 126 | 109 | ||
| 127 | @Override | 110 | @Override |
| 128 | protected void configure(HttpSecurity http) throws Exception { | 111 | protected void configure(HttpSecurity http) throws Exception { |
| 129 | - http.cors().and().csrf().disable(); | ||
| 130 | - // 设置允许添加静态文件 | ||
| 131 | - http.headers().contentTypeOptions().disable(); | ||
| 132 | - http.authorizeRequests() | ||
| 133 | - // 放行接口 | ||
| 134 | - .antMatchers("/api/user/login","/index/hook/**").permitAll() | ||
| 135 | - // 除上面外的所有请求全部需要鉴权认证 | 112 | + http.headers().contentTypeOptions().disable() |
| 113 | + .and().cors().configurationSource(configurationSource()) | ||
| 114 | + .and().csrf().disable() | ||
| 115 | + .sessionManagement() | ||
| 116 | + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
| 117 | + | ||
| 118 | + // 配置拦截规则 | ||
| 119 | + .and() | ||
| 120 | + .authorizeRequests() | ||
| 121 | + .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() | ||
| 122 | + .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll() | ||
| 123 | + .antMatchers("/api/user/login","/index/hook/**","/zlm_Proxy/FhTuMYqB2HeCuNOb/record/t/1/2023-03-25/16:35:07-16:35:16-9353.mp4").permitAll() | ||
| 136 | .anyRequest().authenticated() | 124 | .anyRequest().authenticated() |
| 137 | - // 异常处理(权限拒绝、登录失效等) | ||
| 138 | - .and().exceptionHandling() | ||
| 139 | - //匿名用户访问无权限资源时的异常处理 | 125 | + // 异常处理器 |
| 126 | + .and() | ||
| 127 | + .exceptionHandling() | ||
| 140 | .authenticationEntryPoint(anonymousAuthenticationEntryPoint) | 128 | .authenticationEntryPoint(anonymousAuthenticationEntryPoint) |
| 141 | -// .accessDeniedHandler(accessDeniedHandler)//登录用户没有权限访问资源 | ||
| 142 | - // 登入 允许所有用户 | ||
| 143 | - .and().formLogin().permitAll() | ||
| 144 | - //登录成功处理逻辑 | ||
| 145 | - .successHandler(loginSuccessHandler) | ||
| 146 | - //登录失败处理逻辑 | ||
| 147 | - .failureHandler(loginFailureHandler) | ||
| 148 | - // 登出 | ||
| 149 | .and().logout().logoutUrl("/api/user/logout").permitAll() | 129 | .and().logout().logoutUrl("/api/user/logout").permitAll() |
| 150 | - //登出成功处理逻辑 | ||
| 151 | .logoutSuccessHandler(logoutHandler) | 130 | .logoutSuccessHandler(logoutHandler) |
| 152 | - .deleteCookies("JSESSIONID") | ||
| 153 | - // 会话管理 | ||
| 154 | -// .and().sessionManagement().invalidSessionStrategy(invalidSessionHandler) // 超时处理 | ||
| 155 | -// .maximumSessions(1)//同一账号同时登录最大用户数 | ||
| 156 | -// .expiredSessionStrategy(sessionInformationExpiredHandler) // 顶号处理 | ||
| 157 | ; | 131 | ; |
| 132 | + http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); | ||
| 133 | + | ||
| 134 | + } | ||
| 158 | 135 | ||
| 136 | + CorsConfigurationSource configurationSource(){ | ||
| 137 | + // 配置跨域 | ||
| 138 | + CorsConfiguration corsConfiguration = new CorsConfiguration(); | ||
| 139 | + corsConfiguration.setAllowedHeaders(Arrays.asList("*")); | ||
| 140 | + corsConfiguration.setAllowedMethods(Arrays.asList("*")); | ||
| 141 | + corsConfiguration.setMaxAge(3600L); | ||
| 142 | + corsConfiguration.setAllowCredentials(true); | ||
| 143 | + corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins()); | ||
| 144 | + corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader())); | ||
| 145 | + | ||
| 146 | + UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource(); | ||
| 147 | + url.registerCorsConfiguration("/**",corsConfiguration); | ||
| 148 | + return url; | ||
| 159 | } | 149 | } |
| 160 | 150 | ||
| 161 | /** | 151 | /** |
src/main/java/com/genersoft/iot/vmp/conf/security/dto/JwtUser.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.security.dto; | ||
| 2 | + | ||
| 3 | +public class JwtUser { | ||
| 4 | + | ||
| 5 | + public enum TokenStatus{ | ||
| 6 | + /** | ||
| 7 | + * 正常的使用状态 | ||
| 8 | + */ | ||
| 9 | + NORMAL, | ||
| 10 | + /** | ||
| 11 | + * 过期而失效 | ||
| 12 | + */ | ||
| 13 | + EXPIRED, | ||
| 14 | + /** | ||
| 15 | + * 即将过期 | ||
| 16 | + */ | ||
| 17 | + EXPIRING_SOON, | ||
| 18 | + /** | ||
| 19 | + * 异常 | ||
| 20 | + */ | ||
| 21 | + EXCEPTION | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + private String userName; | ||
| 25 | + | ||
| 26 | + private String password; | ||
| 27 | + | ||
| 28 | + private TokenStatus status; | ||
| 29 | + | ||
| 30 | + public String getUserName() { | ||
| 31 | + return userName; | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + public void setUserName(String userName) { | ||
| 35 | + this.userName = userName; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + public TokenStatus getStatus() { | ||
| 39 | + return status; | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + public void setStatus(TokenStatus status) { | ||
| 43 | + this.status = status; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + public String getPassword() { | ||
| 47 | + return password; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + public void setPassword(String password) { | ||
| 51 | + this.password = password; | ||
| 52 | + } | ||
| 53 | +} |
src/main/java/com/genersoft/iot/vmp/conf/security/dto/LoginUser.java
| @@ -19,6 +19,8 @@ public class LoginUser implements UserDetails, CredentialsContainer { | @@ -19,6 +19,8 @@ public class LoginUser implements UserDetails, CredentialsContainer { | ||
| 19 | */ | 19 | */ |
| 20 | private User user; | 20 | private User user; |
| 21 | 21 | ||
| 22 | + private String accessToken; | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | /** | 25 | /** |
| 24 | * 登录时间 | 26 | * 登录时间 |
| @@ -102,4 +104,11 @@ public class LoginUser implements UserDetails, CredentialsContainer { | @@ -102,4 +104,11 @@ public class LoginUser implements UserDetails, CredentialsContainer { | ||
| 102 | return user.getPushKey(); | 104 | return user.getPushKey(); |
| 103 | } | 105 | } |
| 104 | 106 | ||
| 107 | + public String getAccessToken() { | ||
| 108 | + return accessToken; | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + public void setAccessToken(String accessToken) { | ||
| 112 | + this.accessToken = accessToken; | ||
| 113 | + } | ||
| 105 | } | 114 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
| @@ -171,7 +171,7 @@ public class DigestServerAuthenticationHelper { | @@ -171,7 +171,7 @@ public class DigestServerAuthenticationHelper { | ||
| 171 | */ | 171 | */ |
| 172 | public boolean doAuthenticatePlainTextPassword(Request request, String pass) { | 172 | public boolean doAuthenticatePlainTextPassword(Request request, String pass) { |
| 173 | AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | 173 | AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
| 174 | - if ( authHeader == null ) { | 174 | + if ( authHeader == null || authHeader.getRealm() == null) { |
| 175 | return false; | 175 | return false; |
| 176 | } | 176 | } |
| 177 | String realm = authHeader.getRealm().trim(); | 177 | String realm = authHeader.getRealm().trim(); |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
| @@ -188,6 +188,13 @@ public class Device { | @@ -188,6 +188,13 @@ public class Device { | ||
| 188 | @Schema(description = "SIP交互IP(设备访问平台的IP)") | 188 | @Schema(description = "SIP交互IP(设备访问平台的IP)") |
| 189 | private String localIp; | 189 | private String localIp; |
| 190 | 190 | ||
| 191 | + @Schema(description = "是否作为消息通道") | ||
| 192 | + private boolean asMessageChannel; | ||
| 193 | + | ||
| 194 | + @Schema(description = "设备注册的事务信息") | ||
| 195 | + private SipTransactionInfo sipTransactionInfo; | ||
| 196 | + | ||
| 197 | + | ||
| 191 | public String getDeviceId() { | 198 | public String getDeviceId() { |
| 192 | return deviceId; | 199 | return deviceId; |
| 193 | } | 200 | } |
| @@ -428,4 +435,20 @@ public class Device { | @@ -428,4 +435,20 @@ public class Device { | ||
| 428 | public void setKeepaliveIntervalTime(int keepaliveIntervalTime) { | 435 | public void setKeepaliveIntervalTime(int keepaliveIntervalTime) { |
| 429 | this.keepaliveIntervalTime = keepaliveIntervalTime; | 436 | this.keepaliveIntervalTime = keepaliveIntervalTime; |
| 430 | } | 437 | } |
| 438 | + | ||
| 439 | + public boolean isAsMessageChannel() { | ||
| 440 | + return asMessageChannel; | ||
| 441 | + } | ||
| 442 | + | ||
| 443 | + public void setAsMessageChannel(boolean asMessageChannel) { | ||
| 444 | + this.asMessageChannel = asMessageChannel; | ||
| 445 | + } | ||
| 446 | + | ||
| 447 | + public SipTransactionInfo getSipTransactionInfo() { | ||
| 448 | + return sipTransactionInfo; | ||
| 449 | + } | ||
| 450 | + | ||
| 451 | + public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) { | ||
| 452 | + this.sipTransactionInfo = sipTransactionInfo; | ||
| 453 | + } | ||
| 431 | } | 454 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
| @@ -189,6 +189,9 @@ public class ParentPlatform { | @@ -189,6 +189,9 @@ public class ParentPlatform { | ||
| 189 | @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou") | 189 | @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou") |
| 190 | private String treeType; | 190 | private String treeType; |
| 191 | 191 | ||
| 192 | + @Schema(description = "是否作为消息通道") | ||
| 193 | + private boolean asMessageChannel; | ||
| 194 | + | ||
| 192 | public Integer getId() { | 195 | public Integer getId() { |
| 193 | return id; | 196 | return id; |
| 194 | } | 197 | } |
| @@ -428,4 +431,12 @@ public class ParentPlatform { | @@ -428,4 +431,12 @@ public class ParentPlatform { | ||
| 428 | public void setTreeType(String treeType) { | 431 | public void setTreeType(String treeType) { |
| 429 | this.treeType = treeType; | 432 | this.treeType = treeType; |
| 430 | } | 433 | } |
| 434 | + | ||
| 435 | + public boolean isAsMessageChannel() { | ||
| 436 | + return asMessageChannel; | ||
| 437 | + } | ||
| 438 | + | ||
| 439 | + public void setAsMessageChannel(boolean asMessageChannel) { | ||
| 440 | + this.asMessageChannel = asMessageChannel; | ||
| 441 | + } | ||
| 431 | } | 442 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
| @@ -16,6 +16,8 @@ public class ParentPlatformCatch { | @@ -16,6 +16,8 @@ public class ParentPlatformCatch { | ||
| 16 | 16 | ||
| 17 | private ParentPlatform parentPlatform; | 17 | private ParentPlatform parentPlatform; |
| 18 | 18 | ||
| 19 | + private SipTransactionInfo sipTransactionInfo; | ||
| 20 | + | ||
| 19 | public String getId() { | 21 | public String getId() { |
| 20 | return id; | 22 | return id; |
| 21 | } | 23 | } |
| @@ -55,4 +57,12 @@ public class ParentPlatformCatch { | @@ -55,4 +57,12 @@ public class ParentPlatformCatch { | ||
| 55 | public void setCallId(String callId) { | 57 | public void setCallId(String callId) { |
| 56 | this.callId = callId; | 58 | this.callId = callId; |
| 57 | } | 59 | } |
| 60 | + | ||
| 61 | + public SipTransactionInfo getSipTransactionInfo() { | ||
| 62 | + return sipTransactionInfo; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) { | ||
| 66 | + this.sipTransactionInfo = sipTransactionInfo; | ||
| 67 | + } | ||
| 58 | } | 68 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
| 1 | package com.genersoft.iot.vmp.gb28181.bean; | 1 | package com.genersoft.iot.vmp.gb28181.bean; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | + | ||
| 4 | import java.time.Instant; | 6 | import java.time.Instant; |
| 5 | import java.util.List; | 7 | import java.util.List; |
| 6 | 8 | ||
| @@ -9,22 +11,29 @@ import java.util.List; | @@ -9,22 +11,29 @@ import java.util.List; | ||
| 9 | * @author: swwheihei | 11 | * @author: swwheihei |
| 10 | * @date: 2020年5月8日 下午2:05:56 | 12 | * @date: 2020年5月8日 下午2:05:56 |
| 11 | */ | 13 | */ |
| 14 | +@Schema(description = "设备录像查询结果信息") | ||
| 12 | public class RecordInfo { | 15 | public class RecordInfo { |
| 13 | 16 | ||
| 17 | + @Schema(description = "设备编号") | ||
| 14 | private String deviceId; | 18 | private String deviceId; |
| 15 | 19 | ||
| 20 | + @Schema(description = "通道编号") | ||
| 16 | private String channelId; | 21 | private String channelId; |
| 17 | 22 | ||
| 23 | + @Schema(description = "命令序列号") | ||
| 18 | private String sn; | 24 | private String sn; |
| 19 | 25 | ||
| 26 | + @Schema(description = "设备名称") | ||
| 20 | private String name; | 27 | private String name; |
| 21 | - | 28 | + |
| 29 | + @Schema(description = "列表总数") | ||
| 22 | private int sumNum; | 30 | private int sumNum; |
| 23 | 31 | ||
| 24 | private int count; | 32 | private int count; |
| 25 | 33 | ||
| 26 | private Instant lastTime; | 34 | private Instant lastTime; |
| 27 | - | 35 | + |
| 36 | + @Schema(description = "") | ||
| 28 | private List<RecordItem> recordList; | 37 | private List<RecordItem> recordList; |
| 29 | 38 | ||
| 30 | public String getDeviceId() { | 39 | public String getDeviceId() { |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
| @@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean; | @@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean; | ||
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | import com.genersoft.iot.vmp.utils.DateUtil; | 4 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 5 | import org.jetbrains.annotations.NotNull; | 6 | import org.jetbrains.annotations.NotNull; |
| 6 | 7 | ||
| 7 | -import java.text.ParseException; | ||
| 8 | import java.time.Instant; | 8 | import java.time.Instant; |
| 9 | import java.time.temporal.TemporalAccessor; | 9 | import java.time.temporal.TemporalAccessor; |
| 10 | 10 | ||
| @@ -13,26 +13,37 @@ import java.time.temporal.TemporalAccessor; | @@ -13,26 +13,37 @@ import java.time.temporal.TemporalAccessor; | ||
| 13 | * @author: swwheihei | 13 | * @author: swwheihei |
| 14 | * @date: 2020年5月8日 下午2:06:54 | 14 | * @date: 2020年5月8日 下午2:06:54 |
| 15 | */ | 15 | */ |
| 16 | +@Schema(description = "设备录像详情") | ||
| 16 | public class RecordItem implements Comparable<RecordItem>{ | 17 | public class RecordItem implements Comparable<RecordItem>{ |
| 17 | 18 | ||
| 19 | + @Schema(description = "设备编号") | ||
| 18 | private String deviceId; | 20 | private String deviceId; |
| 19 | - | 21 | + |
| 22 | + @Schema(description = "名称") | ||
| 20 | private String name; | 23 | private String name; |
| 21 | - | 24 | + |
| 25 | + @Schema(description = "文件路径名 (可选)") | ||
| 22 | private String filePath; | 26 | private String filePath; |
| 23 | 27 | ||
| 28 | + @Schema(description = "录像文件大小,单位:Byte(可选)") | ||
| 24 | private String fileSize; | 29 | private String fileSize; |
| 25 | 30 | ||
| 31 | + @Schema(description = "录像地址(可选)") | ||
| 26 | private String address; | 32 | private String address; |
| 27 | - | 33 | + |
| 34 | + @Schema(description = "录像开始时间(可选)") | ||
| 28 | private String startTime; | 35 | private String startTime; |
| 29 | - | 36 | + |
| 37 | + @Schema(description = "录像结束时间(可选)") | ||
| 30 | private String endTime; | 38 | private String endTime; |
| 31 | - | 39 | + |
| 40 | + @Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密") | ||
| 32 | private int secrecy; | 41 | private int secrecy; |
| 33 | - | 42 | + |
| 43 | + @Schema(description = "录像产生类型(可选)time或alarm 或 manua") | ||
| 34 | private String type; | 44 | private String type; |
| 35 | - | 45 | + |
| 46 | + @Schema(description = "录像触发者ID(可选)") | ||
| 36 | private String recorderId; | 47 | private String recorderId; |
| 37 | 48 | ||
| 38 | public String getDeviceId() { | 49 | public String getDeviceId() { |
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java
| 1 | package com.genersoft.iot.vmp.gb28181.event.device; | 1 | package com.genersoft.iot.vmp.gb28181.event.device; |
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 3 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 4 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 5 | import com.genersoft.iot.vmp.service.IDeviceService; | 4 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 6 | import org.springframework.beans.factory.annotation.Autowired; | 5 | import org.springframework.beans.factory.annotation.Autowired; |
| 7 | import org.springframework.context.ApplicationListener; | 6 | import org.springframework.context.ApplicationListener; |
| @@ -9,8 +8,6 @@ import org.springframework.stereotype.Component; | @@ -9,8 +8,6 @@ import org.springframework.stereotype.Component; | ||
| 9 | 8 | ||
| 10 | import javax.sip.ClientTransaction; | 9 | import javax.sip.ClientTransaction; |
| 11 | import javax.sip.address.SipURI; | 10 | import javax.sip.address.SipURI; |
| 12 | -import javax.sip.header.CallIdHeader; | ||
| 13 | -import javax.sip.header.ToHeader; | ||
| 14 | import javax.sip.message.Request; | 11 | import javax.sip.message.Request; |
| 15 | 12 | ||
| 16 | /** | 13 | /** |
| @@ -34,7 +31,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener<RequestTimeo | @@ -34,7 +31,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener<RequestTimeo | ||
| 34 | if (device == null) { | 31 | if (device == null) { |
| 35 | return; | 32 | return; |
| 36 | } | 33 | } |
| 37 | - deviceService.offline(device.getDeviceId()); | 34 | + deviceService.offline(device.getDeviceId(), "等待消息超时"); |
| 38 | } | 35 | } |
| 39 | 36 | ||
| 40 | } | 37 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
| @@ -61,9 +61,9 @@ public class SipRunner implements CommandLineRunner { | @@ -61,9 +61,9 @@ public class SipRunner implements CommandLineRunner { | ||
| 61 | 61 | ||
| 62 | for (Device device : deviceList) { | 62 | for (Device device : deviceList) { |
| 63 | if (deviceService.expire(device)){ | 63 | if (deviceService.expire(device)){ |
| 64 | - deviceService.offline(device.getDeviceId()); | 64 | + deviceService.offline(device.getDeviceId(), "注册已过期"); |
| 65 | }else { | 65 | }else { |
| 66 | - deviceService.online(device); | 66 | + deviceService.online(device, null); |
| 67 | } | 67 | } |
| 68 | } | 68 | } |
| 69 | // 重置cseq计数 | 69 | // 重置cseq计数 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| @@ -120,7 +120,7 @@ public interface ISIPCommander { | @@ -120,7 +120,7 @@ public interface ISIPCommander { | ||
| 120 | */ | 120 | */ |
| 121 | void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 121 | void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 122 | String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | 122 | String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, |
| 123 | - SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; | 123 | + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 124 | 124 | ||
| 125 | 125 | ||
| 126 | /** | 126 | /** |
| @@ -217,7 +217,6 @@ public interface ISIPCommander { | @@ -217,7 +217,6 @@ public interface ISIPCommander { | ||
| 217 | * | 217 | * |
| 218 | * @param device 视频设备 | 218 | * @param device 视频设备 |
| 219 | * @param channelId 通道id,非通道则是设备本身 | 219 | * @param channelId 通道id,非通道则是设备本身 |
| 220 | - * @param frontCmd 上级平台的指令,如果存在则直接下发 | ||
| 221 | * @param enabled 看守位使能:1 = 开启,0 = 关闭 | 220 | * @param enabled 看守位使能:1 = 开启,0 = 关闭 |
| 222 | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) | 221 | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) |
| 223 | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 | 222 | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
| @@ -22,12 +22,10 @@ public interface ISIPCommanderForPlatform { | @@ -22,12 +22,10 @@ public interface ISIPCommanderForPlatform { | ||
| 22 | * @param parentPlatform | 22 | * @param parentPlatform |
| 23 | * @return | 23 | * @return |
| 24 | */ | 24 | */ |
| 25 | - void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) | ||
| 26 | - throws InvalidArgumentException, ParseException, SipException; | 25 | + void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException; |
| 27 | 26 | ||
| 28 | - void register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, | ||
| 29 | - SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) | ||
| 30 | - throws SipException, InvalidArgumentException, ParseException; | 27 | + void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException; |
| 28 | + void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException; | ||
| 31 | 29 | ||
| 32 | /** | 30 | /** |
| 33 | * 向上级平台注销 | 31 | * 向上级平台注销 |
| @@ -35,8 +33,7 @@ public interface ISIPCommanderForPlatform { | @@ -35,8 +33,7 @@ public interface ISIPCommanderForPlatform { | ||
| 35 | * @param parentPlatform | 33 | * @param parentPlatform |
| 36 | * @return | 34 | * @return |
| 37 | */ | 35 | */ |
| 38 | - void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) | ||
| 39 | - throws InvalidArgumentException, ParseException, SipException; | 36 | + void unregister(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException; |
| 40 | 37 | ||
| 41 | 38 | ||
| 42 | /** | 39 | /** |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
| @@ -46,7 +46,7 @@ public class SIPRequestHeaderPlarformProvider { | @@ -46,7 +46,7 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 46 | @Autowired | 46 | @Autowired |
| 47 | private IRedisCatchStorage redisCatchStorage; | 47 | private IRedisCatchStorage redisCatchStorage; |
| 48 | 48 | ||
| 49 | - public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, long CSeq, String fromTag, String viaTag, CallIdHeader callIdHeader, boolean isRegister) throws ParseException, InvalidArgumentException, PeerUnavailableException { | 49 | + public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, long CSeq, String fromTag, String toTag, CallIdHeader callIdHeader, boolean isRegister) throws ParseException, InvalidArgumentException, PeerUnavailableException { |
| 50 | Request request = null; | 50 | Request request = null; |
| 51 | String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); | 51 | String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); |
| 52 | //请求行 | 52 | //请求行 |
| @@ -54,7 +54,8 @@ public class SIPRequestHeaderPlarformProvider { | @@ -54,7 +54,8 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 54 | parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); | 54 | parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| 55 | //via | 55 | //via |
| 56 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); | 56 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 57 | - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(), parentPlatform.getServerPort(), parentPlatform.getTransport(), viaTag); | 57 | + ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(), |
| 58 | + parentPlatform.getServerPort(), parentPlatform.getTransport(), SipUtils.getNewViaTag()); | ||
| 58 | viaHeader.setRPort(); | 59 | viaHeader.setRPort(); |
| 59 | viaHeaders.add(viaHeader); | 60 | viaHeaders.add(viaHeader); |
| 60 | //from | 61 | //from |
| @@ -64,7 +65,7 @@ public class SIPRequestHeaderPlarformProvider { | @@ -64,7 +65,7 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 64 | //to | 65 | //to |
| 65 | SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); | 66 | SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); |
| 66 | Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); | 67 | Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); |
| 67 | - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null); | 68 | + ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,toTag); |
| 68 | 69 | ||
| 69 | //Forwards | 70 | //Forwards |
| 70 | MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); | 71 | MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); |
| @@ -86,15 +87,21 @@ public class SIPRequestHeaderPlarformProvider { | @@ -86,15 +87,21 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 86 | return request; | 87 | return request; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | - public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String viaTag, | ||
| 90 | - String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader, boolean isRegister) throws ParseException, PeerUnavailableException, InvalidArgumentException { | 90 | + public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String toTag, |
| 91 | + WWWAuthenticateHeader www , CallIdHeader callIdHeader, boolean isRegister) throws ParseException, PeerUnavailableException, InvalidArgumentException { | ||
| 91 | 92 | ||
| 92 | 93 | ||
| 93 | - Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader, isRegister); | 94 | + Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, toTag, callIdHeader, isRegister); |
| 94 | SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); | 95 | SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); |
| 95 | if (www == null) { | 96 | if (www == null) { |
| 96 | AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader("Digest"); | 97 | AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader("Digest"); |
| 97 | - authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); | 98 | + String username = parentPlatform.getUsername(); |
| 99 | + if ( username == null || username == "" ) | ||
| 100 | + { | ||
| 101 | + authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); | ||
| 102 | + } else { | ||
| 103 | + authorizationHeader.setUsername(username); | ||
| 104 | + } | ||
| 98 | authorizationHeader.setURI(requestURI); | 105 | authorizationHeader.setURI(requestURI); |
| 99 | authorizationHeader.setAlgorithm("MD5"); | 106 | authorizationHeader.setAlgorithm("MD5"); |
| 100 | registerRequest.addHeader(authorizationHeader); | 107 | registerRequest.addHeader(authorizationHeader); |
| @@ -108,8 +115,6 @@ public class SIPRequestHeaderPlarformProvider { | @@ -108,8 +115,6 @@ public class SIPRequestHeaderPlarformProvider { | ||
| 108 | // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略 | 115 | // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略 |
| 109 | String qop = www.getQop(); | 116 | String qop = www.getQop(); |
| 110 | 117 | ||
| 111 | - callIdHeader.setCallId(callId); | ||
| 112 | - | ||
| 113 | String cNonce = null; | 118 | String cNonce = null; |
| 114 | String nc = "00000001"; | 119 | String nc = "00000001"; |
| 115 | if (qop != null) { | 120 | if (qop != null) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -276,7 +276,7 @@ public class SIPCommander implements ISIPCommander { | @@ -276,7 +276,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 276 | return; | 276 | return; |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); | 279 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); |
| 280 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); | 280 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); |
| 281 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | 281 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { |
| 282 | if (event != null) { | 282 | if (event != null) { |
| @@ -377,7 +377,7 @@ public class SIPCommander implements ISIPCommander { | @@ -377,7 +377,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 377 | SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | 377 | SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { |
| 378 | 378 | ||
| 379 | 379 | ||
| 380 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); | 380 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort()); |
| 381 | String sdpIp; | 381 | String sdpIp; |
| 382 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { | 382 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { |
| 383 | sdpIp = device.getSdpIp(); | 383 | sdpIp = device.getSdpIp(); |
| @@ -479,10 +479,11 @@ public class SIPCommander implements ISIPCommander { | @@ -479,10 +479,11 @@ public class SIPCommander implements ISIPCommander { | ||
| 479 | */ | 479 | */ |
| 480 | @Override | 480 | @Override |
| 481 | public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, | 481 | public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 482 | - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | ||
| 483 | - SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | 482 | + String startTime, String endTime, int downloadSpeed, |
| 483 | + InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | ||
| 484 | + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | ||
| 484 | 485 | ||
| 485 | - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); | 486 | + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort()); |
| 486 | String sdpIp; | 487 | String sdpIp; |
| 487 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { | 488 | if (!ObjectUtils.isEmpty(device.getSdpIp())) { |
| 488 | sdpIp = device.getSdpIp(); | 489 | sdpIp = device.getSdpIp(); |
| @@ -549,11 +550,14 @@ public class SIPCommander implements ISIPCommander { | @@ -549,11 +550,14 @@ public class SIPCommander implements ISIPCommander { | ||
| 549 | content.append("a=downloadspeed:" + downloadSpeed + "\r\n"); | 550 | content.append("a=downloadspeed:" + downloadSpeed + "\r\n"); |
| 550 | 551 | ||
| 551 | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc | 552 | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc |
| 552 | - | 553 | + logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc()); |
| 553 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId()); | 554 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId()); |
| 554 | // 添加订阅 | 555 | // 添加订阅 |
| 556 | + CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); | ||
| 557 | + String callId=newCallIdHeader.getCallId(); | ||
| 555 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | 558 | subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { |
| 556 | - hookEvent.call(new InviteStreamInfo(mediaServerItem, json,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); | 559 | + logger.debug("sipc 添加订阅===callId {}",callId); |
| 560 | + hookEvent.call(new InviteStreamInfo(mediaServerItem, json,callId, "rtp", ssrcInfo.getStream())); | ||
| 557 | subscribe.removeSubscribe(hookSubscribe); | 561 | subscribe.removeSubscribe(hookSubscribe); |
| 558 | hookSubscribe.getContent().put("regist", false); | 562 | hookSubscribe.getContent().put("regist", false); |
| 559 | hookSubscribe.getContent().put("schema", "rtsp"); | 563 | hookSubscribe.getContent().put("schema", "rtsp"); |
| @@ -562,7 +566,7 @@ public class SIPCommander implements ISIPCommander { | @@ -562,7 +566,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 562 | (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> { | 566 | (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> { |
| 563 | logger.info("[录像]下载结束, 发送BYE"); | 567 | logger.info("[录像]下载结束, 发送BYE"); |
| 564 | try { | 568 | try { |
| 565 | - streamByeCmd(device, channelId, ssrcInfo.getStream(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId()); | 569 | + streamByeCmd(device, channelId, ssrcInfo.getStream(),callId); |
| 566 | } catch (InvalidArgumentException | ParseException | SipException | | 570 | } catch (InvalidArgumentException | ParseException | SipException | |
| 567 | SsrcTransactionNotFoundException e) { | 571 | SsrcTransactionNotFoundException e) { |
| 568 | logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); | 572 | logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); |
| @@ -570,15 +574,24 @@ public class SIPCommander implements ISIPCommander { | @@ -570,15 +574,24 @@ public class SIPCommander implements ISIPCommander { | ||
| 570 | }); | 574 | }); |
| 571 | }); | 575 | }); |
| 572 | 576 | ||
| 573 | - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc()); | 577 | + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc()); |
| 574 | if (inviteStreamCallback != null) { | 578 | if (inviteStreamCallback != null) { |
| 575 | - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); | 579 | + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,callId, "rtp", ssrcInfo.getStream())); |
| 576 | } | 580 | } |
| 577 | 581 | ||
| 578 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent -> { | ||
| 579 | - ResponseEvent responseEvent = (ResponseEvent) okEvent.event; | 582 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { |
| 583 | + ResponseEvent responseEvent = (ResponseEvent) event.event; | ||
| 580 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); | 584 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 581 | - streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); | 585 | + String contentString =new String(response.getRawContent()); |
| 586 | + int ssrcIndex = contentString.indexOf("y="); | ||
| 587 | + String ssrc=ssrcInfo.getSsrc(); | ||
| 588 | + if (ssrcIndex >= 0) { | ||
| 589 | + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 590 | + } | ||
| 591 | + logger.debug("接收到的下载响应ssrc====>{}",ssrcInfo.getSsrc()); | ||
| 592 | + logger.debug("接收到的下载响应ssrc====>{}",ssrc); | ||
| 593 | + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); | ||
| 594 | + okEvent.response(event); | ||
| 582 | }); | 595 | }); |
| 583 | } | 596 | } |
| 584 | 597 | ||
| @@ -778,7 +791,7 @@ public class SIPCommander implements ISIPCommander { | @@ -778,7 +791,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 778 | cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); | 791 | cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); |
| 779 | cmdXml.append("</Control>\r\n"); | 792 | cmdXml.append("</Control>\r\n"); |
| 780 | 793 | ||
| 781 | - | 794 | + |
| 782 | 795 | ||
| 783 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | 796 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 784 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); | 797 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); |
| @@ -854,7 +867,6 @@ public class SIPCommander implements ISIPCommander { | @@ -854,7 +867,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 854 | * | 867 | * |
| 855 | * @param device 视频设备 | 868 | * @param device 视频设备 |
| 856 | * @param channelId 通道id,非通道则是设备本身 | 869 | * @param channelId 通道id,非通道则是设备本身 |
| 857 | - * @param frontCmd 上级平台的指令,如果存在则直接下发 | ||
| 858 | * @param enabled 看守位使能:1 = 开启,0 = 关闭 | 870 | * @param enabled 看守位使能:1 = 开启,0 = 关闭 |
| 859 | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) | 871 | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) |
| 860 | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 | 872 | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 |
| @@ -978,7 +990,7 @@ public class SIPCommander implements ISIPCommander { | @@ -978,7 +990,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 978 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | 990 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 979 | catalogXml.append("</Query>\r\n"); | 991 | catalogXml.append("</Query>\r\n"); |
| 980 | 992 | ||
| 981 | - | 993 | + |
| 982 | 994 | ||
| 983 | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | 995 | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 984 | 996 | ||
| @@ -1181,7 +1193,6 @@ public class SIPCommander implements ISIPCommander { | @@ -1181,7 +1193,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 1181 | cmdXml.append("</Query>\r\n"); | 1193 | cmdXml.append("</Query>\r\n"); |
| 1182 | 1194 | ||
| 1183 | 1195 | ||
| 1184 | - | ||
| 1185 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); | 1196 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1186 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); | 1197 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
| 1187 | } | 1198 | } |
| @@ -1427,7 +1438,7 @@ public class SIPCommander implements ISIPCommander { | @@ -1427,7 +1438,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 1427 | if (device == null) { | 1438 | if (device == null) { |
| 1428 | return; | 1439 | return; |
| 1429 | } | 1440 | } |
| 1430 | - logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(), | 1441 | + logger.info("[发送报警通知]设备: {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(), |
| 1431 | deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); | 1442 | deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); |
| 1432 | 1443 | ||
| 1433 | String characterSet = device.getCharset(); | 1444 | String characterSet = device.getCharset(); |
| @@ -1439,7 +1450,7 @@ public class SIPCommander implements ISIPCommander { | @@ -1439,7 +1450,7 @@ public class SIPCommander implements ISIPCommander { | ||
| 1439 | deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n"); | 1450 | deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n"); |
| 1440 | deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n"); | 1451 | deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n"); |
| 1441 | deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n"); | 1452 | deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n"); |
| 1442 | - deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n"); | 1453 | + deviceStatusXml.append("<AlarmTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(deviceAlarm.getAlarmTime()) + "</AlarmTime>\r\n"); |
| 1443 | deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n"); | 1454 | deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n"); |
| 1444 | deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n"); | 1455 | deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n"); |
| 1445 | deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n"); | 1456 | deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n"); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| @@ -24,6 +24,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; | @@ -24,6 +24,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; | ||
| 24 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 24 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 25 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | 25 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; |
| 26 | import com.genersoft.iot.vmp.utils.DateUtil; | 26 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 27 | +import com.genersoft.iot.vmp.utils.GitUtil; | ||
| 27 | import gov.nist.javax.sip.message.MessageFactoryImpl; | 28 | import gov.nist.javax.sip.message.MessageFactoryImpl; |
| 28 | import gov.nist.javax.sip.message.SIPRequest; | 29 | import gov.nist.javax.sip.message.SIPRequest; |
| 29 | import gov.nist.javax.sip.message.SIPResponse; | 30 | import gov.nist.javax.sip.message.SIPResponse; |
| @@ -85,26 +86,49 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -85,26 +86,49 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 85 | @Autowired | 86 | @Autowired |
| 86 | private DynamicTask dynamicTask; | 87 | private DynamicTask dynamicTask; |
| 87 | 88 | ||
| 89 | + @Autowired | ||
| 90 | + private GitUtil gitUtil; | ||
| 91 | + | ||
| 88 | @Override | 92 | @Override |
| 89 | public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException { | 93 | public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException { |
| 90 | register(parentPlatform, null, null, errorEvent, okEvent, false, true); | 94 | register(parentPlatform, null, null, errorEvent, okEvent, false, true); |
| 91 | } | 95 | } |
| 92 | 96 | ||
| 93 | @Override | 97 | @Override |
| 94 | - public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException { | ||
| 95 | - register(parentPlatform, null, null, errorEvent, okEvent, false, false); | 98 | + public void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException { |
| 99 | + | ||
| 100 | + register(parentPlatform, sipTransactionInfo, null, errorEvent, okEvent, false, true); | ||
| 96 | } | 101 | } |
| 97 | 102 | ||
| 98 | @Override | 103 | @Override |
| 99 | - public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, | 104 | + public void unregister(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException { |
| 105 | + register(parentPlatform, sipTransactionInfo, null, errorEvent, okEvent, false, false); | ||
| 106 | + } | ||
| 107 | + | ||
| 108 | + @Override | ||
| 109 | + public void register(ParentPlatform parentPlatform, @Nullable SipTransactionInfo sipTransactionInfo, @Nullable WWWAuthenticateHeader www, | ||
| 100 | SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException { | 110 | SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException { |
| 101 | Request request; | 111 | Request request; |
| 102 | - if (!registerAgain ) { | ||
| 103 | - CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport()); | ||
| 104 | 112 | ||
| 113 | + CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport()); | ||
| 114 | + String fromTag = SipUtils.getNewFromTag(); | ||
| 115 | + String toTag = null; | ||
| 116 | + if (sipTransactionInfo != null ) { | ||
| 117 | + if (sipTransactionInfo.getCallId() != null) { | ||
| 118 | + callIdHeader.setCallId(sipTransactionInfo.getCallId()); | ||
| 119 | + } | ||
| 120 | + if (sipTransactionInfo.getFromTag() != null) { | ||
| 121 | + fromTag = sipTransactionInfo.getFromTag(); | ||
| 122 | + } | ||
| 123 | + if (sipTransactionInfo.getToTag() != null) { | ||
| 124 | + toTag = sipTransactionInfo.getToTag(); | ||
| 125 | + } | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + if (!registerAgain ) { | ||
| 105 | request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, | 129 | request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, |
| 106 | - redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(), | ||
| 107 | - SipUtils.getNewViaTag(), callIdHeader, isRegister); | 130 | + redisCatchStorage.getCSEQ(), fromTag, |
| 131 | + toTag, callIdHeader, isRegister); | ||
| 108 | // 将 callid 写入缓存, 等注册成功可以更新状态 | 132 | // 将 callid 写入缓存, 等注册成功可以更新状态 |
| 109 | String callIdFromHeader = callIdHeader.getCallId(); | 133 | String callIdFromHeader = callIdHeader.getCallId(); |
| 110 | redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister)); | 134 | redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister)); |
| @@ -122,8 +146,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -122,8 +146,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 122 | }); | 146 | }); |
| 123 | 147 | ||
| 124 | }else { | 148 | }else { |
| 125 | - CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport()); | ||
| 126 | - request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister); | 149 | + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, fromTag, toTag, www, callIdHeader, isRegister); |
| 127 | } | 150 | } |
| 128 | 151 | ||
| 129 | sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, okEvent); | 152 | sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, okEvent); |
| @@ -245,6 +268,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -245,6 +268,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 245 | catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n"); | 268 | catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n"); |
| 246 | catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n"); | 269 | catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n"); |
| 247 | catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n"); | 270 | catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n"); |
| 271 | + catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n"); | ||
| 248 | catalogXml.append("<Status>" + (channel.getStatus() == 1?"ON":"OFF") + "</Status>\r\n"); | 272 | catalogXml.append("<Status>" + (channel.getStatus() == 1?"ON":"OFF") + "</Status>\r\n"); |
| 249 | catalogXml.append("<Longitude>" + | 273 | catalogXml.append("<Longitude>" + |
| 250 | (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude()) | 274 | (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude()) |
| @@ -285,6 +309,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -285,6 +309,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 285 | 309 | ||
| 286 | String callId = request.getCallIdHeader().getCallId(); | 310 | String callId = request.getCallIdHeader().getCallId(); |
| 287 | 311 | ||
| 312 | + logger.info("[命令发送] 国标级联{} 目录查询回复: 共{}条,已发送{}条", parentPlatform.getServerGBId(), | ||
| 313 | + channels.size(), Math.min(index + parentPlatform.getCatalogGroup(), channels.size())); | ||
| 314 | + logger.debug(catalogXml); | ||
| 288 | if (sendAfterResponse) { | 315 | if (sendAfterResponse) { |
| 289 | // 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。 | 316 | // 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。 |
| 290 | dynamicTask.startDelay(timeoutTaskKey, ()->{ | 317 | dynamicTask.startDelay(timeoutTaskKey, ()->{ |
| @@ -336,17 +363,22 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -336,17 +363,22 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 336 | if (parentPlatform == null) { | 363 | if (parentPlatform == null) { |
| 337 | return; | 364 | return; |
| 338 | } | 365 | } |
| 366 | + String deviceId = device == null ? parentPlatform.getDeviceGBId() : device.getDeviceId(); | ||
| 367 | + String deviceName = device == null ? parentPlatform.getName() : device.getName(); | ||
| 368 | + String manufacturer = device == null ? "WVP-28181-PRO" : device.getManufacturer(); | ||
| 369 | + String model = device == null ? "platform" : device.getModel(); | ||
| 370 | + String firmware = device == null ? gitUtil.getBuildVersion() : device.getFirmware(); | ||
| 339 | String characterSet = parentPlatform.getCharacterSet(); | 371 | String characterSet = parentPlatform.getCharacterSet(); |
| 340 | StringBuffer deviceInfoXml = new StringBuffer(600); | 372 | StringBuffer deviceInfoXml = new StringBuffer(600); |
| 341 | deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); | 373 | deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); |
| 342 | deviceInfoXml.append("<Response>\r\n"); | 374 | deviceInfoXml.append("<Response>\r\n"); |
| 343 | deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); | 375 | deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); |
| 344 | deviceInfoXml.append("<SN>" +sn + "</SN>\r\n"); | 376 | deviceInfoXml.append("<SN>" +sn + "</SN>\r\n"); |
| 345 | - deviceInfoXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); | ||
| 346 | - deviceInfoXml.append("<DeviceName>" + device.getName() + "</DeviceName>\r\n"); | ||
| 347 | - deviceInfoXml.append("<Manufacturer>" + device.getManufacturer() + "</Manufacturer>\r\n"); | ||
| 348 | - deviceInfoXml.append("<Model>" + device.getModel() + "</Model>\r\n"); | ||
| 349 | - deviceInfoXml.append("<Firmware>" + device.getFirmware() + "</Firmware>\r\n"); | 377 | + deviceInfoXml.append("<DeviceID>" + deviceId + "</DeviceID>\r\n"); |
| 378 | + deviceInfoXml.append("<DeviceName>" + deviceName + "</DeviceName>\r\n"); | ||
| 379 | + deviceInfoXml.append("<Manufacturer>" + manufacturer + "</Manufacturer>\r\n"); | ||
| 380 | + deviceInfoXml.append("<Model>" + model + "</Model>\r\n"); | ||
| 381 | + deviceInfoXml.append("<Firmware>" + firmware + "</Firmware>\r\n"); | ||
| 350 | deviceInfoXml.append("<Result>OK</Result>\r\n"); | 382 | deviceInfoXml.append("<Result>OK</Result>\r\n"); |
| 351 | deviceInfoXml.append("</Response>\r\n"); | 383 | deviceInfoXml.append("</Response>\r\n"); |
| 352 | 384 | ||
| @@ -423,7 +455,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -423,7 +455,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 423 | if (parentPlatform == null) { | 455 | if (parentPlatform == null) { |
| 424 | return; | 456 | return; |
| 425 | } | 457 | } |
| 426 | - logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), | 458 | + logger.info("[发送报警通知]平台: {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), |
| 427 | deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm)); | 459 | deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm)); |
| 428 | String characterSet = parentPlatform.getCharacterSet(); | 460 | String characterSet = parentPlatform.getCharacterSet(); |
| 429 | StringBuffer deviceStatusXml = new StringBuffer(600); | 461 | StringBuffer deviceStatusXml = new StringBuffer(600); |
| @@ -434,7 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -434,7 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 434 | .append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n") | 466 | .append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n") |
| 435 | .append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n") | 467 | .append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n") |
| 436 | .append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n") | 468 | .append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n") |
| 437 | - .append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n") | 469 | + .append("<AlarmTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(deviceAlarm.getAlarmTime()) + "</AlarmTime>\r\n") |
| 438 | .append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n") | 470 | .append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n") |
| 439 | .append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n") | 471 | .append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n") |
| 440 | .append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n") | 472 | .append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n") |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
| @@ -45,7 +45,7 @@ public abstract class SIPRequestProcessorParent { | @@ -45,7 +45,7 @@ public abstract class SIPRequestProcessorParent { | ||
| 45 | try { | 45 | try { |
| 46 | return SipFactory.getInstance().createHeaderFactory(); | 46 | return SipFactory.getInstance().createHeaderFactory(); |
| 47 | } catch (PeerUnavailableException e) { | 47 | } catch (PeerUnavailableException e) { |
| 48 | - e.printStackTrace(); | 48 | + logger.error("未处理的异常 ", e); |
| 49 | } | 49 | } |
| 50 | return null; | 50 | return null; |
| 51 | } | 51 | } |
| @@ -54,7 +54,7 @@ public abstract class SIPRequestProcessorParent { | @@ -54,7 +54,7 @@ public abstract class SIPRequestProcessorParent { | ||
| 54 | try { | 54 | try { |
| 55 | return SipFactory.getInstance().createMessageFactory(); | 55 | return SipFactory.getInstance().createMessageFactory(); |
| 56 | } catch (PeerUnavailableException e) { | 56 | } catch (PeerUnavailableException e) { |
| 57 | - e.printStackTrace(); | 57 | + logger.error("未处理的异常 ", e); |
| 58 | } | 58 | } |
| 59 | return null; | 59 | return null; |
| 60 | } | 60 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; | @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.bean.*; | 8 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | 9 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 10 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; | 10 | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| 11 | +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | ||
| 11 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 12 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 12 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| @@ -457,12 +458,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -457,12 +458,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 457 | if (!userSetting.getPushStreamAfterAck()) { | 458 | if (!userSetting.getPushStreamAfterAck()) { |
| 458 | playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader()); | 459 | playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader()); |
| 459 | } | 460 | } |
| 460 | - } catch (SipException e) { | ||
| 461 | - e.printStackTrace(); | ||
| 462 | - } catch (InvalidArgumentException e) { | ||
| 463 | - e.printStackTrace(); | ||
| 464 | - } catch (ParseException e) { | ||
| 465 | - e.printStackTrace(); | 461 | + } catch (SipException | InvalidArgumentException | ParseException e) { |
| 462 | + logger.error("[命令发送失败] 国标级联 回复SdpAck", e); | ||
| 466 | } | 463 | } |
| 467 | }; | 464 | }; |
| 468 | SipSubscribe.Event errorEvent = ((event) -> { | 465 | SipSubscribe.Event errorEvent = ((event) -> { |
| @@ -471,7 +468,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -471,7 +468,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 471 | Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); | 468 | Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); |
| 472 | sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); | 469 | sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); |
| 473 | } catch (ParseException | SipException e) { | 470 | } catch (ParseException | SipException e) { |
| 474 | - e.printStackTrace(); | 471 | + logger.error("未处理的异常 ", e); |
| 475 | } | 472 | } |
| 476 | }); | 473 | }); |
| 477 | sendRtpItem.setApp("rtp"); | 474 | sendRtpItem.setApp("rtp"); |
| @@ -543,6 +540,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -543,6 +540,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 543 | } | 540 | } |
| 544 | } | 541 | } |
| 545 | } else if (gbStream != null) { | 542 | } else if (gbStream != null) { |
| 543 | + if(ssrc.equals(ssrcDefault)) | ||
| 544 | + { | ||
| 545 | + SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig(); | ||
| 546 | + if(ssrcConfig != null) | ||
| 547 | + { | ||
| 548 | + ssrc = ssrcConfig.getPlaySsrc(); | ||
| 549 | + ssrcConfig.releaseSsrc(ssrc); | ||
| 550 | + } | ||
| 551 | + } | ||
| 546 | if("push".equals(gbStream.getStreamType())) { | 552 | if("push".equals(gbStream.getStreamType())) { |
| 547 | if (streamPushItem != null && streamPushItem.isPushIng()) { | 553 | if (streamPushItem != null && streamPushItem.isPushIng()) { |
| 548 | // 推流状态 | 554 | // 推流状态 |
| @@ -572,7 +578,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -572,7 +578,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 572 | } catch (SdpParseException e) { | 578 | } catch (SdpParseException e) { |
| 573 | logger.error("sdp解析错误", e); | 579 | logger.error("sdp解析错误", e); |
| 574 | } catch (SdpException e) { | 580 | } catch (SdpException e) { |
| 575 | - e.printStackTrace(); | 581 | + logger.error("未处理的异常 ", e); |
| 576 | } | 582 | } |
| 577 | } | 583 | } |
| 578 | 584 | ||
| @@ -727,11 +733,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -727,11 +733,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 727 | mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); | 733 | mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); |
| 728 | responseAck(request, Response.REQUEST_TIMEOUT); // 超时 | 734 | responseAck(request, Response.REQUEST_TIMEOUT); // 超时 |
| 729 | } catch (SipException e) { | 735 | } catch (SipException e) { |
| 730 | - e.printStackTrace(); | 736 | + logger.error("未处理的异常 ", e); |
| 731 | } catch (InvalidArgumentException e) { | 737 | } catch (InvalidArgumentException e) { |
| 732 | - e.printStackTrace(); | 738 | + logger.error("未处理的异常 ", e); |
| 733 | } catch (ParseException e) { | 739 | } catch (ParseException e) { |
| 734 | - e.printStackTrace(); | 740 | + logger.error("未处理的异常 ", e); |
| 735 | } | 741 | } |
| 736 | }, userSetting.getPlatformPlayTimeout()); | 742 | }, userSetting.getPlatformPlayTimeout()); |
| 737 | // 添加监听 | 743 | // 添加监听 |
| @@ -750,11 +756,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -750,11 +756,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 750 | try { | 756 | try { |
| 751 | responseAck(request, Response.BUSY_HERE); | 757 | responseAck(request, Response.BUSY_HERE); |
| 752 | } catch (SipException e) { | 758 | } catch (SipException e) { |
| 753 | - e.printStackTrace(); | 759 | + logger.error("未处理的异常 ", e); |
| 754 | } catch (InvalidArgumentException e) { | 760 | } catch (InvalidArgumentException e) { |
| 755 | - e.printStackTrace(); | 761 | + logger.error("未处理的异常 ", e); |
| 756 | } catch (ParseException e) { | 762 | } catch (ParseException e) { |
| 757 | - e.printStackTrace(); | 763 | + logger.error("未处理的异常 ", e); |
| 758 | } | 764 | } |
| 759 | return; | 765 | return; |
| 760 | } | 766 | } |
| @@ -812,11 +818,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -812,11 +818,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 812 | try { | 818 | try { |
| 813 | responseAck(request, Response.BUSY_HERE); | 819 | responseAck(request, Response.BUSY_HERE); |
| 814 | } catch (SipException e) { | 820 | } catch (SipException e) { |
| 815 | - e.printStackTrace(); | 821 | + logger.error("未处理的异常 ", e); |
| 816 | } catch (InvalidArgumentException e) { | 822 | } catch (InvalidArgumentException e) { |
| 817 | - e.printStackTrace(); | 823 | + logger.error("未处理的异常 ", e); |
| 818 | } catch (ParseException e) { | 824 | } catch (ParseException e) { |
| 819 | - e.printStackTrace(); | 825 | + logger.error("未处理的异常 ", e); |
| 820 | } | 826 | } |
| 821 | return; | 827 | return; |
| 822 | } | 828 | } |
| @@ -869,7 +875,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -869,7 +875,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 869 | content.append("s=Play\r\n"); | 875 | content.append("s=Play\r\n"); |
| 870 | content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); | 876 | content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); |
| 871 | content.append("t=0 0\r\n"); | 877 | content.append("t=0 0\r\n"); |
| 872 | - content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n"); | 878 | + // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口 |
| 879 | + int localPort = sendRtpItem.getLocalPort(); | ||
| 880 | + if(localPort == 0) | ||
| 881 | + { | ||
| 882 | + localPort = new Random().nextInt(65535) + 1; | ||
| 883 | + } | ||
| 884 | + content.append("m=video " + localPort + " RTP/AVP 96\r\n"); | ||
| 873 | content.append("a=sendonly\r\n"); | 885 | content.append("a=sendonly\r\n"); |
| 874 | content.append("a=rtpmap:96 PS/90000\r\n"); | 886 | content.append("a=rtpmap:96 PS/90000\r\n"); |
| 875 | if (sendRtpItem.isTcp()) { | 887 | if (sendRtpItem.isTcp()) { |
| @@ -890,11 +902,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -890,11 +902,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 890 | } | 902 | } |
| 891 | return sipResponse; | 903 | return sipResponse; |
| 892 | } catch (SipException e) { | 904 | } catch (SipException e) { |
| 893 | - e.printStackTrace(); | 905 | + logger.error("未处理的异常 ", e); |
| 894 | } catch (InvalidArgumentException e) { | 906 | } catch (InvalidArgumentException e) { |
| 895 | - e.printStackTrace(); | 907 | + logger.error("未处理的异常 ", e); |
| 896 | } catch (ParseException e) { | 908 | } catch (ParseException e) { |
| 897 | - e.printStackTrace(); | 909 | + logger.error("未处理的异常 ", e); |
| 898 | } | 910 | } |
| 899 | return null; | 911 | return null; |
| 900 | } | 912 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
| @@ -93,7 +93,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -93,7 +93,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 93 | try { | 93 | try { |
| 94 | responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); | 94 | responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); |
| 95 | }catch (SipException | InvalidArgumentException | ParseException e) { | 95 | }catch (SipException | InvalidArgumentException | ParseException e) { |
| 96 | - e.printStackTrace(); | 96 | + logger.error("未处理的异常 ", e); |
| 97 | } | 97 | } |
| 98 | boolean runed = !taskQueue.isEmpty(); | 98 | boolean runed = !taskQueue.isEmpty(); |
| 99 | taskQueue.offer(new HandlerCatchData(evt, null, null)); | 99 | taskQueue.offer(new HandlerCatchData(evt, null, null)); |
| @@ -229,7 +229,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -229,7 +229,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 229 | jsonObject.put("speed", mobilePosition.getSpeed()); | 229 | jsonObject.put("speed", mobilePosition.getSpeed()); |
| 230 | redisCatchStorage.sendMobilePositionMsg(jsonObject); | 230 | redisCatchStorage.sendMobilePositionMsg(jsonObject); |
| 231 | } catch (DocumentException e) { | 231 | } catch (DocumentException e) { |
| 232 | - e.printStackTrace(); | 232 | + logger.error("未处理的异常 ", e); |
| 233 | } | 233 | } |
| 234 | } | 234 | } |
| 235 | 235 | ||
| @@ -339,7 +339,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -339,7 +339,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 339 | publisher.deviceAlarmEventPublish(deviceAlarm); | 339 | publisher.deviceAlarmEventPublish(deviceAlarm); |
| 340 | } | 340 | } |
| 341 | } catch (DocumentException e) { | 341 | } catch (DocumentException e) { |
| 342 | - e.printStackTrace(); | 342 | + logger.error("未处理的异常 ", e); |
| 343 | } | 343 | } |
| 344 | } | 344 | } |
| 345 | 345 | ||
| @@ -397,12 +397,20 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -397,12 +397,20 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 397 | case CatalogEvent.OFF : | 397 | case CatalogEvent.OFF : |
| 398 | // 离线 | 398 | // 离线 |
| 399 | logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | 399 | logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| 400 | - storager.deviceChannelOffline(deviceId, channel.getChannelId()); | 400 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { |
| 401 | + storager.deviceChannelOffline(deviceId, channel.getChannelId()); | ||
| 402 | + }else { | ||
| 403 | + logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 404 | + } | ||
| 401 | break; | 405 | break; |
| 402 | case CatalogEvent.VLOST: | 406 | case CatalogEvent.VLOST: |
| 403 | // 视频丢失 | 407 | // 视频丢失 |
| 404 | logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | 408 | logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| 405 | - storager.deviceChannelOffline(deviceId, channel.getChannelId()); | 409 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { |
| 410 | + storager.deviceChannelOffline(deviceId, channel.getChannelId()); | ||
| 411 | + }else { | ||
| 412 | + logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | ||
| 413 | + } | ||
| 406 | break; | 414 | break; |
| 407 | case CatalogEvent.DEFECT: | 415 | case CatalogEvent.DEFECT: |
| 408 | // 故障 | 416 | // 故障 |
| @@ -432,7 +440,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | @@ -432,7 +440,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements | ||
| 432 | } | 440 | } |
| 433 | } | 441 | } |
| 434 | } catch (DocumentException e) { | 442 | } catch (DocumentException e) { |
| 435 | - e.printStackTrace(); | 443 | + logger.error("未处理的异常 ", e); |
| 436 | } | 444 | } |
| 437 | } | 445 | } |
| 438 | 446 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
| @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; | @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; | 5 | import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 6 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 7 | import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; | 7 | import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; |
| 8 | +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; | 9 | import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; |
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| @@ -18,6 +19,7 @@ import gov.nist.javax.sip.address.AddressImpl; | @@ -18,6 +19,7 @@ import gov.nist.javax.sip.address.AddressImpl; | ||
| 18 | import gov.nist.javax.sip.address.SipUri; | 19 | import gov.nist.javax.sip.address.SipUri; |
| 19 | import gov.nist.javax.sip.header.SIPDateHeader; | 20 | import gov.nist.javax.sip.header.SIPDateHeader; |
| 20 | import gov.nist.javax.sip.message.SIPRequest; | 21 | import gov.nist.javax.sip.message.SIPRequest; |
| 22 | +import gov.nist.javax.sip.message.SIPResponse; | ||
| 21 | import org.slf4j.Logger; | 23 | import org.slf4j.Logger; |
| 22 | import org.slf4j.LoggerFactory; | 24 | import org.slf4j.LoggerFactory; |
| 23 | import org.springframework.beans.factory.InitializingBean; | 25 | import org.springframework.beans.factory.InitializingBean; |
| @@ -34,6 +36,7 @@ import javax.sip.header.AuthorizationHeader; | @@ -34,6 +36,7 @@ import javax.sip.header.AuthorizationHeader; | ||
| 34 | import javax.sip.header.ContactHeader; | 36 | import javax.sip.header.ContactHeader; |
| 35 | import javax.sip.header.FromHeader; | 37 | import javax.sip.header.FromHeader; |
| 36 | import javax.sip.header.ViaHeader; | 38 | import javax.sip.header.ViaHeader; |
| 39 | +import javax.sip.message.Request; | ||
| 37 | import javax.sip.message.Response; | 40 | import javax.sip.message.Response; |
| 38 | import java.security.NoSuchAlgorithmException; | 41 | import java.security.NoSuchAlgorithmException; |
| 39 | import java.text.ParseException; | 42 | import java.text.ParseException; |
| @@ -105,6 +108,30 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | @@ -105,6 +108,30 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | ||
| 105 | SipUri uri = (SipUri) address.getURI(); | 108 | SipUri uri = (SipUri) address.getURI(); |
| 106 | String deviceId = uri.getUser(); | 109 | String deviceId = uri.getUser(); |
| 107 | Device device = deviceService.getDevice(deviceId); | 110 | Device device = deviceService.getDevice(deviceId); |
| 111 | + | ||
| 112 | + RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, | ||
| 113 | + userSetting.getSipUseSourceIpAsRemoteAddress()); | ||
| 114 | + | ||
| 115 | + if (device != null && | ||
| 116 | + device.getSipTransactionInfo() != null && | ||
| 117 | + request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) { | ||
| 118 | + logger.info("[注册请求] 注册续订: {}", device.getDeviceId()); | ||
| 119 | + device.setExpires(request.getExpires().getExpires()); | ||
| 120 | + device.setIp(remoteAddressInfo.getIp()); | ||
| 121 | + device.setPort(remoteAddressInfo.getPort()); | ||
| 122 | + device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); | ||
| 123 | + device.setLocalIp(request.getLocalAddress().getHostAddress()); | ||
| 124 | + Response registerOkResponse = getRegisterOkResponse(request); | ||
| 125 | + // 判断TCP还是UDP | ||
| 126 | + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 127 | + String transport = reqViaHeader.getTransport(); | ||
| 128 | + device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP"); | ||
| 129 | + sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse); | ||
| 130 | + device.setRegisterTime(DateUtil.getNow()); | ||
| 131 | + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)registerOkResponse); | ||
| 132 | + deviceService.online(device, sipTransactionInfo); | ||
| 133 | + return; | ||
| 134 | + } | ||
| 108 | String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword(); | 135 | String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword(); |
| 109 | AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | 136 | AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
| 110 | if (authHead == null && !ObjectUtils.isEmpty(password)) { | 137 | if (authHead == null && !ObjectUtils.isEmpty(password)) { |
| @@ -147,9 +174,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | @@ -147,9 +174,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | ||
| 147 | // 添加Expires头 | 174 | // 添加Expires头 |
| 148 | response.addHeader(request.getExpires()); | 175 | response.addHeader(request.getExpires()); |
| 149 | 176 | ||
| 150 | - RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, | ||
| 151 | - userSetting.getSipUseSourceIpAsRemoteAddress()); | ||
| 152 | - | ||
| 153 | if (device == null) { | 177 | if (device == null) { |
| 154 | device = new Device(); | 178 | device = new Device(); |
| 155 | device.setStreamMode("UDP"); | 179 | device.setStreamMode("UDP"); |
| @@ -182,13 +206,33 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | @@ -182,13 +206,33 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen | ||
| 182 | if (registerFlag) { | 206 | if (registerFlag) { |
| 183 | logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress); | 207 | logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress); |
| 184 | device.setRegisterTime(DateUtil.getNow()); | 208 | device.setRegisterTime(DateUtil.getNow()); |
| 185 | - deviceService.online(device); | 209 | + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response); |
| 210 | + deviceService.online(device, sipTransactionInfo); | ||
| 186 | } else { | 211 | } else { |
| 187 | logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress); | 212 | logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress); |
| 188 | - deviceService.offline(deviceId); | 213 | + deviceService.offline(deviceId, "主动注销"); |
| 189 | } | 214 | } |
| 190 | } catch (SipException | NoSuchAlgorithmException | ParseException e) { | 215 | } catch (SipException | NoSuchAlgorithmException | ParseException e) { |
| 191 | - e.printStackTrace(); | 216 | + logger.error("未处理的异常 ", e); |
| 192 | } | 217 | } |
| 193 | } | 218 | } |
| 219 | + | ||
| 220 | + private Response getRegisterOkResponse(Request request) throws ParseException { | ||
| 221 | + // 携带授权头并且密码正确 | ||
| 222 | + Response response = getMessageFactory().createResponse(Response.OK, request); | ||
| 223 | + // 添加date头 | ||
| 224 | + SIPDateHeader dateHeader = new SIPDateHeader(); | ||
| 225 | + // 使用自己修改的 | ||
| 226 | + WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); | ||
| 227 | + dateHeader.setDate(wvpSipDate); | ||
| 228 | + response.addHeader(dateHeader); | ||
| 229 | + | ||
| 230 | + // 添加Contact头 | ||
| 231 | + response.addHeader(request.getHeader(ContactHeader.NAME)); | ||
| 232 | + // 添加Expires头 | ||
| 233 | + response.addHeader(request.getExpires()); | ||
| 234 | + | ||
| 235 | + return response; | ||
| 236 | + | ||
| 237 | + } | ||
| 194 | } | 238 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 3 | import com.genersoft.iot.vmp.conf.DynamicTask; | 4 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 4 | import com.genersoft.iot.vmp.conf.UserSetting; | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 5 | import com.genersoft.iot.vmp.gb28181.bean.CmdType; | 6 | import com.genersoft.iot.vmp.gb28181.bean.CmdType; |
| @@ -8,14 +9,11 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | @@ -8,14 +9,11 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; | 9 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; |
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; |
| 11 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | ||
| 12 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | ||
| 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 15 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | 14 | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| 16 | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | 15 | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
| 17 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 16 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 18 | -import gov.nist.javax.sip.SipProviderImpl; | ||
| 19 | import gov.nist.javax.sip.message.SIPRequest; | 17 | import gov.nist.javax.sip.message.SIPRequest; |
| 20 | import gov.nist.javax.sip.message.SIPResponse; | 18 | import gov.nist.javax.sip.message.SIPResponse; |
| 21 | import org.dom4j.DocumentException; | 19 | import org.dom4j.DocumentException; |
| @@ -26,7 +24,9 @@ import org.springframework.beans.factory.InitializingBean; | @@ -26,7 +24,9 @@ import org.springframework.beans.factory.InitializingBean; | ||
| 26 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
| 27 | import org.springframework.stereotype.Component; | 25 | import org.springframework.stereotype.Component; |
| 28 | 26 | ||
| 29 | -import javax.sip.*; | 27 | +import javax.sip.InvalidArgumentException; |
| 28 | +import javax.sip.RequestEvent; | ||
| 29 | +import javax.sip.SipException; | ||
| 30 | import javax.sip.header.ExpiresHeader; | 30 | import javax.sip.header.ExpiresHeader; |
| 31 | import javax.sip.message.Response; | 31 | import javax.sip.message.Response; |
| 32 | import java.text.ParseException; | 32 | import java.text.ParseException; |
| @@ -93,7 +93,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | @@ -93,7 +93,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | ||
| 93 | sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); | 93 | sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); |
| 94 | } | 94 | } |
| 95 | } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { | 95 | } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { |
| 96 | - e.printStackTrace(); | 96 | + logger.error("未处理的异常 ", e); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | } | 99 | } |
| @@ -146,7 +146,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | @@ -146,7 +146,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | ||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | } catch (SipException | InvalidArgumentException | ParseException e) { | 148 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 149 | - e.printStackTrace(); | 149 | + logger.error("未处理的异常 ", e); |
| 150 | } | 150 | } |
| 151 | } | 151 | } |
| 152 | 152 | ||
| @@ -192,7 +192,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | @@ -192,7 +192,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme | ||
| 192 | subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo); | 192 | subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo); |
| 193 | } | 193 | } |
| 194 | } catch (SipException | InvalidArgumentException | ParseException e) { | 194 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 195 | - e.printStackTrace(); | 195 | + logger.error("未处理的异常 ", e); |
| 196 | } | 196 | } |
| 197 | } | 197 | } |
| 198 | } | 198 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
| @@ -73,35 +73,38 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent | @@ -73,35 +73,38 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent | ||
| 73 | String channelId = getText(rootElement, "DeviceID"); | 73 | String channelId = getText(rootElement, "DeviceID"); |
| 74 | // 远程启动功能 | 74 | // 远程启动功能 |
| 75 | if (!ObjectUtils.isEmpty(getText(rootElement, "TeleBoot"))) { | 75 | if (!ObjectUtils.isEmpty(getText(rootElement, "TeleBoot"))) { |
| 76 | - if (parentPlatform.getServerGBId().equals(targetGBId)) { | ||
| 77 | - // 远程启动本平台:需要在重新启动程序后先对SipStack解绑 | ||
| 78 | - logger.info("执行远程启动本平台命令"); | ||
| 79 | - try { | ||
| 80 | - cmderFroPlatform.unregister(parentPlatform, null, null); | ||
| 81 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 82 | - logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); | ||
| 83 | - } | ||
| 84 | - taskExecutor.execute(() -> { | ||
| 85 | - // 远程启动 | ||
| 86 | -// try { | ||
| 87 | -// Thread.sleep(3000); | ||
| 88 | -// SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); | ||
| 89 | -// SipStackImpl stack = (SipStackImpl)up.getSipStack(); | ||
| 90 | -// stack.stop(); | ||
| 91 | -// Iterator listener = stack.getListeningPoints(); | ||
| 92 | -// while (listener.hasNext()) { | ||
| 93 | -// stack.deleteListeningPoint((ListeningPoint) listener.next()); | ||
| 94 | -// } | ||
| 95 | -// Iterator providers = stack.getSipProviders(); | ||
| 96 | -// while (providers.hasNext()) { | ||
| 97 | -// stack.deleteSipProvider((SipProvider) providers.next()); | ||
| 98 | -// } | ||
| 99 | -// VManageBootstrap.restart(); | ||
| 100 | -// } catch (InterruptedException | ObjectInUseException e) { | ||
| 101 | -// logger.error("[任务执行失败] 服务重启: {}", e.getMessage()); | ||
| 102 | -// } | ||
| 103 | - }); | ||
| 104 | - } | 76 | + // TODO 拒绝远程启动命令 |
| 77 | + logger.warn("[国标级联]收到平台的远程启动命令, 不处理"); | ||
| 78 | + | ||
| 79 | +// if (parentPlatform.getServerGBId().equals(targetGBId)) { | ||
| 80 | +// // 远程启动本平台:需要在重新启动程序后先对SipStack解绑 | ||
| 81 | +// logger.info("执行远程启动本平台命令"); | ||
| 82 | +// try { | ||
| 83 | +// cmderFroPlatform.unregister(parentPlatform, null, null); | ||
| 84 | +// } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 85 | +// logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); | ||
| 86 | +// } | ||
| 87 | +// taskExecutor.execute(() -> { | ||
| 88 | +// // 远程启动 | ||
| 89 | +//// try { | ||
| 90 | +//// Thread.sleep(3000); | ||
| 91 | +//// SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider"); | ||
| 92 | +//// SipStackImpl stack = (SipStackImpl)up.getSipStack(); | ||
| 93 | +//// stack.stop(); | ||
| 94 | +//// Iterator listener = stack.getListeningPoints(); | ||
| 95 | +//// while (listener.hasNext()) { | ||
| 96 | +//// stack.deleteListeningPoint((ListeningPoint) listener.next()); | ||
| 97 | +//// } | ||
| 98 | +//// Iterator providers = stack.getSipProviders(); | ||
| 99 | +//// while (providers.hasNext()) { | ||
| 100 | +//// stack.deleteSipProvider((SipProvider) providers.next()); | ||
| 101 | +//// } | ||
| 102 | +//// VManageBootstrap.restart(); | ||
| 103 | +//// } catch (InterruptedException | ObjectInUseException e) { | ||
| 104 | +//// logger.error("[任务执行失败] 服务重启: {}", e.getMessage()); | ||
| 105 | +//// } | ||
| 106 | +// }); | ||
| 107 | +// } | ||
| 105 | } | 108 | } |
| 106 | DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement); | 109 | DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement); |
| 107 | logger.info("[接受deviceControl命令] 命令: {}", deviceControlType); | 110 | logger.info("[接受deviceControl命令] 命令: {}", deviceControlType); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
| @@ -186,9 +186,13 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme | @@ -186,9 +186,13 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme | ||
| 186 | // 发送给平台的报警信息。 发送redis通知 | 186 | // 发送给平台的报警信息。 发送redis通知 |
| 187 | logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm)); | 187 | logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm)); |
| 188 | AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); | 188 | AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); |
| 189 | - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); | 189 | + if (deviceAlarm.getAlarmMethod() != null) { |
| 190 | + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); | ||
| 191 | + } | ||
| 190 | alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); | 192 | alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); |
| 191 | - alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); | 193 | + if (deviceAlarm.getAlarmType() != null) { |
| 194 | + alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); | ||
| 195 | + } | ||
| 192 | alarmChannelMessage.setGbId(channelId); | 196 | alarmChannelMessage.setGbId(channelId); |
| 193 | redisCatchStorage.sendAlarmMsg(alarmChannelMessage); | 197 | redisCatchStorage.sendAlarmMsg(alarmChannelMessage); |
| 194 | continue; | 198 | continue; |
| @@ -204,6 +208,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme | @@ -204,6 +208,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme | ||
| 204 | publisher.deviceAlarmEventPublish(deviceAlarm); | 208 | publisher.deviceAlarmEventPublish(deviceAlarm); |
| 205 | } | 209 | } |
| 206 | }catch (Exception e) { | 210 | }catch (Exception e) { |
| 211 | + logger.error("未处理的异常 ", e); | ||
| 207 | logger.warn("[收到报警通知] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); | 212 | logger.warn("[收到报警通知] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); |
| 208 | } | 213 | } |
| 209 | } | 214 | } |
| @@ -264,12 +269,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme | @@ -264,12 +269,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme | ||
| 264 | if (channelId.equals(parentPlatform.getDeviceGBId())) { | 269 | if (channelId.equals(parentPlatform.getDeviceGBId())) { |
| 265 | // 发送给平台的报警信息。 发送redis通知 | 270 | // 发送给平台的报警信息。 发送redis通知 |
| 266 | AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); | 271 | AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); |
| 267 | - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); | 272 | + if (deviceAlarm.getAlarmMethod() != null) { |
| 273 | + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); | ||
| 274 | + } | ||
| 268 | alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); | 275 | alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); |
| 269 | alarmChannelMessage.setGbId(channelId); | 276 | alarmChannelMessage.setGbId(channelId); |
| 270 | - alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); | 277 | + if (deviceAlarm.getAlarmType() != null) { |
| 278 | + alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); | ||
| 279 | + } | ||
| 271 | redisCatchStorage.sendAlarmMsg(alarmChannelMessage); | 280 | redisCatchStorage.sendAlarmMsg(alarmChannelMessage); |
| 272 | - return; | ||
| 273 | } | 281 | } |
| 274 | } | 282 | } |
| 275 | } | 283 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
| @@ -88,13 +88,13 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp | @@ -88,13 +88,13 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp | ||
| 88 | // 对于已经离线的设备判断他的注册是否已经过期 | 88 | // 对于已经离线的设备判断他的注册是否已经过期 |
| 89 | if (!deviceService.expire(device)){ | 89 | if (!deviceService.expire(device)){ |
| 90 | device.setOnline(0); | 90 | device.setOnline(0); |
| 91 | - deviceService.online(device); | 91 | + deviceService.online(device, null); |
| 92 | } | 92 | } |
| 93 | } | 93 | } |
| 94 | // 刷新过期任务 | 94 | // 刷新过期任务 |
| 95 | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); | 95 | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); |
| 96 | // 如果三次心跳失败,则设置设备离线 | 96 | // 如果三次心跳失败,则设置设备离线 |
| 97 | - dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId()), device.getKeepaliveIntervalTime()*1000*3); | 97 | + dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId(), "三次心跳失败"), device.getKeepaliveIntervalTime()*1000*3); |
| 98 | 98 | ||
| 99 | } | 99 | } |
| 100 | 100 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
| @@ -149,9 +149,10 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen | @@ -149,9 +149,10 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen | ||
| 149 | redisCatchStorage.sendMobilePositionMsg(jsonObject); | 149 | redisCatchStorage.sendMobilePositionMsg(jsonObject); |
| 150 | 150 | ||
| 151 | } catch (DocumentException e) { | 151 | } catch (DocumentException e) { |
| 152 | - e.printStackTrace(); | 152 | + logger.error("未处理的异常 ", e); |
| 153 | } catch (Exception e) { | 153 | } catch (Exception e) { |
| 154 | - logger.warn("[移动位置通知] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); | 154 | + logger.warn("[移动位置通知] 发现未处理的异常, \r\n{}", evt.getRequest()); |
| 155 | + logger.error("[移动位置通知] 异常内容: ", e); | ||
| 155 | } | 156 | } |
| 156 | } | 157 | } |
| 157 | }); | 158 | }); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
| @@ -60,17 +60,24 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp | @@ -60,17 +60,24 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp | ||
| 60 | return; | 60 | return; |
| 61 | } | 61 | } |
| 62 | String sn = rootElement.element("SN").getText(); | 62 | String sn = rootElement.element("SN").getText(); |
| 63 | + | ||
| 63 | /*根据WVP原有的数据结构,设备和通道是分开放置,设备信息都是存放在设备表里,通道表里的设备信息不可作为真实信息处理 | 64 | /*根据WVP原有的数据结构,设备和通道是分开放置,设备信息都是存放在设备表里,通道表里的设备信息不可作为真实信息处理 |
| 64 | 大部分NVR/IPC设备对他的通道信息实现都是返回默认的值没有什么参考价值。NVR/IPC通道我们统一使用设备表的设备信息来作为返回。 | 65 | 大部分NVR/IPC设备对他的通道信息实现都是返回默认的值没有什么参考价值。NVR/IPC通道我们统一使用设备表的设备信息来作为返回。 |
| 65 | 我们这里使用查询数据库的方式来实现这个设备信息查询的功能,在其他地方对设备信息更新达到正确的目的。*/ | 66 | 我们这里使用查询数据库的方式来实现这个设备信息查询的功能,在其他地方对设备信息更新达到正确的目的。*/ |
| 67 | + | ||
| 66 | String channelId = getText(rootElement, "DeviceID"); | 68 | String channelId = getText(rootElement, "DeviceID"); |
| 67 | - Device device = storager.queryDeviceInfoByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); | ||
| 68 | - if (device ==null){ | ||
| 69 | - logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId); | ||
| 70 | - return; | 69 | + // 查询这是通道id还是设备id |
| 70 | + Device device = null; | ||
| 71 | + // 如果id指向平台的国标编号,那么就是查询平台的信息 | ||
| 72 | + if (!parentPlatform.getDeviceGBId().equals(channelId)) { | ||
| 73 | + device = storager.queryDeviceInfoByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); | ||
| 74 | + if (device ==null){ | ||
| 75 | + logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId); | ||
| 76 | + return; | ||
| 77 | + } | ||
| 71 | } | 78 | } |
| 72 | try { | 79 | try { |
| 73 | - cmderFroPlatform.deviceInfoResponse(parentPlatform,device, sn, fromHeader.getTag()); | 80 | + cmderFroPlatform.deviceInfoResponse(parentPlatform, device, sn, fromHeader.getTag()); |
| 74 | } catch (SipException | InvalidArgumentException | ParseException e) { | 81 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 75 | logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage()); | 82 | logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage()); |
| 76 | } | 83 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
| @@ -132,7 +132,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | @@ -132,7 +132,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp | ||
| 132 | 132 | ||
| 133 | } | 133 | } |
| 134 | }catch (Exception e) { | 134 | }catch (Exception e) { |
| 135 | - logger.warn("[收到通道] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); | 135 | + logger.warn("[收到通道] 发现未处理的异常, \r\n{}", evt.getRequest()); |
| 136 | + logger.error("[收到通道] 异常内容: ", e); | ||
| 136 | } | 137 | } |
| 137 | } | 138 | } |
| 138 | }); | 139 | }); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSONObject; | 3 | import com.alibaba.fastjson2.JSONObject; |
| 4 | -import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 4 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 5 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 7 | -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | ||
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | 6 | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| 9 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 7 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 8 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| @@ -26,7 +24,6 @@ import javax.sip.RequestEvent; | @@ -26,7 +24,6 @@ import javax.sip.RequestEvent; | ||
| 26 | import javax.sip.SipException; | 24 | import javax.sip.SipException; |
| 27 | import javax.sip.message.Response; | 25 | import javax.sip.message.Response; |
| 28 | import java.text.ParseException; | 26 | import java.text.ParseException; |
| 29 | -import java.util.Objects; | ||
| 30 | 27 | ||
| 31 | @Component | 28 | @Component |
| 32 | public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { | 29 | public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
| @@ -74,9 +71,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen | @@ -74,9 +71,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen | ||
| 74 | } | 71 | } |
| 75 | String text = onlineElement.getText(); | 72 | String text = onlineElement.getText(); |
| 76 | if ("ONLINE".equalsIgnoreCase(text.trim())) { | 73 | if ("ONLINE".equalsIgnoreCase(text.trim())) { |
| 77 | - deviceService.online(device); | 74 | + deviceService.online(device, null); |
| 78 | }else { | 75 | }else { |
| 79 | - deviceService.offline(device.getDeviceId()); | 76 | + deviceService.offline(device.getDeviceId(), "设备状态查询结果:" + text.trim()); |
| 80 | } | 77 | } |
| 81 | RequestMessage msg = new RequestMessage(); | 78 | RequestMessage msg = new RequestMessage(); |
| 82 | msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId()); | 79 | msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
| @@ -142,7 +142,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar | @@ -142,7 +142,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar | ||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | } catch (DocumentException e) { | 144 | } catch (DocumentException e) { |
| 145 | - e.printStackTrace(); | 145 | + logger.error("未处理的异常 ", e); |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | 148 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
| @@ -150,7 +150,8 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent | @@ -150,7 +150,8 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent | ||
| 150 | } | 150 | } |
| 151 | } | 151 | } |
| 152 | } catch (Exception e) { | 152 | } catch (Exception e) { |
| 153 | - logger.error("[国标录像] 发现未处理的异常, "+e.getMessage(), e); | 153 | + logger.error("[国标录像] 发现未处理的异常, \r\n{}", evt.getRequest()); |
| 154 | + logger.error("[国标录像] 异常内容: ", e); | ||
| 154 | } | 155 | } |
| 155 | }); | 156 | }); |
| 156 | } | 157 | } |
| @@ -163,7 +164,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent | @@ -163,7 +164,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent | ||
| 163 | public void releaseRequest(String deviceId, String sn,RecordInfo recordInfo){ | 164 | public void releaseRequest(String deviceId, String sn,RecordInfo recordInfo){ |
| 164 | String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; | 165 | String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; |
| 165 | // 对数据进行排序 | 166 | // 对数据进行排序 |
| 166 | - Collections.sort(recordInfo.getRecordList()); | 167 | + if(recordInfo!=null && recordInfo.getRecordList()!=null) { |
| 168 | + Collections.sort(recordInfo.getRecordList()); | ||
| 169 | + }else{ | ||
| 170 | + recordInfo.setRecordList(new ArrayList<>()); | ||
| 171 | + } | ||
| 167 | 172 | ||
| 168 | RequestMessage msg = new RequestMessage(); | 173 | RequestMessage msg = new RequestMessage(); |
| 169 | msg.setKey(key); | 174 | msg.setKey(key); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
| @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 3 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; | 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | 6 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; |
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 7 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 8 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.service.IPlatformService; | @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.service.IPlatformService; | ||
| 10 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 11 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 11 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 12 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 12 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; | 13 | import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; |
| 14 | +import gov.nist.javax.sip.message.SIPResponse; | ||
| 13 | import org.slf4j.Logger; | 15 | import org.slf4j.Logger; |
| 14 | import org.slf4j.LoggerFactory; | 16 | import org.slf4j.LoggerFactory; |
| 15 | import org.springframework.beans.factory.annotation.Autowired; | 17 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -18,7 +20,6 @@ import org.springframework.stereotype.Component; | @@ -18,7 +20,6 @@ import org.springframework.stereotype.Component; | ||
| 18 | import javax.sip.InvalidArgumentException; | 20 | import javax.sip.InvalidArgumentException; |
| 19 | import javax.sip.ResponseEvent; | 21 | import javax.sip.ResponseEvent; |
| 20 | import javax.sip.SipException; | 22 | import javax.sip.SipException; |
| 21 | -import javax.sip.header.CallIdHeader; | ||
| 22 | import javax.sip.header.WWWAuthenticateHeader; | 23 | import javax.sip.header.WWWAuthenticateHeader; |
| 23 | import javax.sip.message.Response; | 24 | import javax.sip.message.Response; |
| 24 | import java.text.ParseException; | 25 | import java.text.ParseException; |
| @@ -65,9 +66,8 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { | @@ -65,9 +66,8 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { | ||
| 65 | */ | 66 | */ |
| 66 | @Override | 67 | @Override |
| 67 | public void process(ResponseEvent evt) { | 68 | public void process(ResponseEvent evt) { |
| 68 | - Response response = evt.getResponse(); | ||
| 69 | - CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME); | ||
| 70 | - String callId = callIdHeader.getCallId(); | 69 | + SIPResponse response = (SIPResponse)evt.getResponse(); |
| 70 | + String callId = response.getCallIdHeader().getCallId(); | ||
| 71 | PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId); | 71 | PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId); |
| 72 | if (platformRegisterInfo == null) { | 72 | if (platformRegisterInfo == null) { |
| 73 | logger.info(String.format("[国标级联]未找到callId: %s 的注册/注销平台id", callId )); | 73 | logger.info(String.format("[国标级联]未找到callId: %s 的注册/注销平台id", callId )); |
| @@ -90,15 +90,17 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { | @@ -90,15 +90,17 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { | ||
| 90 | 90 | ||
| 91 | if (response.getStatusCode() == Response.UNAUTHORIZED) { | 91 | if (response.getStatusCode() == Response.UNAUTHORIZED) { |
| 92 | WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); | 92 | WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); |
| 93 | + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response); | ||
| 93 | try { | 94 | try { |
| 94 | - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister()); | 95 | + sipCommanderForPlatform.register(parentPlatform, sipTransactionInfo, www, null, null, true, platformRegisterInfo.isRegister()); |
| 95 | } catch (SipException | InvalidArgumentException | ParseException e) { | 96 | } catch (SipException | InvalidArgumentException | ParseException e) { |
| 96 | logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage()); | 97 | logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage()); |
| 97 | } | 98 | } |
| 98 | }else if (response.getStatusCode() == Response.OK){ | 99 | }else if (response.getStatusCode() == Response.OK){ |
| 99 | 100 | ||
| 100 | if (platformRegisterInfo.isRegister()) { | 101 | if (platformRegisterInfo.isRegister()) { |
| 101 | - platformService.online(parentPlatform); | 102 | + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response); |
| 103 | + platformService.online(parentPlatform, sipTransactionInfo); | ||
| 102 | }else { | 104 | }else { |
| 103 | platformService.offline(parentPlatform, false); | 105 | platformService.offline(parentPlatform, false); |
| 104 | } | 106 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
| @@ -9,17 +9,12 @@ import org.jetbrains.annotations.NotNull; | @@ -9,17 +9,12 @@ import org.jetbrains.annotations.NotNull; | ||
| 9 | import org.slf4j.Logger; | 9 | import org.slf4j.Logger; |
| 10 | import org.slf4j.LoggerFactory; | 10 | import org.slf4j.LoggerFactory; |
| 11 | import org.springframework.stereotype.Component; | 11 | import org.springframework.stereotype.Component; |
| 12 | -import org.springframework.util.ObjectUtils; | ||
| 13 | -import org.springframework.util.StringUtils; | ||
| 14 | 12 | ||
| 15 | -import java.io.File; | ||
| 16 | -import java.io.FileOutputStream; | ||
| 17 | import java.io.IOException; | 13 | import java.io.IOException; |
| 18 | import java.net.ConnectException; | 14 | import java.net.ConnectException; |
| 19 | import java.util.HashMap; | 15 | import java.util.HashMap; |
| 20 | import java.util.Map; | 16 | import java.util.Map; |
| 21 | import java.util.Objects; | 17 | import java.util.Objects; |
| 22 | -import java.util.concurrent.TimeUnit; | ||
| 23 | 18 | ||
| 24 | @Component | 19 | @Component |
| 25 | public class AssistRESTfulUtils { | 20 | public class AssistRESTfulUtils { |
| @@ -137,6 +132,11 @@ public class AssistRESTfulUtils { | @@ -137,6 +132,11 @@ public class AssistRESTfulUtils { | ||
| 137 | return sendGet(mediaServerItem, "api/record/file/duration",param, callback); | 132 | return sendGet(mediaServerItem, "api/record/file/duration",param, callback); |
| 138 | } | 133 | } |
| 139 | 134 | ||
| 135 | + public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){ | ||
| 136 | + Map<String, Object> param = new HashMap<>(); | ||
| 137 | + return sendGet(mediaServerItem, "api/record/info",param, callback); | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){ | 140 | public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){ |
| 141 | Map<String, Object> param = new HashMap<>(); | 141 | Map<String, Object> param = new HashMap<>(); |
| 142 | param.put("app",app); | 142 | param.put("app",app); |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| @@ -119,10 +119,11 @@ public class ZLMHttpHookListener { | @@ -119,10 +119,11 @@ public class ZLMHttpHookListener { | ||
| 119 | * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 | 119 | * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 |
| 120 | */ | 120 | */ |
| 121 | @ResponseBody | 121 | @ResponseBody |
| 122 | + | ||
| 122 | @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") | 123 | @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") |
| 123 | public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { | 124 | public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { |
| 124 | 125 | ||
| 125 | - logger.info("[ZLM HOOK] 收到zlm心跳:" + param.getMediaServerId()); | 126 | +// logger.info("[ZLM HOOK] 收到zlm心跳:" + param.getMediaServerId()); |
| 126 | 127 | ||
| 127 | taskExecutor.execute(() -> { | 128 | taskExecutor.execute(() -> { |
| 128 | List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); | 129 | List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); |
| @@ -142,6 +143,7 @@ public class ZLMHttpHookListener { | @@ -142,6 +143,7 @@ public class ZLMHttpHookListener { | ||
| 142 | * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 | 143 | * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 |
| 143 | */ | 144 | */ |
| 144 | @ResponseBody | 145 | @ResponseBody |
| 146 | + | ||
| 145 | @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") | 147 | @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") |
| 146 | public HookResult onPlay(@RequestBody OnPlayHookParam param) { | 148 | public HookResult onPlay(@RequestBody OnPlayHookParam param) { |
| 147 | if (logger.isDebugEnabled()) { | 149 | if (logger.isDebugEnabled()) { |
| @@ -264,9 +266,28 @@ public class ZLMHttpHookListener { | @@ -264,9 +266,28 @@ public class ZLMHttpHookListener { | ||
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | } | 268 | } |
| 269 | + if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { | ||
| 270 | + logger.info("推流时发现尚未设置录像路径,从assist服务中读取"); | ||
| 271 | + JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null); | ||
| 272 | + if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) { | ||
| 273 | + JSONObject dataJson = info.getJSONObject("data"); | ||
| 274 | + if (dataJson != null) { | ||
| 275 | + String recordPath = dataJson.getString("record"); | ||
| 276 | + userSetting.setRecordPath(recordPath); | ||
| 277 | + result.setMp4_save_path(recordPath); | ||
| 278 | + // 修改zlm中的录像路径 | ||
| 279 | + if (mediaInfo.isAutoConfig()) { | ||
| 280 | + taskExecutor.execute(() -> { | ||
| 281 | + mediaServerService.setZLMConfig(mediaInfo, false); | ||
| 282 | + }); | ||
| 283 | + } | ||
| 284 | + } | ||
| 285 | + } | ||
| 286 | + } | ||
| 267 | return result; | 287 | return result; |
| 268 | } | 288 | } |
| 269 | 289 | ||
| 290 | + | ||
| 270 | /** | 291 | /** |
| 271 | * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。 | 292 | * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。 |
| 272 | */ | 293 | */ |
| @@ -293,8 +314,12 @@ public class ZLMHttpHookListener { | @@ -293,8 +314,12 @@ public class ZLMHttpHookListener { | ||
| 293 | subscribe.response(mediaInfo, json); | 314 | subscribe.response(mediaInfo, json); |
| 294 | } | 315 | } |
| 295 | } | 316 | } |
| 296 | - // 流消失移除redis play | 317 | + |
| 318 | + List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); | ||
| 319 | + // TODO 重构此处逻辑 | ||
| 320 | + | ||
| 297 | if (param.isRegist()) { | 321 | if (param.isRegist()) { |
| 322 | + // 处理流注册的鉴权信息 | ||
| 298 | if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() | 323 | if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() |
| 299 | || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() | 324 | || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() |
| 300 | || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { | 325 | || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| @@ -334,9 +334,9 @@ public class ZLMRESTfulUtils { | @@ -334,9 +334,9 @@ public class ZLMRESTfulUtils { | ||
| 334 | sendPost(mediaServerItem, "kick_sessions",param, null); | 334 | sendPost(mediaServerItem, "kick_sessions",param, null); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | - public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { | 337 | + public void getSnap(MediaServerItem mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { |
| 338 | Map<String, Object> param = new HashMap<>(3); | 338 | Map<String, Object> param = new HashMap<>(3); |
| 339 | - param.put("url", flvUrl); | 339 | + param.put("url", streamUrl); |
| 340 | param.put("timeout_sec", timeout_sec); | 340 | param.put("timeout_sec", timeout_sec); |
| 341 | param.put("expire_sec", expire_sec); | 341 | param.put("expire_sec", expire_sec); |
| 342 | sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName); | 342 | sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName); |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| @@ -262,8 +262,11 @@ public class ZLMRTPServerFactory { | @@ -262,8 +262,11 @@ public class ZLMRTPServerFactory { | ||
| 262 | logger.info("[保持端口] {}->监听端口到期继续保持监听", ssrc); | 262 | logger.info("[保持端口] {}->监听端口到期继续保持监听", ssrc); |
| 263 | keepPort(serverItem, ssrc); | 263 | keepPort(serverItem, ssrc); |
| 264 | }); | 264 | }); |
| 265 | - } | ||
| 266 | logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); | 265 | logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); |
| 266 | + logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); | ||
| 267 | + }else { | ||
| 268 | + logger.info("[保持端口] 监听端口失败: {}", ssrc); | ||
| 269 | + } | ||
| 267 | return localPort; | 270 | return localPort; |
| 268 | } | 271 | } |
| 269 | 272 |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java
| @@ -10,21 +10,87 @@ public class ZLMServerConfig { | @@ -10,21 +10,87 @@ public class ZLMServerConfig { | ||
| 10 | @JSONField(name = "api.secret") | 10 | @JSONField(name = "api.secret") |
| 11 | private String apiSecret; | 11 | private String apiSecret; |
| 12 | 12 | ||
| 13 | + @JSONField(name = "api.snapRoot") | ||
| 14 | + private String apiSnapRoot; | ||
| 15 | + | ||
| 16 | + @JSONField(name = "api.defaultSnap") | ||
| 17 | + private String apiDefaultSnap; | ||
| 18 | + | ||
| 13 | @JSONField(name = "ffmpeg.bin") | 19 | @JSONField(name = "ffmpeg.bin") |
| 14 | private String ffmpegBin; | 20 | private String ffmpegBin; |
| 15 | 21 | ||
| 16 | @JSONField(name = "ffmpeg.cmd") | 22 | @JSONField(name = "ffmpeg.cmd") |
| 17 | private String ffmpegCmd; | 23 | private String ffmpegCmd; |
| 18 | 24 | ||
| 25 | + @JSONField(name = "ffmpeg.snap") | ||
| 26 | + private String ffmpegSnap; | ||
| 27 | + | ||
| 19 | @JSONField(name = "ffmpeg.log") | 28 | @JSONField(name = "ffmpeg.log") |
| 20 | private String ffmpegLog; | 29 | private String ffmpegLog; |
| 21 | 30 | ||
| 31 | + @JSONField(name = "ffmpeg.restart_sec") | ||
| 32 | + private String ffmpegRestartSec; | ||
| 33 | + | ||
| 34 | + @JSONField(name = "protocol.modify_stamp") | ||
| 35 | + private String protocolModifyStamp; | ||
| 36 | + | ||
| 37 | + @JSONField(name = "protocol.enable_audio") | ||
| 38 | + private String protocolEnableAudio; | ||
| 39 | + | ||
| 40 | + @JSONField(name = "protocol.add_mute_audio") | ||
| 41 | + private String protocolAddMuteAudio; | ||
| 42 | + | ||
| 43 | + @JSONField(name = "protocol.continue_push_ms") | ||
| 44 | + private String protocolContinuePushMs; | ||
| 45 | + | ||
| 46 | + @JSONField(name = "protocol.enable_hls") | ||
| 47 | + private String protocolEnableHls; | ||
| 48 | + | ||
| 49 | + @JSONField(name = "protocol.enable_mp4") | ||
| 50 | + private String protocolEnableMp4; | ||
| 51 | + | ||
| 52 | + @JSONField(name = "protocol.enable_rtsp") | ||
| 53 | + private String protocolEnableRtsp; | ||
| 54 | + | ||
| 55 | + @JSONField(name = "protocol.enable_rtmp") | ||
| 56 | + private String protocolEnableRtmp; | ||
| 57 | + | ||
| 58 | + @JSONField(name = "protocol.enable_ts") | ||
| 59 | + private String protocolEnableTs; | ||
| 60 | + | ||
| 61 | + @JSONField(name = "protocol.enable_fmp4") | ||
| 62 | + private String protocolEnableFmp4; | ||
| 63 | + | ||
| 64 | + @JSONField(name = "protocol.mp4_as_player") | ||
| 65 | + private String protocolMp4AsPlayer; | ||
| 66 | + | ||
| 67 | + @JSONField(name = "protocol.mp4_max_second") | ||
| 68 | + private String protocolMp4MaxSecond; | ||
| 69 | + | ||
| 70 | + @JSONField(name = "protocol.mp4_save_path") | ||
| 71 | + private String protocolMp4SavePath; | ||
| 72 | + | ||
| 73 | + @JSONField(name = "protocol.hls_save_path") | ||
| 74 | + private String protocolHlsSavePath; | ||
| 75 | + | ||
| 76 | + @JSONField(name = "protocol.hls_demand") | ||
| 77 | + private String protocolHlsDemand; | ||
| 78 | + | ||
| 79 | + @JSONField(name = "protocol.rtsp_demand") | ||
| 80 | + private String protocolRtspDemand; | ||
| 81 | + | ||
| 82 | + @JSONField(name = "protocol.rtmp_demand") | ||
| 83 | + private String protocolRtmpDemand; | ||
| 84 | + | ||
| 85 | + @JSONField(name = "protocol.ts_demand") | ||
| 86 | + private String protocolTsDemand; | ||
| 87 | + | ||
| 88 | + @JSONField(name = "protocol.fmp4_demand") | ||
| 89 | + private String protocolFmp4Demand; | ||
| 90 | + | ||
| 22 | @JSONField(name = "general.enableVhost") | 91 | @JSONField(name = "general.enableVhost") |
| 23 | private String generalEnableVhost; | 92 | private String generalEnableVhost; |
| 24 | 93 | ||
| 25 | - @JSONField(name = "general.mediaServerId") | ||
| 26 | - private String generalMediaServerId; | ||
| 27 | - | ||
| 28 | @JSONField(name = "general.flowThreshold") | 94 | @JSONField(name = "general.flowThreshold") |
| 29 | private String generalFlowThreshold; | 95 | private String generalFlowThreshold; |
| 30 | 96 | ||
| @@ -34,6 +100,25 @@ public class ZLMServerConfig { | @@ -34,6 +100,25 @@ public class ZLMServerConfig { | ||
| 34 | @JSONField(name = "general.streamNoneReaderDelayMS") | 100 | @JSONField(name = "general.streamNoneReaderDelayMS") |
| 35 | private int generalStreamNoneReaderDelayMS; | 101 | private int generalStreamNoneReaderDelayMS; |
| 36 | 102 | ||
| 103 | + @JSONField(name = "general.resetWhenRePlay") | ||
| 104 | + private String generalResetWhenRePlay; | ||
| 105 | + | ||
| 106 | + @JSONField(name = "general.mergeWriteMS") | ||
| 107 | + private String generalMergeWriteMS; | ||
| 108 | + | ||
| 109 | + @JSONField(name = "general.mediaServerId") | ||
| 110 | + private String generalMediaServerId; | ||
| 111 | + | ||
| 112 | + @JSONField(name = "general.wait_track_ready_ms") | ||
| 113 | + private String generalWaitTrackReadyMs; | ||
| 114 | + | ||
| 115 | + @JSONField(name = "general.wait_add_track_ms") | ||
| 116 | + private String generalWaitAddTrackMs; | ||
| 117 | + | ||
| 118 | + @JSONField(name = "general.unready_frame_cache") | ||
| 119 | + private String generalUnreadyFrameCache; | ||
| 120 | + | ||
| 121 | + | ||
| 37 | @JSONField(name = "ip") | 122 | @JSONField(name = "ip") |
| 38 | private String ip; | 123 | private String ip; |
| 39 | 124 | ||
| @@ -59,6 +144,18 @@ public class ZLMServerConfig { | @@ -59,6 +144,18 @@ public class ZLMServerConfig { | ||
| 59 | @JSONField(name = "hls.segNum") | 144 | @JSONField(name = "hls.segNum") |
| 60 | private String hlsSegNum; | 145 | private String hlsSegNum; |
| 61 | 146 | ||
| 147 | + @JSONField(name = "hls.segRetain") | ||
| 148 | + private String hlsSegRetain; | ||
| 149 | + | ||
| 150 | + @JSONField(name = "hls.broadcastRecordTs") | ||
| 151 | + private String hlsBroadcastRecordTs; | ||
| 152 | + | ||
| 153 | + @JSONField(name = "hls.deleteDelaySec") | ||
| 154 | + private String hlsDeleteDelaySec; | ||
| 155 | + | ||
| 156 | + @JSONField(name = "hls.segKeep") | ||
| 157 | + private String hlsSegKeep; | ||
| 158 | + | ||
| 62 | @JSONField(name = "hook.access_file_except_hls") | 159 | @JSONField(name = "hook.access_file_except_hls") |
| 63 | private String hookAccessFileExceptHLS; | 160 | private String hookAccessFileExceptHLS; |
| 64 | 161 | ||
| @@ -104,6 +201,18 @@ public class ZLMServerConfig { | @@ -104,6 +201,18 @@ public class ZLMServerConfig { | ||
| 104 | @JSONField(name = "hook.on_stream_not_found") | 201 | @JSONField(name = "hook.on_stream_not_found") |
| 105 | private String hookOnStreamNotFound; | 202 | private String hookOnStreamNotFound; |
| 106 | 203 | ||
| 204 | + @JSONField(name = "hook.on_server_started") | ||
| 205 | + private String hookOnServerStarted; | ||
| 206 | + | ||
| 207 | + @JSONField(name = "hook.on_server_keepalive") | ||
| 208 | + private String hookOnServerKeepalive; | ||
| 209 | + | ||
| 210 | + @JSONField(name = "hook.on_send_rtp_stopped") | ||
| 211 | + private String hookOnSendRtpStopped; | ||
| 212 | + | ||
| 213 | + @JSONField(name = "hook.on_rtp_server_timeout") | ||
| 214 | + private String hookOnRtpServerTimeout; | ||
| 215 | + | ||
| 107 | @JSONField(name = "hook.timeoutSec") | 216 | @JSONField(name = "hook.timeoutSec") |
| 108 | private String hookTimeoutSec; | 217 | private String hookTimeoutSec; |
| 109 | 218 | ||
| @@ -813,4 +922,292 @@ public class ZLMServerConfig { | @@ -813,4 +922,292 @@ public class ZLMServerConfig { | ||
| 813 | public void setPortRange(String portRange) { | 922 | public void setPortRange(String portRange) { |
| 814 | this.portRange = portRange; | 923 | this.portRange = portRange; |
| 815 | } | 924 | } |
| 925 | + | ||
| 926 | + public String getApiSnapRoot() { | ||
| 927 | + return apiSnapRoot; | ||
| 928 | + } | ||
| 929 | + | ||
| 930 | + public void setApiSnapRoot(String apiSnapRoot) { | ||
| 931 | + this.apiSnapRoot = apiSnapRoot; | ||
| 932 | + } | ||
| 933 | + | ||
| 934 | + public String getApiDefaultSnap() { | ||
| 935 | + return apiDefaultSnap; | ||
| 936 | + } | ||
| 937 | + | ||
| 938 | + public void setApiDefaultSnap(String apiDefaultSnap) { | ||
| 939 | + this.apiDefaultSnap = apiDefaultSnap; | ||
| 940 | + } | ||
| 941 | + | ||
| 942 | + public String getFfmpegSnap() { | ||
| 943 | + return ffmpegSnap; | ||
| 944 | + } | ||
| 945 | + | ||
| 946 | + public void setFfmpegSnap(String ffmpegSnap) { | ||
| 947 | + this.ffmpegSnap = ffmpegSnap; | ||
| 948 | + } | ||
| 949 | + | ||
| 950 | + public String getFfmpegRestartSec() { | ||
| 951 | + return ffmpegRestartSec; | ||
| 952 | + } | ||
| 953 | + | ||
| 954 | + public void setFfmpegRestartSec(String ffmpegRestartSec) { | ||
| 955 | + this.ffmpegRestartSec = ffmpegRestartSec; | ||
| 956 | + } | ||
| 957 | + | ||
| 958 | + public String getProtocolModifyStamp() { | ||
| 959 | + return protocolModifyStamp; | ||
| 960 | + } | ||
| 961 | + | ||
| 962 | + public void setProtocolModifyStamp(String protocolModifyStamp) { | ||
| 963 | + this.protocolModifyStamp = protocolModifyStamp; | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | + public String getProtocolEnableAudio() { | ||
| 967 | + return protocolEnableAudio; | ||
| 968 | + } | ||
| 969 | + | ||
| 970 | + public void setProtocolEnableAudio(String protocolEnableAudio) { | ||
| 971 | + this.protocolEnableAudio = protocolEnableAudio; | ||
| 972 | + } | ||
| 973 | + | ||
| 974 | + public String getProtocolAddMuteAudio() { | ||
| 975 | + return protocolAddMuteAudio; | ||
| 976 | + } | ||
| 977 | + | ||
| 978 | + public void setProtocolAddMuteAudio(String protocolAddMuteAudio) { | ||
| 979 | + this.protocolAddMuteAudio = protocolAddMuteAudio; | ||
| 980 | + } | ||
| 981 | + | ||
| 982 | + public String getProtocolContinuePushMs() { | ||
| 983 | + return protocolContinuePushMs; | ||
| 984 | + } | ||
| 985 | + | ||
| 986 | + public void setProtocolContinuePushMs(String protocolContinuePushMs) { | ||
| 987 | + this.protocolContinuePushMs = protocolContinuePushMs; | ||
| 988 | + } | ||
| 989 | + | ||
| 990 | + public String getProtocolEnableHls() { | ||
| 991 | + return protocolEnableHls; | ||
| 992 | + } | ||
| 993 | + | ||
| 994 | + public void setProtocolEnableHls(String protocolEnableHls) { | ||
| 995 | + this.protocolEnableHls = protocolEnableHls; | ||
| 996 | + } | ||
| 997 | + | ||
| 998 | + public String getProtocolEnableMp4() { | ||
| 999 | + return protocolEnableMp4; | ||
| 1000 | + } | ||
| 1001 | + | ||
| 1002 | + public void setProtocolEnableMp4(String protocolEnableMp4) { | ||
| 1003 | + this.protocolEnableMp4 = protocolEnableMp4; | ||
| 1004 | + } | ||
| 1005 | + | ||
| 1006 | + public String getProtocolEnableRtsp() { | ||
| 1007 | + return protocolEnableRtsp; | ||
| 1008 | + } | ||
| 1009 | + | ||
| 1010 | + public void setProtocolEnableRtsp(String protocolEnableRtsp) { | ||
| 1011 | + this.protocolEnableRtsp = protocolEnableRtsp; | ||
| 1012 | + } | ||
| 1013 | + | ||
| 1014 | + public String getProtocolEnableRtmp() { | ||
| 1015 | + return protocolEnableRtmp; | ||
| 1016 | + } | ||
| 1017 | + | ||
| 1018 | + public void setProtocolEnableRtmp(String protocolEnableRtmp) { | ||
| 1019 | + this.protocolEnableRtmp = protocolEnableRtmp; | ||
| 1020 | + } | ||
| 1021 | + | ||
| 1022 | + public String getProtocolEnableTs() { | ||
| 1023 | + return protocolEnableTs; | ||
| 1024 | + } | ||
| 1025 | + | ||
| 1026 | + public void setProtocolEnableTs(String protocolEnableTs) { | ||
| 1027 | + this.protocolEnableTs = protocolEnableTs; | ||
| 1028 | + } | ||
| 1029 | + | ||
| 1030 | + public String getProtocolEnableFmp4() { | ||
| 1031 | + return protocolEnableFmp4; | ||
| 1032 | + } | ||
| 1033 | + | ||
| 1034 | + public void setProtocolEnableFmp4(String protocolEnableFmp4) { | ||
| 1035 | + this.protocolEnableFmp4 = protocolEnableFmp4; | ||
| 1036 | + } | ||
| 1037 | + | ||
| 1038 | + public String getProtocolMp4AsPlayer() { | ||
| 1039 | + return protocolMp4AsPlayer; | ||
| 1040 | + } | ||
| 1041 | + | ||
| 1042 | + public void setProtocolMp4AsPlayer(String protocolMp4AsPlayer) { | ||
| 1043 | + this.protocolMp4AsPlayer = protocolMp4AsPlayer; | ||
| 1044 | + } | ||
| 1045 | + | ||
| 1046 | + public String getProtocolMp4MaxSecond() { | ||
| 1047 | + return protocolMp4MaxSecond; | ||
| 1048 | + } | ||
| 1049 | + | ||
| 1050 | + public void setProtocolMp4MaxSecond(String protocolMp4MaxSecond) { | ||
| 1051 | + this.protocolMp4MaxSecond = protocolMp4MaxSecond; | ||
| 1052 | + } | ||
| 1053 | + | ||
| 1054 | + public String getProtocolMp4SavePath() { | ||
| 1055 | + return protocolMp4SavePath; | ||
| 1056 | + } | ||
| 1057 | + | ||
| 1058 | + public void setProtocolMp4SavePath(String protocolMp4SavePath) { | ||
| 1059 | + this.protocolMp4SavePath = protocolMp4SavePath; | ||
| 1060 | + } | ||
| 1061 | + | ||
| 1062 | + public String getProtocolHlsSavePath() { | ||
| 1063 | + return protocolHlsSavePath; | ||
| 1064 | + } | ||
| 1065 | + | ||
| 1066 | + public void setProtocolHlsSavePath(String protocolHlsSavePath) { | ||
| 1067 | + this.protocolHlsSavePath = protocolHlsSavePath; | ||
| 1068 | + } | ||
| 1069 | + | ||
| 1070 | + public String getProtocolHlsDemand() { | ||
| 1071 | + return protocolHlsDemand; | ||
| 1072 | + } | ||
| 1073 | + | ||
| 1074 | + public void setProtocolHlsDemand(String protocolHlsDemand) { | ||
| 1075 | + this.protocolHlsDemand = protocolHlsDemand; | ||
| 1076 | + } | ||
| 1077 | + | ||
| 1078 | + public String getProtocolRtspDemand() { | ||
| 1079 | + return protocolRtspDemand; | ||
| 1080 | + } | ||
| 1081 | + | ||
| 1082 | + public void setProtocolRtspDemand(String protocolRtspDemand) { | ||
| 1083 | + this.protocolRtspDemand = protocolRtspDemand; | ||
| 1084 | + } | ||
| 1085 | + | ||
| 1086 | + public String getProtocolRtmpDemand() { | ||
| 1087 | + return protocolRtmpDemand; | ||
| 1088 | + } | ||
| 1089 | + | ||
| 1090 | + public void setProtocolRtmpDemand(String protocolRtmpDemand) { | ||
| 1091 | + this.protocolRtmpDemand = protocolRtmpDemand; | ||
| 1092 | + } | ||
| 1093 | + | ||
| 1094 | + public String getProtocolTsDemand() { | ||
| 1095 | + return protocolTsDemand; | ||
| 1096 | + } | ||
| 1097 | + | ||
| 1098 | + public void setProtocolTsDemand(String protocolTsDemand) { | ||
| 1099 | + this.protocolTsDemand = protocolTsDemand; | ||
| 1100 | + } | ||
| 1101 | + | ||
| 1102 | + public String getProtocolFmp4Demand() { | ||
| 1103 | + return protocolFmp4Demand; | ||
| 1104 | + } | ||
| 1105 | + | ||
| 1106 | + public void setProtocolFmp4Demand(String protocolFmp4Demand) { | ||
| 1107 | + this.protocolFmp4Demand = protocolFmp4Demand; | ||
| 1108 | + } | ||
| 1109 | + | ||
| 1110 | + public String getGeneralResetWhenRePlay() { | ||
| 1111 | + return generalResetWhenRePlay; | ||
| 1112 | + } | ||
| 1113 | + | ||
| 1114 | + public void setGeneralResetWhenRePlay(String generalResetWhenRePlay) { | ||
| 1115 | + this.generalResetWhenRePlay = generalResetWhenRePlay; | ||
| 1116 | + } | ||
| 1117 | + | ||
| 1118 | + public String getGeneralMergeWriteMS() { | ||
| 1119 | + return generalMergeWriteMS; | ||
| 1120 | + } | ||
| 1121 | + | ||
| 1122 | + public void setGeneralMergeWriteMS(String generalMergeWriteMS) { | ||
| 1123 | + this.generalMergeWriteMS = generalMergeWriteMS; | ||
| 1124 | + } | ||
| 1125 | + | ||
| 1126 | + public String getGeneralWaitTrackReadyMs() { | ||
| 1127 | + return generalWaitTrackReadyMs; | ||
| 1128 | + } | ||
| 1129 | + | ||
| 1130 | + public void setGeneralWaitTrackReadyMs(String generalWaitTrackReadyMs) { | ||
| 1131 | + this.generalWaitTrackReadyMs = generalWaitTrackReadyMs; | ||
| 1132 | + } | ||
| 1133 | + | ||
| 1134 | + public String getGeneralWaitAddTrackMs() { | ||
| 1135 | + return generalWaitAddTrackMs; | ||
| 1136 | + } | ||
| 1137 | + | ||
| 1138 | + public void setGeneralWaitAddTrackMs(String generalWaitAddTrackMs) { | ||
| 1139 | + this.generalWaitAddTrackMs = generalWaitAddTrackMs; | ||
| 1140 | + } | ||
| 1141 | + | ||
| 1142 | + public String getGeneralUnreadyFrameCache() { | ||
| 1143 | + return generalUnreadyFrameCache; | ||
| 1144 | + } | ||
| 1145 | + | ||
| 1146 | + public void setGeneralUnreadyFrameCache(String generalUnreadyFrameCache) { | ||
| 1147 | + this.generalUnreadyFrameCache = generalUnreadyFrameCache; | ||
| 1148 | + } | ||
| 1149 | + | ||
| 1150 | + public String getHlsSegRetain() { | ||
| 1151 | + return hlsSegRetain; | ||
| 1152 | + } | ||
| 1153 | + | ||
| 1154 | + public void setHlsSegRetain(String hlsSegRetain) { | ||
| 1155 | + this.hlsSegRetain = hlsSegRetain; | ||
| 1156 | + } | ||
| 1157 | + | ||
| 1158 | + public String getHlsBroadcastRecordTs() { | ||
| 1159 | + return hlsBroadcastRecordTs; | ||
| 1160 | + } | ||
| 1161 | + | ||
| 1162 | + public void setHlsBroadcastRecordTs(String hlsBroadcastRecordTs) { | ||
| 1163 | + this.hlsBroadcastRecordTs = hlsBroadcastRecordTs; | ||
| 1164 | + } | ||
| 1165 | + | ||
| 1166 | + public String getHlsDeleteDelaySec() { | ||
| 1167 | + return hlsDeleteDelaySec; | ||
| 1168 | + } | ||
| 1169 | + | ||
| 1170 | + public void setHlsDeleteDelaySec(String hlsDeleteDelaySec) { | ||
| 1171 | + this.hlsDeleteDelaySec = hlsDeleteDelaySec; | ||
| 1172 | + } | ||
| 1173 | + | ||
| 1174 | + public String getHlsSegKeep() { | ||
| 1175 | + return hlsSegKeep; | ||
| 1176 | + } | ||
| 1177 | + | ||
| 1178 | + public void setHlsSegKeep(String hlsSegKeep) { | ||
| 1179 | + this.hlsSegKeep = hlsSegKeep; | ||
| 1180 | + } | ||
| 1181 | + | ||
| 1182 | + public String getHookOnServerStarted() { | ||
| 1183 | + return hookOnServerStarted; | ||
| 1184 | + } | ||
| 1185 | + | ||
| 1186 | + public void setHookOnServerStarted(String hookOnServerStarted) { | ||
| 1187 | + this.hookOnServerStarted = hookOnServerStarted; | ||
| 1188 | + } | ||
| 1189 | + | ||
| 1190 | + public String getHookOnServerKeepalive() { | ||
| 1191 | + return hookOnServerKeepalive; | ||
| 1192 | + } | ||
| 1193 | + | ||
| 1194 | + public void setHookOnServerKeepalive(String hookOnServerKeepalive) { | ||
| 1195 | + this.hookOnServerKeepalive = hookOnServerKeepalive; | ||
| 1196 | + } | ||
| 1197 | + | ||
| 1198 | + public String getHookOnSendRtpStopped() { | ||
| 1199 | + return hookOnSendRtpStopped; | ||
| 1200 | + } | ||
| 1201 | + | ||
| 1202 | + public void setHookOnSendRtpStopped(String hookOnSendRtpStopped) { | ||
| 1203 | + this.hookOnSendRtpStopped = hookOnSendRtpStopped; | ||
| 1204 | + } | ||
| 1205 | + | ||
| 1206 | + public String getHookOnRtpServerTimeout() { | ||
| 1207 | + return hookOnRtpServerTimeout; | ||
| 1208 | + } | ||
| 1209 | + | ||
| 1210 | + public void setHookOnRtpServerTimeout(String hookOnRtpServerTimeout) { | ||
| 1211 | + this.hookOnRtpServerTimeout = hookOnRtpServerTimeout; | ||
| 1212 | + } | ||
| 816 | } | 1213 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java
| @@ -5,6 +5,7 @@ public class HookResultForOnPublish extends HookResult{ | @@ -5,6 +5,7 @@ public class HookResultForOnPublish extends HookResult{ | ||
| 5 | private boolean enable_audio; | 5 | private boolean enable_audio; |
| 6 | private boolean enable_mp4; | 6 | private boolean enable_mp4; |
| 7 | private int mp4_max_second; | 7 | private int mp4_max_second; |
| 8 | + private String mp4_save_path; | ||
| 8 | 9 | ||
| 9 | public HookResultForOnPublish() { | 10 | public HookResultForOnPublish() { |
| 10 | } | 11 | } |
| @@ -41,4 +42,12 @@ public class HookResultForOnPublish extends HookResult{ | @@ -41,4 +42,12 @@ public class HookResultForOnPublish extends HookResult{ | ||
| 41 | public void setMp4_max_second(int mp4_max_second) { | 42 | public void setMp4_max_second(int mp4_max_second) { |
| 42 | this.mp4_max_second = mp4_max_second; | 43 | this.mp4_max_second = mp4_max_second; |
| 43 | } | 44 | } |
| 45 | + | ||
| 46 | + public String getMp4_save_path() { | ||
| 47 | + return mp4_save_path; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + public void setMp4_save_path(String mp4_save_path) { | ||
| 51 | + this.mp4_save_path = mp4_save_path; | ||
| 52 | + } | ||
| 44 | } | 53 | } |
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
| @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service; | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service; | ||
| 2 | 2 | ||
| 3 | import com.genersoft.iot.vmp.gb28181.bean.Device; | 3 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 4 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | 4 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; | 6 | import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; |
| 6 | import com.genersoft.iot.vmp.vmanager.bean.BaseTree; | 7 | import com.genersoft.iot.vmp.vmanager.bean.BaseTree; |
| 7 | import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; | 8 | import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; |
| @@ -18,13 +19,13 @@ public interface IDeviceService { | @@ -18,13 +19,13 @@ public interface IDeviceService { | ||
| 18 | * 设备上线 | 19 | * 设备上线 |
| 19 | * @param device 设备信息 | 20 | * @param device 设备信息 |
| 20 | */ | 21 | */ |
| 21 | - void online(Device device); | 22 | + void online(Device device, SipTransactionInfo sipTransactionInfo); |
| 22 | 23 | ||
| 23 | /** | 24 | /** |
| 24 | * 设备下线 | 25 | * 设备下线 |
| 25 | * @param deviceId 设备编号 | 26 | * @param deviceId 设备编号 |
| 26 | */ | 27 | */ |
| 27 | - void offline(String deviceId); | 28 | + void offline(String deviceId, String reason); |
| 28 | 29 | ||
| 29 | /** | 30 | /** |
| 30 | * 添加目录订阅 | 31 | * 添加目录订阅 |
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
| @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 6 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | 6 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 7 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 7 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 8 | import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; | 8 | import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; |
| 9 | +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; | ||
| 9 | import com.github.pagehelper.PageInfo; | 10 | import com.github.pagehelper.PageInfo; |
| 10 | 11 | ||
| 11 | import javax.sip.InvalidArgumentException; | 12 | import javax.sip.InvalidArgumentException; |
| @@ -35,10 +36,16 @@ public interface IPlatformService { | @@ -35,10 +36,16 @@ public interface IPlatformService { | ||
| 35 | boolean add(ParentPlatform parentPlatform); | 36 | boolean add(ParentPlatform parentPlatform); |
| 36 | 37 | ||
| 37 | /** | 38 | /** |
| 39 | + * 添加级联平台 | ||
| 40 | + * @param parentPlatform 级联平台 | ||
| 41 | + */ | ||
| 42 | + boolean update(ParentPlatform parentPlatform); | ||
| 43 | + | ||
| 44 | + /** | ||
| 38 | * 平台上线 | 45 | * 平台上线 |
| 39 | * @param parentPlatform 平台信息 | 46 | * @param parentPlatform 平台信息 |
| 40 | */ | 47 | */ |
| 41 | - void online(ParentPlatform parentPlatform); | 48 | + void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo); |
| 42 | 49 | ||
| 43 | /** | 50 | /** |
| 44 | * 平台离线 | 51 | * 平台离线 |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
| @@ -96,7 +96,7 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -96,7 +96,7 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 96 | private ZLMRESTfulUtils zlmresTfulUtils; | 96 | private ZLMRESTfulUtils zlmresTfulUtils; |
| 97 | 97 | ||
| 98 | @Override | 98 | @Override |
| 99 | - public void online(Device device) { | 99 | + public void online(Device device, SipTransactionInfo sipTransactionInfo) { |
| 100 | logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort()); | 100 | logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort()); |
| 101 | Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId()); | 101 | Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId()); |
| 102 | Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); | 102 | Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); |
| @@ -111,6 +111,14 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -111,6 +111,14 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 111 | // 默认心跳间隔60 | 111 | // 默认心跳间隔60 |
| 112 | device.setKeepaliveIntervalTime(60); | 112 | device.setKeepaliveIntervalTime(60); |
| 113 | } | 113 | } |
| 114 | + if (sipTransactionInfo != null) { | ||
| 115 | + device.setSipTransactionInfo(sipTransactionInfo); | ||
| 116 | + }else { | ||
| 117 | + if (deviceInRedis != null) { | ||
| 118 | + device.setSipTransactionInfo(deviceInRedis.getSipTransactionInfo()); | ||
| 119 | + } | ||
| 120 | + } | ||
| 121 | + | ||
| 114 | // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 | 122 | // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 |
| 115 | if (device.getCreateTime() == null) { | 123 | if (device.getCreateTime() == null) { |
| 116 | device.setOnline(1); | 124 | device.setOnline(1); |
| @@ -163,12 +171,12 @@ public class DeviceServiceImpl implements IDeviceService { | @@ -163,12 +171,12 @@ public class DeviceServiceImpl implements IDeviceService { | ||
| 163 | // 刷新过期任务 | 171 | // 刷新过期任务 |
| 164 | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); | 172 | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); |
| 165 | // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 | 173 | // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 |
| 166 | - dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getKeepaliveIntervalTime() * 1000 * 3); | 174 | + dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3); |
| 167 | } | 175 | } |
| 168 | 176 | ||
| 169 | @Override | 177 | @Override |
| 170 | - public void offline(String deviceId) { | ||
| 171 | - logger.error("[设备离线], device:{}", deviceId); | 178 | + public void offline(String deviceId, String reason) { |
| 179 | + logger.error("[设备离线],{}, device:{}", reason, deviceId); | ||
| 172 | Device device = deviceMapper.getDeviceByDeviceId(deviceId); | 180 | Device device = deviceMapper.getDeviceByDeviceId(deviceId); |
| 173 | if (device == null) { | 181 | if (device == null) { |
| 174 | return; | 182 | return; |
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
| @@ -41,6 +41,9 @@ public class GbStreamServiceImpl implements IGbStreamService { | @@ -41,6 +41,9 @@ public class GbStreamServiceImpl implements IGbStreamService { | ||
| 41 | private PlatformGbStreamMapper platformGbStreamMapper; | 41 | private PlatformGbStreamMapper platformGbStreamMapper; |
| 42 | 42 | ||
| 43 | @Autowired | 43 | @Autowired |
| 44 | + private SubscribeHolder subscribeHolder; | ||
| 45 | + | ||
| 46 | + @Autowired | ||
| 44 | private ParentPlatformMapper platformMapper; | 47 | private ParentPlatformMapper platformMapper; |
| 45 | 48 | ||
| 46 | @Autowired | 49 | @Autowired |
| @@ -73,16 +76,23 @@ public class GbStreamServiceImpl implements IGbStreamService { | @@ -73,16 +76,23 @@ public class GbStreamServiceImpl implements IGbStreamService { | ||
| 73 | } | 76 | } |
| 74 | try { | 77 | try { |
| 75 | List<DeviceChannel> deviceChannelList = new ArrayList<>(); | 78 | List<DeviceChannel> deviceChannelList = new ArrayList<>(); |
| 76 | - for (GbStream gbStream : gbStreams) { | 79 | + |
| 80 | + | ||
| 81 | + for (int i = 0; i < gbStreams.size(); i++) { | ||
| 82 | + GbStream gbStream = gbStreams.get(i); | ||
| 77 | gbStream.setCatalogId(catalogId); | 83 | gbStream.setCatalogId(catalogId); |
| 78 | gbStream.setPlatformId(platformId); | 84 | gbStream.setPlatformId(platformId); |
| 79 | // TODO 修改为批量提交 | 85 | // TODO 修改为批量提交 |
| 80 | platformGbStreamMapper.add(gbStream); | 86 | platformGbStreamMapper.add(gbStream); |
| 87 | + logger.info("[关联通道]直播流通道 平台:{}, 共需关联通道数:{}, 已关联:{}", platformId, gbStreams.size(), i + 1); | ||
| 81 | DeviceChannel deviceChannelListByStream = getDeviceChannelListByStreamWithStatus(gbStream, catalogId, parentPlatform); | 88 | DeviceChannel deviceChannelListByStream = getDeviceChannelListByStreamWithStatus(gbStream, catalogId, parentPlatform); |
| 82 | deviceChannelList.add(deviceChannelListByStream); | 89 | deviceChannelList.add(deviceChannelListByStream); |
| 83 | } | 90 | } |
| 84 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 | 91 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 |
| 85 | - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); | 92 | + if (subscribeHolder.getCatalogSubscribe(platformId) != null) { |
| 93 | + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); | ||
| 94 | + } | ||
| 95 | + | ||
| 86 | result = true; | 96 | result = true; |
| 87 | }catch (Exception e) { | 97 | }catch (Exception e) { |
| 88 | logger.error("批量保存流与平台的关系时错误", e); | 98 | logger.error("批量保存流与平台的关系时错误", e); |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; | @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; | ||
| 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 11 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 12 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; | 12 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; |
| 13 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 13 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 14 | +import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; | ||
| 14 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 15 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 16 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 16 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; | 17 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| @@ -38,6 +39,7 @@ import org.springframework.transaction.TransactionDefinition; | @@ -38,6 +39,7 @@ import org.springframework.transaction.TransactionDefinition; | ||
| 38 | import org.springframework.transaction.TransactionStatus; | 39 | import org.springframework.transaction.TransactionStatus; |
| 39 | import org.springframework.util.ObjectUtils; | 40 | import org.springframework.util.ObjectUtils; |
| 40 | 41 | ||
| 42 | +import java.io.File; | ||
| 41 | import java.time.LocalDateTime; | 43 | import java.time.LocalDateTime; |
| 42 | import java.util.*; | 44 | import java.util.*; |
| 43 | 45 | ||
| @@ -64,6 +66,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -64,6 +66,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 64 | private UserSetting userSetting; | 66 | private UserSetting userSetting; |
| 65 | 67 | ||
| 66 | @Autowired | 68 | @Autowired |
| 69 | + private AssistRESTfulUtils assistRESTfulUtils; | ||
| 70 | + | ||
| 71 | + @Autowired | ||
| 67 | private ZLMRESTfulUtils zlmresTfulUtils; | 72 | private ZLMRESTfulUtils zlmresTfulUtils; |
| 68 | 73 | ||
| 69 | @Autowired | 74 | @Autowired |
| @@ -409,13 +414,27 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -409,13 +414,27 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 409 | } | 414 | } |
| 410 | RedisUtil.set(key, serverItem); | 415 | RedisUtil.set(key, serverItem); |
| 411 | resetOnlineServerItem(serverItem); | 416 | resetOnlineServerItem(serverItem); |
| 417 | + | ||
| 418 | + | ||
| 412 | if (serverItem.isAutoConfig()) { | 419 | if (serverItem.isAutoConfig()) { |
| 420 | + // 查看assist服务的录像路径配置 | ||
| 421 | + if (serverItem.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) { | ||
| 422 | + JSONObject info = assistRESTfulUtils.getInfo(serverItem, null); | ||
| 423 | + if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) { | ||
| 424 | + JSONObject dataJson = info.getJSONObject("data"); | ||
| 425 | + if (dataJson != null) { | ||
| 426 | + String recordPath = dataJson.getString("record"); | ||
| 427 | + userSetting.setRecordPath(recordPath); | ||
| 428 | + } | ||
| 429 | + } | ||
| 430 | + } | ||
| 413 | setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); | 431 | setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); |
| 414 | } | 432 | } |
| 415 | final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); | 433 | final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); |
| 416 | dynamicTask.stop(zlmKeepaliveKey); | 434 | dynamicTask.stop(zlmKeepaliveKey); |
| 417 | dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (Math.getExponent(serverItem.getHookAliveInterval()) + 5) * 1000); | 435 | dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (Math.getExponent(serverItem.getHookAliveInterval()) + 5) * 1000); |
| 418 | publisher.zlmOnlineEventPublish(serverItem.getId()); | 436 | publisher.zlmOnlineEventPublish(serverItem.getId()); |
| 437 | + | ||
| 419 | logger.info("[ZLM] 连接成功 {} - {}:{} ", | 438 | logger.info("[ZLM] 连接成功 {} - {}:{} ", |
| 420 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); | 439 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
| 421 | } | 440 | } |
| @@ -549,6 +568,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -549,6 +568,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 549 | 568 | ||
| 550 | Map<String, Object> param = new HashMap<>(); | 569 | Map<String, Object> param = new HashMap<>(); |
| 551 | param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline | 570 | param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline |
| 571 | + if (mediaServerItem.getRtspPort() != 0) { | ||
| 572 | + param.put("ffmpeg.snap", "%s -rtsp_transport tcp -i %s -y -f mjpeg -t 0.001 %s"); | ||
| 573 | + } | ||
| 552 | param.put("hook.enable","1"); | 574 | param.put("hook.enable","1"); |
| 553 | param.put("hook.on_flow_report",""); | 575 | param.put("hook.on_flow_report",""); |
| 554 | param.put("hook.on_play",String.format("%s/on_play", hookPrex)); | 576 | param.put("hook.on_play",String.format("%s/on_play", hookPrex)); |
| @@ -583,6 +605,13 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -583,6 +605,13 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 583 | param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); | 605 | param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); |
| 584 | } | 606 | } |
| 585 | 607 | ||
| 608 | + if (userSetting.getRecordPath() != null) { | ||
| 609 | + File recordPathFile = new File(userSetting.getRecordPath()); | ||
| 610 | + File mp4SavePathFile = recordPathFile.getParentFile().getAbsoluteFile(); | ||
| 611 | + param.put("protocol.mp4_save_path", mp4SavePathFile.getAbsoluteFile()); | ||
| 612 | + param.put("record.appName", recordPathFile.getName()); | ||
| 613 | + } | ||
| 614 | + | ||
| 586 | JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); | 615 | JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); |
| 587 | 616 | ||
| 588 | if (responseJSON != null && responseJSON.getInteger("code") == 0) { | 617 | if (responseJSON != null && responseJSON.getInteger("code") == 0) { |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
| 1 | package com.genersoft.iot.vmp.service.impl; | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | ||
| 3 | -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | ||
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | ||
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; | ||
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.TreeType; | 3 | +import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | 4 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 8 | import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | 5 | import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; |
| 9 | import com.genersoft.iot.vmp.service.IPlatformChannelService; | 6 | import com.genersoft.iot.vmp.service.IPlatformChannelService; |
| @@ -15,7 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | @@ -15,7 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | ||
| 15 | import org.slf4j.Logger; | 12 | import org.slf4j.Logger; |
| 16 | import org.slf4j.LoggerFactory; | 13 | import org.slf4j.LoggerFactory; |
| 17 | import org.springframework.beans.factory.annotation.Autowired; | 14 | import org.springframework.beans.factory.annotation.Autowired; |
| 15 | +import org.springframework.jdbc.datasource.DataSourceTransactionManager; | ||
| 18 | import org.springframework.stereotype.Service; | 16 | import org.springframework.stereotype.Service; |
| 17 | +import org.springframework.transaction.TransactionDefinition; | ||
| 18 | +import org.springframework.transaction.TransactionStatus; | ||
| 19 | import org.springframework.util.ObjectUtils; | 19 | import org.springframework.util.ObjectUtils; |
| 20 | 20 | ||
| 21 | import java.util.ArrayList; | 21 | import java.util.ArrayList; |
| @@ -35,6 +35,16 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { | @@ -35,6 +35,16 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { | ||
| 35 | private PlatformChannelMapper platformChannelMapper; | 35 | private PlatformChannelMapper platformChannelMapper; |
| 36 | 36 | ||
| 37 | @Autowired | 37 | @Autowired |
| 38 | + TransactionDefinition transactionDefinition; | ||
| 39 | + | ||
| 40 | + @Autowired | ||
| 41 | + DataSourceTransactionManager dataSourceTransactionManager; | ||
| 42 | + | ||
| 43 | + @Autowired | ||
| 44 | + private SubscribeHolder subscribeHolder; | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + @Autowired | ||
| 38 | private DeviceChannelMapper deviceChannelMapper; | 48 | private DeviceChannelMapper deviceChannelMapper; |
| 39 | 49 | ||
| 40 | @Autowired | 50 | @Autowired |
| @@ -69,17 +79,47 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { | @@ -69,17 +79,47 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { | ||
| 69 | } | 79 | } |
| 70 | List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); | 80 | List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); |
| 71 | // 对剩下的数据进行存储 | 81 | // 对剩下的数据进行存储 |
| 72 | - int result = 0; | 82 | + int allCount = 0; |
| 83 | + boolean result = false; | ||
| 84 | + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); | ||
| 85 | + int limitCount = 300; | ||
| 73 | if (channelReducesToAdd.size() > 0) { | 86 | if (channelReducesToAdd.size() > 0) { |
| 74 | - result = platformChannelMapper.addChannels(platformId, channelReducesToAdd); | ||
| 75 | - // TODO 后续给平台增加控制开关以控制是否响应目录订阅 | ||
| 76 | - List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform); | ||
| 77 | - if (deviceChannelList != null) { | ||
| 78 | - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); | 87 | + if (channelReducesToAdd.size() > limitCount) { |
| 88 | + for (int i = 0; i < channelReducesToAdd.size(); i += limitCount) { | ||
| 89 | + int toIndex = i + limitCount; | ||
| 90 | + if (i + limitCount > channelReducesToAdd.size()) { | ||
| 91 | + toIndex = channelReducesToAdd.size(); | ||
| 92 | + } | ||
| 93 | + int count = platformChannelMapper.addChannels(platformId, channelReducesToAdd.subList(i, toIndex)); | ||
| 94 | + result = result || count < 0; | ||
| 95 | + allCount += count; | ||
| 96 | + logger.info("[关联通道]国标通道 平台:{}, 共需关联通道数:{}, 已关联:{}", platformId, channelReducesToAdd.size(), toIndex); | ||
| 97 | + } | ||
| 98 | + }else { | ||
| 99 | + allCount = platformChannelMapper.addChannels(platformId, channelReducesToAdd); | ||
| 100 | + result = result || allCount < 0; | ||
| 101 | + logger.info("[关联通道]国标通道 平台:{}, 关联通道数:{}", platformId, channelReducesToAdd.size()); | ||
| 79 | } | 102 | } |
| 80 | - } | ||
| 81 | 103 | ||
| 82 | - return result; | 104 | + if (result) { |
| 105 | + //事务回滚 | ||
| 106 | + dataSourceTransactionManager.rollback(transactionStatus); | ||
| 107 | + allCount = 0; | ||
| 108 | + }else { | ||
| 109 | + logger.info("[关联通道]国标通道 平台:{}, 正在存入数据库", platformId); | ||
| 110 | + dataSourceTransactionManager.commit(transactionStatus); | ||
| 111 | + | ||
| 112 | + } | ||
| 113 | + SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(platformId); | ||
| 114 | + if (catalogSubscribe != null) { | ||
| 115 | + List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform); | ||
| 116 | + if (deviceChannelList != null) { | ||
| 117 | + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); | ||
| 118 | + } | ||
| 119 | + } | ||
| 120 | + logger.info("[关联通道]国标通道 平台:{}, 存入数据库成功", platformId); | ||
| 121 | + } | ||
| 122 | + return allCount; | ||
| 83 | } | 123 | } |
| 84 | 124 | ||
| 85 | private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) { | 125 | private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) { |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
| @@ -21,8 +21,8 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | @@ -21,8 +21,8 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | ||
| 21 | import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; | 21 | import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; |
| 22 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; | 22 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 23 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 23 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 24 | -import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; | ||
| 25 | -import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; | 24 | +import com.genersoft.iot.vmp.storager.dao.*; |
| 25 | +import com.genersoft.iot.vmp.utils.DateUtil; | ||
| 26 | import com.github.pagehelper.PageHelper; | 26 | import com.github.pagehelper.PageHelper; |
| 27 | import com.github.pagehelper.PageInfo; | 27 | import com.github.pagehelper.PageInfo; |
| 28 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
| @@ -54,6 +54,15 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -54,6 +54,15 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 54 | private ParentPlatformMapper platformMapper; | 54 | private ParentPlatformMapper platformMapper; |
| 55 | 55 | ||
| 56 | @Autowired | 56 | @Autowired |
| 57 | + private PlatformCatalogMapper catalogMapper; | ||
| 58 | + | ||
| 59 | + @Autowired | ||
| 60 | + private PlatformChannelMapper platformChannelMapper; | ||
| 61 | + | ||
| 62 | + @Autowired | ||
| 63 | + private PlatformGbStreamMapper platformGbStreamMapper; | ||
| 64 | + | ||
| 65 | + @Autowired | ||
| 57 | private IRedisCatchStorage redisCatchStorage; | 66 | private IRedisCatchStorage redisCatchStorage; |
| 58 | 67 | ||
| 59 | @Autowired | 68 | @Autowired |
| @@ -135,36 +144,106 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -135,36 +144,106 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 135 | } | 144 | } |
| 136 | 145 | ||
| 137 | @Override | 146 | @Override |
| 138 | - public void online(ParentPlatform parentPlatform) { | ||
| 139 | - logger.info("[国标级联]:{}, 平台上线/更新注册", parentPlatform.getServerGBId()); | 147 | + public boolean update(ParentPlatform parentPlatform) { |
| 148 | + logger.info("[国标级联]更新平台 {}", parentPlatform.getDeviceGBId()); | ||
| 149 | + parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase()); | ||
| 150 | + ParentPlatform parentPlatformOld = platformMapper.getParentPlatById(parentPlatform.getId()); | ||
| 151 | + ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatformOld.getServerGBId()); | ||
| 152 | + parentPlatform.setUpdateTime(DateUtil.getNow()); | ||
| 153 | + if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) { | ||
| 154 | + // 目录结构发生变化,清空之前的关联关系 | ||
| 155 | + logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId()); | ||
| 156 | + catalogMapper.delByPlatformId(parentPlatformOld.getServerGBId()); | ||
| 157 | + platformChannelMapper.delByPlatformId(parentPlatformOld.getServerGBId()); | ||
| 158 | + platformGbStreamMapper.delByPlatformId(parentPlatformOld.getServerGBId()); | ||
| 159 | + } | ||
| 160 | + | ||
| 161 | + | ||
| 162 | + // 停止心跳定时 | ||
| 163 | + final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatformOld.getServerGBId(); | ||
| 164 | + dynamicTask.stop(keepaliveTaskKey); | ||
| 165 | + // 停止注册定时 | ||
| 166 | + final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatformOld.getServerGBId(); | ||
| 167 | + dynamicTask.stop(registerTaskKey); | ||
| 168 | + // 注销旧的 | ||
| 169 | + try { | ||
| 170 | + if (parentPlatformOld.isStatus()) { | ||
| 171 | + logger.info("保存平台{}时发现救平台在线,发送注销命令", parentPlatform.getDeviceGBId()); | ||
| 172 | + commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> { | ||
| 173 | + logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId()); | ||
| 174 | + }); | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 178 | + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + // 更新数据库 | ||
| 182 | + if (parentPlatform.getCatalogGroup() == 0) { | ||
| 183 | + parentPlatform.setCatalogGroup(1); | ||
| 184 | + } | ||
| 185 | + if (parentPlatform.getAdministrativeDivision() == null) { | ||
| 186 | + parentPlatform.setAdministrativeDivision(parentPlatform.getAdministrativeDivision()); | ||
| 187 | + } | ||
| 188 | + | ||
| 189 | + platformMapper.updateParentPlatform(parentPlatform); | ||
| 190 | + // 更新redis | ||
| 191 | + redisCatchStorage.delPlatformCatchInfo(parentPlatformOld.getServerGBId()); | ||
| 192 | + ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); | ||
| 193 | + parentPlatformCatch.setParentPlatform(parentPlatform); | ||
| 194 | + parentPlatformCatch.setId(parentPlatform.getServerGBId()); | ||
| 195 | + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | ||
| 196 | + // 注册 | ||
| 197 | + if (parentPlatform.isEnable()) { | ||
| 198 | + // 保存时启用就发送注册 | ||
| 199 | + // 注册成功时由程序直接调用了online方法 | ||
| 200 | + try { | ||
| 201 | + commanderForPlatform.register(parentPlatform, eventResult -> { | ||
| 202 | + logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId()); | ||
| 203 | + }, null); | ||
| 204 | + } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 205 | + logger.error("[命令发送失败] 国标级联: {}", e.getMessage()); | ||
| 206 | + } | ||
| 207 | + } | ||
| 208 | + // 重新开启定时注册, 使用续订消息 | ||
| 209 | + // 重新开始心跳保活 | ||
| 210 | + | ||
| 211 | + | ||
| 212 | + return false; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + | ||
| 216 | + @Override | ||
| 217 | + public void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo) { | ||
| 218 | + logger.info("[国标级联]:{}, 平台上线", parentPlatform.getServerGBId()); | ||
| 140 | platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true); | 219 | platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true); |
| 141 | ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); | 220 | ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); |
| 142 | - if (parentPlatformCatch != null) { | ||
| 143 | - parentPlatformCatch.getParentPlatform().setStatus(true); | ||
| 144 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | ||
| 145 | - }else { | 221 | + if (parentPlatformCatch == null) { |
| 146 | parentPlatformCatch = new ParentPlatformCatch(); | 222 | parentPlatformCatch = new ParentPlatformCatch(); |
| 147 | parentPlatformCatch.setParentPlatform(parentPlatform); | 223 | parentPlatformCatch.setParentPlatform(parentPlatform); |
| 148 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); | 224 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); |
| 149 | parentPlatform.setStatus(true); | 225 | parentPlatform.setStatus(true); |
| 150 | parentPlatformCatch.setParentPlatform(parentPlatform); | 226 | parentPlatformCatch.setParentPlatform(parentPlatform); |
| 151 | - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | ||
| 152 | } | 227 | } |
| 153 | 228 | ||
| 229 | + parentPlatformCatch.getParentPlatform().setStatus(true); | ||
| 230 | + parentPlatformCatch.setSipTransactionInfo(sipTransactionInfo); | ||
| 231 | + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); | ||
| 232 | + | ||
| 154 | final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); | 233 | final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); |
| 155 | if (!dynamicTask.isAlive(registerTaskKey)) { | 234 | if (!dynamicTask.isAlive(registerTaskKey)) { |
| 235 | + logger.info("[国标级联]:{}, 添加定时注册任务", parentPlatform.getServerGBId()); | ||
| 156 | // 添加注册任务 | 236 | // 添加注册任务 |
| 157 | dynamicTask.startCron(registerTaskKey, | 237 | dynamicTask.startCron(registerTaskKey, |
| 158 | // 注册失败(注册成功时由程序直接调用了online方法) | 238 | // 注册失败(注册成功时由程序直接调用了online方法) |
| 159 | - ()-> { | ||
| 160 | - registerTask(parentPlatform); | ||
| 161 | - }, | ||
| 162 | - (parentPlatform.getExpires() - 10) *1000); | 239 | + ()-> registerTask(parentPlatform, sipTransactionInfo), |
| 240 | + parentPlatform.getExpires() * 1000); | ||
| 163 | } | 241 | } |
| 164 | 242 | ||
| 165 | 243 | ||
| 166 | final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); | 244 | final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); |
| 167 | if (!dynamicTask.contains(keepaliveTaskKey)) { | 245 | if (!dynamicTask.contains(keepaliveTaskKey)) { |
| 246 | + logger.info("[国标级联]:{}, 添加定时心跳任务", parentPlatform.getServerGBId()); | ||
| 168 | // 添加心跳任务 | 247 | // 添加心跳任务 |
| 169 | dynamicTask.startCron(keepaliveTaskKey, | 248 | dynamicTask.startCron(keepaliveTaskKey, |
| 170 | ()-> { | 249 | ()-> { |
| @@ -205,11 +284,11 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -205,11 +284,11 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 205 | logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage()); | 284 | logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage()); |
| 206 | } | 285 | } |
| 207 | }, | 286 | }, |
| 208 | - (parentPlatform.getKeepTimeout() - 10)*1000); | 287 | + (parentPlatform.getKeepTimeout())*1000); |
| 209 | } | 288 | } |
| 210 | } | 289 | } |
| 211 | 290 | ||
| 212 | - private void registerTask(ParentPlatform parentPlatform){ | 291 | + private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){ |
| 213 | try { | 292 | try { |
| 214 | // 设置超时重发, 后续从底层支持消息重发 | 293 | // 设置超时重发, 后续从底层支持消息重发 |
| 215 | String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout"; | 294 | String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout"; |
| @@ -217,10 +296,10 @@ public class PlatformServiceImpl implements IPlatformService { | @@ -217,10 +296,10 @@ public class PlatformServiceImpl implements IPlatformService { | ||
| 217 | return; | 296 | return; |
| 218 | } | 297 | } |
| 219 | dynamicTask.startDelay(key, ()->{ | 298 | dynamicTask.startDelay(key, ()->{ |
| 220 | - registerTask(parentPlatform); | 299 | + registerTask(parentPlatform, sipTransactionInfo); |
| 221 | }, 1000); | 300 | }, 1000); |
| 222 | - logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId()); | ||
| 223 | - commanderForPlatform.register(parentPlatform, eventResult -> { | 301 | + logger.info("[国标级联] 平台:{}注册即将到期,开始续订", parentPlatform.getServerGBId()); |
| 302 | + commanderForPlatform.register(parentPlatform, sipTransactionInfo, eventResult -> { | ||
| 224 | dynamicTask.stop(key); | 303 | dynamicTask.stop(key); |
| 225 | offline(parentPlatform, false); | 304 | offline(parentPlatform, false); |
| 226 | },eventResult -> { | 305 | },eventResult -> { |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| @@ -438,7 +438,12 @@ public class PlayServiceImpl implements IPlayService { | @@ -438,7 +438,12 @@ public class PlayServiceImpl implements IPlayService { | ||
| 438 | onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); | 438 | onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); |
| 439 | hookEvent.response(mediaServerItemInuse, response); | 439 | hookEvent.response(mediaServerItemInuse, response); |
| 440 | logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); | 440 | logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); |
| 441 | - String streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.flv", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); | 441 | + String streamUrl; |
| 442 | + if (mediaServerItemInuse.getRtspPort() != 0) { | ||
| 443 | + streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream()); | ||
| 444 | + }else { | ||
| 445 | + streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); | ||
| 446 | + } | ||
| 442 | String path = "snap"; | 447 | String path = "snap"; |
| 443 | String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; | 448 | String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; |
| 444 | // 请求截图 | 449 | // 请求截图 |
| @@ -806,23 +811,75 @@ public class PlayServiceImpl implements IPlayService { | @@ -806,23 +811,75 @@ public class PlayServiceImpl implements IPlayService { | ||
| 806 | hookCallBack.call(downloadResult); | 811 | hookCallBack.call(downloadResult); |
| 807 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | 812 | streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); |
| 808 | }; | 813 | }; |
| 809 | - | 814 | + InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> { |
| 815 | + logger.info("收到订阅消息: " + inviteStreamInfo.getCallId()); | ||
| 816 | + dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 817 | + StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); | ||
| 818 | + streamInfo.setStartTime(startTime); | ||
| 819 | + streamInfo.setEndTime(endTime); | ||
| 820 | + redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); | ||
| 821 | + downloadResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 822 | + downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 823 | + downloadResult.setData(streamInfo); | ||
| 824 | + downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); | ||
| 825 | + downloadResult.setResponse(inviteStreamInfo.getResponse()); | ||
| 826 | + hookCallBack.call(downloadResult); | ||
| 827 | + }; | ||
| 810 | try { | 828 | try { |
| 811 | cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, | 829 | cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, |
| 812 | - inviteStreamInfo -> { | ||
| 813 | - logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); | ||
| 814 | - dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 815 | - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); | ||
| 816 | - streamInfo.setStartTime(startTime); | ||
| 817 | - streamInfo.setEndTime(endTime); | ||
| 818 | - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); | ||
| 819 | - downloadResult.setCode(ErrorCode.SUCCESS.getCode()); | ||
| 820 | - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); | ||
| 821 | - downloadResult.setData(streamInfo); | ||
| 822 | - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); | ||
| 823 | - downloadResult.setResponse(inviteStreamInfo.getResponse()); | ||
| 824 | - hookCallBack.call(downloadResult); | ||
| 825 | - }, errorEvent); | 830 | + hookEvent, errorEvent, eventResult -> |
| 831 | + { | ||
| 832 | + if (eventResult.type == SipSubscribe.EventResultType.response) { | ||
| 833 | + ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | ||
| 834 | + String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
| 835 | + // 获取ssrc | ||
| 836 | + int ssrcIndex = contentString.indexOf("y="); | ||
| 837 | + // 检查是否有y字段 | ||
| 838 | + if (ssrcIndex >= 0) { | ||
| 839 | + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | ||
| 840 | + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | ||
| 841 | + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | ||
| 842 | + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | ||
| 843 | + return; | ||
| 844 | + } | ||
| 845 | + logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | ||
| 846 | + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | ||
| 847 | + logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | ||
| 848 | + | ||
| 849 | + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | ||
| 850 | + // ssrc 不可用 | ||
| 851 | + // 释放ssrc | ||
| 852 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | ||
| 853 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | ||
| 854 | + eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用"; | ||
| 855 | + eventResult.statusCode = 400; | ||
| 856 | + errorEvent.response(eventResult); | ||
| 857 | + return; | ||
| 858 | + } | ||
| 859 | + | ||
| 860 | + // 单端口模式streamId也有变化,需要重新设置监听 | ||
| 861 | + if (!mediaServerItem.isRtpEnable()) { | ||
| 862 | + // 添加订阅 | ||
| 863 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | ||
| 864 | + subscribe.removeSubscribe(hookSubscribe); | ||
| 865 | + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | ||
| 866 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | ||
| 867 | + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | ||
| 868 | + dynamicTask.stop(downLoadTimeOutTaskKey); | ||
| 869 | + // hook响应 | ||
| 870 | + onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, hookCallBack); | ||
| 871 | + hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); | ||
| 872 | + }); | ||
| 873 | + } | ||
| 874 | + // 关闭rtp server | ||
| 875 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | ||
| 876 | + // 重新开启ssrc server | ||
| 877 | + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort()); | ||
| 878 | + } | ||
| 879 | + } | ||
| 880 | + } | ||
| 881 | + | ||
| 882 | + }); | ||
| 826 | } catch (InvalidArgumentException | SipException | ParseException e) { | 883 | } catch (InvalidArgumentException | SipException | ParseException e) { |
| 827 | logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); | 884 | logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); |
| 828 | 885 |
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
| @@ -201,7 +201,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { | @@ -201,7 +201,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { | ||
| 201 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 | 201 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 |
| 202 | result = true; | 202 | result = true; |
| 203 | }catch (Exception e) { | 203 | }catch (Exception e) { |
| 204 | - e.printStackTrace(); | 204 | + logger.error("未处理的异常 ", e); |
| 205 | dataSourceTransactionManager.rollback(transactionStatus); | 205 | dataSourceTransactionManager.rollback(transactionStatus); |
| 206 | } | 206 | } |
| 207 | return result; | 207 | return result; |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java
| 1 | package com.genersoft.iot.vmp.service.redisMsg; | 1 | package com.genersoft.iot.vmp.service.redisMsg; |
| 2 | 2 | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 4 | import com.genersoft.iot.vmp.gb28181.bean.*; | 5 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| @@ -44,13 +45,17 @@ public class RedisAlarmMsgListener implements MessageListener { | @@ -44,13 +45,17 @@ public class RedisAlarmMsgListener implements MessageListener { | ||
| 44 | @Autowired | 45 | @Autowired |
| 45 | private ThreadPoolTaskExecutor taskExecutor; | 46 | private ThreadPoolTaskExecutor taskExecutor; |
| 46 | 47 | ||
| 48 | + @Autowired | ||
| 49 | + private UserSetting userSetting; | ||
| 50 | + | ||
| 47 | @Override | 51 | @Override |
| 48 | public void onMessage(@NotNull Message message, byte[] bytes) { | 52 | public void onMessage(@NotNull Message message, byte[] bytes) { |
| 53 | + // 消息示例: PUBLISH alarm_receive '{ "gbId": "", "alarmSn": 1, "alarmType": "111", "alarmDescription": "222", }' | ||
| 49 | logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); | 54 | logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); |
| 50 | boolean isEmpty = taskQueue.isEmpty(); | 55 | boolean isEmpty = taskQueue.isEmpty(); |
| 51 | taskQueue.offer(message); | 56 | taskQueue.offer(message); |
| 52 | if (isEmpty) { | 57 | if (isEmpty) { |
| 53 | - logger.info("[线程池信息]活动线程数:{}, 最大线程数: {}", taskExecutor.getActiveCount(), taskExecutor.getMaxPoolSize()); | 58 | +// logger.info("[线程池信息]活动线程数:{}, 最大线程数: {}", taskExecutor.getActiveCount(), taskExecutor.getMaxPoolSize()); |
| 54 | taskExecutor.execute(() -> { | 59 | taskExecutor.execute(() -> { |
| 55 | while (!taskQueue.isEmpty()) { | 60 | while (!taskQueue.isEmpty()) { |
| 56 | Message msg = taskQueue.poll(); | 61 | Message msg = taskQueue.poll(); |
| @@ -69,22 +74,52 @@ public class RedisAlarmMsgListener implements MessageListener { | @@ -69,22 +74,52 @@ public class RedisAlarmMsgListener implements MessageListener { | ||
| 69 | deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); | 74 | deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); |
| 70 | deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType()); | 75 | deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType()); |
| 71 | deviceAlarm.setAlarmPriority("1"); | 76 | deviceAlarm.setAlarmPriority("1"); |
| 72 | - deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); | 77 | + deviceAlarm.setAlarmTime(DateUtil.getNow()); |
| 73 | deviceAlarm.setLongitude(0); | 78 | deviceAlarm.setLongitude(0); |
| 74 | deviceAlarm.setLatitude(0); | 79 | deviceAlarm.setLatitude(0); |
| 75 | 80 | ||
| 76 | if (ObjectUtils.isEmpty(gbId)) { | 81 | if (ObjectUtils.isEmpty(gbId)) { |
| 77 | - // 发送给所有的上级 | ||
| 78 | - List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); | ||
| 79 | - if (parentPlatforms.size() > 0) { | ||
| 80 | - for (ParentPlatform parentPlatform : parentPlatforms) { | 82 | + if (userSetting.getSendToPlatformsWhenIdLost()) { |
| 83 | + // 发送给所有的上级 | ||
| 84 | + List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); | ||
| 85 | + if (parentPlatforms.size() > 0) { | ||
| 86 | + for (ParentPlatform parentPlatform : parentPlatforms) { | ||
| 87 | + try { | ||
| 88 | + deviceAlarm.setChannelId(parentPlatform.getDeviceGBId()); | ||
| 89 | + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); | ||
| 90 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 91 | + logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage()); | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + }else { | ||
| 96 | + // 获取开启了消息推送的设备和平台 | ||
| 97 | + List<ParentPlatform> parentPlatforms = storage.queryEnablePlatformListWithAsMessageChannel(); | ||
| 98 | + if (parentPlatforms.size() > 0) { | ||
| 99 | + for (ParentPlatform parentPlatform : parentPlatforms) { | ||
| 100 | + try { | ||
| 101 | + deviceAlarm.setChannelId(parentPlatform.getDeviceGBId()); | ||
| 102 | + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); | ||
| 103 | + } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 104 | + logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage()); | ||
| 105 | + } | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | + } | ||
| 110 | + // 获取开启了消息推送的设备和平台 | ||
| 111 | + List<Device> devices = storage.queryDeviceWithAsMessageChannel(); | ||
| 112 | + if (devices.size() > 0) { | ||
| 113 | + for (Device device : devices) { | ||
| 81 | try { | 114 | try { |
| 82 | - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); | ||
| 83 | - } catch (SipException | InvalidArgumentException | ParseException e) { | ||
| 84 | - logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage()); | 115 | + deviceAlarm.setChannelId(device.getDeviceId()); |
| 116 | + commander.sendAlarmMessage(device, deviceAlarm); | ||
| 117 | + } catch (InvalidArgumentException | SipException | ParseException e) { | ||
| 118 | + logger.error("[命令发送失败] 发送报警: {}", e.getMessage()); | ||
| 85 | } | 119 | } |
| 86 | } | 120 | } |
| 87 | } | 121 | } |
| 122 | + | ||
| 88 | }else { | 123 | }else { |
| 89 | Device device = storage.queryVideoDevice(gbId); | 124 | Device device = storage.queryVideoDevice(gbId); |
| 90 | ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); | 125 | ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); |
| @@ -105,6 +140,7 @@ public class RedisAlarmMsgListener implements MessageListener { | @@ -105,6 +140,7 @@ public class RedisAlarmMsgListener implements MessageListener { | ||
| 105 | } | 140 | } |
| 106 | } | 141 | } |
| 107 | }catch (Exception e) { | 142 | }catch (Exception e) { |
| 143 | + logger.error("未处理的异常 ", e); | ||
| 108 | logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); | 144 | logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); |
| 109 | } | 145 | } |
| 110 | } | 146 | } |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
| @@ -202,7 +202,8 @@ public class RedisGbPlayMsgListener implements MessageListener { | @@ -202,7 +202,8 @@ public class RedisGbPlayMsgListener implements MessageListener { | ||
| 202 | 202 | ||
| 203 | } | 203 | } |
| 204 | }catch (Exception e) { | 204 | }catch (Exception e) { |
| 205 | - logger.warn("[RedisGbPlayMsg] 发现未处理的异常, {}",e.getMessage()); | 205 | + logger.warn("[RedisGbPlayMsg] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); |
| 206 | + logger.error("[RedisGbPlayMsg] 异常内容: ", e); | ||
| 206 | } | 207 | } |
| 207 | } | 208 | } |
| 208 | }); | 209 | }); |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java
| @@ -53,7 +53,8 @@ public class RedisGpsMsgListener implements MessageListener { | @@ -53,7 +53,8 @@ public class RedisGpsMsgListener implements MessageListener { | ||
| 53 | // 只是放入redis缓存起来 | 53 | // 只是放入redis缓存起来 |
| 54 | redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); | 54 | redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); |
| 55 | }catch (Exception e) { | 55 | }catch (Exception e) { |
| 56 | - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); | 56 | + logger.warn("[REDIS的ALARM通知] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); |
| 57 | + logger.error("[REDIS的ALARM通知] 异常内容: ", e); | ||
| 57 | } | 58 | } |
| 58 | } | 59 | } |
| 59 | }); | 60 | }); |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java
| @@ -58,7 +58,8 @@ public class RedisPushStreamResponseListener implements MessageListener { | @@ -58,7 +58,8 @@ public class RedisPushStreamResponseListener implements MessageListener { | ||
| 58 | responseEvents.get(response.getApp() + response.getStream()).run(response); | 58 | responseEvents.get(response.getApp() + response.getStream()).run(response); |
| 59 | } | 59 | } |
| 60 | }catch (Exception e) { | 60 | }catch (Exception e) { |
| 61 | - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); | 61 | + logger.warn("[REDIS消息-请求推流结果] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); |
| 62 | + logger.error("[REDIS消息-请求推流结果] 异常内容: ", e); | ||
| 62 | } | 63 | } |
| 63 | } | 64 | } |
| 64 | }); | 65 | }); |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java
| @@ -95,7 +95,8 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { | @@ -95,7 +95,8 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { | ||
| 95 | gbStreamService.updateGbIdOrName(streamPushItemForUpdate); | 95 | gbStreamService.updateGbIdOrName(streamPushItemForUpdate); |
| 96 | } | 96 | } |
| 97 | }catch (Exception e) { | 97 | }catch (Exception e) { |
| 98 | - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); | 98 | + logger.warn("[REDIS消息-推流设备列表更新] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); |
| 99 | + logger.error("[REDIS消息-推流设备列表更新] 异常内容: ", e); | ||
| 99 | } | 100 | } |
| 100 | } | 101 | } |
| 101 | }); | 102 | }); |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java
| @@ -79,7 +79,8 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic | @@ -79,7 +79,8 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic | ||
| 79 | streamPushService.online(statusChangeFromPushStream.getOnlineStreams()); | 79 | streamPushService.online(statusChangeFromPushStream.getOnlineStreams()); |
| 80 | } | 80 | } |
| 81 | }catch (Exception e) { | 81 | }catch (Exception e) { |
| 82 | - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); | 82 | + logger.warn("[REDIS消息-推流设备状态变化] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); |
| 83 | + logger.error("[REDIS消息-推流设备状态变化] 异常内容: ", e); | ||
| 83 | } | 84 | } |
| 84 | } | 85 | } |
| 85 | }); | 86 | }); |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java
| @@ -82,7 +82,8 @@ public class RedisStreamMsgListener implements MessageListener { | @@ -82,7 +82,8 @@ public class RedisStreamMsgListener implements MessageListener { | ||
| 82 | zlmMediaListManager.removeMedia(app, stream); | 82 | zlmMediaListManager.removeMedia(app, stream); |
| 83 | } | 83 | } |
| 84 | }catch (Exception e) { | 84 | }catch (Exception e) { |
| 85 | - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); | 85 | + logger.warn("[REDIS消息-流变化] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); |
| 86 | + logger.error("[REDIS消息-流变化] 异常内容: ", e); | ||
| 86 | } | 87 | } |
| 87 | } | 88 | } |
| 88 | }); | 89 | }); |
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
| @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | ||
| 5 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | 5 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 6 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; | 6 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; |
| 7 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | 7 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 8 | +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; | ||
| 8 | import com.github.pagehelper.PageInfo; | 9 | import com.github.pagehelper.PageInfo; |
| 9 | 10 | ||
| 10 | import java.util.List; | 11 | import java.util.List; |
| @@ -58,7 +59,7 @@ public interface IVideoManagerStorage { | @@ -58,7 +59,7 @@ public interface IVideoManagerStorage { | ||
| 58 | */ | 59 | */ |
| 59 | public PageInfo<DeviceChannel> queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count); | 60 | public PageInfo<DeviceChannel> queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count); |
| 60 | 61 | ||
| 61 | - public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds); | 62 | + public List<DeviceChannelExtend> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, List<String> channelIds, String query, Boolean hasSubChannel, Boolean online, int start, int limit); |
| 62 | 63 | ||
| 63 | 64 | ||
| 64 | /** | 65 | /** |
| @@ -374,4 +375,10 @@ public interface IVideoManagerStorage { | @@ -374,4 +375,10 @@ public interface IVideoManagerStorage { | ||
| 374 | void cleanContentForPlatform(String serverGBId); | 375 | void cleanContentForPlatform(String serverGBId); |
| 375 | 376 | ||
| 376 | List<DeviceChannel> queryChannelWithCatalog(String serverGBId); | 377 | List<DeviceChannel> queryChannelWithCatalog(String serverGBId); |
| 378 | + | ||
| 379 | + List<DeviceChannelExtend> queryChannelsByDeviceId(String serial, List<String> channelIds, Boolean online); | ||
| 380 | + | ||
| 381 | + List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel(); | ||
| 382 | + | ||
| 383 | + List<Device> queryDeviceWithAsMessageChannel(); | ||
| 377 | } | 384 | } |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
| @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; | 5 | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; |
| 6 | import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; | 6 | import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; |
| 7 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | 7 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 8 | +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; | ||
| 8 | import org.apache.ibatis.annotations.*; | 9 | import org.apache.ibatis.annotations.*; |
| 9 | import org.springframework.stereotype.Repository; | 10 | import org.springframework.stereotype.Repository; |
| 10 | 11 | ||
| @@ -82,7 +83,56 @@ public interface DeviceChannelMapper { | @@ -82,7 +83,56 @@ public interface DeviceChannelMapper { | ||
| 82 | "</foreach> </if>" + | 83 | "</foreach> </if>" + |
| 83 | "ORDER BY dc.channelId " + | 84 | "ORDER BY dc.channelId " + |
| 84 | " </script>"}) | 85 | " </script>"}) |
| 85 | - List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online,List<String> channelIds); | 86 | + List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, List<String> channelIds); |
| 87 | + | ||
| 88 | + @Select(value = {" <script>" + | ||
| 89 | + "SELECT " + | ||
| 90 | + "dc.*, " + | ||
| 91 | + "de.name as deviceName, " + | ||
| 92 | + "de.online as deviceOnline " + | ||
| 93 | + "from " + | ||
| 94 | + "device_channel dc " + | ||
| 95 | + "LEFT JOIN device de ON dc.deviceId = de.deviceId " + | ||
| 96 | + "WHERE 1=1" + | ||
| 97 | + " <if test='deviceId != null'> AND dc.deviceId = #{deviceId} </if> " + | ||
| 98 | + " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " + | ||
| 99 | + " <if test='parentChannelId != null'> AND dc.parentId=#{parentChannelId} </if> " + | ||
| 100 | + " <if test='online == true' > AND dc.status=1</if>" + | ||
| 101 | + " <if test='online == false' > AND dc.status=0</if>" + | ||
| 102 | + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" + | ||
| 103 | + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" + | ||
| 104 | + "<if test='channelIds != null'> AND dc.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" + | ||
| 105 | + "#{item} " + | ||
| 106 | + "</foreach> </if>" + | ||
| 107 | + "ORDER BY dc.channelId ASC" + | ||
| 108 | + " </script>"}) | ||
| 109 | + List<DeviceChannelExtend> queryChannelsWithDeviceInfo(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, List<String> channelIds); | ||
| 110 | + | ||
| 111 | + | ||
| 112 | + @Select(value = {" <script>" + | ||
| 113 | + "SELECT " + | ||
| 114 | + "dc.*, " + | ||
| 115 | + "de.name as deviceName, " + | ||
| 116 | + "de.online as deviceOnline " + | ||
| 117 | + "from " + | ||
| 118 | + "device_channel dc " + | ||
| 119 | + "LEFT JOIN device de ON dc.deviceId = de.deviceId " + | ||
| 120 | + "WHERE 1=1" + | ||
| 121 | + " <if test='deviceId != null'> AND dc.deviceId = #{deviceId} </if> " + | ||
| 122 | + " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " + | ||
| 123 | + " <if test='parentChannelId != null'> AND dc.parentId=#{parentChannelId} </if> " + | ||
| 124 | + " <if test='online == true' > AND dc.status=1</if>" + | ||
| 125 | + " <if test='online == false' > AND dc.status=0</if>" + | ||
| 126 | + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" + | ||
| 127 | + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" + | ||
| 128 | + "<if test='channelIds != null'> AND dc.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" + | ||
| 129 | + "#{item} " + | ||
| 130 | + "</foreach> </if>" + | ||
| 131 | + "ORDER BY dc.channelId ASC " + | ||
| 132 | + "Limit #{limit} OFFSET #{start}" + | ||
| 133 | + " </script>"}) | ||
| 134 | + List<DeviceChannelExtend> queryChannelsByDeviceIdWithStartAndLimit(String deviceId,List<String> channelIds, String parentChannelId, String query, | ||
| 135 | + Boolean hasSubChannel, Boolean online, int start, int limit); | ||
| 86 | 136 | ||
| 87 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") | 137 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") |
| 88 | DeviceChannel queryChannel(String deviceId, String channelId); | 138 | DeviceChannel queryChannel(String deviceId, String channelId); |
| @@ -245,28 +295,6 @@ public interface DeviceChannelMapper { | @@ -245,28 +295,6 @@ public interface DeviceChannelMapper { | ||
| 245 | int batchUpdate(List<DeviceChannel> updateChannels); | 295 | int batchUpdate(List<DeviceChannel> updateChannels); |
| 246 | 296 | ||
| 247 | 297 | ||
| 248 | - @Select(value = {" <script>" + | ||
| 249 | - "SELECT " + | ||
| 250 | - "dc1.* " + | ||
| 251 | - "from " + | ||
| 252 | - "device_channel dc1 " + | ||
| 253 | - "WHERE " + | ||
| 254 | - "dc1.deviceId = #{deviceId} " + | ||
| 255 | - " <if test='query != null'> AND (dc1.channelId LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%'))</if> " + | ||
| 256 | - " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " + | ||
| 257 | - " <if test='online == true' > AND dc1.status=1</if>" + | ||
| 258 | - " <if test='online == false' > AND dc1.status=0</if>" + | ||
| 259 | - " <if test='hasSubChannel == true' > AND dc1.subCount >0</if>" + | ||
| 260 | - " <if test='hasSubChannel == false' > AND dc1.subCount=0</if>" + | ||
| 261 | - "<if test='channelIds != null'> AND dc1.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" + | ||
| 262 | - "#{item} " + | ||
| 263 | - "</foreach> </if>" + | ||
| 264 | - "ORDER BY dc1.channelId ASC " + | ||
| 265 | - "Limit #{limit} OFFSET #{start}" + | ||
| 266 | - " </script>"}) | ||
| 267 | - List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String parentChannelId, String query, | ||
| 268 | - Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds); | ||
| 269 | - | ||
| 270 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") | 298 | @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") |
| 271 | List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); | 299 | List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); |
| 272 | 300 | ||
| @@ -316,10 +344,10 @@ public interface DeviceChannelMapper { | @@ -316,10 +344,10 @@ public interface DeviceChannelMapper { | ||
| 316 | "select * " + | 344 | "select * " + |
| 317 | "from device_channel " + | 345 | "from device_channel " + |
| 318 | "where deviceId=#{deviceId}" + | 346 | "where deviceId=#{deviceId}" + |
| 319 | - " <if test='parentId != null and length != null' > and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} and length(channelId)=#{length} </if>" + | 347 | + " <if test='parentId != null and length != null' > and parentId = #{parentId} or left(channelId, LENGTH(#{parentId})) = #{parentId} and length(channelId)=#{length} </if>" + |
| 320 | " <if test='parentId == null and length != null' > and parentId = #{parentId} or length(channelId)=#{length} </if>" + | 348 | " <if test='parentId == null and length != null' > and parentId = #{parentId} or length(channelId)=#{length} </if>" + |
| 321 | " <if test='parentId == null and length == null' > and parentId = #{parentId} </if>" + | 349 | " <if test='parentId == null and length == null' > and parentId = #{parentId} </if>" + |
| 322 | - " <if test='parentId != null and length == null' > and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} </if>" + | 350 | + " <if test='parentId != null and length == null' > and parentId = #{parentId} or left(channelId, LENGTH(#{parentId})) = #{parentId} </if>" + |
| 323 | " </script>"}) | 351 | " </script>"}) |
| 324 | List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length); | 352 | List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length); |
| 325 | 353 |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
| @@ -39,9 +39,12 @@ public interface DeviceMapper { | @@ -39,9 +39,12 @@ public interface DeviceMapper { | ||
| 39 | "mobilePositionSubmissionInterval," + | 39 | "mobilePositionSubmissionInterval," + |
| 40 | "subscribeCycleForAlarm," + | 40 | "subscribeCycleForAlarm," + |
| 41 | "ssrcCheck," + | 41 | "ssrcCheck," + |
| 42 | + "asMessageChannel," + | ||
| 42 | "geoCoordSys," + | 43 | "geoCoordSys," + |
| 43 | "treeType," + | 44 | "treeType," + |
| 44 | - "online" + | 45 | + "online," + |
| 46 | + "mediaServerId," + | ||
| 47 | + "(SELECT count(0) FROM device_channel WHERE deviceId=device.deviceId) as channelCount "+ | ||
| 45 | " FROM device WHERE deviceId = #{deviceId}") | 48 | " FROM device WHERE deviceId = #{deviceId}") |
| 46 | Device getDeviceByDeviceId(String deviceId); | 49 | Device getDeviceByDeviceId(String deviceId); |
| 47 | 50 | ||
| @@ -70,6 +73,7 @@ public interface DeviceMapper { | @@ -70,6 +73,7 @@ public interface DeviceMapper { | ||
| 70 | "mobilePositionSubmissionInterval," + | 73 | "mobilePositionSubmissionInterval," + |
| 71 | "subscribeCycleForAlarm," + | 74 | "subscribeCycleForAlarm," + |
| 72 | "ssrcCheck," + | 75 | "ssrcCheck," + |
| 76 | + "asMessageChannel," + | ||
| 73 | "geoCoordSys," + | 77 | "geoCoordSys," + |
| 74 | "treeType," + | 78 | "treeType," + |
| 75 | "online" + | 79 | "online" + |
| @@ -98,6 +102,7 @@ public interface DeviceMapper { | @@ -98,6 +102,7 @@ public interface DeviceMapper { | ||
| 98 | "#{mobilePositionSubmissionInterval}," + | 102 | "#{mobilePositionSubmissionInterval}," + |
| 99 | "#{subscribeCycleForAlarm}," + | 103 | "#{subscribeCycleForAlarm}," + |
| 100 | "#{ssrcCheck}," + | 104 | "#{ssrcCheck}," + |
| 105 | + "#{asMessageChannel}," + | ||
| 101 | "#{geoCoordSys}," + | 106 | "#{geoCoordSys}," + |
| 102 | "#{treeType}," + | 107 | "#{treeType}," + |
| 103 | "#{online}" + | 108 | "#{online}" + |
| @@ -152,9 +157,11 @@ public interface DeviceMapper { | @@ -152,9 +157,11 @@ public interface DeviceMapper { | ||
| 152 | "mobilePositionSubmissionInterval," + | 157 | "mobilePositionSubmissionInterval," + |
| 153 | "subscribeCycleForAlarm," + | 158 | "subscribeCycleForAlarm," + |
| 154 | "ssrcCheck," + | 159 | "ssrcCheck," + |
| 160 | + "asMessageChannel," + | ||
| 155 | "geoCoordSys," + | 161 | "geoCoordSys," + |
| 156 | "treeType," + | 162 | "treeType," + |
| 157 | "online," + | 163 | "online," + |
| 164 | + "mediaServerId," + | ||
| 158 | "(SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de" + | 165 | "(SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de" + |
| 159 | "<if test=\"online != null\"> where online=${online}</if>"+ | 166 | "<if test=\"online != null\"> where online=${online}</if>"+ |
| 160 | " </script>" | 167 | " </script>" |
| @@ -164,9 +171,6 @@ public interface DeviceMapper { | @@ -164,9 +171,6 @@ public interface DeviceMapper { | ||
| 164 | @Delete("DELETE FROM device WHERE deviceId=#{deviceId}") | 171 | @Delete("DELETE FROM device WHERE deviceId=#{deviceId}") |
| 165 | int del(String deviceId); | 172 | int del(String deviceId); |
| 166 | 173 | ||
| 167 | - @Update("UPDATE device SET online=0") | ||
| 168 | - int outlineForAll(); | ||
| 169 | - | ||
| 170 | @Select("SELECT " + | 174 | @Select("SELECT " + |
| 171 | "deviceId, " + | 175 | "deviceId, " + |
| 172 | "coalesce(custom_name, name) as name, " + | 176 | "coalesce(custom_name, name) as name, " + |
| @@ -192,6 +196,7 @@ public interface DeviceMapper { | @@ -192,6 +196,7 @@ public interface DeviceMapper { | ||
| 192 | "mobilePositionSubmissionInterval," + | 196 | "mobilePositionSubmissionInterval," + |
| 193 | "subscribeCycleForAlarm," + | 197 | "subscribeCycleForAlarm," + |
| 194 | "ssrcCheck," + | 198 | "ssrcCheck," + |
| 199 | + "asMessageChannel," + | ||
| 195 | "geoCoordSys," + | 200 | "geoCoordSys," + |
| 196 | "treeType," + | 201 | "treeType," + |
| 197 | "online " + | 202 | "online " + |
| @@ -222,6 +227,7 @@ public interface DeviceMapper { | @@ -222,6 +227,7 @@ public interface DeviceMapper { | ||
| 222 | "mobilePositionSubmissionInterval," + | 227 | "mobilePositionSubmissionInterval," + |
| 223 | "subscribeCycleForAlarm," + | 228 | "subscribeCycleForAlarm," + |
| 224 | "ssrcCheck," + | 229 | "ssrcCheck," + |
| 230 | + "asMessageChannel," + | ||
| 225 | "geoCoordSys," + | 231 | "geoCoordSys," + |
| 226 | "treeType," + | 232 | "treeType," + |
| 227 | "online" + | 233 | "online" + |
| @@ -243,12 +249,13 @@ public interface DeviceMapper { | @@ -243,12 +249,13 @@ public interface DeviceMapper { | ||
| 243 | "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=#{mobilePositionSubmissionInterval}</if>" + | 249 | "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=#{mobilePositionSubmissionInterval}</if>" + |
| 244 | "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=#{subscribeCycleForAlarm}</if>" + | 250 | "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=#{subscribeCycleForAlarm}</if>" + |
| 245 | "<if test=\"ssrcCheck != null\">, ssrcCheck=#{ssrcCheck}</if>" + | 251 | "<if test=\"ssrcCheck != null\">, ssrcCheck=#{ssrcCheck}</if>" + |
| 252 | + "<if test=\"asMessageChannel != null\">, asMessageChannel=#{asMessageChannel}</if>" + | ||
| 246 | "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" + | 253 | "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" + |
| 247 | "<if test=\"treeType != null\">, treeType=#{treeType}</if>" + | 254 | "<if test=\"treeType != null\">, treeType=#{treeType}</if>" + |
| 248 | "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" + | 255 | "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" + |
| 249 | "WHERE deviceId=#{deviceId}"+ | 256 | "WHERE deviceId=#{deviceId}"+ |
| 250 | " </script>"}) | 257 | " </script>"}) |
| 251 | - int updateCustom(Device device); | 258 | + void updateCustom(Device device); |
| 252 | 259 | ||
| 253 | @Insert("INSERT INTO device (" + | 260 | @Insert("INSERT INTO device (" + |
| 254 | "deviceId, " + | 261 | "deviceId, " + |
| @@ -259,9 +266,11 @@ public interface DeviceMapper { | @@ -259,9 +266,11 @@ public interface DeviceMapper { | ||
| 259 | "updateTime," + | 266 | "updateTime," + |
| 260 | "charset," + | 267 | "charset," + |
| 261 | "ssrcCheck," + | 268 | "ssrcCheck," + |
| 269 | + "asMessageChannel," + | ||
| 262 | "geoCoordSys," + | 270 | "geoCoordSys," + |
| 263 | "treeType," + | 271 | "treeType," + |
| 264 | - "online" + | 272 | + "online," + |
| 273 | + "mediaServerId" + | ||
| 265 | ") VALUES (" + | 274 | ") VALUES (" + |
| 266 | "#{deviceId}," + | 275 | "#{deviceId}," + |
| 267 | "#{name}," + | 276 | "#{name}," + |
| @@ -271,9 +280,11 @@ public interface DeviceMapper { | @@ -271,9 +280,11 @@ public interface DeviceMapper { | ||
| 271 | "#{updateTime}," + | 280 | "#{updateTime}," + |
| 272 | "#{charset}," + | 281 | "#{charset}," + |
| 273 | "#{ssrcCheck}," + | 282 | "#{ssrcCheck}," + |
| 283 | + "#{asMessageChannel}," + | ||
| 274 | "#{geoCoordSys}," + | 284 | "#{geoCoordSys}," + |
| 275 | "#{treeType}," + | 285 | "#{treeType}," + |
| 276 | - "#{online}" + | 286 | + "#{online}," + |
| 287 | + "#{mediaServerId}" + | ||
| 277 | ")") | 288 | ")") |
| 278 | void addCustomDevice(Device device); | 289 | void addCustomDevice(Device device); |
| 279 | 290 | ||
| @@ -282,4 +293,7 @@ public interface DeviceMapper { | @@ -282,4 +293,7 @@ public interface DeviceMapper { | ||
| 282 | 293 | ||
| 283 | @Select("select * from device") | 294 | @Select("select * from device") |
| 284 | List<Device> getAll(); | 295 | List<Device> getAll(); |
| 296 | + | ||
| 297 | + @Select("select * from device where asMessageChannel = 1") | ||
| 298 | + List<Device> queryDeviceWithAsMessageChannel(); | ||
| 285 | } | 299 | } |
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
| @@ -15,10 +15,10 @@ import java.util.List; | @@ -15,10 +15,10 @@ import java.util.List; | ||
| 15 | public interface ParentPlatformMapper { | 15 | public interface ParentPlatformMapper { |
| 16 | 16 | ||
| 17 | @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + | 17 | @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + |
| 18 | - " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " + | 18 | + " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, asMessageChannel, " + |
| 19 | " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " + | 19 | " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " + |
| 20 | " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + | 20 | " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + |
| 21 | - " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, " + | 21 | + " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " + |
| 22 | " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})") | 22 | " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})") |
| 23 | int addParentPlatform(ParentPlatform parentPlatform); | 23 | int addParentPlatform(ParentPlatform parentPlatform); |
| 24 | 24 | ||
| @@ -40,6 +40,7 @@ public interface ParentPlatformMapper { | @@ -40,6 +40,7 @@ public interface ParentPlatformMapper { | ||
| 40 | "characterSet=#{characterSet}, " + | 40 | "characterSet=#{characterSet}, " + |
| 41 | "ptz=#{ptz}, " + | 41 | "ptz=#{ptz}, " + |
| 42 | "rtcp=#{rtcp}, " + | 42 | "rtcp=#{rtcp}, " + |
| 43 | + "asMessageChannel=#{asMessageChannel}, " + | ||
| 43 | "status=#{status}, " + | 44 | "status=#{status}, " + |
| 44 | "startOfflinePush=#{startOfflinePush}, " + | 45 | "startOfflinePush=#{startOfflinePush}, " + |
| 45 | "catalogGroup=#{catalogGroup}, " + | 46 | "catalogGroup=#{catalogGroup}, " + |
| @@ -68,9 +69,12 @@ public interface ParentPlatformMapper { | @@ -68,9 +69,12 @@ public interface ParentPlatformMapper { | ||
| 68 | "FROM parent_platform pp ") | 69 | "FROM parent_platform pp ") |
| 69 | List<ParentPlatform> getParentPlatformList(); | 70 | List<ParentPlatform> getParentPlatformList(); |
| 70 | 71 | ||
| 71 | - @Select("SELECT * FROM parent_platform WHERE enable=#{enable}") | 72 | + @Select("SELECT * FROM parent_platform WHERE enable=#{enable} ") |
| 72 | List<ParentPlatform> getEnableParentPlatformList(boolean enable); | 73 | List<ParentPlatform> getEnableParentPlatformList(boolean enable); |
| 73 | 74 | ||
| 75 | + @Select("SELECT * FROM parent_platform WHERE enable=1 and asMessageChannel = 1") | ||
| 76 | + List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel(); | ||
| 77 | + | ||
| 74 | @Select("SELECT * FROM parent_platform WHERE serverGBId=#{platformGbId}") | 78 | @Select("SELECT * FROM parent_platform WHERE serverGBId=#{platformGbId}") |
| 75 | ParentPlatform getParentPlatByServerGBId(String platformGbId); | 79 | ParentPlatform getParentPlatByServerGBId(String platformGbId); |
| 76 | 80 |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| @@ -177,12 +177,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -177,12 +177,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 177 | @Override | 177 | @Override |
| 178 | public boolean startDownload(StreamInfo stream, String callId) { | 178 | public boolean startDownload(StreamInfo stream, String callId) { |
| 179 | boolean result; | 179 | boolean result; |
| 180 | + String key=String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, | ||
| 181 | + userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId); | ||
| 180 | if (stream.getProgress() == 1) { | 182 | if (stream.getProgress() == 1) { |
| 181 | - result = RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, | ||
| 182 | - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream); | 183 | + logger.debug("添加下载缓存==已完成下载=》{}",key); |
| 184 | + result = RedisUtil.set(key, stream); | ||
| 183 | }else { | 185 | }else { |
| 184 | - result = RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, | ||
| 185 | - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream, 60*60); | 186 | + logger.debug("添加下载缓存==未完成下载=》{}",key); |
| 187 | + result = RedisUtil.set(key, stream, 60*60); | ||
| 186 | } | 188 | } |
| 187 | return result; | 189 | return result; |
| 188 | } | 190 | } |
| @@ -617,7 +619,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -617,7 +619,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 617 | stream, | 619 | stream, |
| 618 | callId | 620 | callId |
| 619 | ); | 621 | ); |
| 620 | - List<Object> streamInfoScan = RedisUtil.scan(key); | 622 | + List<Object> streamInfoScan = RedisUtil.scan2(key); |
| 621 | if (streamInfoScan.size() > 0) { | 623 | if (streamInfoScan.size() > 0) { |
| 622 | return (StreamInfo) RedisUtil.get((String) streamInfoScan.get(0)); | 624 | return (StreamInfo) RedisUtil.get((String) streamInfoScan.get(0)); |
| 623 | }else { | 625 | }else { |
| @@ -855,7 +857,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -855,7 +857,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 855 | 857 | ||
| 856 | @Override | 858 | @Override |
| 857 | public void sendAlarmMsg(AlarmChannelMessage msg) { | 859 | public void sendAlarmMsg(AlarmChannelMessage msg) { |
| 858 | - String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE; | 860 | + // 此消息用于对接第三方服务下级来的消息内容 |
| 861 | + String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM; | ||
| 859 | logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg)); | 862 | logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg)); |
| 860 | RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); | 863 | RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); |
| 861 | } | 864 | } |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.dao.*; | @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.dao.*; | ||
| 13 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; | 13 | import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; |
| 14 | import com.genersoft.iot.vmp.utils.DateUtil; | 14 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 15 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; | 15 | import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; |
| 16 | +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend; | ||
| 16 | import com.github.pagehelper.PageHelper; | 17 | import com.github.pagehelper.PageHelper; |
| 17 | import com.github.pagehelper.PageInfo; | 18 | import com.github.pagehelper.PageInfo; |
| 18 | import org.slf4j.Logger; | 19 | import org.slf4j.Logger; |
| @@ -189,7 +190,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -189,7 +190,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 189 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 | 190 | dataSourceTransactionManager.commit(transactionStatus); //手动提交 |
| 190 | return true; | 191 | return true; |
| 191 | }catch (Exception e) { | 192 | }catch (Exception e) { |
| 192 | - e.printStackTrace(); | 193 | + logger.error("未处理的异常 ", e); |
| 193 | dataSourceTransactionManager.rollback(transactionStatus); | 194 | dataSourceTransactionManager.rollback(transactionStatus); |
| 194 | return false; | 195 | return false; |
| 195 | } | 196 | } |
| @@ -305,7 +306,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -305,7 +306,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 305 | } | 306 | } |
| 306 | return true; | 307 | return true; |
| 307 | }catch (Exception e) { | 308 | }catch (Exception e) { |
| 308 | - e.printStackTrace(); | 309 | + logger.error("未处理的异常 ", e); |
| 309 | dataSourceTransactionManager.rollback(transactionStatus); | 310 | dataSourceTransactionManager.rollback(transactionStatus); |
| 310 | return false; | 311 | return false; |
| 311 | } | 312 | } |
| @@ -359,8 +360,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -359,8 +360,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 359 | } | 360 | } |
| 360 | 361 | ||
| 361 | @Override | 362 | @Override |
| 362 | - public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds) { | ||
| 363 | - return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit,channelIds); | 363 | + public List<DeviceChannelExtend> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, List<String> channelIds, String query, Boolean hasSubChannel, Boolean online, int start, int limit) { |
| 364 | + return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, channelIds, null, query, hasSubChannel, online, start, limit); | ||
| 364 | } | 365 | } |
| 365 | 366 | ||
| 366 | 367 | ||
| @@ -370,6 +371,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -370,6 +371,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 370 | } | 371 | } |
| 371 | 372 | ||
| 372 | @Override | 373 | @Override |
| 374 | + public List<DeviceChannelExtend> queryChannelsByDeviceId(String deviceId, List<String> channelIds, Boolean online) { | ||
| 375 | + return deviceChannelMapper.queryChannelsWithDeviceInfo(deviceId, null,null, null, online,channelIds); | ||
| 376 | + } | ||
| 377 | + | ||
| 378 | + @Override | ||
| 373 | public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { | 379 | public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { |
| 374 | PageHelper.startPage(page, count); | 380 | PageHelper.startPage(page, count); |
| 375 | List<DeviceChannel> all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online,null); | 381 | List<DeviceChannel> all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online,null); |
| @@ -512,6 +518,16 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | @@ -512,6 +518,16 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { | ||
| 512 | } | 518 | } |
| 513 | 519 | ||
| 514 | @Override | 520 | @Override |
| 521 | + public List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel() { | ||
| 522 | + return platformMapper.queryEnablePlatformListWithAsMessageChannel(); | ||
| 523 | + } | ||
| 524 | + | ||
| 525 | + @Override | ||
| 526 | + public List<Device> queryDeviceWithAsMessageChannel() { | ||
| 527 | + return deviceMapper.queryDeviceWithAsMessageChannel(); | ||
| 528 | + } | ||
| 529 | + | ||
| 530 | + @Override | ||
| 515 | public void outlineForAllParentPlatform() { | 531 | public void outlineForAllParentPlatform() { |
| 516 | platformMapper.outlineForAllParentPlatform(); | 532 | platformMapper.outlineForAllParentPlatform(); |
| 517 | } | 533 | } |
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java
| @@ -45,7 +45,6 @@ public class DateUtil { | @@ -45,7 +45,6 @@ public class DateUtil { | ||
| 45 | 45 | ||
| 46 | public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { | 46 | public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { |
| 47 | return formatter.format(formatterCompatibleISO8601.parse(formatTime)); | 47 | return formatter.format(formatterCompatibleISO8601.parse(formatTime)); |
| 48 | - | ||
| 49 | } | 48 | } |
| 50 | 49 | ||
| 51 | /** | 50 | /** |
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
| @@ -881,7 +881,13 @@ public class RedisUtil { | @@ -881,7 +881,13 @@ public class RedisUtil { | ||
| 881 | 881 | ||
| 882 | return new ArrayList<>(resultKeys); | 882 | return new ArrayList<>(resultKeys); |
| 883 | } | 883 | } |
| 884 | - | 884 | + public static List<Object> scan2(String query) { |
| 885 | + if (redisTemplate == null) { | ||
| 886 | + redisTemplate = SpringBeanFactory.getBean("redisTemplate"); | ||
| 887 | + } | ||
| 888 | + Set<String> keys = redisTemplate.keys(query); | ||
| 889 | + return new ArrayList<>(keys); | ||
| 890 | + } | ||
| 885 | // ============================== 消息发送与订阅 ============================== | 891 | // ============================== 消息发送与订阅 ============================== |
| 886 | public static void convertAndSend(String channel, JSONObject msg) { | 892 | public static void convertAndSend(String channel, JSONObject msg) { |
| 887 | if (redisTemplate == null) { | 893 | if (redisTemplate == null) { |
src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
| @@ -28,6 +28,10 @@ public class WVPResult<T> implements Cloneable{ | @@ -28,6 +28,10 @@ public class WVPResult<T> implements Cloneable{ | ||
| 28 | return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t); | 28 | return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | + public static WVPResult success() { | ||
| 32 | + return new WVPResult<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null); | ||
| 33 | + } | ||
| 34 | + | ||
| 31 | public static <T> WVPResult<T> success(T t) { | 35 | public static <T> WVPResult<T> success(T t) { |
| 32 | return success(t, ErrorCode.SUCCESS.getMsg()); | 36 | return success(t, ErrorCode.SUCCESS.getMsg()); |
| 33 | } | 37 | } |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
| @@ -30,7 +30,7 @@ import java.util.UUID; | @@ -30,7 +30,7 @@ import java.util.UUID; | ||
| 30 | * 位置信息管理 | 30 | * 位置信息管理 |
| 31 | */ | 31 | */ |
| 32 | @Tag(name = "位置信息管理") | 32 | @Tag(name = "位置信息管理") |
| 33 | -@CrossOrigin | 33 | + |
| 34 | @RestController | 34 | @RestController |
| 35 | @RequestMapping("/api/position") | 35 | @RequestMapping("/api/position") |
| 36 | public class MobilePositionController { | 36 | public class MobilePositionController { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java
| @@ -17,7 +17,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; | @@ -17,7 +17,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; | ||
| 17 | * @data: 2021-01-20 | 17 | * @data: 2021-01-20 |
| 18 | */ | 18 | */ |
| 19 | @Tag(name = "SSE推送") | 19 | @Tag(name = "SSE推送") |
| 20 | -@CrossOrigin | 20 | + |
| 21 | @Controller | 21 | @Controller |
| 22 | @RequestMapping("/api") | 22 | @RequestMapping("/api") |
| 23 | public class SseController { | 23 | public class SseController { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
| @@ -6,35 +6,28 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; | @@ -6,35 +6,28 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; | ||
| 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 8 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 9 | -import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener; | ||
| 10 | import com.genersoft.iot.vmp.service.IDeviceAlarmService; | 9 | import com.genersoft.iot.vmp.service.IDeviceAlarmService; |
| 11 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 10 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 12 | import com.genersoft.iot.vmp.utils.DateUtil; | 11 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 13 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 12 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 14 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 15 | import com.github.pagehelper.PageInfo; | 13 | import com.github.pagehelper.PageInfo; |
| 16 | import io.swagger.v3.oas.annotations.Operation; | 14 | import io.swagger.v3.oas.annotations.Operation; |
| 17 | import io.swagger.v3.oas.annotations.Parameter; | 15 | import io.swagger.v3.oas.annotations.Parameter; |
| 18 | -import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
| 19 | import io.swagger.v3.oas.annotations.tags.Tag; | 16 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 20 | import org.slf4j.Logger; | 17 | import org.slf4j.Logger; |
| 21 | import org.slf4j.LoggerFactory; | 18 | import org.slf4j.LoggerFactory; |
| 22 | import org.springframework.beans.factory.annotation.Autowired; | 19 | import org.springframework.beans.factory.annotation.Autowired; |
| 23 | -import org.springframework.http.HttpStatus; | ||
| 24 | -import org.springframework.http.ResponseEntity; | ||
| 25 | import org.springframework.util.ObjectUtils; | 20 | import org.springframework.util.ObjectUtils; |
| 26 | -import org.springframework.util.StringUtils; | ||
| 27 | import org.springframework.web.bind.annotation.*; | 21 | import org.springframework.web.bind.annotation.*; |
| 28 | 22 | ||
| 29 | import javax.sip.InvalidArgumentException; | 23 | import javax.sip.InvalidArgumentException; |
| 30 | import javax.sip.SipException; | 24 | import javax.sip.SipException; |
| 31 | import java.text.ParseException; | 25 | import java.text.ParseException; |
| 32 | -import java.time.LocalDateTime; | ||
| 33 | import java.util.Arrays; | 26 | import java.util.Arrays; |
| 34 | import java.util.List; | 27 | import java.util.List; |
| 35 | 28 | ||
| 36 | @Tag(name = "报警信息管理") | 29 | @Tag(name = "报警信息管理") |
| 37 | -@CrossOrigin | 30 | + |
| 38 | @RestController | 31 | @RestController |
| 39 | @RequestMapping("/api/alarm") | 32 | @RequestMapping("/api/alarm") |
| 40 | public class AlarmController { | 33 | public class AlarmController { |
| @@ -78,11 +71,11 @@ public class AlarmController { | @@ -78,11 +71,11 @@ public class AlarmController { | ||
| 78 | if (ObjectUtils.isEmpty(deviceIds)) { | 71 | if (ObjectUtils.isEmpty(deviceIds)) { |
| 79 | deviceIds = null; | 72 | deviceIds = null; |
| 80 | } | 73 | } |
| 74 | + | ||
| 81 | if (ObjectUtils.isEmpty(time)) { | 75 | if (ObjectUtils.isEmpty(time)) { |
| 82 | time = null; | 76 | time = null; |
| 83 | - } | ||
| 84 | - if (!DateUtil.verification(time, DateUtil.formatter) ){ | ||
| 85 | - return null; | 77 | + }else if (!DateUtil.verification(time, DateUtil.formatter) ){ |
| 78 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "time格式为" + DateUtil.PATTERN); | ||
| 86 | } | 79 | } |
| 87 | List<String> deviceIdList = null; | 80 | List<String> deviceIdList = null; |
| 88 | if (deviceIds != null) { | 81 | if (deviceIds != null) { |
| @@ -110,7 +103,7 @@ public class AlarmController { | @@ -110,7 +103,7 @@ public class AlarmController { | ||
| 110 | deviceAlarm.setAlarmDescription("test"); | 103 | deviceAlarm.setAlarmDescription("test"); |
| 111 | deviceAlarm.setAlarmMethod("1"); | 104 | deviceAlarm.setAlarmMethod("1"); |
| 112 | deviceAlarm.setAlarmPriority("1"); | 105 | deviceAlarm.setAlarmPriority("1"); |
| 113 | - deviceAlarm.setAlarmTime(DateUtil.formatterISO8601.format(LocalDateTime.now())); | 106 | + deviceAlarm.setAlarmTime(DateUtil.getNow()); |
| 114 | deviceAlarm.setAlarmType("1"); | 107 | deviceAlarm.setAlarmType("1"); |
| 115 | deviceAlarm.setLongitude(115.33333); | 108 | deviceAlarm.setLongitude(115.33333); |
| 116 | deviceAlarm.setLatitude(39.33333); | 109 | deviceAlarm.setLatitude(39.33333); |
| @@ -177,16 +170,17 @@ public class AlarmController { | @@ -177,16 +170,17 @@ public class AlarmController { | ||
| 177 | if (ObjectUtils.isEmpty(alarmType)) { | 170 | if (ObjectUtils.isEmpty(alarmType)) { |
| 178 | alarmType = null; | 171 | alarmType = null; |
| 179 | } | 172 | } |
| 173 | + | ||
| 180 | if (ObjectUtils.isEmpty(startTime)) { | 174 | if (ObjectUtils.isEmpty(startTime)) { |
| 181 | startTime = null; | 175 | startTime = null; |
| 176 | + }else if (!DateUtil.verification(startTime, DateUtil.formatter) ){ | ||
| 177 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "startTime格式为" + DateUtil.PATTERN); | ||
| 182 | } | 178 | } |
| 179 | + | ||
| 183 | if (ObjectUtils.isEmpty(endTime)) { | 180 | if (ObjectUtils.isEmpty(endTime)) { |
| 184 | endTime = null; | 181 | endTime = null; |
| 185 | - } | ||
| 186 | - | ||
| 187 | - | ||
| 188 | - if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){ | ||
| 189 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间或结束时间格式有误"); | 182 | + }else if (!DateUtil.verification(endTime, DateUtil.formatter) ){ |
| 183 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "endTime格式为" + DateUtil.PATTERN); | ||
| 190 | } | 184 | } |
| 191 | 185 | ||
| 192 | return deviceAlarmService.getAllAlarm(page, count, deviceId, alarmPriority, alarmMethod, | 186 | return deviceAlarmService.getAllAlarm(page, count, deviceId, alarmPriority, alarmMethod, |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
| @@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | @@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | ||
| 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 15 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 16 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 16 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 17 | - | ||
| 18 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 17 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 19 | import io.swagger.v3.oas.annotations.Operation; | 18 | import io.swagger.v3.oas.annotations.Operation; |
| 20 | import io.swagger.v3.oas.annotations.Parameter; | 19 | import io.swagger.v3.oas.annotations.Parameter; |
| @@ -22,9 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; | @@ -22,9 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; | ||
| 22 | import org.slf4j.Logger; | 21 | import org.slf4j.Logger; |
| 23 | import org.slf4j.LoggerFactory; | 22 | import org.slf4j.LoggerFactory; |
| 24 | import org.springframework.beans.factory.annotation.Autowired; | 23 | import org.springframework.beans.factory.annotation.Autowired; |
| 25 | -import org.springframework.http.ResponseEntity; | ||
| 26 | import org.springframework.util.ObjectUtils; | 24 | import org.springframework.util.ObjectUtils; |
| 27 | -import org.springframework.util.StringUtils; | ||
| 28 | import org.springframework.web.bind.annotation.*; | 25 | import org.springframework.web.bind.annotation.*; |
| 29 | import org.springframework.web.context.request.async.DeferredResult; | 26 | import org.springframework.web.context.request.async.DeferredResult; |
| 30 | 27 | ||
| @@ -34,7 +31,6 @@ import java.text.ParseException; | @@ -34,7 +31,6 @@ import java.text.ParseException; | ||
| 34 | import java.util.UUID; | 31 | import java.util.UUID; |
| 35 | 32 | ||
| 36 | @Tag(name = "国标设备配置") | 33 | @Tag(name = "国标设备配置") |
| 37 | -@CrossOrigin | ||
| 38 | @RestController | 34 | @RestController |
| 39 | @RequestMapping("/api/device/config") | 35 | @RequestMapping("/api/device/config") |
| 40 | public class DeviceConfig { | 36 | public class DeviceConfig { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
| @@ -32,7 +32,7 @@ import java.text.ParseException; | @@ -32,7 +32,7 @@ import java.text.ParseException; | ||
| 32 | import java.util.UUID; | 32 | import java.util.UUID; |
| 33 | 33 | ||
| 34 | @Tag(name = "国标设备控制") | 34 | @Tag(name = "国标设备控制") |
| 35 | -@CrossOrigin | 35 | + |
| 36 | @RestController | 36 | @RestController |
| 37 | @RequestMapping("/api/device/control") | 37 | @RequestMapping("/api/device/control") |
| 38 | public class DeviceControl { | 38 | public class DeviceControl { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
| @@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation; | @@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation; | ||
| 24 | import io.swagger.v3.oas.annotations.Parameter; | 24 | import io.swagger.v3.oas.annotations.Parameter; |
| 25 | import io.swagger.v3.oas.annotations.tags.Tag; | 25 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 26 | import org.apache.commons.compress.utils.IOUtils; | 26 | import org.apache.commons.compress.utils.IOUtils; |
| 27 | +import org.apache.ibatis.annotations.Options; | ||
| 27 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
| 28 | import org.slf4j.LoggerFactory; | 29 | import org.slf4j.LoggerFactory; |
| 29 | import org.springframework.beans.factory.annotation.Autowired; | 30 | import org.springframework.beans.factory.annotation.Autowired; |
| @@ -46,7 +47,7 @@ import java.util.*; | @@ -46,7 +47,7 @@ import java.util.*; | ||
| 46 | 47 | ||
| 47 | @Tag(name = "国标设备查询", description = "国标设备查询") | 48 | @Tag(name = "国标设备查询", description = "国标设备查询") |
| 48 | @SuppressWarnings("rawtypes") | 49 | @SuppressWarnings("rawtypes") |
| 49 | -@CrossOrigin | 50 | + |
| 50 | @RestController | 51 | @RestController |
| 51 | @RequestMapping("/api/device/query") | 52 | @RequestMapping("/api/device/query") |
| 52 | public class DeviceQuery { | 53 | public class DeviceQuery { |
| @@ -97,8 +98,10 @@ public class DeviceQuery { | @@ -97,8 +98,10 @@ public class DeviceQuery { | ||
| 97 | @Parameter(name = "page", description = "当前页", required = true) | 98 | @Parameter(name = "page", description = "当前页", required = true) |
| 98 | @Parameter(name = "count", description = "每页查询数量", required = true) | 99 | @Parameter(name = "count", description = "每页查询数量", required = true) |
| 99 | @GetMapping("/devices") | 100 | @GetMapping("/devices") |
| 101 | + @Options() | ||
| 100 | public PageInfo<Device> devices(int page, int count){ | 102 | public PageInfo<Device> devices(int page, int count){ |
| 101 | - | 103 | +// if (page == null) page = 0; |
| 104 | +// if (count == null) count = 20; | ||
| 102 | return storager.queryVideoDeviceList(page, count,null); | 105 | return storager.queryVideoDeviceList(page, count,null); |
| 103 | } | 106 | } |
| 104 | 107 |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
| @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; | @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; | ||
| 17 | import java.util.List; | 17 | import java.util.List; |
| 18 | 18 | ||
| 19 | @Tag(name = "视频流关联到级联平台") | 19 | @Tag(name = "视频流关联到级联平台") |
| 20 | -@CrossOrigin | 20 | + |
| 21 | @RestController | 21 | @RestController |
| 22 | @RequestMapping("/api/gbStream") | 22 | @RequestMapping("/api/gbStream") |
| 23 | public class GbStreamController { | 23 | public class GbStreamController { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
| @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; | @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; | ||
| 24 | 24 | ||
| 25 | @Tag(name = "媒体流相关") | 25 | @Tag(name = "媒体流相关") |
| 26 | @Controller | 26 | @Controller |
| 27 | -@CrossOrigin | 27 | + |
| 28 | @RequestMapping(value = "/api/media") | 28 | @RequestMapping(value = "/api/media") |
| 29 | public class MediaController { | 29 | public class MediaController { |
| 30 | 30 |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
| @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; | @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; | ||
| 7 | import com.genersoft.iot.vmp.conf.UserSetting; | 7 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 8 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 8 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 9 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 9 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 10 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; | ||
| 10 | import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; | 11 | import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; |
| 11 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; | 12 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; |
| 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| @@ -37,7 +38,7 @@ import java.util.List; | @@ -37,7 +38,7 @@ import java.util.List; | ||
| 37 | * 级联平台管理 | 38 | * 级联平台管理 |
| 38 | */ | 39 | */ |
| 39 | @Tag(name = "级联平台管理") | 40 | @Tag(name = "级联平台管理") |
| 40 | -@CrossOrigin | 41 | + |
| 41 | @RestController | 42 | @RestController |
| 42 | @RequestMapping("/api/platform") | 43 | @RequestMapping("/api/platform") |
| 43 | public class PlatformController { | 44 | public class PlatformController { |
| @@ -205,58 +206,8 @@ public class PlatformController { | @@ -205,58 +206,8 @@ public class PlatformController { | ||
| 205 | ) { | 206 | ) { |
| 206 | throw new ControllerException(ErrorCode.ERROR400); | 207 | throw new ControllerException(ErrorCode.ERROR400); |
| 207 | } | 208 | } |
| 208 | - parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase()); | ||
| 209 | - ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId()); | ||
| 210 | - parentPlatform.setUpdateTime(DateUtil.getNow()); | ||
| 211 | - if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) { | ||
| 212 | - // 目录结构发生变化,清空之前的关联关系 | ||
| 213 | - logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId()); | ||
| 214 | - storager.cleanContentForPlatform(parentPlatform.getServerGBId()); | ||
| 215 | - | ||
| 216 | - } | ||
| 217 | - boolean updateResult = storager.updateParentPlatform(parentPlatform); | ||
| 218 | - | ||
| 219 | - if (updateResult) { | ||
| 220 | - // 保存时启用就发送注册 | ||
| 221 | - if (parentPlatform.isEnable()) { | ||
| 222 | - if (parentPlatformOld != null && parentPlatformOld.isStatus()) { | ||
| 223 | - try { | ||
| 224 | - commanderForPlatform.unregister(parentPlatformOld, null, null); | ||
| 225 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 226 | - logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); | ||
| 227 | - } | ||
| 228 | - try { | ||
| 229 | - Thread.sleep(500); | ||
| 230 | - } catch (InterruptedException e) { | ||
| 231 | - logger.error("[线程休眠失败] : {}", e.getMessage()); | ||
| 232 | - } | ||
| 233 | - // 只要保存就发送注册 | ||
| 234 | - try { | ||
| 235 | - commanderForPlatform.register(parentPlatform, null, null); | ||
| 236 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 237 | - logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage()); | ||
| 238 | - } | ||
| 239 | - | ||
| 240 | - } else { | ||
| 241 | - // 只要保存就发送注册 | ||
| 242 | - try { | ||
| 243 | - commanderForPlatform.register(parentPlatform, null, null); | ||
| 244 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 245 | - logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage()); | ||
| 246 | - } | ||
| 247 | - } | ||
| 248 | - } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销 | ||
| 249 | - try { | ||
| 250 | - commanderForPlatform.unregister(parentPlatformOld, null, null); | ||
| 251 | - } catch (InvalidArgumentException | ParseException | SipException e) { | ||
| 252 | - logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); | ||
| 253 | - } | ||
| 254 | - // 停止订阅相关的定时任务 | ||
| 255 | - subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId()); | ||
| 256 | - } | ||
| 257 | - } else { | ||
| 258 | - throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败"); | ||
| 259 | - } | 209 | + |
| 210 | + platformService.update(parentPlatform); | ||
| 260 | } | 211 | } |
| 261 | 212 | ||
| 262 | /** | 213 | /** |
| @@ -279,12 +230,16 @@ public class PlatformController { | @@ -279,12 +230,16 @@ public class PlatformController { | ||
| 279 | throw new ControllerException(ErrorCode.ERROR400); | 230 | throw new ControllerException(ErrorCode.ERROR400); |
| 280 | } | 231 | } |
| 281 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId); | 232 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId); |
| 233 | + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(serverGBId); | ||
| 282 | if (parentPlatform == null) { | 234 | if (parentPlatform == null) { |
| 283 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在"); | 235 | throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在"); |
| 284 | } | 236 | } |
| 237 | + if (parentPlatformCatch == null) { | ||
| 238 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在"); | ||
| 239 | + } | ||
| 285 | // 发送离线消息,无论是否成功都删除缓存 | 240 | // 发送离线消息,无论是否成功都删除缓存 |
| 286 | try { | 241 | try { |
| 287 | - commanderForPlatform.unregister(parentPlatform, (event -> { | 242 | + commanderForPlatform.unregister(parentPlatform, parentPlatformCatch.getSipTransactionInfo(), (event -> { |
| 288 | // 清空redis缓存 | 243 | // 清空redis缓存 |
| 289 | redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId()); | 244 | redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId()); |
| 290 | redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId()); | 245 | redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId()); |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
| @@ -41,7 +41,7 @@ import java.util.UUID; | @@ -41,7 +41,7 @@ import java.util.UUID; | ||
| 41 | * @author lin | 41 | * @author lin |
| 42 | */ | 42 | */ |
| 43 | @Tag(name = "国标设备点播") | 43 | @Tag(name = "国标设备点播") |
| 44 | -@CrossOrigin | 44 | + |
| 45 | @RestController | 45 | @RestController |
| 46 | @RequestMapping("/api/play") | 46 | @RequestMapping("/api/play") |
| 47 | public class PlayController { | 47 | public class PlayController { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
| @@ -40,7 +40,7 @@ import java.util.UUID; | @@ -40,7 +40,7 @@ import java.util.UUID; | ||
| 40 | * @author lin | 40 | * @author lin |
| 41 | */ | 41 | */ |
| 42 | @Tag(name = "视频回放") | 42 | @Tag(name = "视频回放") |
| 43 | -@CrossOrigin | 43 | + |
| 44 | @RestController | 44 | @RestController |
| 45 | @RequestMapping("/api/playback") | 45 | @RequestMapping("/api/playback") |
| 46 | public class PlaybackController { | 46 | public class PlaybackController { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
| 1 | package com.genersoft.iot.vmp.vmanager.gb28181.ptz; | 1 | package com.genersoft.iot.vmp.vmanager.gb28181.ptz; |
| 2 | 2 | ||
| 3 | - | 3 | + |
| 4 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 4 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 6 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 8 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 9 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 5 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 10 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 6 | import io.swagger.v3.oas.annotations.Operation; | 11 | import io.swagger.v3.oas.annotations.Operation; |
| 7 | import io.swagger.v3.oas.annotations.Parameter; | 12 | import io.swagger.v3.oas.annotations.Parameter; |
| @@ -10,23 +15,16 @@ import org.slf4j.Logger; | @@ -10,23 +15,16 @@ import org.slf4j.Logger; | ||
| 10 | import org.slf4j.LoggerFactory; | 15 | import org.slf4j.LoggerFactory; |
| 11 | import org.springframework.beans.factory.annotation.Autowired; | 16 | import org.springframework.beans.factory.annotation.Autowired; |
| 12 | import org.springframework.util.ObjectUtils; | 17 | import org.springframework.util.ObjectUtils; |
| 13 | -import org.springframework.util.StringUtils; | ||
| 14 | import org.springframework.web.bind.annotation.*; | 18 | import org.springframework.web.bind.annotation.*; |
| 15 | import org.springframework.web.context.request.async.DeferredResult; | 19 | import org.springframework.web.context.request.async.DeferredResult; |
| 16 | 20 | ||
| 17 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 18 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | ||
| 19 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 20 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 21 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 22 | - | ||
| 23 | import javax.sip.InvalidArgumentException; | 21 | import javax.sip.InvalidArgumentException; |
| 24 | import javax.sip.SipException; | 22 | import javax.sip.SipException; |
| 25 | import java.text.ParseException; | 23 | import java.text.ParseException; |
| 26 | import java.util.UUID; | 24 | import java.util.UUID; |
| 27 | 25 | ||
| 28 | @Tag(name = "云台控制") | 26 | @Tag(name = "云台控制") |
| 29 | -@CrossOrigin | 27 | + |
| 30 | @RestController | 28 | @RestController |
| 31 | @RequestMapping("/api/ptz") | 29 | @RequestMapping("/api/ptz") |
| 32 | public class PtzController { | 30 | public class PtzController { |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
| @@ -3,40 +3,37 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record; | @@ -3,40 +3,37 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record; | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 4 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 5 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 5 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; | ||
| 8 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | ||
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | 9 | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| 10 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 7 | import com.genersoft.iot.vmp.service.IDeviceService; | 11 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 8 | import com.genersoft.iot.vmp.service.IPlayService; | 12 | import com.genersoft.iot.vmp.service.IPlayService; |
| 13 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 9 | import com.genersoft.iot.vmp.utils.DateUtil; | 14 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 10 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 15 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 11 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; | 16 | import com.genersoft.iot.vmp.vmanager.bean.StreamContent; |
| 12 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | 17 | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 13 | - | ||
| 14 | import io.swagger.v3.oas.annotations.Operation; | 18 | import io.swagger.v3.oas.annotations.Operation; |
| 15 | import io.swagger.v3.oas.annotations.Parameter; | 19 | import io.swagger.v3.oas.annotations.Parameter; |
| 16 | import io.swagger.v3.oas.annotations.tags.Tag; | 20 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 17 | import org.slf4j.Logger; | 21 | import org.slf4j.Logger; |
| 18 | import org.slf4j.LoggerFactory; | 22 | import org.slf4j.LoggerFactory; |
| 19 | import org.springframework.beans.factory.annotation.Autowired; | 23 | import org.springframework.beans.factory.annotation.Autowired; |
| 20 | -import org.springframework.web.bind.annotation.CrossOrigin; | ||
| 21 | import org.springframework.web.bind.annotation.GetMapping; | 24 | import org.springframework.web.bind.annotation.GetMapping; |
| 22 | import org.springframework.web.bind.annotation.PathVariable; | 25 | import org.springframework.web.bind.annotation.PathVariable; |
| 23 | import org.springframework.web.bind.annotation.RequestMapping; | 26 | import org.springframework.web.bind.annotation.RequestMapping; |
| 24 | import org.springframework.web.bind.annotation.RestController; | 27 | import org.springframework.web.bind.annotation.RestController; |
| 25 | import org.springframework.web.context.request.async.DeferredResult; | 28 | import org.springframework.web.context.request.async.DeferredResult; |
| 26 | 29 | ||
| 27 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 28 | -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; | ||
| 29 | -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; | ||
| 30 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | ||
| 31 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 32 | - | ||
| 33 | import javax.sip.InvalidArgumentException; | 30 | import javax.sip.InvalidArgumentException; |
| 34 | import javax.sip.SipException; | 31 | import javax.sip.SipException; |
| 35 | import java.text.ParseException; | 32 | import java.text.ParseException; |
| 36 | import java.util.UUID; | 33 | import java.util.UUID; |
| 37 | 34 | ||
| 38 | @Tag(name = "国标录像") | 35 | @Tag(name = "国标录像") |
| 39 | -@CrossOrigin | 36 | + |
| 40 | @RestController | 37 | @RestController |
| 41 | @RequestMapping("/api/gb_record") | 38 | @RequestMapping("/api/gb_record") |
| 42 | public class GBRecordController { | 39 | public class GBRecordController { |
| @@ -74,10 +71,10 @@ public class GBRecordController { | @@ -74,10 +71,10 @@ public class GBRecordController { | ||
| 74 | } | 71 | } |
| 75 | DeferredResult<WVPResult<RecordInfo>> result = new DeferredResult<>(); | 72 | DeferredResult<WVPResult<RecordInfo>> result = new DeferredResult<>(); |
| 76 | if (!DateUtil.verification(startTime, DateUtil.formatter)){ | 73 | if (!DateUtil.verification(startTime, DateUtil.formatter)){ |
| 77 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime error, format is " + DateUtil.PATTERN); | 74 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime格式为" + DateUtil.PATTERN); |
| 78 | } | 75 | } |
| 79 | if (!DateUtil.verification(endTime, DateUtil.formatter)){ | 76 | if (!DateUtil.verification(endTime, DateUtil.formatter)){ |
| 80 | - throw new ControllerException(ErrorCode.ERROR100.getCode(), "endTime error, format is " + DateUtil.PATTERN); | 77 | + throw new ControllerException(ErrorCode.ERROR100.getCode(), "endTime格式为" + DateUtil.PATTERN); |
| 81 | } | 78 | } |
| 82 | 79 | ||
| 83 | Device device = storager.queryVideoDevice(deviceId); | 80 | Device device = storager.queryVideoDevice(deviceId); |
src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java
| @@ -6,25 +6,18 @@ import com.genersoft.iot.vmp.service.ILogService; | @@ -6,25 +6,18 @@ import com.genersoft.iot.vmp.service.ILogService; | ||
| 6 | import com.genersoft.iot.vmp.storager.dao.dto.LogDto; | 6 | import com.genersoft.iot.vmp.storager.dao.dto.LogDto; |
| 7 | import com.genersoft.iot.vmp.utils.DateUtil; | 7 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 8 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 8 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 9 | -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; | ||
| 10 | import com.github.pagehelper.PageInfo; | 9 | import com.github.pagehelper.PageInfo; |
| 11 | - | ||
| 12 | import io.swagger.v3.oas.annotations.Operation; | 10 | import io.swagger.v3.oas.annotations.Operation; |
| 13 | import io.swagger.v3.oas.annotations.Parameter; | 11 | import io.swagger.v3.oas.annotations.Parameter; |
| 14 | import io.swagger.v3.oas.annotations.tags.Tag; | 12 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 15 | import org.slf4j.Logger; | 13 | import org.slf4j.Logger; |
| 16 | import org.slf4j.LoggerFactory; | 14 | import org.slf4j.LoggerFactory; |
| 17 | import org.springframework.beans.factory.annotation.Autowired; | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 18 | -import org.springframework.http.HttpStatus; | ||
| 19 | -import org.springframework.http.ResponseEntity; | ||
| 20 | import org.springframework.util.ObjectUtils; | 16 | import org.springframework.util.ObjectUtils; |
| 21 | -import org.springframework.util.StringUtils; | ||
| 22 | import org.springframework.web.bind.annotation.*; | 17 | import org.springframework.web.bind.annotation.*; |
| 23 | 18 | ||
| 24 | -import java.text.ParseException; | ||
| 25 | - | ||
| 26 | @Tag(name = "日志管理") | 19 | @Tag(name = "日志管理") |
| 27 | -@CrossOrigin | 20 | + |
| 28 | @RestController | 21 | @RestController |
| 29 | @RequestMapping("/api/log") | 22 | @RequestMapping("/api/log") |
| 30 | public class LogController { | 23 | public class LogController { |
| @@ -67,18 +60,21 @@ public class LogController { | @@ -67,18 +60,21 @@ public class LogController { | ||
| 67 | if (ObjectUtils.isEmpty(query)) { | 60 | if (ObjectUtils.isEmpty(query)) { |
| 68 | query = null; | 61 | query = null; |
| 69 | } | 62 | } |
| 63 | + | ||
| 64 | + if (!userSetting.getLogInDatebase()) { | ||
| 65 | + logger.warn("自动记录日志功能已关闭,查询结果可能不完整。"); | ||
| 66 | + } | ||
| 67 | + | ||
| 70 | if (ObjectUtils.isEmpty(startTime)) { | 68 | if (ObjectUtils.isEmpty(startTime)) { |
| 71 | startTime = null; | 69 | startTime = null; |
| 70 | + }else if (!DateUtil.verification(startTime, DateUtil.formatter) ){ | ||
| 71 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "startTime格式为" + DateUtil.PATTERN); | ||
| 72 | } | 72 | } |
| 73 | + | ||
| 73 | if (ObjectUtils.isEmpty(endTime)) { | 74 | if (ObjectUtils.isEmpty(endTime)) { |
| 74 | endTime = null; | 75 | endTime = null; |
| 75 | - } | ||
| 76 | - if (!userSetting.getLogInDatebase()) { | ||
| 77 | - logger.warn("自动记录日志功能已关闭,查询结果可能不完整。"); | ||
| 78 | - } | ||
| 79 | - | ||
| 80 | - if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){ | ||
| 81 | - throw new ControllerException(ErrorCode.ERROR400); | 76 | + }else if (!DateUtil.verification(endTime, DateUtil.formatter) ){ |
| 77 | + throw new ControllerException(ErrorCode.ERROR400.getCode(), "endTime格式为" + DateUtil.PATTERN); | ||
| 82 | } | 78 | } |
| 83 | 79 | ||
| 84 | return logService.getAll(page, count, query, type, startTime, endTime); | 80 | return logService.getAll(page, count, query, type, startTime, endTime); |