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

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
#	src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
#	src/main/resources/all-application.yml
#	web_src/config/index.js
#	web_src/src/components/dialog/devicePlayer.vue
This commit is contained in:
648540858 2023-06-27 16:46:26 +08:00
commit 5a7a7a12bd
162 changed files with 7376 additions and 2908 deletions

View File

@ -27,7 +27,7 @@ wvp使用文档 [https://doc.wvp-pro.cn](https://doc.wvp-pro.cn)
ZLM使用文档 [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
> wvp文档由gitee提供服务如果遇到打不开请多刷新几次。
# 社群地址
# 付费社群
[![社群](doc/_media/shequ.png "shequ")](https://t.zsxq.com/0d8VAD3Dm)
> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。
@ -104,6 +104,8 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载
- [X] 支持打包可执行jar和war
- [X] 支持跨域请求,支持前后端分离部署
- [X] 支持MysqlPostgresql金仓等数据库
- [X] 支持Onvif(目前在onvif分支需要安装onvif服务服务请在知识星球获取)
# 授权协议
本项目自有代码使用宽松的MIT协议在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议

View File

@ -14,7 +14,7 @@
- 完全开源且使用MIT许可协议。保留版权的情况下可以用于商业项目。
- 支持多流媒体节点负载均衡。
# 社群
# 付费社群
[![社群](_media/shequ.png "shequ")](https://t.zsxq.com/0d8VAD3Dm)
> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。
@ -62,16 +62,16 @@
- [X] 注册
- [X] 注销
- [X] 实时视音频点播
- [ ] 设备控制
- [ ] 云台控制
- [X] 设备控制
- [X] 云台控制
- [ ] 远程启动
- [ ] 录像控制
- [ ] 报警布防/撤防
- [ ] 报警复位
- [ ] 强制关键帧
- [ ] 拉框放大
- [ ] 拉框缩小
- [ ] 看守位控制
- [X] 录像控制
- [X] 报警布防/撤防
- [X] 报警复位
- [X] 强制关键帧
- [X] 拉框放大
- [X] 拉框缩小
- [X] 看守位控制
- [ ] 设备配置
- [ ] 报警事件通知和分发
- [X] 设备目录订阅
@ -79,7 +79,7 @@
- [X] 设备目录查询
- [X] 设备状态查询
- [ ] 设备配置查询
- [ ] 设备预置位查询
- [X] 设备预置位查询
- [X] 状态信息报送
- [X] 设备视音频文件检索
- [X] 历史视音频的回放
@ -87,7 +87,7 @@
- [x] 暂停
- [x] 进/退
- [x] 停止
- [ ] 视音频文件下载
- [X] 视音频文件下载
- [ ] ~~校时~~
- [X] 订阅和通知
- [X] 事件订阅

View File

@ -29,10 +29,53 @@ java -jar wvp-pro-*.jar
```
这也是我自己最常用的方式。
## 2 配置WVP-PRO
### 2.1 Mysql数据库配置
首先你需要创建一个名为wvp也可使用其他名字的数据库并使用sql/mysql.sql导入数据库初始化数据库结构。
(这里注意取决于版本新版的sql文件夹下有update.sql补丁包一定要注意运行导入)
在application-dev.yml中配置使用1.2方式的是在jar包的同级目录的application.yml配置数据库连接包括数据库连接信息密码。
wvp支持多种数据库包括MysqlPostgresql金仓等配置任选一种即可。
### 2.1 数据库配置
#### 2.1.1 初始化数据库
首先使用创建数据库然后使用sql/初始化.sql初始化数据库如果是从旧版升级上来的使用升级sql更新。
#### 2.1.2 Mysql数据库配置
数据库名称以wvp为例
```yaml
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
username: root
password: 12345678
mybatis:
configuration:
map-underscore-to-camel-case: true
```
#### 2.1.3 Postgresql数据库配置
数据库名称以wvp为例
```yaml
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
username: root
password: 12345678
pagehelper:
helper-dialect: postgresql
```
#### 2.1.4 金仓数据库配置
数据库名称以wvp为例
```yaml
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.kingbase8.Driver
url: jdbc:kingbase8://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=utf8
username: root
password: 12345678
pagehelper:
helper-dialect: postgresql
```
### 2.2 Redis数据库配置
配置wvp中的redis连接信息建议wvp自己单独使用一个db。
### 2.3 配置服务启动端口(可直接使用默认配置)

BIN
doc/_media/1372762149.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
doc/_media/903207146.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

BIN
doc/_media/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -7,7 +7,7 @@
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="icon" href="_media/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
<link rel="stylesheet" href="./lib/css/vue.css">
<!-- <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/dark.css">-->
<style>
.cover{
@ -47,11 +47,11 @@
}
</script>
<!-- Docsify v4 -->
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
<script src="//unpkg.com/docsify-plantuml/dist/docsify-plantuml.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="./lib/js/docsify@4.js"></script>
<script src="./lib/js/docsify-plantuml.min.js"></script>
<script src="./lib/js/search.min.js"></script>
<script src="./lib/js/zoom-image.min.js"></script>
<script src="./lib/js/docsify-copy-code.min.js"></script>
</script>
<!-- <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/disqus.min.js"></script>-->

1
doc/lib/css/vue.css Normal file

File diff suppressed because one or more lines are too long

9
doc/lib/js/docsify-copy-code.min.js vendored Normal file
View File

@ -0,0 +1,9 @@
/*!
* docsify-copy-code
* v2.1.1
* https://github.com/jperasmus/docsify-copy-code
* (c) 2017-2020 JP Erasmus <jperasmus11@gmail.com>
* MIT license
*/
!function(){"use strict";function s(o){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o})(o)}!function(o,e){void 0===e&&(e={});var t=e.insertAt;if(o&&"undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],c=document.createElement("style");c.type="text/css","top"===t&&n.firstChild?n.insertBefore(c,n.firstChild):n.appendChild(c),c.styleSheet?c.styleSheet.cssText=o:c.appendChild(document.createTextNode(o))}}(".docsify-copy-code-button,.docsify-copy-code-button span{cursor:pointer;transition:all .25s ease}.docsify-copy-code-button{position:absolute;z-index:1;top:0;right:0;overflow:visible;padding:.65em .8em;border:0;border-radius:0;outline:0;font-size:1em;background:grey;background:var(--theme-color,grey);color:#fff;opacity:0}.docsify-copy-code-button span{border-radius:3px;background:inherit;pointer-events:none}.docsify-copy-code-button .error,.docsify-copy-code-button .success{position:absolute;z-index:-100;top:50%;right:0;padding:.5em .65em;font-size:.825em;opacity:0;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.docsify-copy-code-button.error .error,.docsify-copy-code-button.success .success{right:100%;opacity:1;-webkit-transform:translate(-115%,-50%);transform:translate(-115%,-50%)}.docsify-copy-code-button:focus,pre:hover .docsify-copy-code-button{opacity:1}"),document.querySelector('link[href*="docsify-copy-code"]')&&console.warn("[Deprecation] Link to external docsify-copy-code stylesheet is no longer necessary."),window.DocsifyCopyCodePlugin={init:function(){return function(o,e){o.ready(function(){console.warn("[Deprecation] Manually initializing docsify-copy-code using window.DocsifyCopyCodePlugin.init() is no longer necessary.")})}}},window.$docsify=window.$docsify||{},window.$docsify.plugins=[function(o,r){o.doneEach(function(){var o=Array.apply(null,document.querySelectorAll("pre[data-lang]")),c={buttonText:"Copy to clipboard",errorText:"Error",successText:"Copied"};r.config.copyCode&&Object.keys(c).forEach(function(t){var n=r.config.copyCode[t];"string"==typeof n?c[t]=n:"object"===s(n)&&Object.keys(n).some(function(o){var e=-1<location.href.indexOf(o);return c[t]=e?n[o]:c[t],e})});var e=['<button class="docsify-copy-code-button">','<span class="label">'.concat(c.buttonText,"</span>"),'<span class="error">'.concat(c.errorText,"</span>"),'<span class="success">'.concat(c.successText,"</span>"),"</button>"].join("");o.forEach(function(o){o.insertAdjacentHTML("beforeend",e)})}),o.mounted(function(){document.querySelector(".content").addEventListener("click",function(o){if(o.target.classList.contains("docsify-copy-code-button")){var e="BUTTON"===o.target.tagName?o.target:o.target.parentNode,t=document.createRange(),n=e.parentNode.querySelector("code"),c=window.getSelection();t.selectNode(n),c.removeAllRanges(),c.addRange(t);try{document.execCommand("copy")&&(e.classList.add("success"),setTimeout(function(){e.classList.remove("success")},1e3))}catch(o){console.error("docsify-copy-code: ".concat(o)),e.classList.add("error"),setTimeout(function(){e.classList.remove("error")},1e3)}"function"==typeof(c=window.getSelection()).removeRange?c.removeRange(t):"function"==typeof c.removeAllRanges&&c.removeAllRanges()}})})}].concat(window.$docsify.plugins||[])}();
//# sourceMappingURL=docsify-copy-code.min.js.map

1
doc/lib/js/docsify-plantuml.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
doc/lib/js/docsify@4.js Normal file

File diff suppressed because one or more lines are too long

1
doc/lib/js/search.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
doc/lib/js/zoom-image.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

23
pom.xml
View File

@ -11,7 +11,7 @@
<groupId>com.genersoft</groupId>
<artifactId>wvp-pro</artifactId>
<version>2.6.8</version>
<version>2.6.9</version>
<name>web video platform</name>
<description>国标28181视频平台</description>
<packaging>${project.packaging}</packaging>
@ -135,11 +135,30 @@
<version>8.0.30</version>
</dependency>
<!--postgresql-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.5.1</version>
</dependency>
<!-- kingbase人大金仓 -->
<!-- 手动下载驱动后安装 -->
<!-- mvn install:install-file -Dfile=/home/lin/soft/kingbase/jdbc-aarch/kingbase8-8.6.0.jar -DgroupId=com.kingbase -DartifactId=kingbase8 -Dversion=8.6.0 -Dpackaging=jar
-->
<dependency>
<groupId>com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
<version>8.6.0</version>
<scope>system</scope>
<systemPath>${basedir}/libs/jdbc-aarch/kingbase8-8.6.0.jar</systemPath>
</dependency>
<!--Mybatis分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.3</version>
<version>1.4.6</version>
</dependency>
<!--在线文档 -->

View File

@ -7,6 +7,7 @@ alter table parent_platform
alter table device
add mediaServerId varchar(50) default null;
ALTER TABLE device
ADD COLUMN `switchPrimarySubStream` bit(1) NOT NULL DEFAULT b'0' COMMENT '开启主子码流切换的开关0-不开启1-开启)现在已知支持设备为 大华、TP——LINK全系设备' AFTER `keepalive_interval_time`

479
sql/2.6.8升级2.6.9.sql Normal file
View File

@ -0,0 +1,479 @@
alter table device
change deviceId device_id varchar(50) not null;
alter table device
change streamMode stream_mode varchar(50) null;
alter table device
change registerTime register_time varchar(50) null;
alter table device
change keepaliveTime keepalive_time varchar(50) null;
alter table device
change createTime create_time varchar(50) not null;
alter table device
change updateTime update_time varchar(50) not null;
alter table device
change subscribeCycleForCatalog subscribe_cycle_for_catalog bool default false;
alter table device
change subscribeCycleForMobilePosition subscribe_cycle_for_mobile_position bool default false;
alter table device
change mobilePositionSubmissionInterval mobile_position_submission_interval int default 5 not null;
alter table device
change subscribeCycleForAlarm subscribe_cycle_for_alarm bool default false;
alter table device
change hostAddress host_address varchar(50) null;
alter table device
change ssrcCheck ssrc_check bool default false;
alter table device
change geoCoordSys geo_coord_sys varchar(50) not null;
alter table device
drop column treeType;
alter table device
change mediaServerId media_server_id varchar(50) default 'auto' null;
alter table device
change sdpIp sdp_ip varchar(50) null;
alter table device
change localIp local_ip varchar(50) null;
alter table device
change asMessageChannel as_message_channel bool default false;
alter table device
change keepaliveIntervalTime keepalive_interval_time int null;
alter table device
change online on_line varchar(50) null;
alter table device
add COLUMN switch_primary_sub_stream bool default false comment '开启主子码流切换的开关0-不开启1-开启)现在已知支持设备为 大华、TP——LINK全系设备'
alter table device_alarm
change deviceId device_id varchar(50) not null;
alter table device_alarm
change channelId channel_id varchar(50) not null;
alter table device_alarm
change alarmPriority alarm_priority varchar(50) not null;
alter table device_alarm
change alarmMethod alarm_method varchar(50) null;
alter table device_alarm
change alarmTime alarm_time varchar(50) not null;
alter table device_alarm
change alarmDescription alarm_description varchar(255) null;
alter table device_alarm
change alarmType alarm_type varchar(50) null;
alter table device_alarm
change createTime create_time varchar(50) null;
alter table device_channel
change channelId channel_id varchar(50) not null;
alter table device_channel
change civilCode civil_code varchar(50) null;
alter table device_channel
change parentId parent_id varchar(50) null;
alter table device_channel
change safetyWay safety_way int null;
alter table device_channel
change registerWay register_way int null;
alter table device_channel
change certNum cert_num varchar(50) null;
alter table device_channel
change errCode err_code int null;
alter table device_channel
change endTime end_time varchar(50) null;
alter table device_channel
change ipAddress ip_address varchar(50) null;
alter table device_channel
change PTZType ptz_type int null;
alter table device_channel
change status status bool default false;
alter table device_channel
change streamId stream_id varchar(50) null;
alter table device_channel
change deviceId device_id varchar(50) not null;
alter table device_channel
change hasAudio has_audio bool default false;
alter table device_channel
change createTime create_time varchar(50) not null;
alter table device_channel
change updateTime update_time varchar(50) not null;
alter table device_channel
change subCount sub_count int default 0 null;
alter table device_channel
change longitudeGcj02 longitude_gcj02 double null;
alter table device_channel
change latitudeGcj02 latitude_gcj02 double null;
alter table device_channel
change longitudeWgs84 longitude_wgs84 double null;
alter table device_channel
change latitudeWgs84 latitude_wgs84 double null;
alter table device_channel
change businessGroupId business_group_id varchar(50) null;
alter table device_channel
change gpsTime gps_time varchar(50) null;
alter table device_mobile_position
change deviceId device_id varchar(50) not null;
alter table device_mobile_position
change channelId channel_id varchar(50) not null;
alter table device_mobile_position
change deviceName device_name varchar(255) null;
alter table device_mobile_position
change reportSource report_source varchar(50) null;
alter table device_mobile_position
change longitudeGcj02 longitude_gcj02 double null;
alter table device_mobile_position
change latitudeGcj02 latitude_gcj02 double null;
alter table device_mobile_position
change longitudeWgs84 longitude_wgs84 double null;
alter table device_mobile_position
change latitudeWgs84 latitude_wgs84 double null;
alter table device_mobile_position
change createTime create_time varchar(50) null;
alter table gb_stream
change gbStreamId gb_stream_id int auto_increment;
alter table gb_stream
change gbId gb_id varchar(50) not null;
alter table gb_stream
change streamType stream_type varchar(50) null;
alter table gb_stream
change mediaServerId media_server_id varchar(50) null;
alter table gb_stream
change createTime create_time varchar(50) null;
alter table log
change createTime create_time varchar(50) not null;
alter table media_server
change hookIp hook_ip varchar(50) not null;
alter table media_server
change sdpIp sdp_ip varchar(50) not null;
alter table media_server
change streamIp stream_ip varchar(50) not null;
alter table media_server
change httpPort http_port int not null;
alter table media_server
change httpSSlPort http_ssl_port int not null;
alter table media_server
change rtmpPort rtmp_port int not null;
alter table media_server
change rtmpSSlPort rtmp_ssl_port int not null;
alter table media_server
change rtpProxyPort rtp_proxy_port int not null;
alter table media_server
change rtspPort rtsp_port int not null;
alter table media_server
change rtspSSLPort rtsp_ssl_port int not null;
alter table media_server
change autoConfig auto_config bool default true;
alter table media_server
change rtpEnable rtp_enable bool default false;
alter table media_server
change rtpPortRange rtp_port_range varchar(50) not null;
alter table media_server
change recordAssistPort record_assist_port int not null;
alter table media_server
change defaultServer default_server bool default false;
alter table media_server
change createTime create_time varchar(50) not null;
alter table media_server
change updateTime update_time varchar(50) not null;
alter table media_server
change hookAliveInterval hook_alive_interval int not null;
alter table parent_platform
change serverGBId server_gb_id varchar(50) not null;
alter table parent_platform
change serverGBDomain server_gb_domain varchar(50) null;
alter table parent_platform
change serverIP server_ip varchar(50) null;
alter table parent_platform
change serverPort server_port int null;
alter table parent_platform
change deviceGBId device_gb_id varchar(50) not null;
alter table parent_platform
change deviceIp device_ip varchar(50) null;
alter table parent_platform
change devicePort device_port varchar(50) null;
alter table parent_platform
change keepTimeout keep_timeout varchar(50) null;
alter table parent_platform
change characterSet character_set varchar(50) null;
alter table parent_platform
change catalogId catalog_id varchar(50) not null;
alter table parent_platform
change startOfflinePush start_offline_push bool default false;
alter table parent_platform
change administrativeDivision administrative_division varchar(50) not null;
alter table parent_platform
change catalogGroup catalog_group int default 1 null;
alter table parent_platform
change createTime create_time varchar(50) null;
alter table parent_platform
change updateTime update_time varchar(50) null;
alter table parent_platform
drop column treeType;
alter table parent_platform
change asMessageChannel as_message_channel bool default false;
alter table parent_platform
change enable enable bool default false;
alter table parent_platform
change ptz ptz bool default false;
alter table parent_platform
change rtcp rtcp bool default false;
alter table parent_platform
change status status bool default false;
alter table parent_platform
change status status bool default false;
alter table platform_catalog
change platformId platform_id varchar(50) not null;
alter table platform_catalog
change parentId parent_id varchar(50) null;
alter table platform_catalog
change civilCode civil_code varchar(50) null;
alter table platform_catalog
change businessGroupId business_group_id varchar(50) null;
alter table platform_gb_channel
change platformId platform_id varchar(50) not null;
alter table platform_gb_channel
change catalogId catalog_id varchar(50) not null;
alter table platform_gb_channel
change deviceChannelId device_channel_id int not null;
alter table platform_gb_stream
change platformId platform_id varchar(50) not null;
alter table platform_gb_stream
change catalogId catalog_id varchar(50) not null;
alter table platform_gb_stream
change gbStreamId gb_stream_id int not null;
alter table stream_proxy
change mediaServerId media_server_id varchar(50) null;
alter table stream_proxy
change createTime create_time varchar(50) not null;
alter table stream_proxy
change updateTime update_time varchar(50) null;
alter table stream_proxy
change enable_remove_none_reader enable_remove_none_reader bool default false;
alter table stream_proxy
change enable_disable_none_reader enable_disable_none_reader bool default false;
alter table stream_proxy
change enable_audio enable_audio bool default false;
alter table stream_proxy
change enable_mp4 enable_mp4 bool default false;
alter table stream_proxy
change enable enable bool default false;
alter table stream_push
change totalReaderCount total_reader_count varchar(50) null;
alter table stream_push
change originType origin_type int null;
alter table stream_push
change originTypeStr origin_type_str varchar(50) null;
alter table stream_push
change createTime create_time varchar(50) null;
alter table stream_push
change aliveSecond alive_second int null;
alter table stream_push
change mediaServerId media_server_id varchar(50) null;
alter table stream_push
change status status bool default false;
alter table stream_push
change pushTime push_time varchar(50) null;
alter table stream_push
change updateTime update_time varchar(50) null;
alter table stream_push
change pushIng push_ing bool default false;
alter table stream_push
change status status bool default false;
alter table stream_push
change self self bool default false;
alter table stream_push
drop column serverId;
alter table user
change roleId role_id int not null;
alter table user
change createTime create_time varchar(50) not null;
alter table user
change updateTime update_time varchar(50) not null;
alter table user
change pushKey push_key varchar(50) null;
alter table user_role
change createTime create_time varchar(50) not null;
alter table user_role
change updateTime update_time varchar(50) not null;
rename table device to wvp_device;
rename table device_alarm to wvp_device_alarm;
rename table device_channel to wvp_device_channel;
rename table device_mobile_position to wvp_device_mobile_position;
rename table gb_stream to wvp_gb_stream;
rename table log to wvp_log;
rename table media_server to wvp_media_server;
rename table parent_platform to wvp_platform;
rename table platform_catalog to wvp_platform_catalog;
rename table platform_gb_channel to wvp_platform_gb_channel;
rename table platform_gb_stream to wvp_platform_gb_stream;
rename table stream_proxy to wvp_stream_proxy;
rename table stream_push to wvp_stream_push;
rename table user to wvp_user;
rename table user_role to wvp_user_role;

View File

@ -1,13 +1,13 @@
delete from device;
delete from device_alarm;
delete from device_channel;
delete from device_mobile_position;
delete from gb_stream;
delete from log;
delete from media_server;
delete from parent_platform;
delete from platform_catalog;
delete from platform_gb_channel;
delete from platform_gb_stream;
delete from stream_proxy;
delete from stream_push;
delete from wvp-device;
delete from wvp-device_alarm;
delete from wvp-device_channel;
delete from wvp-device_mobile_position;
delete from wvp-gb_stream;
delete from wvp-log;
delete from wvp-media_server;
delete from wvp-parent_platform;
delete from wvp-platform_catalog;
delete from wvp-platform_gb_channel;
delete from wvp-platform_gb_stream;
delete from wvp-stream_proxy;
delete from wvp-stream_push;

View File

@ -1,580 +1,286 @@
-- MySQL dump 10.13 Distrib 8.0.31, for Linux (x86_64)
--
-- Host: 127.0.0.1 Database: wvp
-- ------------------------------------------------------
-- Server version 8.0.30
/*建表*/
create table wvp_device (
id serial primary key ,
device_id character varying(50) not null ,
name character varying(255),
manufacturer character varying(255),
model character varying(255),
firmware character varying(255),
transport character varying(50),
stream_mode character varying(50),
on_line bool default false,
register_time character varying(50),
keepalive_time character varying(50),
ip character varying(50),
create_time character varying(50),
update_time character varying(50),
port integer,
expires integer,
subscribe_cycle_for_catalog integer DEFAULT 0,
subscribe_cycle_for_mobile_position integer DEFAULT 0,
mobile_position_submission_interval integer DEFAULT 5,
subscribe_cycle_for_alarm integer DEFAULT 0,
host_address character varying(50),
charset character varying(50),
ssrc_check bool default false,
geo_coord_sys character varying(50),
media_server_id character varying(50),
custom_name character varying(255),
sdp_ip character varying(50),
local_ip character varying(50),
password character varying(255),
as_message_channel bool default false,
keepalive_interval_time integer,
switch_primary_sub_stream bool default false,
constraint uk_device_device unique (device_id)
);
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
create table wvp_device_alarm (
id serial primary key ,
device_id character varying(50) not null,
channel_id character varying(50) not null,
alarm_priority character varying(50),
alarm_method character varying(50),
alarm_time character varying(50),
alarm_description character varying(255),
longitude double precision,
latitude double precision,
alarm_type character varying(50),
create_time character varying(50) not null
);
--
-- Table structure for table `device`
--
create table wvp_device_channel (
id serial primary key ,
channel_id character varying(50) not null,
name character varying(255),
manufacture character varying(50),
model character varying(50),
owner character varying(50),
civil_code character varying(50),
block character varying(50),
address character varying(50),
parent_id character varying(50),
safety_way integer,
register_way integer,
cert_num character varying(50),
certifiable integer,
err_code integer,
end_time character varying(50),
secrecy character varying(50),
ip_address character varying(50),
port integer,
password character varying(255),
ptz_type integer,
status bool default false,
longitude double precision,
latitude double precision,
stream_id character varying(50),
device_id character varying(50) not null,
parental character varying(50),
has_audio bool default false,
create_time character varying(50) not null,
update_time character varying(50) not null,
sub_count integer,
longitude_gcj02 double precision,
latitude_gcj02 double precision,
longitude_wgs84 double precision,
latitude_wgs84 double precision,
business_group_id character varying(50),
gps_time character varying(50),
constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
);
DROP TABLE IF EXISTS `device`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device` (
`id` int NOT NULL AUTO_INCREMENT,
`deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`manufacturer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`firmware` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`port` int DEFAULT NULL,
`expires` int DEFAULT NULL,
`keepaliveIntervalTime` int DEFAULT NULL,
`subscribeCycleForCatalog` int DEFAULT NULL,
`hostAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`charset` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`subscribeCycleForMobilePosition` int DEFAULT NULL,
`mobilePositionSubmissionInterval` int DEFAULT '5',
`subscribeCycleForAlarm` int DEFAULT NULL,
`ssrcCheck` int DEFAULT '0',
`asMessageChannel` int DEFAULT '0',
`geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`custom_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`sdpIp` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`localIp` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `device_deviceId_uindex` (`deviceId`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
create table wvp_device_mobile_position (
id serial primary key,
device_id character varying(50) not null,
channel_id character varying(50) not null,
device_name character varying(255),
time character varying(50),
longitude double precision,
latitude double precision,
altitude double precision,
speed double precision,
direction double precision,
report_source character varying(50),
longitude_gcj02 double precision,
latitude_gcj02 double precision,
longitude_wgs84 double precision,
latitude_wgs84 double precision,
create_time character varying(50)
);
--
-- Dumping data for table `device`
--
create table wvp_gb_stream (
gb_stream_id serial primary key,
app character varying(255) not null,
stream character varying(255) not null,
gb_id character varying(50) not null,
name character varying(255),
longitude double precision,
latitude double precision,
stream_type character varying(50),
media_server_id character varying(50),
create_time character varying(50),
constraint uk_gb_stream_unique_gb_id unique (gb_id),
constraint uk_gb_stream_unique_app_stream unique (app, stream)
);
LOCK TABLES `device` WRITE;
/*!40000 ALTER TABLE `device` DISABLE KEYS */;
/*!40000 ALTER TABLE `device` ENABLE KEYS */;
UNLOCK TABLES;
create table wvp_log (
id serial primary key ,
name character varying(50),
type character varying(50),
uri character varying(200),
address character varying(50),
result character varying(50),
timing bigint,
username character varying(50),
create_time character varying(50)
);
--
-- Table structure for table `device_alarm`
--
create table wvp_media_server (
id character varying(255) primary key ,
ip character varying(50),
hook_ip character varying(50),
sdp_ip character varying(50),
stream_ip character varying(50),
http_port integer,
http_ssl_port integer,
rtmp_port integer,
rtmp_ssl_port integer,
rtp_proxy_port integer,
rtsp_port integer,
rtsp_ssl_port integer,
auto_config bool default false,
secret character varying(50),
rtp_enable bool default false,
rtp_port_range character varying(50),
record_assist_port integer,
default_server bool default false,
create_time character varying(50),
update_time character varying(50),
hook_alive_interval integer,
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
DROP TABLE IF EXISTS `device_alarm`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_alarm` (
`id` int NOT NULL AUTO_INCREMENT,
`deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL,
`alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
create table wvp_platform (
id serial primary key ,
enable bool default false,
name character varying(255),
server_gb_id character varying(50),
server_gb_domain character varying(50),
server_ip character varying(50),
server_port integer,
device_gb_id character varying(50),
device_ip character varying(50),
device_port character varying(50),
username character varying(255),
password character varying(50),
expires character varying(50),
keep_timeout character varying(50),
transport character varying(50),
character_set character varying(50),
catalog_id character varying(50),
ptz bool default false,
rtcp bool default false,
status bool default false,
start_offline_push bool default false,
administrative_division character varying(50),
catalog_group integer,
create_time character varying(50),
update_time character varying(50),
as_message_channel bool default false,
constraint uk_platform_unique_server_gb_id unique (server_gb_id)
);
--
-- Dumping data for table `device_alarm`
--
create table wvp_platform_catalog (
id character varying(50),
platform_id character varying(50),
name character varying(255),
parent_id character varying(50),
civil_code character varying(50),
business_group_id character varying(50),
constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
);
LOCK TABLES `device_alarm` WRITE;
/*!40000 ALTER TABLE `device_alarm` DISABLE KEYS */;
/*!40000 ALTER TABLE `device_alarm` ENABLE KEYS */;
UNLOCK TABLES;
create table wvp_platform_gb_channel (
id serial primary key ,
platform_id character varying(50),
catalog_id character varying(50),
device_channel_id integer,
constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
);
--
-- Table structure for table `device_channel`
--
create table wvp_platform_gb_stream (
id serial primary key,
platform_id character varying(50),
catalog_id character varying(50),
gb_stream_id integer,
constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
);
DROP TABLE IF EXISTS `device_channel`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_channel` (
`id` int NOT NULL AUTO_INCREMENT,
`channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`safetyWay` int DEFAULT NULL,
`registerWay` int DEFAULT NULL,
`certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`certifiable` int DEFAULT NULL,
`errCode` int DEFAULT NULL,
`endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`port` int DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`PTZType` int DEFAULT NULL,
`status` int DEFAULT NULL,
`longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL,
`streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`hasAudio` bit(1) DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`subCount` int DEFAULT '0',
`longitudeGcj02` double DEFAULT NULL,
`latitudeGcj02` double DEFAULT NULL,
`longitudeWgs84` double DEFAULT NULL,
`latitudeWgs84` double DEFAULT NULL,
`businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`gpsTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `device_channel_id_uindex` (`id`),
UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
create table wvp_stream_proxy (
id serial primary key,
type character varying(50),
app character varying(255),
stream character varying(255),
url character varying(255),
src_url character varying(255),
dst_url character varying(255),
timeout_ms integer,
ffmpeg_cmd_key character varying(255),
rtp_type character varying(50),
media_server_id character varying(50),
enable_audio bool default false,
enable_mp4 bool default false,
enable bool default false,
status boolean,
enable_remove_none_reader bool default false,
create_time character varying(50),
name character varying(255),
update_time character varying(50),
enable_disable_none_reader bool default false,
constraint uk_stream_proxy_app_stream unique (app, stream)
);
--
-- Dumping data for table `device_channel`
--
create table wvp_stream_push (
id serial primary key,
app character varying(255),
stream character varying(255),
total_reader_count character varying(50),
origin_type integer,
origin_type_str character varying(50),
create_time character varying(50),
alive_second integer,
media_server_id character varying(50),
push_time character varying(50),
status bool default false,
update_time character varying(50),
push_ing bool default false,
self bool default false,
constraint uk_stream_push_app_stream unique (app, stream)
);
LOCK TABLES `device_channel` WRITE;
/*!40000 ALTER TABLE `device_channel` DISABLE KEYS */;
/*!40000 ALTER TABLE `device_channel` ENABLE KEYS */;
UNLOCK TABLES;
create table wvp_user (
id serial primary key,
username character varying(255),
password character varying(255),
role_id integer,
create_time character varying(50),
update_time character varying(50),
push_key character varying(50),
constraint uk_user_username unique (username)
);
--
-- Table structure for table `device_mobile_position`
--
create table wvp_user_role (
id serial primary key,
name character varying(50),
authority character varying(50),
create_time character varying(50),
update_time character varying(50)
);
DROP TABLE IF EXISTS `device_mobile_position`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_mobile_position` (
`id` int NOT NULL AUTO_INCREMENT,
`deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`deviceName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`longitude` double NOT NULL,
`latitude` double NOT NULL,
`altitude` double DEFAULT NULL,
`speed` double DEFAULT NULL,
`direction` double DEFAULT NULL,
`reportSource` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`longitudeGcj02` double DEFAULT NULL,
`latitudeGcj02` double DEFAULT NULL,
`longitudeWgs84` double DEFAULT NULL,
`latitudeWgs84` double DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*初始数据*/
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
--
-- Dumping data for table `device_mobile_position`
--
LOCK TABLES `device_mobile_position` WRITE;
/*!40000 ALTER TABLE `device_mobile_position` DISABLE KEYS */;
/*!40000 ALTER TABLE `device_mobile_position` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `gb_stream`
--
DROP TABLE IF EXISTS `gb_stream`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `gb_stream` (
`gbStreamId` int NOT NULL AUTO_INCREMENT,
`app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL,
`streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`gbStreamId`) USING BTREE,
UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
UNIQUE KEY `gbId` (`gbId`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `gb_stream`
--
LOCK TABLES `gb_stream` WRITE;
/*!40000 ALTER TABLE `gb_stream` DISABLE KEYS */;
/*!40000 ALTER TABLE `gb_stream` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `log`
--
DROP TABLE IF EXISTS `log`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `log` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`timing` bigint NOT NULL,
`username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `log`
--
LOCK TABLES `log` WRITE;
/*!40000 ALTER TABLE `log` DISABLE KEYS */;
/*!40000 ALTER TABLE `log` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `media_server`
--
DROP TABLE IF EXISTS `media_server`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `media_server` (
`id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`httpPort` int NOT NULL,
`httpSSlPort` int NOT NULL,
`rtmpPort` int NOT NULL,
`rtmpSSlPort` int NOT NULL,
`rtpProxyPort` int NOT NULL,
`rtspPort` int NOT NULL,
`rtspSSLPort` int NOT NULL,
`autoConfig` int NOT NULL,
`secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`rtpEnable` int NOT NULL,
`rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`recordAssistPort` int NOT NULL,
`defaultServer` int NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`hookAliveInterval` int NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `media_server`
--
LOCK TABLES `media_server` WRITE;
/*!40000 ALTER TABLE `media_server` DISABLE KEYS */;
/*!40000 ALTER TABLE `media_server` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `parent_platform`
--
DROP TABLE IF EXISTS `parent_platform`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `parent_platform` (
`id` int NOT NULL AUTO_INCREMENT,
`enable` int DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`serverPort` int DEFAULT NULL,
`deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`ptz` int DEFAULT NULL,
`rtcp` int DEFAULT NULL,
`asMessageChannel` int DEFAULT '0',
`status` bit(1) DEFAULT NULL,
`startOfflinePush` int DEFAULT '0',
`administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`catalogGroup` int DEFAULT '1',
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `parent_platform_id_uindex` (`id`),
UNIQUE KEY `parent_platform_pk` (`serverGBId`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `parent_platform`
--
LOCK TABLES `parent_platform` WRITE;
/*!40000 ALTER TABLE `parent_platform` DISABLE KEYS */;
/*!40000 ALTER TABLE `parent_platform` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `platform_catalog`
--
DROP TABLE IF EXISTS `platform_catalog`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_catalog` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `platform_catalog`
--
LOCK TABLES `platform_catalog` WRITE;
/*!40000 ALTER TABLE `platform_catalog` DISABLE KEYS */;
/*!40000 ALTER TABLE `platform_catalog` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `platform_gb_channel`
--
DROP TABLE IF EXISTS `platform_gb_channel`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_gb_channel` (
`id` int NOT NULL AUTO_INCREMENT,
`platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`deviceChannelId` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `platform_gb_channel`
--
LOCK TABLES `platform_gb_channel` WRITE;
/*!40000 ALTER TABLE `platform_gb_channel` DISABLE KEYS */;
/*!40000 ALTER TABLE `platform_gb_channel` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `platform_gb_stream`
--
DROP TABLE IF EXISTS `platform_gb_stream`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_gb_stream` (
`id` int NOT NULL AUTO_INCREMENT,
`platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`gbStreamId` int NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `platform_gb_stream`
--
LOCK TABLES `platform_gb_stream` WRITE;
/*!40000 ALTER TABLE `platform_gb_stream` DISABLE KEYS */;
/*!40000 ALTER TABLE `platform_gb_stream` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `stream_proxy`
--
DROP TABLE IF EXISTS `stream_proxy`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `stream_proxy` (
`id` int NOT NULL AUTO_INCREMENT,
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`src_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`dst_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`timeout_ms` int DEFAULT NULL,
`ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`enable_audio` bit(1) DEFAULT NULL,
`enable_mp4` bit(1) DEFAULT NULL,
`enable` bit(1) NOT NULL,
`status` bit(1) NOT NULL,
`enable_remove_none_reader` bit(1) NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`enable_disable_none_reader` bit(1) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `stream_proxy_pk` (`app`,`stream`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `stream_proxy`
--
LOCK TABLES `stream_proxy` WRITE;
/*!40000 ALTER TABLE `stream_proxy` DISABLE KEYS */;
/*!40000 ALTER TABLE `stream_proxy` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `stream_push`
--
DROP TABLE IF EXISTS `stream_push`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `stream_push` (
`id` int NOT NULL AUTO_INCREMENT,
`app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`totalReaderCount` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`originType` int DEFAULT NULL,
`originTypeStr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`aliveSecond` int DEFAULT NULL,
`mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`serverId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`pushTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`status` int DEFAULT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`pushIng` int DEFAULT NULL,
`self` int DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `stream_push_pk` (`app`,`stream`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `stream_push`
--
LOCK TABLES `stream_push` WRITE;
/*!40000 ALTER TABLE `stream_push` DISABLE KEYS */;
/*!40000 ALTER TABLE `stream_push` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `user`
--
DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`roleId` int NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`pushKey` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `user`
--
LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `user_role`
--
DROP TABLE IF EXISTS `user_role`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `user_role` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `user_role`
--
LOCK TABLES `user_role` WRITE;
/*!40000 ALTER TABLE `user_role` DISABLE KEYS */;
INSERT INTO `user_role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
/*!40000 ALTER TABLE `user_role` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2022-11-29 11:47:46

View File

@ -0,0 +1,42 @@
package com.genersoft.iot.vmp.common;
public class CivilCodePo {
private String code;
private String name;
private String parentCode;
public static CivilCodePo getInstance(String[] infoArray) {
CivilCodePo civilCodePo = new CivilCodePo();
civilCodePo.setCode(infoArray[0]);
civilCodePo.setName(infoArray[1]);
civilCodePo.setParentCode(infoArray[2]);
return civilCodePo;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getParentCode() {
return parentCode;
}
public void setParentCode(String parentCode) {
this.parentCode = parentCode;
}
}

View File

@ -0,0 +1,5 @@
package com.genersoft.iot.vmp.common;
public interface GeneralCallback<T>{
void run(int code, String msg, T data);
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.common;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 记录每次发送invite消息的状态
@ -28,7 +29,7 @@ public class InviteInfo {
private StreamInfo streamInfo;
public static InviteInfo getinviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo,
public static InviteInfo getInviteInfo(String deviceId, String channelId, String stream, SSRCInfo ssrcInfo,
String receiveIp, Integer receivePort, String streamMode,
InviteSessionType type, InviteSessionStatus status) {
InviteInfo inviteInfo = new InviteInfo();
@ -123,4 +124,21 @@ public class InviteInfo {
public void setStreamMode(String streamMode) {
this.streamMode = streamMode;
}
/*=========================设备主子码流逻辑START====================*/
@Schema(description = "是否为子码流(true-是false-主码流)")
private boolean subStream;
public boolean isSubStream() {
return subStream;
}
public void setSubStream(boolean subStream) {
this.subStream = subStream;
}
}

View File

@ -528,4 +528,19 @@ public class StreamInfo implements Serializable, Cloneable{
}
return instance;
}
/*=========================设备主子码流逻辑START====================*/
@Schema(description = "是否为子码流(true-是false-主码流)")
private boolean subStream;
public boolean isSubStream() {
return subStream;
}
public void setSubStream(boolean subStream) {
this.subStream = subStream;
}
}

View File

@ -107,6 +107,11 @@ public class VideoManagerConstants {
*/
public static final String VM_MSG_STREAM_PUSH_RESPONSE = "VM_MSG_STREAM_PUSH_RESPONSE";
/**
* redis 通知平台关闭推流
*/
public static final String VM_MSG_STREAM_PUSH_CLOSE = "VM_MSG_STREAM_PUSH_CLOSE";
/**
* redis 消息请求所有的在线通道
*/

View File

@ -0,0 +1,101 @@
package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.common.CivilCodePo;
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ObjectUtils;
import java.io.*;
import java.nio.file.Files;
import java.util.Map;
/**
* 启动时读取行政区划表
*/
@Configuration
@Order(value=14)
public class CivilCodeFileConf implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(CivilCodeFileConf.class);
private final Map<String, CivilCodePo> civilCodeMap= new ConcurrentHashMap<>();
@Autowired
@Lazy
private UserSetting userSetting;
@Override
public void run(String... args) throws Exception {
if (ObjectUtils.isEmpty(userSetting.getCivilCodeFile())) {
logger.warn("[行政区划] 文件未设置,可能造成目录刷新结果不完整");
return;
}
InputStream inputStream;
if (userSetting.getCivilCodeFile().startsWith("classpath:")){
String filePath = userSetting.getCivilCodeFile().substring("classpath:".length());
ClassPathResource civilCodeFile = new ClassPathResource(filePath);
if (!civilCodeFile.exists()) {
logger.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
return;
}
inputStream = civilCodeFile.getInputStream();
}else {
File civilCodeFile = new File(userSetting.getCivilCodeFile());
if (!civilCodeFile.exists()) {
logger.warn("[行政区划] 文件<{}>不存在,可能造成目录刷新结果不完整", userSetting.getCivilCodeFile());
return;
}
inputStream = Files.newInputStream(civilCodeFile.toPath());
}
BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(inputStream));
int index = -1;
String line;
while ((line = inputStreamReader.readLine()) != null) {
index ++;
if (index == 0) {
continue;
}
String[] infoArray = line.split(",");
CivilCodePo civilCodePo = CivilCodePo.getInstance(infoArray);
civilCodeMap.put(civilCodePo.getCode(), civilCodePo);
}
inputStreamReader.close();
inputStream.close();
if (civilCodeMap.size() == 0) {
logger.warn("[行政区划] 文件内容为空,可能造成目录刷新结果不完整");
}else {
logger.info("[行政区划] 加载成功,共加载数据{}条", civilCodeMap.size());
}
}
public CivilCodePo getParentCode(String code) {
if (code.length() > 8) {
return null;
}
if (code.length() == 8) {
String parentCode = code.substring(0, 6);
return civilCodeMap.get(parentCode);
}else {
CivilCodePo civilCodePo = civilCodeMap.get(code);
if (civilCodePo == null){
return null;
}
String parentCode = civilCodePo.getParentCode();
if (parentCode == null) {
return null;
}
return civilCodeMap.get(parentCode);
}
}
}

View File

@ -2,11 +2,11 @@ package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.junit.jupiter.api.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.util.ObjectUtils;
import java.net.InetAddress;

View File

@ -0,0 +1,36 @@
package com.genersoft.iot.vmp.conf;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import javax.sql.DataSource;
/**
* 配置mybatis
*/
@Configuration
@Order(value=1)
public class MybatisConfig {
@Autowired
private UserSetting userSetting;
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
final SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
sqlSessionFactory.setDataSource(dataSource);
org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
if (userSetting.getSqlLog()){
config.setLogImpl(StdOutImpl.class);
}
config.setMapUnderscoreToCamelCase(true);
sqlSessionFactory.setConfiguration(config);
return sqlSessionFactory.getObject();
}
}

View File

@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.service.IMediaServerService;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.junit.jupiter.api.Order;
import org.springframework.core.annotation.Order;
import org.mitre.dsmiley.httpproxy.ProxyServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.conf;
import org.junit.jupiter.api.Order;
import org.springframework.core.annotation.Order;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

View File

@ -56,7 +56,7 @@ public class SipPlatformRunner implements CommandLineRunner {
}
// 设置所有平台离线
platformService.offline(parentPlatform, true);
platformService.offline(parentPlatform, false);
}
}
}

View File

@ -4,7 +4,7 @@ import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.junit.jupiter.api.Order;
import org.springframework.core.annotation.Order;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

View File

@ -1,8 +1,8 @@
package com.genersoft.iot.vmp.conf;
import org.junit.jupiter.api.Order;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

View File

@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.conf;
import org.junit.jupiter.api.Order;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
@ -50,6 +50,7 @@ public class UserSetting {
private Boolean pushStreamAfterAck = Boolean.FALSE;
private Boolean sipLog = Boolean.FALSE;
private Boolean sqlLog = Boolean.FALSE;
private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE;
private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE;
@ -65,12 +66,18 @@ public class UserSetting {
private String broadcastForPlatform = "UDP";
private String civilCodeFile = "classpath:civilCode.csv";
private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
private List<String> allowedOrigins = new ArrayList<>();
private int maxNotifyCountQueue = 10000;
private int registerAgainAfterTime = 60;
private boolean registerKeepIntDialog = false;
public Boolean getSavePositionHistory() {
return savePositionHistory;
}
@ -306,4 +313,36 @@ public class UserSetting {
public void setUseCustomSsrcForParentInvite(Boolean useCustomSsrcForParentInvite) {
this.useCustomSsrcForParentInvite = useCustomSsrcForParentInvite;
}
public Boolean getSqlLog() {
return sqlLog;
}
public void setSqlLog(Boolean sqlLog) {
this.sqlLog = sqlLog;
}
public String getCivilCodeFile() {
return civilCodeFile;
}
public void setCivilCodeFile(String civilCodeFile) {
this.civilCodeFile = civilCodeFile;
}
public int getRegisterAgainAfterTime() {
return registerAgainAfterTime;
}
public void setRegisterAgainAfterTime(int registerAgainAfterTime) {
this.registerAgainAfterTime = registerAgainAfterTime;
}
public boolean isRegisterKeepIntDialog() {
return registerKeepIntDialog;
}
public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
this.registerKeepIntDialog = registerKeepIntDialog;
}
}

View File

@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.conf;
import org.junit.jupiter.api.Order;
import org.springframework.core.annotation.Order;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

View File

@ -43,6 +43,9 @@ public class RedisMsgListenConfig {
@Autowired
private RedisPushStreamResponseListener redisPushStreamResponseListener;
@Autowired
private RedisCloseStreamMsgListener redisCloseStreamMsgListener;
/**
* redis消息监听器容器 可以添加多个监听不同话题的redis监听器只需要把消息监听器和相应的消息订阅处理器绑定该消息监听器
@ -63,6 +66,7 @@ public class RedisMsgListenConfig {
container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
container.addMessageListener(redisPushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE));
container.addMessageListener(redisPushStreamResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE));
container.addMessageListener(redisCloseStreamMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE));
return container;
}
}

View File

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.conf.security;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
@ -12,6 +13,7 @@ import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* 处理匿名用户访问逻辑
@ -35,6 +37,8 @@ public class AnonymousAuthenticationEntryPoint implements AuthenticationEntry
jsonObject.put("msg", e.getMessage());
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
try {
response.getWriter().print(jsonObject.toJSONString());
} catch (IOException ioException) {

View File

@ -1,7 +1,7 @@
package com.genersoft.iot.vmp.conf.security;
import com.genersoft.iot.vmp.conf.UserSetting;
import org.junit.jupiter.api.Order;
import org.springframework.core.annotation.Order;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -77,8 +77,8 @@ public class Device {
/**
* 在线
*/
@Schema(description = "是否在线,1为在线0为离线")
private int online;
@Schema(description = "是否在线,true为在线false为离线")
private boolean onLine;
/**
@ -140,7 +140,7 @@ public class Device {
/**
* 目录订阅周期0为不订阅
*/
@Schema(description = "目录订阅周期,0为不订阅")
@Schema(description = "目录订阅周期,o为不订阅")
private int subscribeCycleForCatalog;
/**
@ -173,12 +173,6 @@ public class Device {
@Schema(description = "地理坐标系, 目前支持 WGS84,GCJ02")
private String geoCoordSys;
/**
* 树类型 国标规定了两种树的展现方式 行政区划CivilCode 和业务分组:BusinessGroup
*/
@Schema(description = "树类型 国标规定了两种树的展现方式 行政区划CivilCode 和业务分组:BusinessGroup")
private String treeType;
@Schema(description = "密码")
private String password;
@ -195,6 +189,8 @@ public class Device {
private SipTransactionInfo sipTransactionInfo;
public String getDeviceId() {
return deviceId;
}
@ -286,12 +282,12 @@ public class Device {
this.hostAddress = hostAddress;
}
public int getOnline() {
return online;
public boolean isOnLine() {
return onLine;
}
public void setOnline(int online) {
this.online = online;
public void setOnLine(boolean onLine) {
this.onLine = onLine;
}
public int getChannelCount() {
@ -406,15 +402,6 @@ public class Device {
this.geoCoordSys = geoCoordSys;
}
public String getTreeType() {
return treeType;
}
public void setTreeType(String treeType) {
this.treeType = treeType;
}
public String getPassword() {
return password;
}
@ -462,4 +449,20 @@ public class Device {
public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
this.sipTransactionInfo = sipTransactionInfo;
}
/*======================设备主子码流逻辑START=========================*/
@Schema(description = "开启主子码流切换的开关false-不开启true-开启)")
private boolean switchPrimarySubStream;
public boolean isSwitchPrimarySubStream() {
return switchPrimarySubStream;
}
public void setSwitchPrimarySubStream(boolean switchPrimarySubStream) {
this.switchPrimarySubStream = switchPrimarySubStream;
}
/*======================设备主子码流逻辑END=========================*/
}

View File

@ -172,7 +172,7 @@ public class DeviceChannel {
* 遇到过NVR下的IPC下发信令可以推流 但是 Status 响应 OFF
*/
@Schema(description = "在线/离线, 1在线,0离线")
private int status;
private boolean status;
/**
* 经度
@ -455,11 +455,11 @@ public class DeviceChannel {
this.PTZTypeText = PTZTypeText;
}
public int getStatus() {
public boolean isStatus() {
return status;
}
public void setStatus(int status) {
public void setStatus(boolean status) {
this.status = status;
}

View File

@ -0,0 +1,46 @@
package com.genersoft.iot.vmp.gb28181.bean;
import javax.sdp.SessionDescription;
/**
* 28181 的SDP解析器
*/
public class Gb28181Sdp {
private SessionDescription baseSdb;
private String ssrc;
private String mediaDescription;
public static Gb28181Sdp getInstance(SessionDescription baseSdb, String ssrc, String mediaDescription) {
Gb28181Sdp gb28181Sdp = new Gb28181Sdp();
gb28181Sdp.setBaseSdb(baseSdb);
gb28181Sdp.setSsrc(ssrc);
gb28181Sdp.setMediaDescription(mediaDescription);
return gb28181Sdp;
}
public SessionDescription getBaseSdb() {
return baseSdb;
}
public void setBaseSdb(SessionDescription baseSdb) {
this.baseSdb = baseSdb;
}
public String getSsrc() {
return ssrc;
}
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
public String getMediaDescription() {
return mediaDescription;
}
public void setMediaDescription(String mediaDescription) {
this.mediaDescription = mediaDescription;
}
}

View File

@ -10,7 +10,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
public class GbStream extends PlatformGbStream{
@Schema(description = "ID")
private Integer gbStreamId;
private int gbStreamId;
@Schema(description = "应用名")
private String app;
@Schema(description = "流ID")

View File

@ -183,12 +183,6 @@ public class ParentPlatform {
@Schema(description = "创建时间")
private String createTime;
/**
* 树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGroup
*/
@Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou")
private String treeType;
@Schema(description = "是否作为消息通道")
private boolean asMessageChannel;
@ -424,14 +418,6 @@ public class ParentPlatform {
this.createTime = createTime;
}
public String getTreeType() {
return treeType;
}
public void setTreeType(String treeType) {
this.treeType = treeType;
}
public boolean isAsMessageChannel() {
return asMessageChannel;
}

View File

@ -5,7 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
public class PlatformGbStream {
@Schema(description = "ID")
private Integer gbStreamId;
private int gbStreamId;
@Schema(description = "平台ID")
private String platformId;

View File

@ -1,10 +0,0 @@
package com.genersoft.iot.vmp.gb28181.bean;
/**
* 目录结构类型
* @author lin
*/
public class TreeType {
public static final String BUSINESS_GROUP = "BusinessGroup";
public static final String CIVIL_CODE = "CivilCode";
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
@ -31,10 +32,13 @@ public class SSRCFactory {
@Autowired
private SipConfig sipConfig;
@Autowired
private UserSetting userSetting;
public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
String ssrcPrefix = sipConfig.getDomain().substring(3, 8);
String redisKey = SSRC_INFO_KEY + mediaServerId;
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
List<String> ssrcList = new ArrayList<>();
for (int i = 1; i < MAX_STREAM_COUNT; i++) {
String ssrc = String.format("%s%04d", ssrcPrefix, i);
@ -77,7 +81,7 @@ public class SSRCFactory {
return;
}
String sn = ssrc.substring(1);
String redisKey = SSRC_INFO_KEY + mediaServerId;
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
redisTemplate.opsForSet().add(redisKey, sn);
}
@ -86,7 +90,7 @@ public class SSRCFactory {
*/
private String getSN(String mediaServerId) {
String sn = null;
String redisKey = SSRC_INFO_KEY + mediaServerId;
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
Long size = redisTemplate.opsForSet().size(redisKey);
if (size == null || size == 0) {
throw new RuntimeException("ssrc已经用完");
@ -113,20 +117,8 @@ public class SSRCFactory {
* @param mediaServerId 流媒体服务ID
*/
public boolean hasMediaServerSSRC(String mediaServerId) {
String redisKey = SSRC_INFO_KEY + mediaServerId;
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
return redisTemplate.opsForSet().members(redisKey) != null;
}
/**
* 查询ssrc是否可用
*
* @param mediaServerId
* @param ssrc
* @return
*/
public boolean checkSsrc(String mediaServerId, String ssrc) {
String sn = ssrc.substring(1);
String redisKey = SSRC_INFO_KEY + mediaServerId;
return redisTemplate.opsForSet().isMember(redisKey, sn) != null;
}
}

View File

@ -39,16 +39,22 @@ public class DeferredResultHolder {
public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY";
public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL";
public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION";
public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM";
public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP";
private Map<String, Map<String, DeferredResultEx>> map = new ConcurrentHashMap<>();
@ -149,4 +155,6 @@ public class DeferredResultHolder {
map.remove(msg.getKey());
}
}
}

View File

@ -80,7 +80,7 @@ public interface ISIPCommanderForPlatform {
* @param fromTag
* @return
*/
void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,int status) throws SipException, InvalidArgumentException, ParseException ;
void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,boolean status) throws SipException, InvalidArgumentException, ParseException;
/**
* 向上级回复移动位置订阅消息

View File

@ -55,8 +55,8 @@ public class SIPRequestHeaderPlarformProvider {
parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
//via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(),
parentPlatform.getServerPort(), parentPlatform.getTransport(), SipUtils.getNewViaTag());
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(),
Integer.parseInt(parentPlatform.getDevicePort()), parentPlatform.getTransport(), SipUtils.getNewViaTag());
viaHeader.setRPort();
viaHeaders.add(viaHeader);
//from

View File

@ -1,13 +1,14 @@
package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
@ -21,6 +22,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamPush;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
@ -155,6 +157,11 @@ public class SIPCommander implements ISIPCommander {
builder.append(strTmp, 0, 2);
strTmp = String.format("%02X", parameter2);
builder.append(strTmp, 0, 2);
//优化zoom变倍速率
if ((combineCode2 > 0) && (combineCode2 <16))
{
combineCode2 = 16;
}
strTmp = String.format("%X", combineCode2);
builder.append(strTmp, 0, 1).append("0");
//计算校验码
@ -280,9 +287,9 @@ public class SIPCommander implements ISIPCommander {
logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
if (event != null) {
event.response(mediaServerItemInUse, json);
event.response(mediaServerItemInUse, hookParam);
subscribe.removeSubscribe(hookSubscribe);
}
});
@ -345,6 +352,22 @@ public class SIPCommander implements ISIPCommander {
}
}
if( device.isSwitchPrimarySubStream() ){
if("TP-LINK".equals(device.getManufacturer())){
if (device.isSwitchPrimarySubStream()){
content.append("a=streamMode:sub\r\n");
}else {
content.append("a=streamMode:main\r\n");
}
}else {
if (device.isSwitchPrimarySubStream()){
content.append("a=streamprofile:1\r\n");
}else {
content.append("a=streamprofile:0\r\n");
}
}
}
content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
// f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
@ -360,7 +383,8 @@ public class SIPCommander implements ISIPCommander {
// 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
ResponseEvent responseEvent = (ResponseEvent) e.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAY);
streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response,
InviteSessionType.PLAY);
okEvent.response(e);
});
}
@ -450,13 +474,13 @@ public class SIPCommander implements ISIPCommander {
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
// 添加订阅
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> {
if (hookEvent != null) {
hookEvent.response(mediaServerItemInUse, json);
hookEvent.response(mediaServerItemInUse, hookParam);
}
subscribe.removeSubscribe(hookSubscribe);
});
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc());
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc());
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
ResponseEvent responseEvent = (ResponseEvent) event.event;
@ -553,15 +577,15 @@ public class SIPCommander implements ISIPCommander {
// 添加订阅
CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport());
String callId= newCallIdHeader.getCallId();
subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> {
logger.debug("sipc 添加订阅===callId {}",callId);
hookEvent.response(mediaServerItemInUse, json);
hookEvent.response(mediaServerItemInUse, hookParam);
subscribe.removeSubscribe(hookSubscribe);
hookSubscribe.getContent().put("regist", false);
hookSubscribe.getContent().put("schema", "rtsp");
// 添加流注销的订阅注销了后向设备发送bye
subscribe.addSubscribe(hookSubscribe,
(MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> {
(mediaServerItemForEnd, hookParam1) -> {
logger.info("[录像]下载结束, 发送BYE");
try {
streamByeCmd(device, channelId, ssrcInfo.getStream(), callId);
@ -572,17 +596,13 @@ public class SIPCommander implements ISIPCommander {
});
});
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc());
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc());
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
ResponseEvent responseEvent = (ResponseEvent) event.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse();
String contentString =new String(response.getRawContent());
int ssrcIndex = contentString.indexOf("y=");
String ssrc=ssrcInfo.getSsrc();
if (ssrcIndex >= 0) {
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
}
String ssrc = SipUtils.getSsrcFromSdp(contentString);
streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, InviteSessionType.DOWNLOAD);
okEvent.response(event);
});

View File

@ -230,59 +230,150 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
// 行政区划分组只需要这两项就可以
catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
if (channel.getParentId() != null) {
// 业务分组加上这一项即可提高兼容性
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
// catalogXml.append("<ParentID>" + parentPlatform.getDeviceGBId() + "/" + channel.getParentId() + "</ParentID>\r\n");
}
if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
// 虚拟组织增加BusinessGroupID字段
catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
}
if (!channel.getChannelId().equals(parentPlatform.getDeviceGBId())) {
catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
if (channel.getParental() == 0) {
catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
if (channel.getChannelId().length() <= 8) {
catalogXml.append("</Item>\r\n");
continue;
}else {
if (channel.getChannelId().length() != 20) {
catalogXml.append("</Item>\r\n");
continue;
}
}
if (channel.getParental() == 0) {
// 通道项
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
String civilCode = channel.getCivilCode() == null?parentPlatform.getAdministrativeDivision() : channel.getCivilCode();
if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
catalogXml.append("<Owner>" + parentPlatform.getDeviceGBId()+ "</Owner>\r\n");
catalogXml.append("<CivilCode>" + civilCode + "</CivilCode>\r\n");
if (channel.getAddress() == null) {
catalogXml.append("<Address></Address>\r\n");
}else {
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
}
catalogXml.append("<Block>" + channel.getBlock() + "</Block>\r\n");
catalogXml.append("<SafetyWay>" + channel.getSafetyWay() + "</SafetyWay>\r\n");
catalogXml.append("<CertNum>" + channel.getCertNum() + "</CertNum>\r\n");
catalogXml.append("<Certifiable>" + channel.getCertifiable() + "</Certifiable>\r\n");
catalogXml.append("<ErrCode>" + channel.getErrCode() + "</ErrCode>\r\n");
catalogXml.append("<EndTime>" + channel.getEndTime() + "</EndTime>\r\n");
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n");
catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 1?"ON":"OFF") + "</Status>\r\n");
catalogXml.append("<Longitude>" +
(channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
+ "</Longitude>\r\n");
catalogXml.append("<Latitude>" +
(channel.getLatitudeWgs84() != 0? channel.getLatitudeWgs84():channel.getLatitude())
+ "</Latitude>\r\n");
switch (Integer.parseInt(channel.getChannelId().substring(10, 13))){
case 200:
// catalogXml.append("<Manufacturer>三永华通</Manufacturer>\r\n");
// GitUtil gitUtil = SpringBeanFactory.getBean("gitUtil");
// String model = (gitUtil == null || gitUtil.getBuildVersion() == null)?"1.0": gitUtil.getBuildVersion();
// catalogXml.append("<Model>" + model + "</Manufacturer>\r\n");
// catalogXml.append("<Owner>三永华通</Owner>\r\n");
if (channel.getCivilCode() != null) {
catalogXml.append("<CivilCode>"+channel.getCivilCode()+"</CivilCode>\r\n");
}else {
catalogXml.append("<CivilCode></CivilCode>\r\n");
}
catalogXml.append("<RegisterWay>1</RegisterWay>\r\n");
catalogXml.append("<Secrecy>0</Secrecy>\r\n");
break;
case 215:
if (!ObjectUtils.isEmpty(channel.getParentId())) {
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}
break;
case 216:
if (!ObjectUtils.isEmpty(channel.getParentId())) {
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}else {
catalogXml.append("<ParentID></ParentID>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getBusinessGroupId())) {
catalogXml.append("<BusinessGroupID>" + channel.getBusinessGroupId() + "</BusinessGroupID>\r\n");
}else {
catalogXml.append("<BusinessGroupID></BusinessGroupID>\r\n");
}
break;
default:
// 通道项
if (channel.getManufacture() != null) {
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
}else {
catalogXml.append("<Manufacturer></Manufacturer>\r\n");
}
if (channel.getSecrecy() != null) {
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
}else {
catalogXml.append("<Secrecy></Secrecy>\r\n");
}
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
if (channel.getModel() != null) {
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
}else {
catalogXml.append("<Model></Model>\r\n");
}
if (channel.getOwner() != null) {
catalogXml.append("<Owner>" + channel.getOwner()+ "</Owner>\r\n");
}else {
catalogXml.append("<Owner></Owner>\r\n");
}
if (channel.getCivilCode() != null) {
catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
}else {
catalogXml.append("<CivilCode></CivilCode>\r\n");
}
if (channel.getAddress() == null) {
catalogXml.append("<Address></Address>\r\n");
}else {
catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getParentId())) {
catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
}else {
catalogXml.append("<ParentID></ParentID>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getBlock())) {
catalogXml.append("<Block>" + channel.getBlock() + "</Block>\r\n");
}else {
catalogXml.append("<Block></Block>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getSafetyWay())) {
catalogXml.append("<SafetyWay>" + channel.getSafetyWay() + "</SafetyWay>\r\n");
}else {
catalogXml.append("<SafetyWay></SafetyWay>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getCertNum())) {
catalogXml.append("<CertNum>" + channel.getCertNum() + "</CertNum>\r\n");
}else {
catalogXml.append("<CertNum></CertNum>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getCertifiable())) {
catalogXml.append("<Certifiable>" + channel.getCertifiable() + "</Certifiable>\r\n");
}else {
catalogXml.append("<Certifiable></Certifiable>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getErrCode())) {
catalogXml.append("<ErrCode>" + channel.getErrCode() + "</ErrCode>\r\n");
}else {
catalogXml.append("<ErrCode></ErrCode>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getEndTime())) {
catalogXml.append("<EndTime>" + channel.getEndTime() + "</EndTime>\r\n");
}else {
catalogXml.append("<EndTime></EndTime>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getSecrecy())) {
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
}else {
catalogXml.append("<Secrecy></Secrecy>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getIpAddress())) {
catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
}else {
catalogXml.append("<IPAddress></IPAddress>\r\n");
}
catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
if (!ObjectUtils.isEmpty(channel.getPassword())) {
catalogXml.append("<Password>" + channel.getPassword() + "</Password>\r\n");
}else {
catalogXml.append("<Password></Password>\r\n");
}
if (!ObjectUtils.isEmpty(channel.getPTZType())) {
catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
}else {
catalogXml.append("<PTZType></PTZType>\r\n");
}
catalogXml.append("<Status>" + (channel.isStatus() ?"ON":"OFF") + "</Status>\r\n");
catalogXml.append("<Longitude>" +
(channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
+ "</Longitude>\r\n");
catalogXml.append("<Latitude>" +
(channel.getLatitudeWgs84() != 0? channel.getLatitudeWgs84():channel.getLatitude())
+ "</Latitude>\r\n");
break;
}
catalogXml.append("</Item>\r\n");
}
catalogXml.append("</Item>\r\n");
}
}
@ -399,11 +490,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return
*/
@Override
public void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,int status) throws SipException, InvalidArgumentException, ParseException {
public void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,boolean status) throws SipException, InvalidArgumentException, ParseException {
if (parentPlatform == null) {
return ;
}
String statusStr = (status==1)?"ONLINE":"OFFLINE";
String statusStr = (status)?"ONLINE":"OFFLINE";
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
@ -564,7 +655,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n")
.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n")
.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n")
.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
.append("<Status>" + (channel.isStatus() ? "ON" : "OFF") + "</Status>\r\n");
if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n")

View File

@ -166,9 +166,8 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream());
}
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channelId);
inviteStreamService.removeInviteInfo(inviteInfo);
if (inviteInfo != null) {
inviteStreamService.removeInviteInfo(inviteInfo);
if (inviteInfo.getStreamInfo() != null) {
mediaServerService.closeRTPServer(inviteInfo.getStreamInfo().getMediaServerId(), inviteInfo.getStream());
}

View File

@ -22,11 +22,12 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.*;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@ -217,6 +218,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
logger.error("[命令发送失败] invite GONE: {}", e.getMessage());
}
return;
}else {
// TODO 可能漏回复消息
}
}
} else {
@ -270,18 +273,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 解析sdp消息, 使用jainsip 自带的sdp解析方式
String contentString = new String(request.getRawContent());
// jainSip不支持y=字段 移除以解析
// 检查是否有y字段
int ssrcIndex = contentString.indexOf("y=");
SessionDescription sdp;
if (ssrcIndex >= 0) {
//ssrc规定长度为10个字节不取余下长度以避免后续还有f=字段
String substring = contentString.substring(0, ssrcIndex);
sdp = SdpFactory.getInstance().createSessionDescription(substring);
} else {
sdp = SdpFactory.getInstance().createSessionDescription(contentString);
}
Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString);
SessionDescription sdp = gb28181Sdp.getBaseSdb();
String sessionName = sdp.getSessionName().getValue();
Long startTime = null;
@ -369,11 +362,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}
String ssrc;
if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) {
if (userSetting.getUseCustomSsrcForParentInvite() || gb28181Sdp.getSsrc() == null) {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
} else {
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
}else {
ssrc = gb28181Sdp.getSsrc();
}
String streamTypeStr = null;
if (mediaTransmissionTCP) {
@ -406,8 +399,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
Long finalStartTime = startTime;
Long finalStopTime = stopTime;
InviteErrorCallback<Object> hookEvent = (code, msg, data) -> {
StreamInfo streamInfo = (StreamInfo) data;
ErrorCallback<Object> hookEvent = (code, msg, data) -> {
StreamInfo streamInfo = (StreamInfo)data;
MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId());
logger.info("[上级Invite]下级已经开始推流。 回复200OK(SDP) {}/{}", streamInfo.getApp(), streamInfo.getStream());
// * 0 等待设备推流上来
@ -460,7 +453,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
logger.error("[命令发送失败] 国标级联 回复SdpAck", e);
}
};
InviteErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> {
ErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> {
// 未知错误直接转发设备点播的错误
try {
if (statusCode > 0) {
@ -547,11 +540,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} else if (gbStream != null) {
String ssrc;
if (userSetting.getUseCustomSsrcForParentInvite() || ssrcIndex < 0) {
if (userSetting.getUseCustomSsrcForParentInvite() || gb28181Sdp.getSsrc() == null) {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
} else {
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
}else {
ssrc = gb28181Sdp.getSsrc();
}
if ("push".equals(gbStream.getStreamType())) {
@ -690,10 +683,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream());
// 监听流上线
HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(gbStream.getApp(), gbStream.getStream(), true, "rtsp", mediaServerItem.getId());
zlmHttpHookSubscribe.addSubscribe(hookSubscribe, (mediaServerItemInUSe, responseJSON) -> {
String app = responseJSON.getString("app");
String stream = responseJSON.getString("stream");
logger.info("[上级点播]拉流代理已经就绪, {}/{}", app, stream);
zlmHttpHookSubscribe.addSubscribe(hookSubscribe, (mediaServerItemInUSe, hookParam) -> {
OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam;
logger.info("[上级点播]拉流代理已经就绪, {}/{}", streamChangedHookParam.getApp(), streamChangedHookParam.getStream());
dynamicTask.stop(callIdHeader.getCallId());
pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
@ -971,20 +963,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
}
String contentString = new String(request.getRawContent());
// jainSip不支持y=字段 移除移除以解析
String substring = contentString;
String ssrc = "0000000404";
int ssrcIndex = contentString.indexOf("y=");
if (ssrcIndex > 0) {
substring = contentString.substring(0, ssrcIndex);
ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12).trim();
}
ssrcIndex = substring.indexOf("f=");
if (ssrcIndex > 0) {
substring = contentString.substring(0, ssrcIndex);
}
try {
SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
try {
Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString);
SessionDescription sdp = gb28181Sdp.getBaseSdb();
// 获取支持的格式
Vector mediaDescriptions = sdp.getMediaDescriptions(true);

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.Device;
@ -20,7 +21,10 @@ import org.springframework.stereotype.Component;
import javax.sip.RequestEvent;
import javax.sip.header.FromHeader;
import java.util.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@ -56,6 +60,9 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
@Autowired
private DynamicTask dynamicTask;
@Autowired
private CivilCodeFileConf civilCodeFileConf;
private final static String talkKey = "notify-request-for-catalog-task";
public void process(RequestEvent evt) {
@ -65,7 +72,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
Device device = redisCatchStorage.getDevice(deviceId);
if (device == null || device.getOnline() == 0) {
if (device == null || !device.isOnLine()) {
logger.warn("[收到目录订阅]{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" ));
return;
}
@ -96,7 +103,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
}else {
event = eventElement.getText().toUpperCase();
}
DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, event, civilCodeFileConf);
channel.setDeviceId(device.getDeviceId());
logger.info("[收到目录订阅]{}/{}", device.getDeviceId(), channel.getChannelId());
@ -175,6 +182,11 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
}
}else {
addChannelMap.put(channel.getChannelId(), channel);
if (userSetting.getDeviceStatusNotify()) {
// 发送redis消息
redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), channel.getChannelId(), true);
}
if (addChannelMap.keySet().size() > 300) {
executeSaveForAdd();
}
@ -185,6 +197,10 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
// 删除
logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
deleteChannelList.add(channel);
if (userSetting.getDeviceStatusNotify()) {
// 发送redis消息
redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), channel.getChannelId(), false);
}
if (deleteChannelList.size() > 300) {
executeSaveForDelete();
}
@ -205,6 +221,10 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
if (addChannelMap.keySet().size() > 300) {
executeSaveForAdd();
}
if (userSetting.getDeviceStatusNotify()) {
// 发送redis消息
redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), channel.getChannelId(), true);
}
}
break;
default:
@ -232,7 +252,6 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
}
private void executeSave(){
System.out.println("定时存储数据");
executeSaveForUpdate();
executeSaveForDelete();
executeSaveForOnline();

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*;
@ -79,6 +80,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
@Autowired
private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor;
@Autowired
private CivilCodeFileConf civilCodeFileConf;
private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
@Qualifier("taskExecutor")
@ -192,7 +196,12 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
mobilePosition.setDeviceId(device.getDeviceId());
mobilePosition.setChannelId(channelId);
String time = XmlUtil.getText(rootElement, "Time");
mobilePosition.setTime(time);
if (ObjectUtils.isEmpty(time)){
mobilePosition.setTime(DateUtil.getNow());
}else {
mobilePosition.setTime(SipUtils.parseTime(time));
}
mobilePosition.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
mobilePosition.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
if (NumericUtil.isDouble(XmlUtil.getText(rootElement, "Speed"))) {
@ -237,7 +246,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
// 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject();
jsonObject.put("time", time);
jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime()));
jsonObject.put("serial", deviceId);
jsonObject.put("code", channelId);
jsonObject.put("longitude", mobilePosition.getLongitude());
@ -339,7 +348,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
storager.updateChannelPosition(deviceChannel);
// 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject();
jsonObject.put("time", mobilePosition.getTime());
jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime()));
jsonObject.put("serial", deviceChannel.getDeviceId());
jsonObject.put("code", deviceChannel.getChannelId());
jsonObject.put("longitude", mobilePosition.getLongitude());
@ -372,7 +381,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);
Device device = redisCatchStorage.getDevice(deviceId);
if (device == null || device.getOnline() == 0) {
if (device == null || !device.isOnLine()) {
logger.warn("[收到目录订阅]{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" ));
return;
}
@ -403,7 +412,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
}else {
event = eventElement.getText().toUpperCase();
}
DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, event, civilCodeFileConf);
channel.setDeviceId(device.getDeviceId());
logger.info("[收到目录订阅]{}/{}", device.getDeviceId(), channel.getChannelId());
switch (event) {

View File

@ -167,9 +167,8 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
device.setStreamMode("UDP");
device.setCharset("GB2312");
device.setGeoCoordSys("WGS84");
device.setTreeType("CivilCode");
device.setDeviceId(deviceId);
device.setOnline(0);
device.setOnLine(false);
}
device.setIp(remoteAddressInfo.getIp());
device.setPort(remoteAddressInfo.getPort());

View File

@ -164,7 +164,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
// 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject();
jsonObject.put("time", mobilePosition.getTime());
jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime()));
jsonObject.put("serial", deviceChannel.getDeviceId());
jsonObject.put("code", deviceChannel.getChannelId());
jsonObject.put("longitude", mobilePosition.getLongitude());

View File

@ -83,12 +83,12 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
device.setKeepaliveTime(DateUtil.getNow());
if (device.getOnline() == 1) {
if (device.isOnLine()) {
deviceService.updateDevice(device);
}else {
// 对于已经离线的设备判断他的注册是否已经过期
if (!deviceService.expire(device)){
device.setOnline(0);
device.setOnLine(false);
deviceService.online(device, null);
}
}

View File

@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@ -95,7 +96,12 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
}
mobilePosition.setDeviceId(sipMsgInfo.getDevice().getDeviceId());
mobilePosition.setChannelId(getText(rootElementAfterCharset, "DeviceID"));
mobilePosition.setTime(getText(rootElementAfterCharset, "Time"));
String time = getText(rootElementAfterCharset, "Time");
if (ObjectUtils.isEmpty(time)){
mobilePosition.setTime(DateUtil.getNow());
}else {
mobilePosition.setTime(SipUtils.parseTime(time));
}
mobilePosition.setLongitude(Double.parseDouble(getText(rootElementAfterCharset, "Longitude")));
mobilePosition.setLatitude(Double.parseDouble(getText(rootElementAfterCharset, "Latitude")));
if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Speed"))) {
@ -138,7 +144,7 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
// 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject();
jsonObject.put("time", mobilePosition.getTime());
jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime()));
jsonObject.put("serial", deviceChannel.getDeviceId());
jsonObject.put("code", deviceChannel.getChannelId());
jsonObject.put("longitude", mobilePosition.getLongitude());

View File

@ -77,7 +77,7 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
return;
}
try {
cmderFroPlatform.deviceStatusResponse(parentPlatform,channelId, sn, fromHeader.getTag(),deviceChannel.getStatus());
cmderFroPlatform.deviceStatusResponse(parentPlatform,channelId, sn, fromHeader.getTag(),deviceChannel.isStatus());
} catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@ -54,6 +55,9 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
@Autowired
private CivilCodeFileConf civilCodeFileConf;
@Override
public void afterPropertiesSet() throws Exception {
responseMessageHandler.addHandler(cmdType, this);
@ -101,6 +105,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
if (deviceListIterator != null) {
List<DeviceChannel> channelList = new ArrayList<>();
List<String> parentChannelIds = new ArrayList<>();
// 遍历DeviceList
while (deviceListIterator.hasNext()) {
Element itemDevice = deviceListIterator.next();
@ -108,7 +113,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
if (channelDeviceElement == null) {
continue;
}
DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
DeviceChannel deviceChannel = XmlUtil.channelContentHandler(itemDevice, device, null, civilCodeFileConf);
deviceChannel = SipUtils.updateGps(deviceChannel, device.getGeoCoordSys());
deviceChannel.setDeviceId(take.getDevice().getDeviceId());

View File

@ -1,18 +1,13 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
@ -59,7 +54,7 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
logger.debug("接收到DeviceInfo应答消息");
// 检查设备是否存在 不存在则不回复
if (device == null || device.getOnline() == 0) {
if (device == null || !device.isOnLine()) {
logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]" + (device != null ? device.getDeviceId():"" ));
return;
}

View File

@ -2,17 +2,21 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.GpsUtil;
import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.DocumentException;
import org.dom4j.Element;
@ -56,6 +60,9 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
@Autowired
private IDeviceChannelService deviceChannelService;
@Autowired
private DeferredResultHolder resultHolder;
@Override
public void afterPropertiesSet() throws Exception {
responseMessageHandler.addHandler(cmdType, this);
@ -83,7 +90,13 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
}
mobilePosition.setDeviceId(device.getDeviceId());
mobilePosition.setChannelId(getText(rootElement, "DeviceID"));
mobilePosition.setTime(getText(rootElement, "Time"));
//兼容ISO 8601格式时间
String time = getText(rootElement, "Time");
if (ObjectUtils.isEmpty(time)){
mobilePosition.setTime(DateUtil.getNow());
}else {
mobilePosition.setTime(SipUtils.parseTime(time));
}
mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude")));
mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude")));
if (NumericUtil.isDouble(getText(rootElement, "Speed"))) {
@ -121,11 +134,18 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
if (userSetting.getSavePositionHistory()) {
storager.insertMobilePosition(mobilePosition);
}
storager.updateChannelPosition(deviceChannel);
String key = DeferredResultHolder.CALLBACK_CMD_MOBILE_POSITION + device.getDeviceId();
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setData(mobilePosition);
resultHolder.invokeAllResult(msg);
// 发送redis消息 通知位置信息的变化
JSONObject jsonObject = new JSONObject();
jsonObject.put("time", mobilePosition.getTime());
jsonObject.put("time", DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(mobilePosition.getTime()));
jsonObject.put("serial", deviceChannel.getDeviceId());
jsonObject.put("code", deviceChannel.getChannelId());
jsonObject.put("longitude", mobilePosition.getLongitude());

View File

@ -1,10 +1,12 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
import com.genersoft.iot.vmp.gb28181.SipLayer;
import com.genersoft.iot.vmp.gb28181.bean.Gb28181Sdp;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
import com.genersoft.iot.vmp.gb28181.transmit.event.response.SIPResponseProcessorAbstract;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import gov.nist.javax.sip.ResponseEventExt;
import gov.nist.javax.sip.message.SIPResponse;
import org.slf4j.Logger;
@ -12,7 +14,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sdp.SdpFactory;
import javax.sdp.SdpParseException;
import javax.sdp.SessionDescription;
import javax.sip.InvalidArgumentException;
@ -82,19 +83,8 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract {
ResponseEventExt event = (ResponseEventExt)evt;
String contentString = new String(response.getRawContent());
// jainSip不支持y=字段 移除以解析
int ssrcIndex = contentString.indexOf("y=");
// 检查是否有y字段
SessionDescription sdp;
if (ssrcIndex >= 0) {
//ssrc规定长度为10字节不取余下长度以避免后续还有f=字段
String substring = contentString.substring(0, contentString.indexOf("y="));
sdp = SdpFactory.getInstance().createSessionDescription(substring);
} else {
sdp = SdpFactory.getInstance().createSessionDescription(contentString);
}
// 查看是否是来自设备的此是回复
Gb28181Sdp gb28181Sdp = SipUtils.parseSDP(contentString);
SessionDescription sdp = gb28181Sdp.getBaseSdb();
SipURI requestUri = SipFactory.getInstance().createAddressFactory().createSipURI(sdp.getOrigin().getUsername(), event.getRemoteIpAddress() + ":" + event.getRemotePort());
Request reqAck = headerProvider.createAckRequest(response.getLocalAddress().getHostAddress(), requestUri, response);

View File

@ -102,7 +102,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
platformService.online(parentPlatform, sipTransactionInfo);
}else {
platformService.offline(parentPlatform, false);
platformService.offline(parentPlatform, true);
}
// 注册/注销成功移除缓存的信息

View File

@ -1,14 +1,22 @@
package com.genersoft.iot.vmp.gb28181.utils;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.Gb28181Sdp;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.header.Subject;
import gov.nist.javax.sip.message.SIPRequest;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ObjectUtils;
import javax.sdp.SdpFactory;
import javax.sdp.SdpParseException;
import javax.sdp.SessionDescription;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
import javax.sip.header.FromHeader;
@ -16,6 +24,8 @@ import javax.sip.header.Header;
import javax.sip.header.UserAgentHeader;
import javax.sip.message.Request;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -28,6 +38,8 @@ import java.util.UUID;
*/
public class SipUtils {
private final static Logger logger = LoggerFactory.getLogger(SipUtils.class);
public static String getUserIdFromFromHeader(Request request) {
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
return getUserIdFromFromHeader(fromHeader);
@ -51,7 +63,7 @@ public class SipUtils {
}
public static String getNewViaTag() {
return "z9hG4bK" + System.currentTimeMillis();
return "z9hG4bK" + RandomStringUtils.randomNumeric(10);
}
public static UserAgentHeader createUserAgentHeader(GitUtil gitUtil) throws PeerUnavailableException, ParseException {
@ -113,6 +125,12 @@ public class SipUtils {
strTmp = String.format("%02X", moveSpeed);
builder.append(strTmp, 0, 2);
builder.append(strTmp, 0, 2);
//优化zoom低倍速下的变倍速率
if ((zoomSpeed > 0) && (zoomSpeed <16))
{
zoomSpeed = 16;
}
strTmp = String.format("%X", zoomSpeed);
builder.append(strTmp, 0, 1).append("0");
//计算校验码
@ -203,4 +221,66 @@ public class SipUtils {
}
return deviceChannel;
}
public static Gb28181Sdp parseSDP(String sdpStr) throws SdpParseException {
// jainSip不支持y= f=字段 移除以解析
int ssrcIndex = sdpStr.indexOf("y=");
int mediaDescriptionIndex = sdpStr.indexOf("f=");
// 检查是否有y字段
SessionDescription sdp;
String ssrc = null;
String mediaDescription = null;
if (mediaDescriptionIndex == 0 && ssrcIndex == 0) {
sdp = SdpFactory.getInstance().createSessionDescription(sdpStr);
}else {
String lines[] = sdpStr.split("\\r?\\n");
StringBuilder sdpBuffer = new StringBuilder();
for (String line : lines) {
if (line.trim().startsWith("y=")) {
ssrc = line.substring(2);
}else if (line.trim().startsWith("f=")) {
mediaDescription = line.substring(2);
}else {
sdpBuffer.append(line.trim()).append("\r\n");
}
}
sdp = SdpFactory.getInstance().createSessionDescription(sdpBuffer.toString());
}
return Gb28181Sdp.getInstance(sdp, ssrc, mediaDescription);
}
public static String getSsrcFromSdp(String sdpStr) {
// jainSip不支持y= f=字段 移除以解析
int ssrcIndex = sdpStr.indexOf("y=");
if (ssrcIndex == 0) {
return null;
}
String lines[] = sdpStr.split("\\r?\\n");
for (String line : lines) {
if (line.trim().startsWith("y=")) {
return line.substring(2);
}
}
return null;
}
public static String parseTime(String timeStr) {
if (ObjectUtils.isEmpty(timeStr)){
return null;
}
LocalDateTime localDateTime;
try {
localDateTime = LocalDateTime.parse(timeStr);
}catch (DateTimeParseException e) {
try {
localDateTime = LocalDateTime.parse(timeStr, DateUtil.formatterISO8601);
}catch (DateTimeParseException e2) {
logger.error("[格式化时间] 无法格式化时间: {}", timeStr);
return null;
}
}
return localDateTime.format(DateUtil.formatterISO8601);
}
}

View File

@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.utils;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.CivilCodePo;
import com.genersoft.iot.vmp.conf.CivilCodeFileConf;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
@ -192,7 +194,7 @@ public class XmlUtil {
CivilCode, BusinessGroup,VirtualOrganization,Other
}
public static DeviceChannel channelContentHander(Element itemDevice, Device device, String event){
public static DeviceChannel channelContentHandler(Element itemDevice, Device device, String event, CivilCodeFileConf civilCodeFileConf){
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(device.getDeviceId());
Element channdelIdElement = itemDevice.element("DeviceID");
@ -210,208 +212,353 @@ public class XmlUtil {
// 除了ADD和update情况下需要识别全部内容
return deviceChannel;
}
ChannelType channelType = ChannelType.Other;
if (channelId.length() <= 8) {
channelType = ChannelType.CivilCode;
Element nameElement = itemDevice.element("Name");
if (nameElement != null) {
deviceChannel.setName(nameElement.getText());
}
if(channelId.length() <= 8) {
deviceChannel.setHasAudio(false);
}else {
if (channelId.length() == 20) {
int code = Integer.parseInt(channelId.substring(10, 13));
switch (code){
case 215:
channelType = ChannelType.BusinessGroup;
deviceChannel.setHasAudio(false);
break;
case 216:
channelType = ChannelType.VirtualOrganization;
deviceChannel.setHasAudio(false);
break;
case 136:
case 137:
case 138:
deviceChannel.setHasAudio(true);
break;
default:
deviceChannel.setHasAudio(false);
break;
}
}
}
Element channdelNameElement = itemDevice.element("Name");
String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim() : "";
deviceChannel.setName(channelName);
String civilCode = XmlUtil.getText(itemDevice, "CivilCode");
deviceChannel.setCivilCode(civilCode);
if (channelType == ChannelType.CivilCode && civilCode == null) {
deviceChannel.setParental(1);
// 行政区划如果没有传递具体值则推测一个
if (channelId.length() > 2) {
deviceChannel.setCivilCode(channelId.substring(0, channelId.length() - 2));
}
}
if (channelType.equals(ChannelType.CivilCode)) {
// 行政区划其他字段没必要识别了默认在线即可
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setCreateTime(DateUtil.getNow());
deviceChannel.setUpdateTime(DateUtil.getNow());
return deviceChannel;
}
/**
* 行政区划展示设备树与业务分组展示设备树是两种不同的模式
* 行政区划展示设备树 各个目录之间主要靠deviceId做关联,摄像头通过CivilCode指定其属于那个行政区划;都是不超过十位的编号; 结构如下:
* 河北省
* --> 石家庄市
* --> 摄像头
*String parentId = XmlUtil.getText(itemDevice, "ParentID");
if (parentId != null) {
if (parentId.contains("/")) {
String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
String businessGroup = parentId.substring(0, parentId.indexOf("/"));
deviceChannel.setParentId(lastParentId);
}else {
deviceChannel.setParentId(parentId);
}
}
deviceCh --> 正定县
* --> 摄像头
* --> 摄像头
*
* 业务分组展示设备树是顶级是业务分组,其下的虚拟组织靠BusinessGroupID指定其所属的业务分组;摄像头通过ParentId来指定其所属于的虚拟组织:
* 业务分组
* --> 虚拟组织
* --> 摄像头
* --> 虚拟组织
* --> 摄像头
* --> 摄像头
*/
String parentId = XmlUtil.getText(itemDevice, "ParentID");
String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
if (parentId != null) {
if (parentId.contains("/")) {
String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
if (businessGroupID == null) {
businessGroupID = parentId.substring(0, parentId.indexOf("/"));
}
deviceChannel.setParentId(lastParentId);
CivilCodePo parentCode = civilCodeFileConf.getParentCode(channelId);
if (parentCode != null) {
deviceChannel.setParentId(parentCode.getCode());
deviceChannel.setCivilCode(parentCode.getCode());
}else {
deviceChannel.setParentId(parentId);
logger.warn("[xml解析] 无法确定行政区划{}的上级行政区划", channelId);
}
// 兼容设备通道信息中自己为自己父节点的情况
if (deviceChannel.getParentId().equals(deviceChannel.getChannelId())) {
deviceChannel.setParentId(null);
}
}
deviceChannel.setBusinessGroupId(businessGroupID);
if (channelType.equals(ChannelType.BusinessGroup) || channelType.equals(ChannelType.VirtualOrganization)) {
// 业务分组和虚拟组织 其他字段没必要识别了默认在线即可
deviceChannel.setStatus(1);
deviceChannel.setParental(1);
deviceChannel.setCreateTime(DateUtil.getNow());
deviceChannel.setUpdateTime(DateUtil.getNow());
deviceChannel.setStatus(true);
return deviceChannel;
}
Element statusElement = itemDevice.element("Status");
if (statusElement != null) {
String status = statusElement.getTextTrim().trim();
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
deviceChannel.setStatus(1);
}
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
deviceChannel.setStatus(0);
}
}else {
deviceChannel.setStatus(1);
}
// 识别自带的目录标识
String parental = XmlUtil.getText(itemDevice, "Parental");
// 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
deviceChannel.setParental(0);
}else {
deviceChannel.setParental(1);
}
deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
String safetyWay = XmlUtil.getText(itemDevice, "SafetyWay");
if (ObjectUtils.isEmpty(safetyWay)) {
deviceChannel.setSafetyWay(0);
} else {
deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
}
String registerWay = XmlUtil.getText(itemDevice, "RegisterWay");
if (ObjectUtils.isEmpty(registerWay)) {
deviceChannel.setRegisterWay(1);
} else {
deviceChannel.setRegisterWay(Integer.parseInt(registerWay));
}
if (XmlUtil.getText(itemDevice, "Certifiable") == null
|| XmlUtil.getText(itemDevice, "Certifiable") == "") {
deviceChannel.setCertifiable(0);
} else {
deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
}
if (XmlUtil.getText(itemDevice, "ErrCode") == null
|| XmlUtil.getText(itemDevice, "ErrCode") == "") {
deviceChannel.setErrCode(0);
} else {
deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
}
deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
if (XmlUtil.getText(itemDevice, "Port") == null || XmlUtil.getText(itemDevice, "Port") == "") {
deviceChannel.setPort(0);
} else {
deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
}
String longitude = XmlUtil.getText(itemDevice, "Longitude");
if (NumericUtil.isDouble(longitude)) {
deviceChannel.setLongitude(Double.parseDouble(longitude));
} else {
deviceChannel.setLongitude(0.00);
}
String latitude = XmlUtil.getText(itemDevice, "Latitude");
if (NumericUtil.isDouble(latitude)) {
deviceChannel.setLatitude(Double.parseDouble(latitude));
} else {
deviceChannel.setLatitude(0.00);
}
deviceChannel.setGpsTime(DateUtil.getNow());
if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
//兼容INFO中的信息
Element info = itemDevice.element("Info");
if(XmlUtil.getText(info, "PTZType") == null || "".equals(XmlUtil.getText(info, "PTZType"))){
deviceChannel.setPTZType(0);
}else{
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(info, "PTZType")));
if(channelId.length() != 20) {
logger.warn("[xml解析] 失败编号不符合国标28181定义 {}", channelId);
return null;
}
int code = Integer.parseInt(channelId.substring(10, 13));
if (code == 136 || code == 137 || code == 138) {
deviceChannel.setHasAudio(true);
}else {
deviceChannel.setHasAudio(false);
}
// 设备厂商
String manufacturer = getText(itemDevice, "Manufacturer");
// 设备型号
String model = getText(itemDevice, "Model");
// 设备归属
String owner = getText(itemDevice, "Owner");
// 行政区域
String civilCode = getText(itemDevice, "CivilCode");
// 虚拟组织所属的业务分组ID,业务分组根据特定的业务需求制定,一个业务分组包含一组特定的虚拟组织
String businessGroupID = getText(itemDevice, "BusinessGroupID");
// 父设备/区域/系统ID
String parentID = getText(itemDevice, "ParentID");
if (parentID != null && parentID.equalsIgnoreCase("null")) {
parentID = null;
}
// 注册方式(必选)缺省为1;1:符合IETFRFC3261标准的认证注册模式;2:基于口令的双向认证注册模式;3:基于数字证书的双向认证注册模式
String registerWay = getText(itemDevice, "RegisterWay");
// 保密属性(必选)缺省为0;0:不涉密,1:涉密
String secrecy = getText(itemDevice, "Secrecy");
// 安装地址
String address = getText(itemDevice, "Address");
switch (code){
case 200:
// 系统目录
if (!ObjectUtils.isEmpty(manufacturer)) {
deviceChannel.setManufacture(manufacturer);
}
if (!ObjectUtils.isEmpty(model)) {
deviceChannel.setModel(model);
}
if (!ObjectUtils.isEmpty(owner)) {
deviceChannel.setOwner(owner);
}
if (!ObjectUtils.isEmpty(civilCode)) {
deviceChannel.setCivilCode(civilCode);
deviceChannel.setParentId(civilCode);
}else {
if (!ObjectUtils.isEmpty(parentID)) {
deviceChannel.setParentId(parentID);
}
}
if (!ObjectUtils.isEmpty(address)) {
deviceChannel.setAddress(address);
}
deviceChannel.setStatus(true);
if (!ObjectUtils.isEmpty(registerWay)) {
try {
deviceChannel.setRegisterWay(Integer.parseInt(registerWay));
}catch (NumberFormatException exception) {
logger.warn("[xml解析] 从通道数据获取registerWay失败 {}", registerWay);
}
}
if (!ObjectUtils.isEmpty(secrecy)) {
deviceChannel.setSecrecy(secrecy);
}
return deviceChannel;
case 215:
// 业务分组
deviceChannel.setStatus(true);
if (!ObjectUtils.isEmpty(parentID)) {
if (!parentID.trim().equalsIgnoreCase(device.getDeviceId())) {
deviceChannel.setParentId(parentID);
}
}else {
logger.warn("[xml解析] 业务分组数据中缺少关键信息->ParentId");
if (!ObjectUtils.isEmpty(civilCode)) {
deviceChannel.setCivilCode(civilCode);
}
}
break;
case 216:
// 虚拟组织
deviceChannel.setStatus(true);
if (!ObjectUtils.isEmpty(businessGroupID)) {
deviceChannel.setBusinessGroupId(businessGroupID);
}
if (!ObjectUtils.isEmpty(parentID)) {
if (parentID.contains("/")) {
String[] parentIdArray = parentID.split("/");
parentID = parentIdArray[parentIdArray.length - 1];
}
deviceChannel.setParentId(parentID);
}else {
if (!ObjectUtils.isEmpty(businessGroupID)) {
deviceChannel.setParentId(businessGroupID);
}
}
break;
default:
// 设备目录
if (!ObjectUtils.isEmpty(manufacturer)) {
deviceChannel.setManufacture(manufacturer);
}
if (!ObjectUtils.isEmpty(model)) {
deviceChannel.setModel(model);
}
if (!ObjectUtils.isEmpty(owner)) {
deviceChannel.setOwner(owner);
}
if (!ObjectUtils.isEmpty(civilCode)) {
deviceChannel.setCivilCode(civilCode);
}
if (!ObjectUtils.isEmpty(businessGroupID)) {
deviceChannel.setBusinessGroupId(businessGroupID);
}
// 警区
String block = getText(itemDevice, "Block");
if (!ObjectUtils.isEmpty(block)) {
deviceChannel.setBlock(block);
}
if (!ObjectUtils.isEmpty(address)) {
deviceChannel.setAddress(address);
}
if (!ObjectUtils.isEmpty(secrecy)) {
deviceChannel.setSecrecy(secrecy);
}
// 当为设备时,是否有子设备(必选)1有,0没有
String parental = getText(itemDevice, "Parental");
if (!ObjectUtils.isEmpty(parental)) {
try {
// 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
deviceChannel.setParental(0);
}else {
deviceChannel.setParental(1);
}
}catch (NumberFormatException e) {
logger.warn("[xml解析] 从通道数据获取 parental失败 {}", parental);
}
}
// 父设备/区域/系统ID
String realParentId = parentID;
if (!ObjectUtils.isEmpty(parentID)) {
if (parentID.contains("/")) {
String[] parentIdArray = parentID.split("/");
realParentId = parentIdArray[parentIdArray.length - 1];
}
deviceChannel.setParentId(realParentId);
}else {
if (!ObjectUtils.isEmpty(businessGroupID)) {
deviceChannel.setParentId(businessGroupID);
}else {
if (!ObjectUtils.isEmpty(civilCode)) {
deviceChannel.setParentId(civilCode);
}
}
}
// 注册方式
if (!ObjectUtils.isEmpty(registerWay)) {
try {
int registerWayInt = Integer.parseInt(registerWay);
deviceChannel.setRegisterWay(registerWayInt);
}catch (NumberFormatException exception) {
logger.warn("[xml解析] 从通道数据获取registerWay失败 {}", registerWay);
deviceChannel.setRegisterWay(1);
}
}else {
deviceChannel.setRegisterWay(1);
}
// 信令安全模式(可选)缺省为0; 0:不采用;2:S/MIME 签名方式;3:S/MIME加密签名同时采用方式;4:数字摘要方式
String safetyWay = getText(itemDevice, "SafetyWay");
if (!ObjectUtils.isEmpty(safetyWay)) {
try {
deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
}catch (NumberFormatException e) {
logger.warn("[xml解析] 从通道数据获取 safetyWay失败 {}", safetyWay);
}
}
// 证书序列号(有证书的设备必选)
String certNum = getText(itemDevice, "CertNum");
if (!ObjectUtils.isEmpty(certNum)) {
deviceChannel.setCertNum(certNum);
}
// 证书有效标识(有证书的设备必选)缺省为0;证书有效标识:0:无效 1:有效
String certifiable = getText(itemDevice, "Certifiable");
if (!ObjectUtils.isEmpty(certifiable)) {
try {
deviceChannel.setCertifiable(Integer.parseInt(certifiable));
}catch (NumberFormatException e) {
logger.warn("[xml解析] 从通道数据获取 Certifiable失败 {}", certifiable);
}
}
// 无效原因码(有证书且证书无效的设备必选)
String errCode = getText(itemDevice, "ErrCode");
if (!ObjectUtils.isEmpty(errCode)) {
try {
deviceChannel.setErrCode(Integer.parseInt(errCode));
}catch (NumberFormatException e) {
logger.warn("[xml解析] 从通道数据获取 ErrCode失败 {}", errCode);
}
}
// 证书终止有效期(有证书的设备必选)
String endTime = getText(itemDevice, "EndTime");
if (!ObjectUtils.isEmpty(endTime)) {
deviceChannel.setEndTime(endTime);
}
// 设备/区域/系统IP地址
String ipAddress = getText(itemDevice, "IPAddress");
if (!ObjectUtils.isEmpty(ipAddress)) {
deviceChannel.setIpAddress(ipAddress);
}
// 设备/区域/系统端口
String port = getText(itemDevice, "Port");
if (!ObjectUtils.isEmpty(port)) {
try {
deviceChannel.setPort(Integer.parseInt(port));
}catch (NumberFormatException e) {
logger.warn("[xml解析] 从通道数据获取 Port失败 {}", port);
}
}
// 设备口令
String password = getText(itemDevice, "Password");
if (!ObjectUtils.isEmpty(password)) {
deviceChannel.setPassword(password);
}
// 设备状态
String status = getText(itemDevice, "Status");
if (status != null) {
// ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
deviceChannel.setStatus(true);
}
if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
deviceChannel.setStatus(false);
}
}else {
deviceChannel.setStatus(true);
}
// 经度
String longitude = getText(itemDevice, "Longitude");
if (NumericUtil.isDouble(longitude)) {
deviceChannel.setLongitude(Double.parseDouble(longitude));
} else {
deviceChannel.setLongitude(0.00);
}
// 纬度
String latitude = getText(itemDevice, "Latitude");
if (NumericUtil.isDouble(latitude)) {
deviceChannel.setLatitude(Double.parseDouble(latitude));
} else {
deviceChannel.setLatitude(0.00);
}
deviceChannel.setGpsTime(DateUtil.getNow());
// -摄像机类型扩展,标识摄像机类型:1-球机;2-半球;3-固定枪机;4-遥控枪机当目录项为摄像机时可选
String ptzType = getText(itemDevice, "PTZType");
if (ObjectUtils.isEmpty(ptzType)) {
//兼容INFO中的信息
Element info = itemDevice.element("Info");
String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType");
if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){
try {
deviceChannel.setPTZType(Integer.parseInt(ptzTypeFromInfo));
}catch (NumberFormatException e){
logger.warn("[xml解析] 从通道数据info中获取PTZType失败 {}", ptzTypeFromInfo);
}
}
} else {
try {
deviceChannel.setPTZType(Integer.parseInt(ptzType));
}catch (NumberFormatException e){
logger.warn("[xml解析] 从通道数据中获取PTZType失败 {}", ptzType);
}
}
// TODO 摄像机位置类型扩展
// 1-省际检查站
// 2-党政机关
// 3-车站码头
// 4-中心广场
// 5-体育场馆
// 6-商业中心
// 7-宗教场所
// 8-校园周边
// 9-治安复杂区域
// 10-交通干线
// String positionType = getText(itemDevice, "PositionType");
// TODO 摄像机安装位置室外室内属性1-室外2-室内
// String roomType = getText(itemDevice, "RoomType");
// TODO 摄像机用途属性
// String useType = getText(itemDevice, "UseType");
// TODO 摄像机补光属性1-无补光2-红外补光3-白光补光
// String supplyLightType = getText(itemDevice, "SupplyLightType");
// TODO 摄像机监视方位属性1-2-西3-4-5-东南6-东北7-西南8-西北
// String directionType = getText(itemDevice, "DirectionType");
// TODO 摄像机支持的分辨率,可有多个分辨率值,各个取值间以/分隔分辨率取值参见附录 F中SDPf字段规定
// String resolution = getText(itemDevice, "Resolution");
// TODO 下载倍速范围(可选),各可选参数以/分隔,如设备支持1,2,4倍速下载则应写为1/2/4
// String downloadSpeed = getText(itemDevice, "DownloadSpeed");
// TODO 空域编码能力,取值0:不支持;1:1级增强(1个增强层);2:2级增强(2个增强层);3:3级增强(3个增强层)
// String svcSpaceSupportMode = getText(itemDevice, "SVCSpaceSupportMode");
// TODO 时域编码能力,取值0:不支持;1:1级增强;2:2级增强;3:3级增强
// String svcTimeSupportMode = getText(itemDevice, "SVCTimeSupportMode");
deviceChannel.setSecrecy(secrecy);
break;
}
} else {
deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType")));
}
return deviceChannel;

View File

@ -131,14 +131,12 @@ public class ZLMHttpHookListener {
@PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) {
// logger.info("[ZLM HOOK] 收到zlm心跳" + param.getMediaServerId());
taskExecutor.execute(() -> {
List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
JSONObject json = (JSONObject) JSON.toJSON(param);
if (subscribes != null && subscribes.size() > 0) {
for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
subscribe.response(null, json);
subscribe.response(null, param);
}
}
});
@ -165,7 +163,7 @@ public class ZLMHttpHookListener {
if (subscribe != null) {
MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
if (mediaInfo != null) {
subscribe.response(mediaInfo, json);
subscribe.response(mediaInfo, param);
}
}
});
@ -198,13 +196,13 @@ public class ZLMHttpHookListener {
if (userSetting.getPushAuthority()) {
// 推流鉴权
if (param.getParams() == null) {
logger.info("推流鉴权失败: 缺少要参数sign=md5(user表的pushKey)");
logger.info("推流鉴权失败: 缺少要参数sign=md5(user表的pushKey)");
return new HookResultForOnPublish(401, "Unauthorized");
}
Map<String, String> paramMap = urlParamToMap(param.getParams());
String sign = paramMap.get("sign");
if (sign == null) {
logger.info("推流鉴权失败: 缺少要参数sign=md5(user表的pushKey)");
logger.info("推流鉴权失败: 缺少要参数sign=md5(user表的pushKey)");
return new HookResultForOnPublish(401, "Unauthorized");
}
// 推流自定义播放鉴权码
@ -241,7 +239,7 @@ public class ZLMHttpHookListener {
ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
if (subscribe != null) {
if (mediaInfo != null) {
subscribe.response(mediaInfo, json);
subscribe.response(mediaInfo, param);
} else {
new HookResultForOnPublish(1, "zlm not register");
}
@ -321,7 +319,7 @@ public class ZLMHttpHookListener {
return;
}
if (subscribe != null) {
subscribe.response(mediaInfo, json);
subscribe.response(mediaInfo, param);
}
List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
@ -551,7 +549,9 @@ public class ZLMHttpHookListener {
Device device = deviceService.getDevice(inviteInfo.getDeviceId());
if (device != null) {
try {
if (inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()) != null) {
InviteInfo info = inviteStreamService.getInviteInfo(inviteInfo.getType(),
inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream());
if (info != null) {
cmder.streamByeCmd(device, inviteInfo.getChannelId(),
inviteInfo.getStream(), null);
}
@ -578,13 +578,13 @@ public class ZLMHttpHookListener {
// 拉流代理
StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
if (streamProxyItem != null) {
if (streamProxyItem.isEnable_remove_none_reader()) {
if (streamProxyItem.isEnableDisableNoneReader()) {
// 无人观看自动移除
ret.put("close", true);
streamProxyService.del(param.getApp(), param.getStream());
String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrc_url();
String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl();
logger.info("[{}/{}]<-[{}] 拉流代理无人观看已经移除", param.getApp(), param.getStream(), url);
} else if (streamProxyItem.isEnable_disable_none_reader()) {
} else if (streamProxyItem.isEnableDisableNoneReader()) {
// 无人观看停用
ret.put("close", true);
// 修改数据
@ -669,7 +669,7 @@ public class ZLMHttpHookListener {
} else {
// 拉流代理
StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnable_disable_none_reader()) {
if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnableDisableNoneReader()) {
streamProxyService.start(param.getApp(), param.getStream());
}
DeferredResult<HookResult> result = new DeferredResult<>();
@ -693,7 +693,7 @@ public class ZLMHttpHookListener {
List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started);
if (subscribes != null && subscribes.size() > 0) {
for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
subscribe.response(null, jsonObject);
subscribe.response(null, zlmServerConfig);
}
}
mediaServerService.zlmServerOnline(zlmServerConfig);
@ -749,7 +749,7 @@ public class ZLMHttpHookListener {
List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);
if (subscribes != null && subscribes.size() > 0) {
for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
subscribe.response(null, json);
subscribe.response(null, param);
}
}
});

View File

@ -157,7 +157,6 @@ public class ZLMRESTfulUtils {
public void sendGetForImg(MediaServerItem mediaServerItem, String api, Map<String, Object> params, String targetPath, String fileName) {
String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api);
logger.debug(url);
HttpUrl parseUrl = HttpUrl.parse(url);
if (parseUrl == null) {
return;

View File

@ -9,6 +9,11 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRtpServerTimeoutHookParam;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -228,7 +233,7 @@ public class ZLMRTPServerFactory {
int localPort = 0;
if (userSetting.getGbSendStreamStrict()) {
if (userSetting.getGbSendStreamStrict()) {
localPort = keepPort(serverItem, ssrc, null);
localPort = keepPort(serverItem, ssrc, localPort);
if (localPort == 0) {
return null;
}
@ -264,7 +269,7 @@ public class ZLMRTPServerFactory {
// 默认为随机端口
int localPort = 0;
if (userSetting.getGbSendStreamStrict()) {
localPort = keepPort(serverItem, ssrc, null);
localPort = keepPort(serverItem, ssrc, localPort);
if (localPort == 0) {
return null;
}
@ -290,9 +295,6 @@ public class ZLMRTPServerFactory {
*/
public int keepPort(MediaServerItem serverItem, String ssrc, Integer localPort) {
Map<String, Object> param = new HashMap<>(3);
if (localPort == null) {
localPort = 0;
}
param.put("port", localPort);
param.put("enable_tcp", 1);
param.put("stream_id", ssrc);
@ -302,22 +304,24 @@ public class ZLMRTPServerFactory {
HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId());
Integer finalLocalPort = localPort;
hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout,
(MediaServerItem mediaServerItem, JSONObject response)->{
if (ssrc.equals(response.getString("ssrc"))) {
logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc);
int port = keepPort(serverItem, ssrc, finalLocalPort);
if (port == 0) {
logger.info("[上级点播] {}->监听端口失败,移除监听", ssrc);
hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout);
}
(MediaServerItem mediaServerItem, HookParam hookParam)->{
logger.info("[上级点播] {}->监听端口到期继续保持监听: {}", ssrc, finalLocalPort);
OnRtpServerTimeoutHookParam rtpServerTimeoutHookParam = (OnRtpServerTimeoutHookParam) hookParam;
if (!ssrc.equals(rtpServerTimeoutHookParam.getSsrc())) {
return;
}
int port = keepPort(serverItem, ssrc, finalLocalPort);
if (port == 0) {
logger.info("[上级点播] {}->监听端口失败,移除监听", ssrc);
hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout);
}
});
logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort);
logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort);
logger.info("[上级点播] {}->监听端口: {}", ssrc, localPort);
return localPort;
}else {
logger.info("[保持端口] 监听端口失败: {}", ssrc);
logger.info("[上级点播] 监听端口失败: {}->{}", ssrc, localPort);
return 0;
}
return localPort;
}
/**

View File

@ -65,8 +65,8 @@ public class ZLMRunner implements CommandLineRunner {
HookSubscribeForServerStarted hookSubscribeForServerStarted = HookSubscribeFactory.on_server_started();
// 订阅 zlm启动事件, 新的zlm也会从这里进入系统
hookSubscribe.addSubscribe(hookSubscribeForServerStarted,
(MediaServerItem mediaServerItem, JSONObject response)->{
ZLMServerConfig zlmServerConfig = response.to(ZLMServerConfig.class);
(mediaServerItem, hookParam)->{
ZLMServerConfig zlmServerConfig = (ZLMServerConfig)hookParam;
if (zlmServerConfig !=null ) {
if (startGetMedia != null) {
startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());

View File

@ -1,8 +1,9 @@
package com.genersoft.iot.vmp.media.zlm;
import com.alibaba.fastjson2.annotation.JSONField;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
public class ZLMServerConfig {
public class ZLMServerConfig extends HookParam {
@JSONField(name = "api.apiDebug")
private String apiDebug;

View File

@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.media.zlm.dto.HookType;
import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
@ -26,7 +27,7 @@ public class ZlmHttpHookSubscribe {
@FunctionalInterface
public interface Event{
void response(MediaServerItem mediaServerItem, JSONObject response);
void response(MediaServerItem mediaServerItem, HookParam hookParam);
}
private Map<HookType, Map<IHookSubscribe, ZlmHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();

View File

@ -20,28 +20,26 @@ public class StreamProxyItem extends GbStream {
@Schema(description = "拉流地址")
private String url;
@Schema(description = "拉流地址")
private String src_url;
private String srcUrl;
@Schema(description = "目标地址")
private String dst_url;
private String dstUrl;
@Schema(description = "超时时间")
private int timeout_ms;
private int timeoutMs;
@Schema(description = "ffmpeg模板KEY")
private String ffmpeg_cmd_key;
private String ffmpegCmdKey;
@Schema(description = "rtsp拉流时拉流方式0tcp1udp2组播")
private String rtp_type;
private String rtpType;
@Schema(description = "是否启用")
private boolean enable;
@Schema(description = "是否启用音频")
private boolean enable_audio;
private boolean enableAudio;
@Schema(description = "是否启用MP4")
private boolean enable_mp4;
private boolean enableMp4;
@Schema(description = "是否 无人观看时删除")
private boolean enable_remove_none_reader;
private boolean enableRemoveNoneReader;
@Schema(description = "是否 无人观看时自动停用")
private boolean enable_disable_none_reader;
@Schema(description = "创建时间")
private String createTime;
private boolean enableDisableNoneReader;
public String getType() {
return type;
@ -89,44 +87,44 @@ public class StreamProxyItem extends GbStream {
this.url = url;
}
public String getSrc_url() {
return src_url;
public String getSrcUrl() {
return srcUrl;
}
public void setSrc_url(String src_url) {
this.src_url = src_url;
public void setSrcUrl(String src_url) {
this.srcUrl = src_url;
}
public String getDst_url() {
return dst_url;
public String getDstUrl() {
return dstUrl;
}
public void setDst_url(String dst_url) {
this.dst_url = dst_url;
public void setDstUrl(String dst_url) {
this.dstUrl = dst_url;
}
public int getTimeout_ms() {
return timeout_ms;
public int getTimeoutMs() {
return timeoutMs;
}
public void setTimeout_ms(int timeout_ms) {
this.timeout_ms = timeout_ms;
public void setTimeoutMs(int timeout_ms) {
this.timeoutMs = timeout_ms;
}
public String getFfmpeg_cmd_key() {
return ffmpeg_cmd_key;
public String getFfmpegCmdKey() {
return ffmpegCmdKey;
}
public void setFfmpeg_cmd_key(String ffmpeg_cmd_key) {
this.ffmpeg_cmd_key = ffmpeg_cmd_key;
public void setFfmpegCmdKey(String ffmpeg_cmd_key) {
this.ffmpegCmdKey = ffmpeg_cmd_key;
}
public String getRtp_type() {
return rtp_type;
public String getRtpType() {
return rtpType;
}
public void setRtp_type(String rtp_type) {
this.rtp_type = rtp_type;
public void setRtpType(String rtp_type) {
this.rtpType = rtp_type;
}
public boolean isEnable() {
@ -137,45 +135,37 @@ public class StreamProxyItem extends GbStream {
this.enable = enable;
}
public boolean isEnable_mp4() {
return enable_mp4;
public boolean isEnableMp4() {
return enableMp4;
}
public void setEnable_mp4(boolean enable_mp4) {
this.enable_mp4 = enable_mp4;
public void setEnableMp4(boolean enable_mp4) {
this.enableMp4 = enable_mp4;
}
@Override
public String getCreateTime() {
return createTime;
public boolean isEnableRemoveNoneReader() {
return enableRemoveNoneReader;
}
@Override
public void setCreateTime(String createTime) {
this.createTime = createTime;
public void setEnableRemoveNoneReader(boolean enable_remove_none_reader) {
this.enableRemoveNoneReader = enable_remove_none_reader;
}
public boolean isEnable_remove_none_reader() {
return enable_remove_none_reader;
public boolean isEnableDisableNoneReader() {
return enableDisableNoneReader;
}
public void setEnable_remove_none_reader(boolean enable_remove_none_reader) {
this.enable_remove_none_reader = enable_remove_none_reader;
public void setEnableDisableNoneReader(boolean enable_disable_none_reader) {
this.enableDisableNoneReader = enable_disable_none_reader;
}
public boolean isEnable_disable_none_reader() {
return enable_disable_none_reader;
public boolean isEnableAudio() {
return enableAudio;
}
public void setEnable_disable_none_reader(boolean enable_disable_none_reader) {
this.enable_disable_none_reader = enable_disable_none_reader;
public void setEnableAudio(boolean enable_audio) {
this.enableAudio = enable_audio;
}
public boolean isEnable_audio() {
return enable_audio;
}
public void setEnable_audio(boolean enable_audio) {
this.enable_audio = enable_audio;
}
}

View File

@ -325,5 +325,65 @@ public class StreamPushItem extends GbStream implements Comparable<StreamPushIte
public void setSelf(boolean self) {
this.self = self;
}
// @Override
// public Integer getGbStreamId() {
// return super.getGbStreamId();
// }
//
// @Override
// public void setGbStreamId(Integer gbStreamId) {
// super.setGbStreamId(gbStreamId);
// }
//
//
// public String getGbId() {
// return super.getGbId();
// }
//
// public void setGbId(String gbId) {
// super.setGbId(gbId);
// }
//
// public String getName() {
// return super.getName();
// }
//
// public void setName(String name) {
// super.setName(name);
// }
//
// public double getLongitude() {
// return super.getLongitude();
// }
//
// public void setLongitude(double longitude) {
// super.setLongitude(longitude);
// }
//
// public double getLatitude() {
// return super.getLatitude();
// }
//
// public void setLatitude(double latitude) {
// super.setLatitude(latitude);
// }
//
// public String getStreamType() {
// return super.getStreamType();
// }
//
// public void setStreamType(String streamType) {
// super.setStreamType(streamType);
// }
//
// public boolean isStatus() {
// return super.isStatus();
// }
//
// public void setStatus(boolean status) {
// super.setStatus(status);
// }
}

View File

@ -50,4 +50,6 @@ public class HookResultForOnPublish extends HookResult{
public void setMp4_save_path(String mp4_save_path) {
this.mp4_save_path = mp4_save_path;
}
}

View File

@ -81,6 +81,15 @@ public class OnPlayHookParam extends HookParam{
@Override
public String toString() {
return String.format("%s://%s:%s/%s/%s?%s", schema, ip, port, app, stream, params);
return "OnPlayHookParam{" +
"id='" + id + '\'' +
", app='" + app + '\'' +
", stream='" + stream + '\'' +
", ip='" + ip + '\'' +
", params='" + params + '\'' +
", port=" + port +
", schema='" + schema + '\'' +
", vhost='" + vhost + '\'' +
'}';
}
}

View File

@ -81,6 +81,15 @@ public class OnPublishHookParam extends HookParam{
@Override
public String toString() {
return String.format("%s://%s:%s/%s/%s?%s", schema, ip, port, app, stream, params);
return "OnPublishHookParam{" +
"id='" + id + '\'' +
", app='" + app + '\'' +
", stream='" + stream + '\'' +
", ip='" + ip + '\'' +
", params='" + params + '\'' +
", port=" + port +
", schema='" + schema + '\'' +
", vhost='" + vhost + '\'' +
'}';
}
}

View File

@ -50,4 +50,15 @@ public class OnRtpServerTimeoutHookParam extends HookParam{
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
@Override
public String toString() {
return "OnRtpServerTimeoutHookParam{" +
"local_port=" + local_port +
", stream_id='" + stream_id + '\'' +
", tcpMode=" + tcpMode +
", re_use_port=" + re_use_port +
", ssrc='" + ssrc + '\'' +
'}';
}
}

View File

@ -24,4 +24,12 @@ public class OnSendRtpStoppedHookParam extends HookParam{
public void setStream(String stream) {
this.stream = stream;
}
@Override
public String toString() {
return "OnSendRtpStoppedHookParam{" +
"app='" + app + '\'' +
", stream='" + stream + '\'' +
'}';
}
}

View File

@ -17,4 +17,11 @@ public class OnServerKeepaliveHookParam extends HookParam{
public void setData(ServerKeepaliveData data) {
this.data = data;
}
@Override
public String toString() {
return "OnServerKeepaliveHookParam{" +
"data=" + data +
'}';
}
}

View File

@ -430,4 +430,14 @@ public class OnStreamChangedHookParam extends HookParam{
public void setCallId(String callId) {
this.callId = callId;
}
@Override
public String toString() {
return "OnStreamChangedHookParam{" +
"regist=" + regist +
", app='" + app + '\'' +
", stream='" + stream + '\'' +
", severId='" + severId + '\'' +
'}';
}
}

View File

@ -38,4 +38,14 @@ public class OnStreamNoneReaderHookParam extends HookParam{
public void setVhost(String vhost) {
this.vhost = vhost;
}
@Override
public String toString() {
return "OnStreamNoneReaderHookParam{" +
"schema='" + schema + '\'' +
", app='" + app + '\'' +
", stream='" + stream + '\'' +
", vhost='" + vhost + '\'' +
'}';
}
}

View File

@ -81,6 +81,15 @@ public class OnStreamNotFoundHookParam extends HookParam{
@Override
public String toString() {
return String.format("%s://%s:%s/%s/%s?%s", schema, ip, port, app, stream, params);
return "OnStreamNotFoundHookParam{" +
"id='" + id + '\'' +
", app='" + app + '\'' +
", stream='" + stream + '\'' +
", ip='" + ip + '\'' +
", params='" + params + '\'' +
", port=" + port +
", schema='" + schema + '\'' +
", vhost='" + vhost + '\'' +
'}';
}
}

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import java.util.List;
@ -38,7 +38,7 @@ public interface IDeviceChannelService {
* 获取统计信息
* @return
*/
ResourceBaceInfo getOverview();
ResourceBaseInfo getOverview();
/**
* 查询所有未分配的通道

View File

@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import java.util.List;
@ -162,7 +162,7 @@ public interface IDeviceService {
* 获取统计信息
* @return
*/
ResourceBaceInfo getOverview();
ResourceBaseInfo getOverview();
/**
* 获取所有设备

View File

@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
/**
* 记录国标点播的状态包括实时预览下载录像回放
@ -14,6 +14,8 @@ public interface IInviteStreamService {
*/
void updateInviteInfo(InviteInfo inviteInfo);
InviteInfo updateInviteInfoForStream(InviteInfo inviteInfo, String stream);
/**
* 获取点播的状态信息
*/
@ -54,7 +56,7 @@ public interface IInviteStreamService {
/**
* 添加一个invite回调
*/
void once(InviteSessionType type, String deviceId, String channelId, String stream, InviteErrorCallback<Object> callback);
void once(InviteSessionType type, String deviceId, String channelId, String stream, ErrorCallback<Object> callback);
/**
* 调用一个invite回调
@ -65,4 +67,12 @@ public interface IInviteStreamService {
* 清空一个设备的所有invite信息
*/
void clearInviteInfo(String deviceId);
/**
* 统计同一个zlm下的国标收流个数
*/
int getStreamInfoCount(String mediaServerId);
}

View File

@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
@ -25,8 +25,8 @@ import java.util.Map;
public interface IPlayService {
void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
InviteErrorCallback<Object> callback);
SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, InviteErrorCallback<Object> callback);
ErrorCallback<Object> callback);
SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, ErrorCallback<Object> callback);
StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId);
@ -37,13 +37,13 @@ public interface IPlayService {
*/
MediaServerItem getNewMediaServerItemHasAssist(Device device);
void playBack(String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback);
void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback);
void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
void zlmServerOffline(String mediaServerId);
void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback);
void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback);
void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback);
StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
@ -69,4 +69,6 @@ public interface IPlayService {
void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event);
void stopTalk(Device device, String channelId, Boolean streamIsReady);
void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback);
}

View File

@ -1,8 +0,0 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
import com.github.pagehelper.PageInfo;
public interface IRecordInfoServer {
PageInfo<RecordInfo> getRecordList(int page, int count);
}

View File

@ -1,10 +1,11 @@
package com.genersoft.iot.vmp.service;
import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.GeneralCallback;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.github.pagehelper.PageInfo;
public interface IStreamProxyService {
@ -13,7 +14,7 @@ public interface IStreamProxyService {
* 保存视频代理
* @param param
*/
StreamInfo save(StreamProxyItem param);
void save(StreamProxyItem param, GeneralCallback<StreamInfo> callback);
/**
* 添加视频代理到zlm
@ -108,6 +109,6 @@ public interface IStreamProxyService {
* 获取统计信息
* @return
*/
ResourceBaceInfo getOverview();
ResourceBaseInfo getOverview();
}

View File

@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.github.pagehelper.PageInfo;
import java.util.List;
@ -113,5 +113,5 @@ public interface IStreamPushService {
* 获取统计信息
* @return
*/
ResourceBaceInfo getOverview();
ResourceBaseInfo getOverview();
}

View File

@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.service.bean;
public interface InviteErrorCallback<T> {
public interface ErrorCallback<T> {
void run(int code, String msg, T data);
}

View File

@ -5,6 +5,7 @@ package com.genersoft.iot.vmp.service.bean;
*/
public enum InviteErrorCode {
SUCCESS(0, "成功"),
FAIL(-100, "失败"),
ERROR_FOR_SIGNALLING_TIMEOUT(-1, "信令超时"),
ERROR_FOR_STREAM_TIMEOUT(-2, "收流超时"),
ERROR_FOR_RESOURCE_EXHAUSTION(-3, "资源耗尽"),

View File

@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,8 +50,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
}
if ("WGS84".equals(device.getGeoCoordSys())) {
deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
@ -175,8 +173,12 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
}
@Override
public ResourceBaceInfo getOverview() {
return channelMapper.getOverview();
public ResourceBaseInfo getOverview() {
int online = channelMapper.getOnlineCount();
int total = channelMapper.getAllChannelCount();
return new ResourceBaseInfo(total, online);
}
@ -258,4 +260,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
}
}
}
}

View File

@ -1,8 +1,10 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@ -10,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@ -23,7 +26,7 @@ import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -48,6 +51,8 @@ public class DeviceServiceImpl implements IDeviceService {
private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);
@Autowired
private SIPCommander cmder;
@Autowired
private DynamicTask dynamicTask;
@ -124,9 +129,10 @@ public class DeviceServiceImpl implements IDeviceService {
}
// 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
if (device.getCreateTime() == null) {
device.setOnline(1);
if (deviceInDb == null) {
device.setOnLine(true);
device.setCreateTime(now);
device.setUpdateTime(now);
logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
deviceMapper.add(device);
redisCatchStorage.updateDevice(device);
@ -137,8 +143,12 @@ public class DeviceServiceImpl implements IDeviceService {
}
sync(device);
}else {
if(device.getOnline() == 0){
device.setOnline(1);
if (deviceInDb != null) {
device.setSwitchPrimarySubStream(deviceInDb.isSwitchPrimarySubStream());
}
if(!device.isOnLine()){
device.setOnLine(true);
device.setCreateTime(now);
deviceMapper.update(device);
redisCatchStorage.updateDevice(device);
@ -185,14 +195,14 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public void offline(String deviceId, String reason) {
logger.error("[设备离线]{}, device{}", reason, deviceId);
logger.warn("[设备离线]{}, device{}", reason, deviceId);
Device device = deviceMapper.getDeviceByDeviceId(deviceId);
if (device == null) {
return;
}
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId;
dynamicTask.stop(registerExpireTaskKey);
device.setOnline(0);
device.setOnLine(false);
redisCatchStorage.updateDevice(device);
deviceMapper.update(device);
//进行通道离线
@ -256,7 +266,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
logger.info("[移除目录订阅]: {}", device.getDeviceId());
String taskKey = device.getDeviceId() + "catalog";
if (device.getOnline() == 1) {
if (device.isOnLine()) {
Runnable runnable = dynamicTask.get(taskKey);
if (runnable instanceof ISubscribeTask) {
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
@ -289,7 +299,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
logger.info("[移除移动位置订阅]: {}", device.getDeviceId());
String taskKey = device.getDeviceId() + "mobile_position";
if (device.getOnline() == 1) {
if (device.isOnLine()) {
Runnable runnable = dynamicTask.get(taskKey);
if (runnable instanceof ISubscribeTask) {
ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
@ -356,7 +366,7 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public void checkDeviceStatus(Device device) {
if (device == null || device.getOnline() == 0) {
if (device == null || !device.isOnLine()) {
return;
}
try {
@ -405,63 +415,11 @@ public class DeviceServiceImpl implements IDeviceService {
if (device == null) {
return null;
}
if (parentId == null || parentId.equals(deviceId)) {
// 字根节点开始查询
List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), true, !onlyCatalog);
return transportChannelsToTree(rootNodes, "");
if (ObjectUtils.isEmpty(parentId) || parentId.equals(deviceId)) {
parentId = null;
}
if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
if (parentId.length()%2 != 0) {
return null;
}
// 使用行政区划展示树
// if (parentId.length() > 10) {
// // TODO 可能是行政区划与业务分组混杂的情形
// return null;
// }
if (parentId.length() == 10 ) {
if (onlyCatalog) {
return null;
}
// parentId为行业编码 其下不会再有行政区划
List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(channels, parentId);
return trees;
}
// 查询其下的行政区划和摄像机
List<DeviceChannel> channelsForCivilCode = deviceChannelMapper.getChannelsWithCivilCodeAndLength(deviceId, parentId, parentId.length() + 2);
if (!onlyCatalog) {
List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
for(DeviceChannel channel : channels) {
boolean flag = false;
for(DeviceChannel deviceChannel : channelsForCivilCode) {
if(channel.getChannelId().equals(deviceChannel.getChannelId())) {
flag = true;
}
}
if(!flag) {
channelsForCivilCode.add(channel);
}
}
}
List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(channelsForCivilCode, parentId);
return trees;
}
// 使用业务分组展示树
if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
if (parentId.length() < 14 ) {
return null;
}
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null);
List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(deviceChannels, parentId);
return trees;
}
return null;
List<DeviceChannel> rootNodes = deviceChannelMapper.getSubChannelsByDeviceId(deviceId, parentId, onlyCatalog);
return transportChannelsToTree(rootNodes, "");
}
@Override
@ -470,42 +428,11 @@ public class DeviceServiceImpl implements IDeviceService {
if (device == null) {
return null;
}
if (parentId == null || parentId.equals(deviceId)) {
// 字根节点开始查询
List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), false, true);
return rootNodes;
if (ObjectUtils.isEmpty(parentId) || parentId.equals(deviceId)) {
return deviceChannelMapper.getSubChannelsByDeviceId(deviceId, null, false);
}else {
return deviceChannelMapper.getSubChannelsByDeviceId(deviceId, parentId, false);
}
if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
if (parentId.length()%2 != 0) {
return null;
}
// 使用行政区划展示树
if (parentId.length() > 10) {
// TODO 可能是行政区划与业务分组混杂的情形
return null;
}
if (parentId.length() == 10 ) {
// parentId为行业编码 其下不会再有行政区划
List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
return channels;
}
// 查询其下的行政区划和摄像机
List<DeviceChannel> channels = deviceChannelMapper.getChannelsByCivilCode(deviceId, parentId);
return channels;
}
// 使用业务分组展示树
if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
if (parentId.length() < 14 ) {
return null;
}
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null);
return deviceChannels;
}
return null;
}
private List<BaseTree<DeviceChannel>> transportChannelsToTree(List<DeviceChannel> channels, String parentId) {
@ -525,13 +452,21 @@ public class DeviceServiceImpl implements IDeviceService {
node.setPid(parentId);
node.setBasicData(channel);
node.setParent(false);
if (channel.getChannelId().length() > 8) {
if (channel.getChannelId().length() > 13) {
String gbCodeType = channel.getChannelId().substring(10, 13);
node.setParent(gbCodeType.equals(ChannelIdType.BUSINESS_GROUP) || gbCodeType.equals(ChannelIdType.VIRTUAL_ORGANIZATION) );
}
}else {
if (channel.getChannelId().length() <= 8) {
node.setParent(true);
}else {
if (channel.getChannelId().length() != 20) {
node.setParent(channel.getParental() == 1);
}else {
try {
int type = Integer.parseInt(channel.getChannelId().substring(10, 13));
if (type == 215 || type == 216 || type == 200) {
node.setParent(true);
}
}catch (NumberFormatException e) {
node.setParent(false);
}
}
}
treeNotes.add(node);
}
@ -539,53 +474,6 @@ public class DeviceServiceImpl implements IDeviceService {
return treeNotes;
}
private List<DeviceChannel> getRootNodes(String deviceId, boolean isCivilCode, boolean haveCatalog, boolean haveChannel) {
if (!haveCatalog && !haveChannel) {
return null;
}
List<DeviceChannel> result = new ArrayList<>();
if (isCivilCode) {
// 使用行政区划
Integer length= deviceChannelMapper.getChannelMinLength(deviceId);
if (length == null) {
return null;
}
if (length <= 10) {
if (haveCatalog) {
List<DeviceChannel> provinceNode = deviceChannelMapper.getChannelsWithCivilCodeAndLength(deviceId, null, length);
if (provinceNode != null && provinceNode.size() > 0) {
result.addAll(provinceNode);
}
}
if (haveChannel) {
// 查询那些civilCode不在通道中的不规范通道放置在根目录
List<DeviceChannel> nonstandardNode = deviceChannelMapper.getChannelWithoutCiviCode(deviceId);
if (nonstandardNode != null && nonstandardNode.size() > 0) {
result.addAll(nonstandardNode);
}
}
}else {
if (haveChannel) {
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null,null);
if (deviceChannels != null && deviceChannels.size() > 0) {
result.addAll(deviceChannels);
}
}
}
}else {
// 使用业务分组+虚拟组织
// 只获取业务分组
List<DeviceChannel> deviceChannels = deviceChannelMapper.getBusinessGroups(deviceId, ChannelIdType.BUSINESS_GROUP);
if (deviceChannels != null && deviceChannels.size() > 0) {
result.addAll(deviceChannels);
}
}
return result;
}
@Override
public boolean isExist(String deviceId) {
return deviceMapper.getDeviceByDeviceId(deviceId) != null;
@ -593,7 +481,7 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
public void addDevice(Device device) {
device.setOnline(0);
device.setOnLine(false);
device.setCreateTime(DateUtil.getNow());
device.setUpdateTime(DateUtil.getNow());
deviceMapper.addCustomDevice(device);
@ -606,6 +494,22 @@ public class DeviceServiceImpl implements IDeviceService {
logger.warn("更新设备时未找到设备信息");
return;
}
if(deviceInStore.isSwitchPrimarySubStream() != device.isSwitchPrimarySubStream()){
//当修改设备的主子码流开关时需要校验是否存在流如果存在流则直接关闭
List<SsrcTransaction> ssrcTransactionForAll = streamSession.getSsrcTransactionForAll(device.getDeviceId(), null, null, null);
if(ssrcTransactionForAll != null){
for (SsrcTransaction ssrcTransaction: ssrcTransactionForAll) {
try {
cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), ssrcTransaction.getStream(), null, null);
} catch (InvalidArgumentException | SsrcTransactionNotFoundException | ParseException | SipException e) {
throw new RuntimeException(e);
}
}
}
deviceChannelMapper.clearPlay(device.getDeviceId());
inviteStreamService.clearInviteInfo(device.getDeviceId());
}
if (!ObjectUtils.isEmpty(device.getName())) {
deviceInStore.setName(device.getName());
}
@ -617,7 +521,6 @@ public class DeviceServiceImpl implements IDeviceService {
}
deviceInStore.setSdpIp(device.getSdpIp());
deviceInStore.setCharset(device.getCharset());
deviceInStore.setTreeType(device.getTreeType());
// 目录订阅相关的信息
if (device.getSubscribeCycleForCatalog() > 0) {
@ -673,12 +576,17 @@ public class DeviceServiceImpl implements IDeviceService {
}catch (Exception e) {
dataSourceTransactionManager.rollback(transactionStatus);
}
if (result) {
redisCatchStorage.removeDevice(deviceId);
}
return result;
}
@Override
public ResourceBaceInfo getOverview() {
return deviceMapper.getOverview();
public ResourceBaseInfo getOverview() {
List<Device> onlineDevices = deviceMapper.getOnlineDevices();
List<Device> all = deviceMapper.getAll();
return new ResourceBaseInfo(all.size(), onlineDevices.size());
}
@Override

View File

@ -110,23 +110,18 @@ public class GbStreamServiceImpl implements IGbStreamService {
deviceChannel.setLatitude(gbStream.getLatitude());
deviceChannel.setDeviceId(platform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro");
deviceChannel.setStatus(gbStream.isStatus()?1:0);
deviceChannel.setStatus(gbStream.isStatus());
deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
deviceChannel.setCivilCode(catalogId);
}else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
PlatformCatalog catalog = catalogMapper.select(catalogId);
if (catalog == null) {
deviceChannel.setParentId(platform.getDeviceGBId());
deviceChannel.setBusinessGroupId(null);
}else {
deviceChannel.setParentId(catalog.getId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}
PlatformCatalog catalog = catalogMapper.select(catalogId);
if (catalog != null) {
deviceChannel.setCivilCode(catalog.getCivilCode());
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}else {
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
deviceChannel.setParentId(platform.getDeviceGBId());
}
deviceChannel.setModel("live");
@ -218,23 +213,17 @@ public class GbStreamServiceImpl implements IGbStreamService {
}else {
status = gbStreamMapper.selectStatusForPush(gbStream.getApp(), gbStream.getStream());
}
deviceChannel.setStatus((status != null && status )?1:0);
deviceChannel.setStatus(status != null && status);
deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
deviceChannel.setCivilCode(catalogId);
}else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
PlatformCatalog catalog = catalogMapper.select(catalogId);
if (catalog == null) {
deviceChannel.setParentId(platform.getDeviceGBId());
deviceChannel.setBusinessGroupId(null);
}else {
deviceChannel.setParentId(catalog.getId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}
PlatformCatalog catalog = catalogMapper.select(catalogId);
if (catalog != null) {
deviceChannel.setCivilCode(catalog.getCivilCode());
deviceChannel.setParentId(catalog.getParentId());
deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
}else {
deviceChannel.setCivilCode(platform.getAdministrativeDivision());
deviceChannel.setParentId(platform.getDeviceGBId());
}
deviceChannel.setModel("live");

View File

@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.common.InviteSessionStatus;
import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.service.IInviteStreamService;
import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -24,7 +24,7 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
private final Logger logger = LoggerFactory.getLogger(InviteStreamServiceImpl.class);
private final Map<String, List<InviteErrorCallback<Object>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();
private final Map<String, List<ErrorCallback<Object>>> inviteErrorCallbackMap = new ConcurrentHashMap<>();
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@ -84,6 +84,24 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
redisTemplate.opsForValue().set(key, inviteInfoForUpdate);
}
@Override
public InviteInfo updateInviteInfoForStream(InviteInfo inviteInfo, String stream) {
InviteInfo inviteInfoInDb = getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream());
if (inviteInfoInDb == null) {
return null;
}
removeInviteInfo(inviteInfoInDb);
String key = VideoManagerConstants.INVITE_PREFIX +
"_" + inviteInfo.getType() +
"_" + inviteInfo.getDeviceId() +
"_" + inviteInfo.getChannelId() +
"_" + stream;
inviteInfoInDb.setStream(stream);
redisTemplate.opsForValue().set(key, inviteInfoInDb);
return inviteInfoInDb;
}
@Override
public InviteInfo getInviteInfo(InviteSessionType type, String deviceId, String channelId, String stream) {
String key = VideoManagerConstants.INVITE_PREFIX +
@ -141,9 +159,9 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
}
@Override
public void once(InviteSessionType type, String deviceId, String channelId, String stream, InviteErrorCallback<Object> callback) {
public void once(InviteSessionType type, String deviceId, String channelId, String stream, ErrorCallback<Object> callback) {
String key = buildKey(type, deviceId, channelId, stream);
List<InviteErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
if (callbacks == null) {
callbacks = new CopyOnWriteArrayList<>();
inviteErrorCallbackMap.put(key, callbacks);
@ -152,19 +170,6 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
}
@Override
public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) {
String key = buildKey(type, deviceId, channelId, stream);
List<InviteErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
if (callbacks == null) {
return;
}
for (InviteErrorCallback<Object> callback : callbacks) {
callback.run(code, msg, data);
}
inviteErrorCallbackMap.remove(key);
}
private String buildKey(InviteSessionType type, String deviceId, String channelId, String stream) {
String key = type + "_" + deviceId + "_" + channelId;
// 如果ssrc未null那么可以实现一个通道只能一次操作ssrc不为null则可以支持一个通道多次invite
@ -179,4 +184,46 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
public void clearInviteInfo(String deviceId) {
removeInviteInfo(null, deviceId, null, null);
}
@Override
public int getStreamInfoCount(String mediaServerId) {
int count = 0;
String key = VideoManagerConstants.INVITE_PREFIX + "_*_*_*_*";
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
if (scanResult.size() == 0) {
return 0;
}else {
for (Object keyObj : scanResult) {
String keyStr = (String) keyObj;
InviteInfo inviteInfo = (InviteInfo) redisTemplate.opsForValue().get(keyStr);
if (inviteInfo != null && inviteInfo.getStreamInfo() != null && inviteInfo.getStreamInfo().getMediaServerId().equals(mediaServerId)) {
count++;
}
}
}
return count;
}
@Override
public void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data) {
String key = buildSubStreamKey(type, deviceId, channelId, stream);
List<ErrorCallback<Object>> callbacks = inviteErrorCallbackMap.get(key);
if (callbacks == null) {
return;
}
for (ErrorCallback<Object> callback : callbacks) {
callback.run(code, msg, data);
}
inviteErrorCallbackMap.remove(key);
}
private String buildSubStreamKey(InviteSessionType type, String deviceId, String channelId, String stream) {
String key = type + "_" + "_" + deviceId + "_" + channelId;
// 如果ssrc为null那么可以实现一个通道只能一次操作ssrc不为null则可以支持一个通道多次invite
if (stream != null) {
key += ("_" + stream);
}
return key;
}
}

View File

@ -17,6 +17,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData;
import com.genersoft.iot.vmp.service.IInviteStreamService;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@ -97,6 +98,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IInviteStreamService inviteStreamService;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@ -423,7 +427,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
}
final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId();
dynamicTask.stop(zlmKeepaliveKey);
dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (Math.getExponent(serverItem.getHookAliveInterval()) + 5) * 1000);
dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (serverItem.getHookAliveInterval().intValue() + 5) * 1000);
publisher.zlmOnlineEventPublish(serverItem.getId());
logger.info("[ZLM] 连接成功 {} - {}:{} ",
@ -694,7 +698,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
// 缓存不存在从数据库查询如果数据库不存在则是错误的
mediaServerItem = getOneFromDatabase(mediaServerId);
if (mediaServerItem == null) {
logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");
logger.warn("[更新ZLM 保活信息] 流媒体{}尚未加入使用,请检查节点中是否含有此流媒体 ", mediaServerId);
return;
}
// zlm连接重试
@ -744,7 +748,8 @@ public class MediaServerServiceImpl implements IMediaServerService {
result.setId(mediaServerItem.getId());
result.setPush(redisCatchStorage.getPushStreamCount(mediaServerItem.getId()));
result.setProxy(redisCatchStorage.getProxyStreamCount(mediaServerItem.getId()));
result.setGbReceive(redisCatchStorage.getGbReceiveCount(mediaServerItem.getId()));
result.setGbReceive(inviteStreamService.getStreamInfoCount(mediaServerItem.getId()));
result.setGbSend(redisCatchStorage.getGbSendCount(mediaServerItem.getId()));
return result;
}

Some files were not shown because too many files have changed in this diff Show More