Commit c8831bc58fd967a4215cbe3ea8c89d753b4d31f7

Authored by wangyimeng
1 parent 69d9692f

更新同步wvp

Showing 65 changed files with 1944 additions and 889 deletions

Too many changes to show.

To preserve performance only 65 of 225 files are displayed.

DOCKERFILE
... ... @@ -84,7 +84,7 @@ RUN echo '#!/bin/bash' > run.sh && \
84 84 echo 'nohup java -jar *.jar --userSettings.record=/opt/media/www/record/ &' >> run.sh && \
85 85 echo 'nohup /opt/media/MediaServer -d -m 3 &' >> run.sh && \
86 86 echo 'cd /opt/wvp' >> run.sh && \
87   - echo 'if [${WVP_CONFIG}]; then' >> run.sh && \
  87 + echo 'if [-n "${WVP_CONFIG}"]; then' >> run.sh && \
88 88 echo ' java -jar *.jar --spring.config.location=/opt/wvp/config/application.yml --media.record-assist-port=18081 ${WVP_CONFIG}' >> run.sh && \
89 89 echo 'else' >> run.sh && \
90 90 echo ' java -jar *.jar --spring.config.location=/opt/wvp/config/application.yml --media.record-assist-port=18081 --media.ip=127.0.0.1 --media.sdp-ip=${WVP_IP} --sip.ip=${WVP_IP} --media.stream-ip=${WVP_IP}' >> run.sh && \
... ...
README.md
1   -![logo](https://gitee.com/pan648540858/wvp-GB28181-pro/raw/wvp-28181-2.0/web_src/static/logo.png)
  1 +![logo](https://raw.githubusercontent.com/648540858/wvp-GB28181-pro/wvp-28181-2.0/web_src/static/logo.png)
2 2 # 开箱即用的的28181协议视频平台
3 3  
4 4 [![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit)
... ... @@ -10,9 +10,9 @@
10 10  
11 11 WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网络视频平台,负责实现核心信令与设备管理后台部分,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联,支持将不带国标功能的摄像机/直播流/直播推流转发到其他国标平台。
12 12  
13   -流媒体服务基于ZLMediaKit-https://github.com/xiongziliang/ZLMediaKit
14   -
15   -前端页面基于MediaServerUI进行修改.
  13 +流媒体服务基于@夏楚 ZLMediaKit [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
  14 +播放器使用@dexter jessibuca [https://github.com/langhuihui/jessibuca/tree/v3](https://github.com/langhuihui/jessibuca/tree/v3)
  15 +前端页面基于@Kyle MediaServerUI [https://gitee.com/kkkkk5G/MediaServerUI](https://gitee.com/kkkkk5G/MediaServerUI) 进行修改.
16 16  
17 17 # 应用场景:
18 18 支持浏览器无插件播放摄像头视频。
... ... @@ -128,7 +128,18 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
128 128 QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
129 129 QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助,欢迎star和提交pr。
130 130  
  131 +# 授权协议
  132 +本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议
131 133  
132 134 # 致谢
133   -感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架
  135 +感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架,并在开发过程中给予支持与帮助。
  136 +感谢作者[dexter langhuihui](https://github.com/langhuihui) 开源这么好用的WEB播放器。
  137 +感谢作者[Kyle](https://gitee.com/kkkkk5G) 开源了好用的前端页面
  138 +感谢各位大佬的赞助以及对项目的指正与帮助。包括但不限于代码贡献、问题反馈、资金捐赠等各种方式的支持!以下排名不分先后:
  139 +[lawrencehj](https://github.com/lawrencehj) [Smallwhitepig](https://github.com/Smallwhitepig) [swwhaha](https://github.com/swwheihei)
  140 +[hotcoffie](https://github.com/hotcoffie) [xiaomu](https://github.com/nikmu) [TristingChen](https://github.com/TristingChen)
  141 +[chenparty](https://github.com/chenparty) [Hotleave](https://github.com/hotleave) [ydwxb](https://github.com/ydwxb)
  142 +[ydpd](https://github.com/ydpd) [szy833](https://github.com/szy833) [ydwxb](https://github.com/ydwxb) [Albertzhu666](https://github.com/Albertzhu666)
  143 +
  144 +ps: 刚增加了这个名单,肯定遗漏了一些大佬,欢迎大佬联系我添加。
134 145  
... ...
... ... @@ -11,7 +11,7 @@
11 11  
12 12 <groupId>com.genersoft</groupId>
13 13 <artifactId>wvp-pro</artifactId>
14   - <version>2.0.2</version>
  14 + <version>2.2.1</version>
15 15 <name>web video platform</name>
16 16 <description>国标28181视频平台</description>
17 17  
... ... @@ -269,13 +269,13 @@
269 269 </configuration>
270 270 </plugin>
271 271  
272   - <plugin>
  272 + <!-- <plugin>
273 273 <groupId>pl.project13.maven</groupId>
274 274 <artifactId>git-commit-id-plugin</artifactId>
275 275 <configuration>
276 276 <offline>true</offline>
277 277 </configuration>
278   - </plugin>
  278 + </plugin>-->
279 279  
280 280 <plugin>
281 281 <groupId>org.apache.maven.plugins</groupId>
... ...
sql/clean.sql 0 → 100644
  1 +delete from device;
  2 +delete from device_alarm;
  3 +delete from device_channel;
  4 +delete from device_mobile_position;
  5 +delete from gb_stream;
  6 +delete from log;
  7 +delete from media_server;
  8 +delete from parent_platform;
  9 +delete from platform_catalog;
  10 +delete from platform_gb_channel;
  11 +delete from platform_gb_stream;
  12 +delete from stream_proxy;
  13 +delete from stream_push;
0 14 \ No newline at end of file
... ...
sql/mysql.sql
1   --- MySQL dump 10.13 Distrib 8.0.28, for Linux (x86_64)
  1 +-- MariaDB dump 10.19 Distrib 10.7.3-MariaDB, for Linux (x86_64)
2 2 --
3   --- Host: 127.0.0.1 Database: wvp
  3 +-- Host: 127.0.0.1 Database: wvp3
4 4 -- ------------------------------------------------------
5   --- Server version 8.0.28-0ubuntu0.20.04.3
  5 +-- Server version 8.0.0-dmr
6 6  
7 7 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
8 8 /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
9 9 /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
10   -/*!50503 SET NAMES utf8mb4 */;
  10 +/*!40101 SET NAMES utf8mb4 */;
11 11 /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
12 12 /*!40103 SET TIME_ZONE='+00:00' */;
13 13 /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
... ... @@ -21,30 +21,34 @@
21 21  
22 22 DROP TABLE IF EXISTS `device`;
23 23 /*!40101 SET @saved_cs_client = @@character_set_client */;
24   -/*!50503 SET character_set_client = utf8mb4 */;
  24 +/*!40101 SET character_set_client = utf8 */;
25 25 CREATE TABLE `device` (
26   - `id` int NOT NULL AUTO_INCREMENT,
27   - `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
28   - `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
29   - `manufacturer` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
30   - `model` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
31   - `firmware` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
32   - `transport` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
33   - `streamMode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
34   - `online` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
35   - `registerTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
36   - `keepaliveTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
37   - `ip` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
38   - `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
39   - `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
40   - `port` int NOT NULL,
41   - `expires` int NOT NULL,
42   - `subscribeCycleForCatalog` int NOT NULL,
43   - `hostAddress` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
44   - `charset` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  26 + `id` int(11) NOT NULL AUTO_INCREMENT,
  27 + `deviceId` varchar(50) NOT NULL,
  28 + `name` varchar(255) DEFAULT NULL,
  29 + `manufacturer` varchar(255) DEFAULT NULL,
  30 + `model` varchar(255) DEFAULT NULL,
  31 + `firmware` varchar(255) DEFAULT NULL,
  32 + `transport` varchar(50) DEFAULT NULL,
  33 + `streamMode` varchar(50) DEFAULT NULL,
  34 + `online` varchar(50) DEFAULT NULL,
  35 + `registerTime` varchar(50) DEFAULT NULL,
  36 + `keepaliveTime` varchar(50) DEFAULT NULL,
  37 + `ip` varchar(50) NOT NULL,
  38 + `createTime` varchar(50) NOT NULL,
  39 + `updateTime` varchar(50) NOT NULL,
  40 + `port` int(11) NOT NULL,
  41 + `expires` int(11) NOT NULL,
  42 + `subscribeCycleForCatalog` int(11) NOT NULL,
  43 + `subscribeCycleForMobilePosition` int(11) NOT NULL,
  44 + `mobilePositionSubmissionInterval` int(11) NOT NULL DEFAULT '5',
  45 + `subscribeCycleForAlarm` int(11) NOT NULL,
  46 + `hostAddress` varchar(50) NOT NULL,
  47 + `charset` varchar(50) NOT NULL,
  48 + `ssrcCheck` int(11) DEFAULT '0',
45 49 PRIMARY KEY (`id`),
46 50 UNIQUE KEY `device_deviceId_uindex` (`deviceId`)
47   -) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  51 +) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4;
48 52 /*!40101 SET character_set_client = @saved_cs_client */;
49 53  
50 54 --
... ... @@ -62,20 +66,20 @@ UNLOCK TABLES;
62 66  
63 67 DROP TABLE IF EXISTS `device_alarm`;
64 68 /*!40101 SET @saved_cs_client = @@character_set_client */;
65   -/*!50503 SET character_set_client = utf8mb4 */;
  69 +/*!40101 SET character_set_client = utf8 */;
66 70 CREATE TABLE `device_alarm` (
67   - `id` int NOT NULL AUTO_INCREMENT,
68   - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
69   - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
70   - `alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
71   - `alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
72   - `alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
73   - `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  71 + `id` int(11) NOT NULL AUTO_INCREMENT,
  72 + `deviceId` varchar(50) NOT NULL,
  73 + `channelId` varchar(50) NOT NULL,
  74 + `alarmPriority` varchar(50) NOT NULL,
  75 + `alarmMethod` varchar(50) DEFAULT NULL,
  76 + `alarmTime` varchar(50) NOT NULL,
  77 + `alarmDescription` varchar(255) DEFAULT NULL,
74 78 `longitude` double DEFAULT NULL,
75 79 `latitude` double DEFAULT NULL,
76   - `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  80 + `alarmType` varchar(50) DEFAULT NULL,
77 81 PRIMARY KEY (`id`) USING BTREE
78   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  82 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
79 83 /*!40101 SET character_set_client = @saved_cs_client */;
80 84  
81 85 --
... ... @@ -93,43 +97,43 @@ UNLOCK TABLES;
93 97  
94 98 DROP TABLE IF EXISTS `device_channel`;
95 99 /*!40101 SET @saved_cs_client = @@character_set_client */;
96   -/*!50503 SET character_set_client = utf8mb4 */;
  100 +/*!40101 SET character_set_client = utf8 */;
97 101 CREATE TABLE `device_channel` (
98   - `id` int NOT NULL AUTO_INCREMENT,
99   - `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
100   - `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
101   - `manufacture` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
102   - `model` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
103   - `owner` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
104   - `civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
105   - `block` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
106   - `address` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
107   - `parentId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
108   - `safetyWay` int DEFAULT NULL,
109   - `registerWay` int DEFAULT NULL,
110   - `certNum` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
111   - `certifiable` int DEFAULT NULL,
112   - `errCode` int DEFAULT NULL,
113   - `endTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
114   - `secrecy` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
115   - `ipAddress` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
116   - `port` int DEFAULT NULL,
117   - `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
118   - `PTZType` int DEFAULT NULL,
119   - `status` int DEFAULT NULL,
  102 + `id` int(11) NOT NULL AUTO_INCREMENT,
  103 + `channelId` varchar(50) NOT NULL,
  104 + `name` varchar(255) DEFAULT NULL,
  105 + `manufacture` varchar(50) DEFAULT NULL,
  106 + `model` varchar(50) DEFAULT NULL,
  107 + `owner` varchar(50) DEFAULT NULL,
  108 + `civilCode` varchar(50) DEFAULT NULL,
  109 + `block` varchar(50) DEFAULT NULL,
  110 + `address` varchar(50) DEFAULT NULL,
  111 + `parentId` varchar(50) DEFAULT NULL,
  112 + `safetyWay` int(11) DEFAULT NULL,
  113 + `registerWay` int(11) DEFAULT NULL,
  114 + `certNum` varchar(50) DEFAULT NULL,
  115 + `certifiable` int(11) DEFAULT NULL,
  116 + `errCode` int(11) DEFAULT NULL,
  117 + `endTime` varchar(50) DEFAULT NULL,
  118 + `secrecy` varchar(50) DEFAULT NULL,
  119 + `ipAddress` varchar(50) DEFAULT NULL,
  120 + `port` int(11) DEFAULT NULL,
  121 + `password` varchar(255) DEFAULT NULL,
  122 + `PTZType` int(11) DEFAULT NULL,
  123 + `status` int(11) DEFAULT NULL,
120 124 `longitude` double DEFAULT NULL,
121 125 `latitude` double DEFAULT NULL,
122   - `streamId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
123   - `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
124   - `parental` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  126 + `streamId` varchar(50) DEFAULT NULL,
  127 + `deviceId` varchar(50) NOT NULL,
  128 + `parental` varchar(50) DEFAULT NULL,
125 129 `hasAudio` bit(1) DEFAULT NULL,
126   - `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
127   - `updateTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
128   - `subCount` int DEFAULT '0',
  130 + `createTime` varchar(50) NOT NULL,
  131 + `updateTime` varchar(50) NOT NULL,
  132 + `subCount` int(11) DEFAULT '0',
129 133 PRIMARY KEY (`id`),
130 134 UNIQUE KEY `device_channel_id_uindex` (`id`),
131 135 UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`)
132   -) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  136 +) ENGINE=InnoDB AUTO_INCREMENT=81657 DEFAULT CHARSET=utf8mb4;
133 137 /*!40101 SET character_set_client = @saved_cs_client */;
134 138  
135 139 --
... ... @@ -147,24 +151,24 @@ UNLOCK TABLES;
147 151  
148 152 DROP TABLE IF EXISTS `device_mobile_position`;
149 153 /*!40101 SET @saved_cs_client = @@character_set_client */;
150   -/*!50503 SET character_set_client = utf8mb4 */;
  154 +/*!40101 SET character_set_client = utf8 */;
151 155 CREATE TABLE `device_mobile_position` (
152   - `id` int NOT NULL AUTO_INCREMENT,
153   - `deviceId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
154   - `channelId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
155   - `deviceName` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
156   - `time` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  156 + `id` int(11) NOT NULL AUTO_INCREMENT,
  157 + `deviceId` varchar(50) NOT NULL,
  158 + `channelId` varchar(50) NOT NULL,
  159 + `deviceName` varchar(255) DEFAULT NULL,
  160 + `time` varchar(50) NOT NULL,
157 161 `longitude` double NOT NULL,
158 162 `latitude` double NOT NULL,
159 163 `altitude` double DEFAULT NULL,
160 164 `speed` double DEFAULT NULL,
161 165 `direction` double DEFAULT NULL,
162   - `reportSource` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
163   - `geodeticSystem` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
164   - `cnLng` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
165   - `cnLat` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  166 + `reportSource` varchar(50) DEFAULT NULL,
  167 + `geodeticSystem` varchar(50) DEFAULT NULL,
  168 + `cnLng` varchar(50) DEFAULT NULL,
  169 + `cnLat` varchar(50) DEFAULT NULL,
166 170 PRIMARY KEY (`id`)
167   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  171 +) ENGINE=InnoDB AUTO_INCREMENT=6108 DEFAULT CHARSET=utf8mb4;
168 172 /*!40101 SET character_set_client = @saved_cs_client */;
169 173  
170 174 --
... ... @@ -182,23 +186,23 @@ UNLOCK TABLES;
182 186  
183 187 DROP TABLE IF EXISTS `gb_stream`;
184 188 /*!40101 SET @saved_cs_client = @@character_set_client */;
185   -/*!50503 SET character_set_client = utf8mb4 */;
  189 +/*!40101 SET character_set_client = utf8 */;
186 190 CREATE TABLE `gb_stream` (
187   - `gbStreamId` int NOT NULL AUTO_INCREMENT,
188   - `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
189   - `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
190   - `gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
191   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  191 + `gbStreamId` int(11) NOT NULL AUTO_INCREMENT,
  192 + `app` varchar(255) NOT NULL,
  193 + `stream` varchar(255) NOT NULL,
  194 + `gbId` varchar(50) NOT NULL,
  195 + `name` varchar(255) DEFAULT NULL,
192 196 `longitude` double DEFAULT NULL,
193 197 `latitude` double DEFAULT NULL,
194   - `streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
195   - `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
196   - `status` int DEFAULT NULL,
197   - `createStamp` bigint DEFAULT NULL,
  198 + `streamType` varchar(50) DEFAULT NULL,
  199 + `mediaServerId` varchar(50) DEFAULT NULL,
  200 + `status` int(11) DEFAULT NULL,
  201 + `createStamp` bigint(20) DEFAULT NULL,
198 202 PRIMARY KEY (`gbStreamId`) USING BTREE,
199 203 UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
200 204 UNIQUE KEY `gbId` (`gbId`) USING BTREE
201   -) ENGINE=InnoDB AUTO_INCREMENT=300766 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  205 +) ENGINE=InnoDB AUTO_INCREMENT=300769 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
202 206 /*!40101 SET character_set_client = @saved_cs_client */;
203 207  
204 208 --
... ... @@ -216,19 +220,19 @@ UNLOCK TABLES;
216 220  
217 221 DROP TABLE IF EXISTS `log`;
218 222 /*!40101 SET @saved_cs_client = @@character_set_client */;
219   -/*!50503 SET character_set_client = utf8mb4 */;
  223 +/*!40101 SET character_set_client = utf8 */;
220 224 CREATE TABLE `log` (
221   - `id` int NOT NULL AUTO_INCREMENT,
222   - `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
223   - `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
224   - `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
225   - `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
226   - `result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
227   - `timing` bigint NOT NULL,
228   - `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
229   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  225 + `id` int(11) NOT NULL AUTO_INCREMENT,
  226 + `name` varchar(50) NOT NULL,
  227 + `type` varchar(50) NOT NULL,
  228 + `uri` varchar(200) NOT NULL,
  229 + `address` varchar(50) NOT NULL,
  230 + `result` varchar(50) NOT NULL,
  231 + `timing` bigint(20) NOT NULL,
  232 + `username` varchar(50) NOT NULL,
  233 + `createTime` varchar(50) NOT NULL,
230 234 PRIMARY KEY (`id`) USING BTREE
231   -) ENGINE=InnoDB AUTO_INCREMENT=962 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  235 +) ENGINE=InnoDB AUTO_INCREMENT=1552 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
232 236 /*!40101 SET character_set_client = @saved_cs_client */;
233 237  
234 238 --
... ... @@ -246,34 +250,34 @@ UNLOCK TABLES;
246 250  
247 251 DROP TABLE IF EXISTS `media_server`;
248 252 /*!40101 SET @saved_cs_client = @@character_set_client */;
249   -/*!50503 SET character_set_client = utf8mb4 */;
  253 +/*!40101 SET character_set_client = utf8 */;
250 254 CREATE TABLE `media_server` (
251   - `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
252   - `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
253   - `hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
254   - `sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
255   - `streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
256   - `httpPort` int NOT NULL,
257   - `httpSSlPort` int NOT NULL,
258   - `rtmpPort` int NOT NULL,
259   - `rtmpSSlPort` int NOT NULL,
260   - `rtpProxyPort` int NOT NULL,
261   - `rtspPort` int NOT NULL,
262   - `rtspSSLPort` int NOT NULL,
263   - `autoConfig` int NOT NULL,
264   - `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
265   - `streamNoneReaderDelayMS` int NOT NULL,
266   - `rtpEnable` int NOT NULL,
267   - `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
268   - `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
269   - `recordAssistPort` int NOT NULL,
270   - `defaultServer` int NOT NULL,
271   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
272   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
273   - `hookAliveInterval` int NOT NULL,
  255 + `id` varchar(255) NOT NULL,
  256 + `ip` varchar(50) NOT NULL,
  257 + `hookIp` varchar(50) NOT NULL,
  258 + `sdpIp` varchar(50) NOT NULL,
  259 + `streamIp` varchar(50) NOT NULL,
  260 + `httpPort` int(11) NOT NULL,
  261 + `httpSSlPort` int(11) NOT NULL,
  262 + `rtmpPort` int(11) NOT NULL,
  263 + `rtmpSSlPort` int(11) NOT NULL,
  264 + `rtpProxyPort` int(11) NOT NULL,
  265 + `rtspPort` int(11) NOT NULL,
  266 + `rtspSSLPort` int(11) NOT NULL,
  267 + `autoConfig` int(11) NOT NULL,
  268 + `secret` varchar(50) NOT NULL,
  269 + `streamNoneReaderDelayMS` int(11) NOT NULL,
  270 + `rtpEnable` int(11) NOT NULL,
  271 + `rtpPortRange` varchar(50) NOT NULL,
  272 + `sendRtpPortRange` varchar(50) NOT NULL,
  273 + `recordAssistPort` int(11) NOT NULL,
  274 + `defaultServer` int(11) NOT NULL,
  275 + `createTime` varchar(50) NOT NULL,
  276 + `updateTime` varchar(50) NOT NULL,
  277 + `hookAliveInterval` int(11) NOT NULL,
274 278 PRIMARY KEY (`id`) USING BTREE,
275 279 UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE
276   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  280 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
277 281 /*!40101 SET character_set_client = @saved_cs_client */;
278 282  
279 283 --
... ... @@ -291,33 +295,36 @@ UNLOCK TABLES;
291 295  
292 296 DROP TABLE IF EXISTS `parent_platform`;
293 297 /*!40101 SET @saved_cs_client = @@character_set_client */;
294   -/*!50503 SET character_set_client = utf8mb4 */;
  298 +/*!40101 SET character_set_client = utf8 */;
295 299 CREATE TABLE `parent_platform` (
296   - `id` int NOT NULL AUTO_INCREMENT,
297   - `enable` int DEFAULT NULL,
298   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
299   - `serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
300   - `serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
301   - `serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
302   - `serverPort` int DEFAULT NULL,
303   - `deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
304   - `deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
305   - `devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
306   - `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
307   - `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
308   - `expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
309   - `keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
310   - `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
311   - `characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
312   - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
313   - `ptz` int DEFAULT NULL,
314   - `rtcp` int DEFAULT NULL,
  300 + `id` int(11) NOT NULL AUTO_INCREMENT,
  301 + `enable` int(11) DEFAULT NULL,
  302 + `name` varchar(255) DEFAULT NULL,
  303 + `serverGBId` varchar(50) NOT NULL,
  304 + `serverGBDomain` varchar(50) DEFAULT NULL,
  305 + `serverIP` varchar(50) DEFAULT NULL,
  306 + `serverPort` int(11) DEFAULT NULL,
  307 + `deviceGBId` varchar(50) NOT NULL,
  308 + `deviceIp` varchar(50) DEFAULT NULL,
  309 + `devicePort` varchar(50) DEFAULT NULL,
  310 + `username` varchar(255) DEFAULT NULL,
  311 + `password` varchar(50) DEFAULT NULL,
  312 + `expires` varchar(50) DEFAULT NULL,
  313 + `keepTimeout` varchar(50) DEFAULT NULL,
  314 + `transport` varchar(50) DEFAULT NULL,
  315 + `characterSet` varchar(50) DEFAULT NULL,
  316 + `catalogId` varchar(50) NOT NULL,
  317 + `ptz` int(11) DEFAULT NULL,
  318 + `rtcp` int(11) DEFAULT NULL,
315 319 `status` bit(1) DEFAULT NULL,
316   - `shareAllLiveStream` int DEFAULT NULL,
  320 + `shareAllLiveStream` int(11) DEFAULT NULL,
  321 + `startOfflinePush` int(11) DEFAULT '0',
  322 + `administrativeDivision` varchar(50) NOT NULL,
  323 + `catalogGroup` int(11) DEFAULT '1',
317 324 PRIMARY KEY (`id`),
318 325 UNIQUE KEY `parent_platform_id_uindex` (`id`),
319 326 UNIQUE KEY `parent_platform_pk` (`serverGBId`)
320   -) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  327 +) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
321 328 /*!40101 SET character_set_client = @saved_cs_client */;
322 329  
323 330 --
... ... @@ -335,14 +342,14 @@ UNLOCK TABLES;
335 342  
336 343 DROP TABLE IF EXISTS `platform_catalog`;
337 344 /*!40101 SET @saved_cs_client = @@character_set_client */;
338   -/*!50503 SET character_set_client = utf8mb4 */;
  345 +/*!40101 SET character_set_client = utf8 */;
339 346 CREATE TABLE `platform_catalog` (
340   - `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
341   - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
342   - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
343   - `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  347 + `id` varchar(50) NOT NULL,
  348 + `platformId` varchar(50) NOT NULL,
  349 + `name` varchar(255) NOT NULL,
  350 + `parentId` varchar(50) DEFAULT NULL,
344 351 PRIMARY KEY (`id`) USING BTREE
345   -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  352 +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
346 353 /*!40101 SET character_set_client = @saved_cs_client */;
347 354  
348 355 --
... ... @@ -360,14 +367,14 @@ UNLOCK TABLES;
360 367  
361 368 DROP TABLE IF EXISTS `platform_gb_channel`;
362 369 /*!40101 SET @saved_cs_client = @@character_set_client */;
363   -/*!50503 SET character_set_client = utf8mb4 */;
  370 +/*!40101 SET character_set_client = utf8 */;
364 371 CREATE TABLE `platform_gb_channel` (
365   - `id` int NOT NULL AUTO_INCREMENT,
366   - `platformId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
367   - `catalogId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
368   - `deviceChannelId` int NOT NULL,
  372 + `id` int(11) NOT NULL AUTO_INCREMENT,
  373 + `platformId` varchar(50) NOT NULL,
  374 + `catalogId` varchar(50) NOT NULL,
  375 + `deviceChannelId` int(11) NOT NULL,
369 376 PRIMARY KEY (`id`)
370   -) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  377 +) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=utf8mb4;
371 378 /*!40101 SET character_set_client = @saved_cs_client */;
372 379  
373 380 --
... ... @@ -385,15 +392,15 @@ UNLOCK TABLES;
385 392  
386 393 DROP TABLE IF EXISTS `platform_gb_stream`;
387 394 /*!40101 SET @saved_cs_client = @@character_set_client */;
388   -/*!50503 SET character_set_client = utf8mb4 */;
  395 +/*!40101 SET character_set_client = utf8 */;
389 396 CREATE TABLE `platform_gb_stream` (
390   - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
391   - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
392   - `gbStreamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
393   - `id` int NOT NULL AUTO_INCREMENT,
  397 + `platformId` varchar(50) NOT NULL,
  398 + `catalogId` varchar(50) NOT NULL,
  399 + `gbStreamId` int(11) NOT NULL,
  400 + `id` int(11) NOT NULL AUTO_INCREMENT,
394 401 PRIMARY KEY (`id`),
395 402 UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`)
396   -) ENGINE=InnoDB AUTO_INCREMENT=301207 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  403 +) ENGINE=InnoDB AUTO_INCREMENT=301210 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
397 404 /*!40101 SET character_set_client = @saved_cs_client */;
398 405  
399 406 --
... ... @@ -411,29 +418,29 @@ UNLOCK TABLES;
411 418  
412 419 DROP TABLE IF EXISTS `stream_proxy`;
413 420 /*!40101 SET @saved_cs_client = @@character_set_client */;
414   -/*!50503 SET character_set_client = utf8mb4 */;
  421 +/*!40101 SET character_set_client = utf8 */;
415 422 CREATE TABLE `stream_proxy` (
416   - `id` int NOT NULL AUTO_INCREMENT,
417   - `type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
418   - `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
419   - `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
420   - `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
421   - `url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
422   - `src_url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
423   - `dst_url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
424   - `timeout_ms` int DEFAULT NULL,
425   - `ffmpeg_cmd_key` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
426   - `rtp_type` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
427   - `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  423 + `id` int(11) NOT NULL AUTO_INCREMENT,
  424 + `type` varchar(50) NOT NULL,
  425 + `app` varchar(255) NOT NULL,
  426 + `stream` varchar(255) NOT NULL,
  427 + `url` varchar(255) DEFAULT NULL,
  428 + `src_url` varchar(255) DEFAULT NULL,
  429 + `dst_url` varchar(255) DEFAULT NULL,
  430 + `timeout_ms` int(11) DEFAULT NULL,
  431 + `ffmpeg_cmd_key` varchar(255) DEFAULT NULL,
  432 + `rtp_type` varchar(50) DEFAULT NULL,
  433 + `mediaServerId` varchar(50) DEFAULT NULL,
428 434 `enable_hls` bit(1) DEFAULT NULL,
429 435 `enable_mp4` bit(1) DEFAULT NULL,
430 436 `enable` bit(1) NOT NULL,
431 437 `status` bit(1) NOT NULL,
432 438 `enable_remove_none_reader` bit(1) NOT NULL,
433   - `createTime` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  439 + `createTime` varchar(50) NOT NULL,
  440 + `name` varchar(255) DEFAULT NULL,
434 441 PRIMARY KEY (`id`),
435 442 UNIQUE KEY `stream_proxy_pk` (`app`,`stream`)
436   -) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  443 +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4;
437 444 /*!40101 SET character_set_client = @saved_cs_client */;
438 445  
439 446 --
... ... @@ -451,20 +458,20 @@ UNLOCK TABLES;
451 458  
452 459 DROP TABLE IF EXISTS `stream_push`;
453 460 /*!40101 SET @saved_cs_client = @@character_set_client */;
454   -/*!50503 SET character_set_client = utf8mb4 */;
  461 +/*!40101 SET character_set_client = utf8 */;
455 462 CREATE TABLE `stream_push` (
456   - `id` int NOT NULL AUTO_INCREMENT,
457   - `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
458   - `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
459   - `totalReaderCount` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
460   - `originType` int DEFAULT NULL,
461   - `originTypeStr` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
462   - `createStamp` bigint DEFAULT NULL,
463   - `aliveSecond` int DEFAULT NULL,
464   - `mediaServerId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  463 + `id` int(11) NOT NULL AUTO_INCREMENT,
  464 + `app` varchar(255) NOT NULL,
  465 + `stream` varchar(255) NOT NULL,
  466 + `totalReaderCount` varchar(50) DEFAULT NULL,
  467 + `originType` int(11) DEFAULT NULL,
  468 + `originTypeStr` varchar(50) DEFAULT NULL,
  469 + `createStamp` bigint(20) DEFAULT NULL,
  470 + `aliveSecond` int(11) DEFAULT NULL,
  471 + `mediaServerId` varchar(50) DEFAULT NULL,
465 472 PRIMARY KEY (`id`),
466 473 UNIQUE KEY `stream_push_pk` (`app`,`stream`)
467   -) ENGINE=InnoDB AUTO_INCREMENT=300799 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
  474 +) ENGINE=InnoDB AUTO_INCREMENT=300838 DEFAULT CHARSET=utf8mb4;
468 475 /*!40101 SET character_set_client = @saved_cs_client */;
469 476  
470 477 --
... ... @@ -482,17 +489,17 @@ UNLOCK TABLES;
482 489  
483 490 DROP TABLE IF EXISTS `user`;
484 491 /*!40101 SET @saved_cs_client = @@character_set_client */;
485   -/*!50503 SET character_set_client = utf8mb4 */;
  492 +/*!40101 SET character_set_client = utf8 */;
486 493 CREATE TABLE `user` (
487   - `id` int NOT NULL AUTO_INCREMENT,
488   - `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
489   - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
490   - `roleId` int NOT NULL,
491   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
492   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  494 + `id` int(11) NOT NULL AUTO_INCREMENT,
  495 + `username` varchar(255) NOT NULL,
  496 + `password` varchar(255) NOT NULL,
  497 + `roleId` int(11) NOT NULL,
  498 + `createTime` varchar(50) NOT NULL,
  499 + `updateTime` varchar(50) NOT NULL,
493 500 PRIMARY KEY (`id`) USING BTREE,
494 501 UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
495   -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  502 +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
496 503 /*!40101 SET character_set_client = @saved_cs_client */;
497 504  
498 505 --
... ... @@ -501,7 +508,8 @@ CREATE TABLE `user` (
501 508  
502 509 LOCK TABLES `user` WRITE;
503 510 /*!40000 ALTER TABLE `user` DISABLE KEYS */;
504   -INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
  511 +INSERT INTO `user` VALUES
  512 + (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57');
505 513 /*!40000 ALTER TABLE `user` ENABLE KEYS */;
506 514 UNLOCK TABLES;
507 515  
... ... @@ -511,15 +519,15 @@ UNLOCK TABLES;
511 519  
512 520 DROP TABLE IF EXISTS `user_role`;
513 521 /*!40101 SET @saved_cs_client = @@character_set_client */;
514   -/*!50503 SET character_set_client = utf8mb4 */;
  522 +/*!40101 SET character_set_client = utf8 */;
515 523 CREATE TABLE `user_role` (
516   - `id` int NOT NULL AUTO_INCREMENT,
517   - `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
518   - `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
519   - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
520   - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  524 + `id` int(11) NOT NULL AUTO_INCREMENT,
  525 + `name` varchar(50) NOT NULL,
  526 + `authority` varchar(50) NOT NULL,
  527 + `createTime` varchar(50) NOT NULL,
  528 + `updateTime` varchar(50) NOT NULL,
521 529 PRIMARY KEY (`id`) USING BTREE
522   -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
  530 +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
523 531 /*!40101 SET character_set_client = @saved_cs_client */;
524 532  
525 533 --
... ... @@ -528,7 +536,8 @@ CREATE TABLE `user_role` (
528 536  
529 537 LOCK TABLES `user_role` WRITE;
530 538 /*!40000 ALTER TABLE `user_role` DISABLE KEYS */;
531   -INSERT INTO `user_role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
  539 +INSERT INTO `user_role` VALUES
  540 + (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
532 541 /*!40000 ALTER TABLE `user_role` ENABLE KEYS */;
533 542 UNLOCK TABLES;
534 543 /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
... ... @@ -541,4 +550,4 @@ UNLOCK TABLES;
541 550 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
542 551 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
543 552  
544   --- Dump completed on 2022-03-07 8:26:30
  553 +-- Dump completed on 2022-04-18 10:50:27
... ...
sql/update.sql 0 → 100644
  1 +alter table parent_platform
  2 + add startOfflinePush int default 0 null;
  3 +
  4 +alter table parent_platform
  5 + add administrativeDivision varchar(50) not null;
  6 +
  7 +alter table parent_platform
  8 + add catalogGroup int default 1 null;
  9 +
  10 +alter table device
  11 + add ssrcCheck int default 0 null;
  12 +
... ...
src/main/java/com/genersoft/iot/vmp/common/ApiSaveConstant.java
... ... @@ -38,10 +38,14 @@ public class ApiSaveConstant {
38 38 }
39 39 break;
40 40 case "query":
41   - if (keyItemArray.length <= 5) return null;
  41 + if (keyItemArray.length <= 5) {
  42 + return null;
  43 + }
42 44 switch (keyItemArray[4]) {
43 45 case "devices":
44   - if (keyItemArray.length < 7) return null;
  46 + if (keyItemArray.length < 7) {
  47 + return null;
  48 + }
45 49 switch (keyItemArray[6]) {
46 50 case "sync":
47 51 return "[设备查询] 同步设备通道";
... ...
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
... ... @@ -31,6 +31,9 @@ public class StreamInfo {
31 31 private String rtc;
32 32 private String mediaServerId;
33 33 private Object tracks;
  34 + private String startTime;
  35 + private String endTime;
  36 + private double progress;
34 37  
35 38 public static class TransactionInfo{
36 39 public String callId;
... ... @@ -264,4 +267,29 @@ public class StreamInfo {
264 267 public void setHttps_ts(String https_ts) {
265 268 this.https_ts = https_ts;
266 269 }
  270 +
  271 +
  272 + public String getStartTime() {
  273 + return startTime;
  274 + }
  275 +
  276 + public void setStartTime(String startTime) {
  277 + this.startTime = startTime;
  278 + }
  279 +
  280 + public String getEndTime() {
  281 + return endTime;
  282 + }
  283 +
  284 + public void setEndTime(String endTime) {
  285 + this.endTime = endTime;
  286 + }
  287 +
  288 + public double getProgress() {
  289 + return progress;
  290 + }
  291 +
  292 + public void setProgress(double progress) {
  293 + this.progress = progress;
  294 + }
267 295 }
... ...
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -22,6 +22,9 @@ public class VideoManagerConstants {
22 22  
23 23 public static final String DEVICE_PREFIX = "VMP_DEVICE_";
24 24  
  25 + // 设备同步完成
  26 + public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_";
  27 +
25 28 public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_";
26 29  
27 30 public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_";
... ... @@ -69,9 +72,29 @@ public class VideoManagerConstants {
69 72  
70 73 public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
71 74  
  75 +
72 76 //************************** redis 消息*********************************
  77 +
  78 + // 流变化的通知
73 79 public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
74   - public static final String WVP_MSG_GPS_PREFIX = "VM_MSG_GPS";
  80 +
  81 + // 接收推流设备的GPS变化通知
  82 + public static final String VM_MSG_GPS = "VM_MSG_GPS";
  83 +
  84 + // redis 消息通知设备推流到平台
  85 + public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
  86 +
  87 + // 移动位置订阅通知
  88 + public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
  89 +
  90 + // 报警订阅的通知(收到报警向redis发出通知)
  91 + public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm";
  92 +
  93 + // 报警通知的发送 (收到redis发出的通知,转发给其他平台)
  94 + public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive";
  95 +
  96 + // 设备状态订阅的通知
  97 + public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
75 98  
76 99 //************************** 第三方 ****************************************
77 100 public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
... ...
src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
... ... @@ -29,7 +29,7 @@ public class ApiAccessFilter extends OncePerRequestFilter {
29 29 private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
30 30  
31 31 @Autowired
32   - private UserSetup userSetup;
  32 + private UserSetting userSetting;
33 33  
34 34 @Autowired
35 35 private ILogService logService;
... ... @@ -48,7 +48,7 @@ public class ApiAccessFilter extends OncePerRequestFilter {
48 48  
49 49 filterChain.doFilter(servletRequest, servletResponse);
50 50  
51   - if (uriName != null && userSetup.getLogInDatebase()) {
  51 + if (uriName != null && userSetting.getLogInDatebase()) {
52 52  
53 53 LogDto logDto = new LogDto();
54 54 logDto.setName(uriName);
... ...
src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
  4 +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
3 7 import org.springframework.beans.factory.annotation.Autowired;
4 8 import org.springframework.context.annotation.Bean;
5 9 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
... ... @@ -7,6 +11,7 @@ import org.springframework.stereotype.Component;
7 11  
8 12 import java.util.Date;
9 13 import java.util.Map;
  14 +import java.util.Set;
10 15 import java.util.concurrent.ConcurrentHashMap;
11 16 import java.util.concurrent.ScheduledFuture;
12 17  
... ... @@ -16,14 +21,22 @@ import java.util.concurrent.ScheduledFuture;
16 21 @Component
17 22 public class DynamicTask {
18 23  
  24 + private Logger logger = LoggerFactory.getLogger(DynamicTask.class);
  25 +
19 26 @Autowired
20 27 private ThreadPoolTaskScheduler threadPoolTaskScheduler;
21 28  
22 29 private Map<String, ScheduledFuture<?>> futureMap = new ConcurrentHashMap<>();
  30 + private Map<String, Runnable> runnableMap = new ConcurrentHashMap<>();
23 31  
24 32 @Bean
25 33 public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
26   - return new ThreadPoolTaskScheduler();
  34 + ThreadPoolTaskScheduler schedulerPool = new ThreadPoolTaskScheduler();
  35 + schedulerPool.setPoolSize(300);
  36 + schedulerPool.setWaitForTasksToCompleteOnShutdown(true);
  37 + schedulerPool.setAwaitTerminationSeconds(10);
  38 + return schedulerPool;
  39 +
27 40 }
28 41  
29 42 /**
... ... @@ -33,33 +46,66 @@ public class DynamicTask {
33 46 * @param cycleForCatalog 间隔
34 47 * @return
35 48 */
36   - public String startCron(String key, Runnable task, int cycleForCatalog) {
37   - stop(key);
  49 + public void startCron(String key, Runnable task, int cycleForCatalog) {
  50 + ScheduledFuture future = futureMap.get(key);
  51 + if (future != null) {
  52 + if (future.isCancelled()) {
  53 + logger.info("任务【{}】已存在但是关闭状态!!!", key);
  54 + } else {
  55 + logger.info("任务【{}】已存在且已启动!!!", key);
  56 + return;
  57 + }
  58 + }
38 59 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
39   - ScheduledFuture future = threadPoolTaskScheduler.scheduleWithFixedDelay(task, cycleForCatalog * 1000L);
40   - futureMap.put(key, future);
41   - return "startCron";
  60 + future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog * 1000L);
  61 + if (future != null){
  62 + futureMap.put(key, future);
  63 + runnableMap.put(key, task);
  64 + logger.info("任务【{}】启动成功!!!", key);
  65 + }else {
  66 + logger.info("任务【{}】启动失败!!!", key);
  67 + }
42 68 }
43 69  
44 70 /**
45 71 * 延时任务
46 72 * @param key 任务ID
47 73 * @param task 任务
48   - * @param delay 延时 /
  74 + * @param delay 延时 /
49 75 * @return
50 76 */
51   - public String startDelay(String key, Runnable task, int delay) {
  77 + public void startDelay(String key, Runnable task, int delay) {
52 78 stop(key);
53   - Date starTime = new Date(System.currentTimeMillis() + delay * 1000);
  79 + Date starTime = new Date(System.currentTimeMillis() + delay);
  80 +
  81 + ScheduledFuture future = futureMap.get(key);
  82 + if (future != null) {
  83 + if (future.isCancelled()) {
  84 + logger.info("任务【{}】已存在但是关闭状态!!!", key);
  85 + } else {
  86 + logger.info("任务【{}】已存在且已启动!!!", key);
  87 + return;
  88 + }
  89 + }
54 90 // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔
55   - ScheduledFuture future = threadPoolTaskScheduler.schedule(task, starTime);
56   - futureMap.put(key, future);
57   - return "startCron";
  91 + future = threadPoolTaskScheduler.schedule(task, starTime);
  92 + if (future != null){
  93 + futureMap.put(key, future);
  94 + runnableMap.put(key, task);
  95 + logger.info("任务【{}】启动成功!!!", key);
  96 + }else {
  97 + logger.info("任务【{}】启动失败!!!", key);
  98 + }
58 99 }
59 100  
60 101 public void stop(String key) {
61 102 if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
62 103 futureMap.get(key).cancel(true);
  104 + Runnable runnable = runnableMap.get(key);
  105 + if (runnable instanceof ISubscribeTask) {
  106 + ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
  107 + subscribeTask.stop();
  108 + }
63 109 }
64 110 }
65 111  
... ... @@ -67,4 +113,11 @@ public class DynamicTask {
67 113 return futureMap.get(key) != null;
68 114 }
69 115  
  116 + public Set<String> getAllKeys() {
  117 + return futureMap.keySet();
  118 + }
  119 +
  120 + public Runnable get(String key) {
  121 + return runnableMap.get(key);
  122 + }
70 123 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
3 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
  4 +import com.genersoft.iot.vmp.service.impl.RedisAlarmMsgListener;
4 5 import com.genersoft.iot.vmp.service.impl.RedisGPSMsgListener;
5 6 import org.apache.commons.lang3.StringUtils;
6 7 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -48,6 +49,9 @@ public class RedisConfig extends CachingConfigurerSupport {
48 49 @Autowired
49 50 private RedisGPSMsgListener redisGPSMsgListener;
50 51  
  52 + @Autowired
  53 + private RedisAlarmMsgListener redisAlarmMsgListener;
  54 +
51 55 @Bean
52 56 public JedisPool jedisPool() {
53 57 if (StringUtils.isBlank(password)) {
... ... @@ -92,7 +96,8 @@ public class RedisConfig extends CachingConfigurerSupport {
92 96  
93 97 RedisMessageListenerContainer container = new RedisMessageListenerContainer();
94 98 container.setConnectionFactory(connectionFactory);
95   - container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_GPS_PREFIX));
  99 + container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GPS));
  100 + container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
96 101 return container;
97 102 }
98 103  
... ...
src/main/java/com/genersoft/iot/vmp/conf/RedisKeyExpirationEventMessageListener.java
... ... @@ -3,25 +3,24 @@ package com.genersoft.iot.vmp.conf;
3 3 import org.springframework.data.redis.connection.RedisConnection;
4 4 import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
5 5 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
6   -import org.springframework.util.StringUtils;
7 6  
8 7 import java.util.Properties;
9 8  
10 9 public class RedisKeyExpirationEventMessageListener extends KeyExpirationEventMessageListener {
11 10  
12   - private UserSetup userSetup;
  11 + private UserSetting userSetting;
13 12 private RedisMessageListenerContainer listenerContainer;
14 13 private String keyspaceNotificationsConfigParameter = "EA";
15 14  
16   - public RedisKeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
  15 + public RedisKeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {
17 16 super(listenerContainer);
18 17 this.listenerContainer = listenerContainer;
19   - this.userSetup = userSetup;
  18 + this.userSetting = userSetting;
20 19 }
21 20  
22 21 @Override
23 22 public void init() {
24   - if (!userSetup.getRedisConfig()) {
  23 + if (!userSetting.getRedisConfig()) {
25 24 // 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用
26 25 setKeyspaceNotificationsConfigParameter("");
27 26 }else {
... ...
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
... ... @@ -29,7 +29,7 @@ public class SipConfig {
29 29  
30 30 Integer registerTimeInterval = 120;
31 31  
32   - private boolean alarm = false;
  32 + private boolean alarm;
33 33  
34 34 public void setIp(String ip) {
35 35 this.ip = ip;
... ...
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
... ... @@ -4,9 +4,8 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
4 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
5 5 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
7   -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
8 7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  8 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 9 import org.springframework.beans.factory.annotation.Autowired;
11 10 import org.springframework.boot.CommandLineRunner;
12 11 import org.springframework.core.annotation.Order;
... ... @@ -22,7 +21,7 @@ import java.util.List;
22 21 public class SipPlatformRunner implements CommandLineRunner {
23 22  
24 23 @Autowired
25   - private IVideoManagerStorager storager;
  24 + private IVideoManagerStorage storager;
26 25  
27 26 @Autowired
28 27 private IRedisCatchStorage redisCatchStorage;
... ...
src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java
... ... @@ -7,6 +7,10 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
7 7  
8 8 import java.util.concurrent.ThreadPoolExecutor;
9 9  
  10 +/**
  11 + * ThreadPoolTask 配置类
  12 + * @author lin
  13 + */
10 14 @Configuration
11 15 @EnableAsync(proxyTargetClass = true)
12 16 public class ThreadPoolTaskConfig {
... ... @@ -40,6 +44,10 @@ public class ThreadPoolTaskConfig {
40 44 */
41 45 private static final String threadNamePrefix = "wvp-";
42 46  
  47 + /**
  48 + *
  49 + * @return
  50 + */
43 51 @Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
44 52 public ThreadPoolTaskExecutor taskExecutor() {
45 53 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
... ...
src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java renamed to src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
1 1 package com.genersoft.iot.vmp.conf;
2 2  
  3 +import io.swagger.models.auth.In;
3 4 import org.springframework.boot.context.properties.ConfigurationProperties;
4 5 import org.springframework.stereotype.Component;
5 6  
6 7 import java.util.ArrayList;
7 8 import java.util.List;
8 9  
9   -
  10 +/**
  11 + * 配置文件 user-settings 映射的配置信息
  12 + */
10 13 @Component
11 14 @ConfigurationProperties(prefix = "user-settings", ignoreInvalidFields = true)
12   -public class UserSetup {
  15 +public class UserSetting {
13 16  
14 17 private Boolean savePositionHistory = Boolean.FALSE;
15 18  
... ... @@ -17,7 +20,9 @@ public class UserSetup {
17 20  
18 21 private Boolean seniorSdp = Boolean.FALSE;
19 22  
20   - private Long playTimeout = 18000L;
  23 + private Integer playTimeout = 18000;
  24 +
  25 + private int platformPlayTimeout = 60000;
21 26  
22 27 private Boolean interfaceAuthentication = Boolean.TRUE;
23 28  
... ... @@ -51,7 +56,7 @@ public class UserSetup {
51 56 return seniorSdp;
52 57 }
53 58  
54   - public Long getPlayTimeout() {
  59 + public Integer getPlayTimeout() {
55 60 return playTimeout;
56 61 }
57 62  
... ... @@ -79,7 +84,7 @@ public class UserSetup {
79 84 this.seniorSdp = seniorSdp;
80 85 }
81 86  
82   - public void setPlayTimeout(Long playTimeout) {
  87 + public void setPlayTimeout(Integer playTimeout) {
83 88 this.playTimeout = playTimeout;
84 89 }
85 90  
... ... @@ -134,4 +139,12 @@ public class UserSetup {
134 139 public void setRecordSip(Boolean recordSip) {
135 140 this.recordSip = recordSip;
136 141 }
  142 +
  143 + public int getPlatformPlayTimeout() {
  144 + return platformPlayTimeout;
  145 + }
  146 +
  147 + public void setPlatformPlayTimeout(int platformPlayTimeout) {
  148 + this.platformPlayTimeout = platformPlayTimeout;
  149 + }
137 150 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java
1 1 package com.genersoft.iot.vmp.conf.runner;
2 2  
3   -import com.genersoft.iot.vmp.conf.UserSetup;
  3 +import com.genersoft.iot.vmp.conf.UserSetting;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.service.IDeviceService;
6 6 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
7   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  7 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
8 8 import org.springframework.beans.factory.annotation.Autowired;
9 9 import org.springframework.boot.CommandLineRunner;
10 10 import org.springframework.core.annotation.Order;
... ... @@ -14,20 +14,20 @@ import java.util.List;
14 14  
15 15  
16 16 /**
17   - * 系统启动时控制设备离线
  17 + * 系统启动时控制设备
18 18 */
19 19 @Component
20 20 @Order(value=4)
21 21 public class SipDeviceRunner implements CommandLineRunner {
22 22  
23 23 @Autowired
24   - private IVideoManagerStorager storager;
  24 + private IVideoManagerStorage storager;
25 25  
26 26 @Autowired
27 27 private IRedisCatchStorage redisCatchStorage;
28 28  
29 29 @Autowired
30   - private UserSetup userSetup;
  30 + private UserSetting userSetting;
31 31  
32 32 @Autowired
33 33 private IDeviceService deviceService;
... ... @@ -41,9 +41,14 @@ public class SipDeviceRunner implements CommandLineRunner {
41 41 for (String deviceId : onlineForAll) {
42 42 storager.online(deviceId);
43 43 Device device = redisCatchStorage.getDevice(deviceId);
44   - if (device != null && device.getSubscribeCycleForCatalog() > 0) {
45   - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
46   - deviceService.addCatalogSubscribe(device);
  44 + if (device != null ) {
  45 + if (device.getSubscribeCycleForCatalog() > 0) {
  46 + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
  47 + deviceService.addCatalogSubscribe(device);
  48 + }
  49 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  50 + deviceService.addMobilePositionSubscribe(device);
  51 + }
47 52 }
48 53 }
49 54 // 重置cseq计数
... ...
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
1 1 package com.genersoft.iot.vmp.conf.security;
2 2  
3   -import com.genersoft.iot.vmp.conf.UserSetup;
  3 +import com.genersoft.iot.vmp.conf.UserSetting;
4 4 import org.slf4j.Logger;
5 5 import org.slf4j.LoggerFactory;
6 6 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -29,7 +29,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
29 29 private final static Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
30 30  
31 31 @Autowired
32   - private UserSetup userSetup;
  32 + private UserSetting userSetting;
33 33  
34 34 @Autowired
35 35 private DefaultUserDetailsServiceImpl userDetailsService;
... ... @@ -77,7 +77,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
77 77 @Override
78 78 public void configure(WebSecurity web) {
79 79  
80   - if (!userSetup.isInterfaceAuthentication()) {
  80 + if (!userSetting.isInterfaceAuthentication()) {
81 81 web.ignoring().antMatchers("**");
82 82 }else {
83 83 // 可以直接访问的静态数据
... ... @@ -91,7 +91,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
91 91 .antMatchers("/swagger-resources/**")
92 92 .antMatchers("/v3/api-docs/**")
93 93 .antMatchers("/js/**");
94   - List<String> interfaceAuthenticationExcludes = userSetup.getInterfaceAuthenticationExcludes();
  94 + List<String> interfaceAuthenticationExcludes = userSetting.getInterfaceAuthenticationExcludes();
95 95 for (String interfaceAuthenticationExclude : interfaceAuthenticationExcludes) {
96 96 if (interfaceAuthenticationExclude.split("/").length < 4 ) {
97 97 logger.warn("{}不满足两级目录,已忽略", interfaceAuthenticationExclude);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
... ... @@ -8,6 +8,7 @@ import org.slf4j.Logger;
8 8 import org.slf4j.LoggerFactory;
9 9 import org.springframework.beans.factory.annotation.Autowired;
10 10 import org.springframework.context.annotation.Bean;
  11 +import org.springframework.context.annotation.Configuration;
11 12 import org.springframework.context.annotation.DependsOn;
12 13 import org.springframework.stereotype.Component;
13 14  
... ... @@ -18,7 +19,7 @@ import java.util.concurrent.LinkedBlockingQueue;
18 19 import java.util.concurrent.ThreadPoolExecutor;
19 20 import java.util.concurrent.TimeUnit;
20 21  
21   -@Component
  22 +@Configuration
22 23 public class SipLayer{
23 24  
24 25 private final static Logger logger = LoggerFactory.getLogger(SipLayer.class);
... ... @@ -35,7 +36,7 @@ public class SipLayer{
35 36  
36 37  
37 38 @Bean("sipFactory")
38   - private SipFactory createSipFactory() {
  39 + SipFactory createSipFactory() {
39 40 sipFactory = SipFactory.getInstance();
40 41 sipFactory.setPathName("gov.nist");
41 42 return sipFactory;
... ... @@ -43,11 +44,12 @@ public class SipLayer{
43 44  
44 45 @Bean("sipStack")
45 46 @DependsOn({"sipFactory"})
46   - private SipStack createSipStack() throws PeerUnavailableException {
  47 + SipStack createSipStack() throws PeerUnavailableException {
47 48 Properties properties = new Properties();
48 49 properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
49 50 properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp());
50 51 properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
  52 + properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); // 接收所有notify请求,即使没有订阅
51 53 /**
52 54 * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE =
53 55 * 0; public static final int TRACE_MESSAGES = 16; public static final int
... ... @@ -63,7 +65,7 @@ public class SipLayer{
63 65  
64 66 @Bean(name = "tcpSipProvider")
65 67 @DependsOn("sipStack")
66   - private SipProviderImpl startTcpListener() {
  68 + SipProviderImpl startTcpListener() {
67 69 ListeningPoint tcpListeningPoint = null;
68 70 SipProviderImpl tcpSipProvider = null;
69 71 try {
... ... @@ -88,7 +90,7 @@ public class SipLayer{
88 90  
89 91 @Bean(name = "udpSipProvider")
90 92 @DependsOn("sipStack")
91   - private SipProviderImpl startUdpListener() {
  93 + SipProviderImpl startUdpListener() {
92 94 ListeningPoint udpListeningPoint = null;
93 95 SipProviderImpl udpSipProvider = null;
94 96 try {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
... ... @@ -129,7 +129,9 @@ public class DigestServerAuthenticationHelper {
129 129 */
130 130 public boolean doAuthenticateHashedPassword(Request request, String hashedPassword) {
131 131 AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
132   - if ( authHeader == null ) return false;
  132 + if ( authHeader == null ) {
  133 + return false;
  134 + }
133 135 String realm = authHeader.getRealm();
134 136 String username = authHeader.getUsername();
135 137  
... ... @@ -176,7 +178,9 @@ public class DigestServerAuthenticationHelper {
176 178 */
177 179 public boolean doAuthenticatePlainTextPassword(Request request, String pass) {
178 180 AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
179   - if ( authHeader == null ) return false;
  181 + if ( authHeader == null ) {
  182 + return false;
  183 + }
180 184 String realm = authHeader.getRealm().trim();
181 185 String username = authHeader.getUsername().trim();
182 186  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/auth/RegisterLogicHandler.java
1 1 package com.genersoft.iot.vmp.gb28181.auth;
2 2  
3   -import com.genersoft.iot.vmp.storager.impl.VideoManagerStoragerImpl;
  3 +import com.genersoft.iot.vmp.storager.impl.VideoManagerStorageImpl;
4 4 import org.slf4j.Logger;
5 5 import org.slf4j.LoggerFactory;
6 6 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -23,7 +23,7 @@ public class RegisterLogicHandler {
23 23 private SIPCommander cmder;
24 24  
25 25 @Autowired
26   - private VideoManagerStoragerImpl storager;
  26 + private VideoManagerStorageImpl storager;
27 27  
28 28 public void onRegister(Device device) {
29 29 // 只有第一次注册时调用查询设备信息,如需更新调用更新API接口
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AlarmChannelMessage.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * 通过redis分发报警消息
  5 + */
  6 +public class AlarmChannelMessage {
  7 + /**
  8 + * 国标编号
  9 + */
  10 + private String gbId;
  11 +
  12 + /**
  13 + * 报警编号
  14 + */
  15 + private int alarmSn;
  16 +
  17 +
  18 + /**
  19 + * 报警描述
  20 + */
  21 + private String alarmDescription;
  22 +
  23 + public String getGbId() {
  24 + return gbId;
  25 + }
  26 +
  27 + public void setGbId(String gbId) {
  28 + this.gbId = gbId;
  29 + }
  30 +
  31 + public int getAlarmSn() {
  32 + return alarmSn;
  33 + }
  34 +
  35 + public void setAlarmSn(int alarmSn) {
  36 + this.alarmSn = alarmSn;
  37 + }
  38 +
  39 + public String getAlarmDescription() {
  40 + return alarmDescription;
  41 + }
  42 +
  43 + public void setAlarmDescription(String alarmDescription) {
  44 + this.alarmDescription = alarmDescription;
  45 + }
  46 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
... ... @@ -4,10 +4,26 @@ import java.util.Date;
4 4 import java.util.List;
5 5  
6 6 public class CatalogData {
  7 + private int sn; // 命令序列号
7 8 private int total;
8 9 private List<DeviceChannel> channelList;
9 10 private Date lastTime;
10 11 private Device device;
  12 + private String errorMsg;
  13 +
  14 + public enum CatalogDataStatus{
  15 + ready, runIng, end
  16 + }
  17 + private CatalogDataStatus status;
  18 +
  19 +
  20 + public int getSn() {
  21 + return sn;
  22 + }
  23 +
  24 + public void setSn(int sn) {
  25 + this.sn = sn;
  26 + }
11 27  
12 28 public int getTotal() {
13 29 return total;
... ... @@ -40,4 +56,20 @@ public class CatalogData {
40 56 public void setDevice(Device device) {
41 57 this.device = device;
42 58 }
  59 +
  60 + public String getErrorMsg() {
  61 + return errorMsg;
  62 + }
  63 +
  64 + public void setErrorMsg(String errorMsg) {
  65 + this.errorMsg = errorMsg;
  66 + }
  67 +
  68 + public CatalogDataStatus getStatus() {
  69 + return status;
  70 + }
  71 +
  72 + public void setStatus(CatalogDataStatus status) {
  73 + this.status = status;
  74 + }
43 75 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
... ... @@ -105,15 +105,34 @@ public class Device {
105 105 private boolean firsRegister;
106 106  
107 107 /**
108   - * 字符集, 支持 utf-8 与 gb2312
  108 + * 字符集, 支持 UTF-8 与 GB2312
109 109 */
110 110 private String charset ;
111 111  
112 112 /**
113 113 * 目录订阅周期,0为不订阅
114 114 */
115   - private int subscribeCycleForCatalog ;
  115 + private int subscribeCycleForCatalog;
116 116  
  117 + /**
  118 + * 移动设备位置订阅周期,0为不订阅
  119 + */
  120 + private int subscribeCycleForMobilePosition;
  121 +
  122 + /**
  123 + * 移动设备位置信息上报时间间隔,单位:秒,默认值5
  124 + */
  125 + private int mobilePositionSubmissionInterval = 5;
  126 +
  127 + /**
  128 + * 报警订阅周期,0为不订阅
  129 + */
  130 + private int subscribeCycleForAlarm;
  131 +
  132 + /**
  133 + * 是否开启ssrc校验,默认关闭,开启可以防止串流
  134 + */
  135 + private boolean ssrcCheck;
117 136  
118 137  
119 138 public String getDeviceId() {
... ... @@ -283,4 +302,36 @@ public class Device {
283 302 public void setSubscribeCycleForCatalog(int subscribeCycleForCatalog) {
284 303 this.subscribeCycleForCatalog = subscribeCycleForCatalog;
285 304 }
  305 +
  306 + public int getSubscribeCycleForMobilePosition() {
  307 + return subscribeCycleForMobilePosition;
  308 + }
  309 +
  310 + public void setSubscribeCycleForMobilePosition(int subscribeCycleForMobilePosition) {
  311 + this.subscribeCycleForMobilePosition = subscribeCycleForMobilePosition;
  312 + }
  313 +
  314 + public int getMobilePositionSubmissionInterval() {
  315 + return mobilePositionSubmissionInterval;
  316 + }
  317 +
  318 + public void setMobilePositionSubmissionInterval(int mobilePositionSubmissionInterval) {
  319 + this.mobilePositionSubmissionInterval = mobilePositionSubmissionInterval;
  320 + }
  321 +
  322 + public int getSubscribeCycleForAlarm() {
  323 + return subscribeCycleForAlarm;
  324 + }
  325 +
  326 + public void setSubscribeCycleForAlarm(int subscribeCycleForAlarm) {
  327 + this.subscribeCycleForAlarm = subscribeCycleForAlarm;
  328 + }
  329 +
  330 + public boolean isSsrcCheck() {
  331 + return ssrcCheck;
  332 + }
  333 +
  334 + public void setSsrcCheck(boolean ssrcCheck) {
  335 + this.ssrcCheck = ssrcCheck;
  336 + }
286 337 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java
... ... @@ -50,7 +50,30 @@ public class DeviceAlarm {
50 50 private double latitude;
51 51  
52 52 /**
53   - * 报警类型
  53 + * 报警类型,
  54 + * 报警方式为2时,不携带 AlarmType为默认的报警设备报警,
  55 + * 携带 AlarmType取值及对应报警类型如下:
  56 + * 1-视频丢失报警;
  57 + * 2-设备防拆报警;
  58 + * 3-存储设备磁盘满报警;
  59 + * 4-设备高温报警;
  60 + * 5-设备低温报警。
  61 + * 报警方式为5时,取值如下:
  62 + * 1-人工视频报警;
  63 + * 2-运动目标检测报警;
  64 + * 3-遗留物检测报警;
  65 + * 4-物体移除检测报警;
  66 + * 5-绊线检测报警;
  67 + * 6-入侵检测报警;
  68 + * 7-逆行检测报警;
  69 + * 8-徘徊检测报警;
  70 + * 9-流量统计报警;
  71 + * 10-密度检测报警;
  72 + * 11-视频异常检测报警;
  73 + * 12-快速移动报警。
  74 + * 报警方式为6时,取值下:
  75 + * 1-存储设备磁盘故障报警;
  76 + * 2-存储设备风扇故障报警。
54 77 */
55 78 private String alarmType;
56 79  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java
... ... @@ -4,7 +4,7 @@ public class DeviceChannel {
4 4  
5 5  
6 6 /**
7   - * 数据库自ID
  7 + * 数据库自ID
8 8 */
9 9 private int id;
10 10  
... ... @@ -169,6 +169,11 @@ public class DeviceChannel {
169 169 */
170 170 private boolean hasAudio;
171 171  
  172 + /**
  173 + * 标记通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
  174 + */
  175 + private int channelType;
  176 +
172 177 public int getId() {
173 178 return id;
174 179 }
... ... @@ -441,4 +446,12 @@ public class DeviceChannel {
441 446 public void setUpdateTime(String updateTime) {
442 447 this.updateTime = updateTime;
443 448 }
  449 +
  450 + public int getChannelType() {
  451 + return channelType;
  452 + }
  453 +
  454 + public void setChannelType(int channelType) {
  455 + this.channelType = channelType;
  456 + }
444 457 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannelInPlatform.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +public class DeviceChannelInPlatform extends DeviceChannel{
  4 +
  5 + private String platFormId;
  6 + private String catalogId;
  7 +
  8 + public String getPlatFormId() {
  9 + return platFormId;
  10 + }
  11 +
  12 + public void setPlatFormId(String platFormId) {
  13 + this.platFormId = platFormId;
  14 + }
  15 +
  16 + public String getCatalogId() {
  17 + return catalogId;
  18 + }
  19 +
  20 + public void setCatalogId(String catalogId) {
  21 + this.catalogId = catalogId;
  22 + }
  23 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java
... ... @@ -25,6 +25,7 @@ public class GbStream extends PlatformGbStream{
25 25 return gbStreamId;
26 26 }
27 27  
  28 + @Override
28 29 public void setGbStreamId(Integer gbStreamId) {
29 30 this.gbStreamId = gbStreamId;
30 31 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +public enum InviteStreamType {
  4 +
  5 + PLAY,PLAYBACK,PUSH,PROXY,CLOUD_RECORD_PUSH,CLOUD_RECORD_PROXY
  6 +
  7 +
  8 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
... ... @@ -125,9 +125,24 @@ public class ParentPlatform {
125 125 private boolean alarmSubscribe;
126 126  
127 127 /**
128   - * 已被订阅GPS信息
  128 + * 已被订阅移动位置信息
129 129 */
130   - private boolean gpsSubscribe;
  130 + private boolean mobilePositionSubscribe;
  131 +
  132 + /**
  133 + * 点播未推流的设备时是否使用redis通知拉起
  134 + */
  135 + private boolean startOfflinePush;
  136 +
  137 + /**
  138 + * 目录分组-每次向上级发送通道信息时单个包携带的通道数量,取值1,2,4,8
  139 + */
  140 + private int catalogGroup;
  141 +
  142 + /**
  143 + * 行政区划
  144 + */
  145 + private String administrativeDivision;
131 146  
132 147 public Integer getId() {
133 148 return id;
... ... @@ -322,11 +337,35 @@ public class ParentPlatform {
322 337 this.alarmSubscribe = alarmSubscribe;
323 338 }
324 339  
325   - public boolean isGpsSubscribe() {
326   - return gpsSubscribe;
  340 + public boolean isMobilePositionSubscribe() {
  341 + return mobilePositionSubscribe;
  342 + }
  343 +
  344 + public void setMobilePositionSubscribe(boolean mobilePositionSubscribe) {
  345 + this.mobilePositionSubscribe = mobilePositionSubscribe;
  346 + }
  347 +
  348 + public boolean isStartOfflinePush() {
  349 + return startOfflinePush;
  350 + }
  351 +
  352 + public void setStartOfflinePush(boolean startOfflinePush) {
  353 + this.startOfflinePush = startOfflinePush;
  354 + }
  355 +
  356 + public int getCatalogGroup() {
  357 + return catalogGroup;
  358 + }
  359 +
  360 + public void setCatalogGroup(int catalogGroup) {
  361 + this.catalogGroup = catalogGroup;
  362 + }
  363 +
  364 + public String getAdministrativeDivision() {
  365 + return administrativeDivision;
327 366 }
328 367  
329   - public void setGpsSubscribe(boolean gpsSubscribe) {
330   - this.gpsSubscribe = gpsSubscribe;
  368 + public void setAdministrativeDivision(String administrativeDivision) {
  369 + this.administrativeDivision = administrativeDivision;
331 370 }
332 371 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
... ... @@ -77,9 +77,9 @@ public class SendRtpItem {
77 77 private String CallId;
78 78  
79 79 /**
80   - * 是否是play, false是playback
  80 + * 播放类型
81 81 */
82   - private boolean isPlay;
  82 + private InviteStreamType playType;
83 83  
84 84 private byte[] transaction;
85 85  
... ... @@ -197,12 +197,12 @@ public class SendRtpItem {
197 197 CallId = callId;
198 198 }
199 199  
200   - public boolean isPlay() {
201   - return isPlay;
  200 + public InviteStreamType getPlayType() {
  201 + return playType;
202 202 }
203 203  
204   - public void setPlay(boolean play) {
205   - isPlay = play;
  204 + public void setPlayType(InviteStreamType playType) {
  205 + this.playType = playType;
206 206 }
207 207  
208 208 public byte[] getTransaction() {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
  3 +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  4 +
3 5 public class SsrcTransaction {
4 6  
5 7 private String deviceId;
... ... @@ -10,6 +12,7 @@ public class SsrcTransaction {
10 12 private byte[] dialog;
11 13 private String mediaServerId;
12 14 private String ssrc;
  15 + private VideoStreamSessionManager.SessionType type;
13 16  
14 17 public String getDeviceId() {
15 18 return deviceId;
... ... @@ -74,4 +77,12 @@ public class SsrcTransaction {
74 77 public void setSsrc(String ssrc) {
75 78 this.ssrc = ssrc;
76 79 }
  80 +
  81 + public VideoStreamSessionManager.SessionType getType() {
  82 + return type;
  83 + }
  84 +
  85 + public void setType(VideoStreamSessionManager.SessionType type) {
  86 + this.type = type;
  87 + }
77 88 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
  3 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
  4 +import com.genersoft.iot.vmp.conf.DynamicTask;
  5 +import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  7 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  8 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  9 +import org.springframework.beans.factory.annotation.Autowired;
3 10 import org.springframework.stereotype.Component;
4 11  
5 12 import java.util.ArrayList;
... ... @@ -9,12 +16,32 @@ import java.util.concurrent.ConcurrentHashMap;
9 16 @Component
10 17 public class SubscribeHolder {
11 18  
  19 + @Autowired
  20 + private DynamicTask dynamicTask;
  21 +
  22 + @Autowired
  23 + private IRedisCatchStorage redisCatchStorage;
  24 +
  25 + @Autowired
  26 + private ISIPCommanderForPlatform sipCommanderForPlatform;
  27 +
  28 + @Autowired
  29 + private IVideoManagerStorage storager;
  30 +
  31 + private final String taskOverduePrefix = "subscribe_overdue_";
  32 +
12 33 private static ConcurrentHashMap<String, SubscribeInfo> catalogMap = new ConcurrentHashMap<>();
13 34 private static ConcurrentHashMap<String, SubscribeInfo> mobilePositionMap = new ConcurrentHashMap<>();
14 35  
15 36  
16 37 public void putCatalogSubscribe(String platformId, SubscribeInfo subscribeInfo) {
17 38 catalogMap.put(platformId, subscribeInfo);
  39 + // 添加订阅到期
  40 + String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
  41 + dynamicTask.stop(taskOverdueKey);
  42 + // 添加任务处理订阅过期
  43 + dynamicTask.startDelay(taskOverdueKey, () -> removeCatalogSubscribe(subscribeInfo.getId()),
  44 + subscribeInfo.getExpires() * 1000);
18 45 }
19 46  
20 47 public SubscribeInfo getCatalogSubscribe(String platformId) {
... ... @@ -23,10 +50,26 @@ public class SubscribeHolder {
23 50  
24 51 public void removeCatalogSubscribe(String platformId) {
25 52 catalogMap.remove(platformId);
  53 + String taskOverdueKey = taskOverduePrefix + "catalog_" + platformId;
  54 + // 添加任务处理订阅过期
  55 + dynamicTask.stop(taskOverdueKey);
26 56 }
27 57  
28 58 public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) {
29 59 mobilePositionMap.put(platformId, subscribeInfo);
  60 + String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
  61 + // 添加任务处理GPS定时推送
  62 + dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform,
  63 + storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask),
  64 + subscribeInfo.getGpsInterval());
  65 + String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
  66 + dynamicTask.stop(taskOverdueKey);
  67 + // 添加任务处理订阅过期
  68 + dynamicTask.startDelay(taskOverdueKey, () -> {
  69 + System.out.println("订阅过期");
  70 + removeMobilePositionSubscribe(subscribeInfo.getId());
  71 + },
  72 + subscribeInfo.getExpires() * 1000);
30 73 }
31 74  
32 75 public SubscribeInfo getMobilePositionSubscribe(String platformId) {
... ... @@ -35,6 +78,12 @@ public class SubscribeHolder {
35 78  
36 79 public void removeMobilePositionSubscribe(String platformId) {
37 80 mobilePositionMap.remove(platformId);
  81 + String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId;
  82 + // 结束任务处理GPS定时推送
  83 + dynamicTask.stop(key);
  84 + String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId;
  85 + // 添加任务处理订阅过期
  86 + dynamicTask.stop(taskOverdueKey);
38 87 }
39 88  
40 89 public List<String> getAllCatalogSubscribePlatform() {
... ... @@ -46,4 +95,9 @@ public class SubscribeHolder {
46 95 }
47 96 return platforms;
48 97 }
  98 +
  99 + public void removeAllSubscribe(String platformId) {
  100 + removeMobilePositionSubscribe(platformId);
  101 + removeCatalogSubscribe(platformId);
  102 + }
49 103 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
... ... @@ -25,6 +25,9 @@ public class SubscribeInfo {
25 25 this.callId = callIdHeader.getCallId();
26 26 }
27 27  
  28 + public SubscribeInfo() {
  29 + }
  30 +
28 31 private String id;
29 32 private int expires;
30 33 private String callId;
... ... @@ -33,6 +36,14 @@ public class SubscribeInfo {
33 36 private ServerTransaction transaction;
34 37 private Dialog dialog;
35 38  
  39 + /**
  40 + * 以下为可选字段
  41 + * @return
  42 + */
  43 + private String sn;
  44 + private int gpsInterval;
  45 +
  46 +
36 47 public String getId() {
37 48 return id;
38 49 }
... ... @@ -88,4 +99,20 @@ public class SubscribeInfo {
88 99 public void setDialog(Dialog dialog) {
89 100 this.dialog = dialog;
90 101 }
  102 +
  103 + public String getSn() {
  104 + return sn;
  105 + }
  106 +
  107 + public void setSn(String sn) {
  108 + this.sn = sn;
  109 + }
  110 +
  111 + public int getGpsInterval() {
  112 + return gpsInterval;
  113 + }
  114 +
  115 + public void setGpsInterval(int gpsInterval) {
  116 + this.gpsInterval = gpsInterval;
  117 + }
91 118 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * 摄像机同步状态
  5 + */
  6 +public class SyncStatus {
  7 + private int total;
  8 + private int current;
  9 + private String errorMsg;
  10 +
  11 + public int getTotal() {
  12 + return total;
  13 + }
  14 +
  15 + public void setTotal(int total) {
  16 + this.total = total;
  17 + }
  18 +
  19 + public int getCurrent() {
  20 + return current;
  21 + }
  22 +
  23 + public void setCurrent(int current) {
  24 + this.current = current;
  25 + }
  26 +
  27 + public String getErrorMsg() {
  28 + return errorMsg;
  29 + }
  30 +
  31 + public void setErrorMsg(String errorMsg) {
  32 + this.errorMsg = errorMsg;
  33 + }
  34 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/DeviceOffLineDetector.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.event;
2   -
3   -import com.genersoft.iot.vmp.conf.UserSetup;
4   -import org.springframework.beans.factory.annotation.Autowired;
5   -import org.springframework.stereotype.Component;
6   -
7   -import com.genersoft.iot.vmp.common.VideoManagerConstants;
8   -import com.genersoft.iot.vmp.utils.redis.RedisUtil;
9   -
10   -/**
11   - * @description:设备离在线状态检测器,用于检测设备状态
12   - * @author: swwheihei
13   - * @date: 2020年5月13日 下午2:40:29
14   - */
15   -@Component
16   -public class DeviceOffLineDetector {
17   -
18   - @Autowired
19   - private RedisUtil redis;
20   -
21   - @Autowired
22   - private UserSetup userSetup;
23   -
24   - public boolean isOnline(String deviceId) {
25   - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_" + deviceId;
26   - return redis.hasKey(key);
27   - }
28   -}
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
1 1 package com.genersoft.iot.vmp.gb28181.event.offline;
2 2  
3 3 import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
4   -import com.genersoft.iot.vmp.conf.UserSetup;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
5 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 7 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
8   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  8 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
9 9 import org.slf4j.Logger;
10 10 import org.slf4j.LoggerFactory;
11   -import org.springframework.beans.factory.InitializingBean;
12 11 import org.springframework.beans.factory.annotation.Autowired;
13   -import org.springframework.context.annotation.DependsOn;
14 12 import org.springframework.data.redis.connection.Message;
15   -import org.springframework.data.redis.connection.RedisConnection;
16   -import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
17 13 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
18 14 import org.springframework.stereotype.Component;
19 15  
20 16 import com.genersoft.iot.vmp.common.VideoManagerConstants;
21 17 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
22   -import org.springframework.util.StringUtils;
23   -
24   -import java.util.Properties;
25 18  
26 19 /**
27 20 * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件
... ... @@ -37,16 +30,16 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent
37 30 private EventPublisher publisher;
38 31  
39 32 @Autowired
40   - private UserSetup userSetup;
  33 + private UserSetting userSetting;
41 34  
42 35 @Autowired
43 36 private SipSubscribe sipSubscribe;
44 37  
45 38 @Autowired
46   - private IVideoManagerStorager storager;
  39 + private IVideoManagerStorage storager;
47 40  
48   - public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
49   - super(listenerContainer, userSetup);
  41 + public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {
  42 + super(listenerContainer, userSetting);
50 43 }
51 44  
52 45  
... ... @@ -59,12 +52,11 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent
59 52 public void onMessage(Message message, byte[] pattern) {
60 53 // 获取失效的key
61 54 String expiredKey = message.toString();
62   - logger.debug(expiredKey);
63 55 // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线
64   - String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetup.getServerId() + "_";
65   - String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetup.getServerId() + "_";
66   - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_";
67   - String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetup.getServerId() + "_";
  56 + String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_";
  57 + String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_";
  58 + String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_";
  59 + String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_";
68 60 if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {
69 61 String platformGBId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length(),expiredKey.length());
70 62 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGBId);
... ... @@ -84,12 +76,14 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent
84 76 publisher.outlineEventPublish(deviceId, KEEPLIVEKEY_PREFIX);
85 77 }
86 78 }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) {
87   - String callid = expiredKey.substring(REGISTER_INFO_PREFIX.length());
88   - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult();
89   - eventResult.callId = callid;
90   - eventResult.msg = "注册超时";
91   - eventResult.type = "register timeout";
92   - sipSubscribe.getErrorSubscribe(callid).response(eventResult);
  79 + String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length());
  80 + if (sipSubscribe.getErrorSubscribe(callId) != null) {
  81 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult();
  82 + eventResult.callId = callId;
  83 + eventResult.msg = "注册超时";
  84 + eventResult.type = "register timeout";
  85 + sipSubscribe.getErrorSubscribe(callId).response(eventResult);
  86 + }
93 87 }
94 88  
95 89 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java
1 1 package com.genersoft.iot.vmp.gb28181.event.offline;
2 2  
3 3 import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
4   -import com.genersoft.iot.vmp.conf.UserSetup;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
5 5 import org.slf4j.Logger;
6 6 import org.slf4j.LoggerFactory;
7 7 import org.springframework.beans.factory.annotation.Autowired;
8   -import org.springframework.context.annotation.DependsOn;
9   -import org.springframework.context.annotation.Lazy;
10 8 import org.springframework.data.redis.connection.Message;
11   -import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
12 9 import org.springframework.data.redis.listener.RedisMessageListenerContainer;
13 10 import org.springframework.stereotype.Component;
14 11  
... ... @@ -29,15 +26,15 @@ public class KeepliveTimeoutListener extends RedisKeyExpirationEventMessageListe
29 26 private EventPublisher publisher;
30 27  
31 28 @Autowired
32   - private UserSetup userSetup;
  29 + private UserSetting userSetting;
33 30  
34   - public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
35   - super(listenerContainer, userSetup);
  31 + public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) {
  32 + super(listenerContainer, userSetting);
36 33 }
37 34  
38 35 @Override
39 36 public void init() {
40   - if (!userSetup.getRedisConfig()) {
  37 + if (!userSetting.getRedisConfig()) {
41 38 // 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用
42 39 setKeyspaceNotificationsConfigParameter("");
43 40 }
... ... @@ -54,7 +51,7 @@ public class KeepliveTimeoutListener extends RedisKeyExpirationEventMessageListe
54 51 public void onMessage(Message message, byte[] pattern) {
55 52 // 获取失效的key
56 53 String expiredKey = message.toString();
57   - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_";
  54 + String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_";
58 55 if(!expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){
59 56 logger.debug("收到redis过期监听,但开头不是"+KEEPLIVEKEY_PREFIX+",忽略");
60 57 return;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java
1 1 package com.genersoft.iot.vmp.gb28181.event.offline;
2 2  
3   -import com.genersoft.iot.vmp.conf.UserSetup;
  3 +import com.genersoft.iot.vmp.conf.UserSetting;
4 4 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
5 5 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
6 6 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
7 7 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
8 8 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
9 9 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
10   -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 10 import com.genersoft.iot.vmp.service.IMediaServerService;
12 11 import org.slf4j.Logger;
13 12 import org.slf4j.LoggerFactory;
14 13 import org.springframework.beans.factory.annotation.Autowired;
15 14 import org.springframework.context.ApplicationListener;
16   -import org.springframework.context.annotation.DependsOn;
17   -import org.springframework.context.annotation.Lazy;
18 15 import org.springframework.stereotype.Component;
19 16  
20 17 import com.genersoft.iot.vmp.common.VideoManagerConstants;
21   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  18 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
22 19 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
23 20  
24 21 import java.util.List;
... ... @@ -36,7 +33,7 @@ public class OfflineEventListener implements ApplicationListener&lt;OfflineEvent&gt; {
36 33 private final static Logger logger = LoggerFactory.getLogger(OfflineEventListener.class);
37 34  
38 35 @Autowired
39   - private IVideoManagerStorager storager;
  36 + private IVideoManagerStorage storager;
40 37  
41 38 @Autowired
42 39 private VideoStreamSessionManager streamSession;
... ... @@ -45,7 +42,7 @@ public class OfflineEventListener implements ApplicationListener&lt;OfflineEvent&gt; {
45 42 private RedisUtil redis;
46 43  
47 44 @Autowired
48   - private UserSetup userSetup;
  45 + private UserSetting userSetting;
49 46  
50 47 @Autowired
51 48 private EventPublisher eventPublisher;
... ... @@ -60,12 +57,10 @@ public class OfflineEventListener implements ApplicationListener&lt;OfflineEvent&gt; {
60 57  
61 58 @Override
62 59 public void onApplicationEvent(OfflineEvent event) {
63   -
64   - if (logger.isDebugEnabled()) {
65   - logger.debug("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom());
66   - }
67 60  
68   - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_" + event.getDeviceId();
  61 + logger.info("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom());
  62 +
  63 + String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + event.getDeviceId();
69 64  
70 65 switch (event.getFrom()) {
71 66 // 心跳超时触发的离线事件,说明redis中已删除,无需处理
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
1 1 package com.genersoft.iot.vmp.gb28181.event.online;
2 2  
3 3 import com.genersoft.iot.vmp.conf.SipConfig;
4   -import com.genersoft.iot.vmp.conf.UserSetup;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
5 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
7 7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 8 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
9 9 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
10 10 import com.genersoft.iot.vmp.service.IDeviceService;
11   -import com.genersoft.iot.vmp.storager.dao.dto.User;
12 11 import org.slf4j.Logger;
13 12 import org.slf4j.LoggerFactory;
14 13 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -16,7 +15,7 @@ import org.springframework.context.ApplicationListener;
16 15 import org.springframework.stereotype.Component;
17 16  
18 17 import com.genersoft.iot.vmp.common.VideoManagerConstants;
19   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  18 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20 19 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
21 20  
22 21 import java.text.SimpleDateFormat;
... ... @@ -35,7 +34,7 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
35 34 private final static Logger logger = LoggerFactory.getLogger(OnlineEventListener.class);
36 35  
37 36 @Autowired
38   - private IVideoManagerStorager storager;
  37 + private IVideoManagerStorage storager;
39 38  
40 39 @Autowired
41 40 private IDeviceService deviceService;
... ... @@ -47,7 +46,7 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
47 46 private SipConfig sipConfig;
48 47  
49 48 @Autowired
50   - private UserSetup userSetup;
  49 + private UserSetting userSetting;
51 50  
52 51 @Autowired
53 52 private EventPublisher eventPublisher;
... ... @@ -55,17 +54,18 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
55 54 @Autowired
56 55 private SIPCommander cmder;
57 56  
  57 +
58 58 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
59 59  
60 60 @Override
61 61 public void onApplicationEvent(OnlineEvent event) {
62   -
63   - if (logger.isDebugEnabled()) {
64   - logger.debug("设备上线事件触发,deviceId:" + event.getDevice().getDeviceId() + ",from:" + event.getFrom());
65   - }
  62 +
  63 + logger.info("设备上线事件触发,deviceId:" + event.getDevice().getDeviceId() + ",from:" + event.getFrom());
66 64 Device device = event.getDevice();
67   - if (device == null) return;
68   - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetup.getServerId() + "_" + event.getDevice().getDeviceId();
  65 + if (device == null) {
  66 + return;
  67 + }
  68 + String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + event.getDevice().getDeviceId();
69 69 Device deviceInStore = storager.queryVideoDevice(device.getDeviceId());
70 70 device.setOnline(1);
71 71 switch (event.getFrom()) {
... ... @@ -77,7 +77,7 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
77 77 if (deviceInStore == null) { //第一次上线
78 78 logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());
79 79 cmder.deviceInfoQuery(device);
80   - cmder.catalogQuery(device, null);
  80 + deviceService.sync(device);
81 81 }
82 82 break;
83 83 // 设备主动发送心跳触发的在线事件
... ... @@ -98,11 +98,13 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
98 98 }
99 99 // 处理上线监听
100 100 storager.updateDevice(device);
101   - List<DeviceChannel> deviceChannelList = storager.queryOnlineChannelsByDeviceId(device.getDeviceId());
102   - eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.ON);
103 101 // 上线添加订阅
104 102 if (device.getSubscribeCycleForCatalog() > 0) {
  103 + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
105 104 deviceService.addCatalogSubscribe(device);
106 105 }
  106 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  107 + deviceService.addMobilePositionSubscribe(device);
  108 + }
107 109 }
108 110 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformKeepaliveExpire/PlatformKeepaliveExpireEventLister.java
... ... @@ -6,7 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
6 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
8 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  9 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
10 10 import org.jetbrains.annotations.NotNull;
11 11 import org.slf4j.Logger;
12 12 import org.slf4j.LoggerFactory;
... ... @@ -14,7 +14,6 @@ import org.springframework.beans.factory.annotation.Autowired;
14 14 import org.springframework.context.ApplicationListener;
15 15 import org.springframework.stereotype.Component;
16 16  
17   -import javax.sip.ResponseEvent;
18 17 import javax.sip.message.Response;
19 18  
20 19 /**
... ... @@ -29,7 +28,7 @@ public class PlatformKeepaliveExpireEventLister implements ApplicationListener&lt;P
29 28 private final static Logger logger = LoggerFactory.getLogger(PlatformKeepaliveExpireEventLister.class);
30 29  
31 30 @Autowired
32   - private IVideoManagerStorager storager;
  31 + private IVideoManagerStorage storager;
33 32  
34 33 @Autowired
35 34 private IRedisCatchStorage redisCatchStorage;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformCycleRegisterEventLister.java
1 1 package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
2 2  
  3 +import com.genersoft.iot.vmp.conf.DynamicTask;
3 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
4 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
5 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
6   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  7 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
7 8 import org.slf4j.Logger;
8 9 import org.slf4j.LoggerFactory;
9 10 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -19,9 +20,11 @@ public class PlatformCycleRegisterEventLister implements ApplicationListener&lt;Pla
19 20 private final static Logger logger = LoggerFactory.getLogger(PlatformCycleRegisterEventLister.class);
20 21  
21 22 @Autowired
22   - private IVideoManagerStorager storager;
  23 + private IVideoManagerStorage storager;
23 24 @Autowired
24 25 private ISIPCommanderForPlatform sipCommanderFroPlatform;
  26 + @Autowired
  27 + private DynamicTask dynamicTask;
25 28  
26 29 @Override
27 30 public void onApplicationEvent(PlatformCycleRegisterEvent event) {
... ... @@ -31,17 +34,13 @@ public class PlatformCycleRegisterEventLister implements ApplicationListener&lt;Pla
31 34 logger.info("[ 平台未注册事件 ] 平台已经删除!!! 平台国标ID:" + event.getPlatformGbID());
32 35 return;
33 36 }
34   - Timer timer = new Timer();
  37 + String taskKey = "platform-cycle-register" + parentPlatform.getServerGBId();;
35 38 SipSubscribe.Event okEvent = (responseEvent)->{
36   - timer.cancel();
  39 + dynamicTask.stop(taskKey);
37 40 };
38   - sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
39   - timer.schedule(new TimerTask() {
40   - @Override
41   - public void run() {
42   - logger.info("[平台注册]再次向平台注册,平台国标ID:" + event.getPlatformGbID());
43   - sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
44   - }
45   - }, 15*1000 ,Long.parseLong(parentPlatform.getExpires())* 1000);
  41 + dynamicTask.startCron(taskKey, ()->{
  42 + logger.info("[平台注册]再次向平台注册,平台国标ID:" + event.getPlatformGbID());
  43 + sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
  44 + }, Integer.parseInt(parentPlatform.getExpires())* 1000);
46 45 }
47 46 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
1 1 package com.genersoft.iot.vmp.gb28181.event.platformNotRegister;
2 2  
  3 +import com.genersoft.iot.vmp.conf.DynamicTask;
3 4 import com.genersoft.iot.vmp.conf.SipConfig;
4 5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5 6 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
... ... @@ -9,7 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
9 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 11 import com.genersoft.iot.vmp.service.IMediaServerService;
11 12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  13 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
13 14 import org.slf4j.Logger;
14 15 import org.slf4j.LoggerFactory;
15 16 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -31,7 +32,7 @@ public class PlatformNotRegisterEventLister implements ApplicationListener&lt;Platf
31 32 private final static Logger logger = LoggerFactory.getLogger(PlatformNotRegisterEventLister.class);
32 33  
33 34 @Autowired
34   - private IVideoManagerStorager storager;
  35 + private IVideoManagerStorage storager;
35 36 @Autowired
36 37 private IRedisCatchStorage redisCatchStorage;
37 38 @Autowired
... ... @@ -46,6 +47,9 @@ public class PlatformNotRegisterEventLister implements ApplicationListener&lt;Platf
46 47 @Autowired
47 48 private SipConfig config;
48 49  
  50 + @Autowired
  51 + private DynamicTask dynamicTask;
  52 +
49 53 // @Autowired
50 54 // private RedisUtil redis;
51 55  
... ... @@ -64,40 +68,24 @@ public class PlatformNotRegisterEventLister implements ApplicationListener&lt;Platf
64 68 logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流size", sendRtpItems.size());
65 69 if (sendRtpItems != null && sendRtpItems.size() > 0) {
66 70 logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流", event.getPlatformGbID());
67   - StringBuilder app = new StringBuilder();
68   - StringBuilder stream = new StringBuilder();
69 71 for (SendRtpItem sendRtpItem : sendRtpItems) {
70   - if (app.length() != 0) {
71   - app.append(",");
72   - }
73   - app.append(sendRtpItem.getApp());
74   - if (stream.length() != 0) {
75   - stream.append(",");
76   - }
77   - stream.append(sendRtpItem.getStreamId());
78 72 redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId(), null, null);
79 73 MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
80 74 Map<String, Object> param = new HashMap<>();
81 75 param.put("vhost", "__defaultVhost__");
82   - param.put("app", app.toString());
83   - param.put("stream", stream.toString());
  76 + param.put("app", sendRtpItem.getApp());
  77 + param.put("stream", sendRtpItem.getStreamId());
84 78 zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
85 79 }
86 80  
87 81 }
88   - Timer timer = new Timer();
  82 + String taskKey = "platform-not-register-" + parentPlatform.getServerGBId();
89 83 SipSubscribe.Event okEvent = (responseEvent)->{
90   - timer.cancel();
  84 + dynamicTask.stop(taskKey);
91 85 };
92   - logger.info("[平台注册]平台国标ID:" + event.getPlatformGbID());
93   - sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
94   - // 设置注册失败则每隔15秒发起一次注册
95   - timer.schedule(new TimerTask() {
96   - @Override
97   - public void run() {
98   - logger.info("[平台注册]再次向平台注册,平台国标ID:" + event.getPlatformGbID());
99   - sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
100   - }
101   - }, config.getRegisterTimeInterval()* 1000, config.getRegisterTimeInterval()* 1000);//十五秒后再次发起注册
  86 + dynamicTask.startCron(taskKey, ()->{
  87 + logger.info("[平台注册]再次向平台注册,平台国标ID:" + event.getPlatformGbID());
  88 + sipCommanderFroPlatform.register(parentPlatform, null, okEvent);
  89 + }, config.getRegisterTimeInterval()* 1000);
102 90 }
103 91 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java
... ... @@ -31,10 +31,8 @@ public class RecordEndEventListener implements ApplicationListener&lt;RecordEndEven
31 31 private Map<String, RecordEndEventHandler> handlerMap = new HashMap<>();
32 32 @Override
33 33 public void onApplicationEvent(RecordEndEvent event) {
34   - if (logger.isDebugEnabled()) {
35   - logger.debug("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}条", event.getRecordInfo().getDeviceId(),
36   - event.getRecordInfo().getChannelId(), event.getRecordInfo().getRecordList().size() );
37   - }
  34 + logger.info("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}条", event.getRecordInfo().getDeviceId(),
  35 + event.getRecordInfo().getChannelId(), event.getRecordInfo().getSumNum() );
38 36 if (handlerMap.size() > 0) {
39 37 for (RecordEndEventHandler recordEndEventHandler : handlerMap.values()) {
40 38 recordEndEventHandler.handler(event.getRecordInfo());
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/SubscribeListenerForPlatform.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.event.subscribe;
2   -
3   -import com.genersoft.iot.vmp.common.VideoManagerConstants;
4   -import com.genersoft.iot.vmp.conf.DynamicTask;
5   -import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
6   -import com.genersoft.iot.vmp.conf.UserSetup;
7   -import org.slf4j.Logger;
8   -import org.slf4j.LoggerFactory;
9   -import org.springframework.beans.factory.annotation.Autowired;
10   -import org.springframework.data.redis.connection.Message;
11   -import org.springframework.data.redis.listener.RedisMessageListenerContainer;
12   -import org.springframework.stereotype.Component;
13   -
14   -/**
15   - * 平台订阅到期事件
16   - */
17   -@Component
18   -public class SubscribeListenerForPlatform extends RedisKeyExpirationEventMessageListener {
19   -
20   - private Logger logger = LoggerFactory.getLogger(SubscribeListenerForPlatform.class);
21   -
22   - @Autowired
23   - private UserSetup userSetup;
24   -
25   - @Autowired
26   - private DynamicTask dynamicTask;
27   -
28   - public SubscribeListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
29   - super(listenerContainer, userSetup);
30   - }
31   -
32   -
33   - /**
34   - * 监听失效的key
35   - * @param message
36   - * @param pattern
37   - */
38   - @Override
39   - public void onMessage(Message message, byte[] pattern) {
40   - // 获取失效的key
41   - String expiredKey = message.toString();
42   - logger.debug(expiredKey);
43   - // 订阅到期
44   - String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_";
45   - if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {
46   - // 取消定时任务
47   - dynamicTask.stop(expiredKey);
48   - }
49   - }
50   -}
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
... ... @@ -2,17 +2,14 @@ package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
2 2  
3 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 4 import com.genersoft.iot.vmp.conf.SipConfig;
5   -import com.genersoft.iot.vmp.conf.UserSetup;
  5 +import com.genersoft.iot.vmp.conf.UserSetting;
6 6 import com.genersoft.iot.vmp.gb28181.bean.*;
7   -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
8   -import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent;
9 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
10 8 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
11   -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 9 import com.genersoft.iot.vmp.service.IGbStreamService;
13 10 import com.genersoft.iot.vmp.service.IMediaServerService;
14 11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  12 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
16 13 import org.slf4j.Logger;
17 14 import org.slf4j.LoggerFactory;
18 15 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -31,7 +28,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
31 28 private final static Logger logger = LoggerFactory.getLogger(CatalogEventLister.class);
32 29  
33 30 @Autowired
34   - private IVideoManagerStorager storager;
  31 + private IVideoManagerStorage storager;
35 32 @Autowired
36 33 private IRedisCatchStorage redisCatchStorage;
37 34 @Autowired
... ... @@ -47,7 +44,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
47 44 private SipConfig config;
48 45  
49 46 @Autowired
50   - private UserSetup userSetup;
  47 + private UserSetting userSetting;
51 48  
52 49 @Autowired
53 50 private IGbStreamService gbStreamService;
... ... @@ -63,13 +60,13 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
63 60 Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
64 61 if (event.getPlatformId() != null) {
65 62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
66   - if (parentPlatform != null && !parentPlatform.isStatus())return;
67   - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId();
68   -// subscribe = redisCatchStorage.getSubscribe(key);
  63 + if (parentPlatform != null && !parentPlatform.isStatus()) {
  64 + return;
  65 + }
69 66 subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
70 67  
71 68 if (subscribe == null) {
72   - logger.debug("发送订阅消息时发现订阅信息已经不存在");
  69 + logger.info("发送订阅消息时发现订阅信息已经不存在");
73 70 return;
74 71 }
75 72 }else {
... ... @@ -85,7 +82,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
85 82 }else if (event.getGbStreams() != null) {
86 83 if (platforms.size() > 0) {
87 84 for (GbStream gbStream : event.getGbStreams()) {
88   - if (gbStream == null || StringUtils.isEmpty(gbStream.getGbId())) continue;
  85 + if (gbStream == null || StringUtils.isEmpty(gbStream.getGbId())) {
  86 + continue;
  87 + }
89 88 List<ParentPlatform> parentPlatformsForGB = storager.queryPlatFormListForStreamWithGBId(gbStream.getApp(),gbStream.getStream(), platforms);
90 89 parentPlatformMap.put(gbStream.getGbId(), parentPlatformsForGB);
91 90 }
... ... @@ -104,7 +103,7 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
104 103 }
105 104 if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
106 105 for (GbStream gbStream : event.getGbStreams()) {
107   - DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId());
  106 + DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
108 107 deviceChannelList.add(deviceChannelByStream);
109 108 }
110 109 }
... ... @@ -118,7 +117,9 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
118 117 if (parentPlatforms != null && parentPlatforms.size() > 0) {
119 118 for (ParentPlatform platform : parentPlatforms) {
120 119 SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
121   - if (subscribeInfo == null) continue;
  120 + if (subscribeInfo == null) {
  121 + continue;
  122 + }
122 123 logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId);
123 124 List<DeviceChannel> deviceChannelList = new ArrayList<>();
124 125 DeviceChannel deviceChannel = new DeviceChannel();
... ... @@ -143,7 +144,10 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
143 144 }
144 145 if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
145 146 for (GbStream gbStream : event.getGbStreams()) {
146   - DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId());
  147 + DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
  148 + if (deviceChannelByStream.getParentId().length() <= 10) { // 父节点是行政区划,则设置CivilCode使用此行政区划
  149 + deviceChannelByStream.setCivilCode(deviceChannelByStream.getParentId());
  150 + }
147 151 deviceChannelList.add(deviceChannelByStream);
148 152 }
149 153 }
... ... @@ -156,18 +160,20 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
156 160 List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
157 161 if (parentPlatforms != null && parentPlatforms.size() > 0) {
158 162 for (ParentPlatform platform : parentPlatforms) {
159   -// String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId();
160   -// SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key);
161   - SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
162   - if (subscribeInfo == null) continue;
  163 + SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
  164 + if (subscribeInfo == null) {
  165 + continue;
  166 + }
163 167 logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId);
164 168 List<DeviceChannel> deviceChannelList = new ArrayList<>();
165 169 DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(platform.getServerGBId(), gbId);
166 170 deviceChannelList.add(deviceChannel);
167 171 GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId);
168   - DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform.getDeviceGBId());
169   - deviceChannelList.add(deviceChannelByStream);
170   - sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null);
  172 + if(gbStream != null){
  173 + DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform);
  174 + deviceChannelList.add(deviceChannelByStream);
  175 + }
  176 + sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null);
171 177 }
172 178 }
173 179 }
... ... @@ -178,3 +184,4 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
178 184 }
179 185 }
180 186 }
  187 +
181 188 \ No newline at end of file
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
... ... @@ -3,9 +3,10 @@ package com.genersoft.iot.vmp.gb28181.session;
3 3 import com.genersoft.iot.vmp.gb28181.bean.CatalogData;
4 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
5 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  6 +import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
7 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
8   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  9 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
9 10 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
10 11 import org.springframework.beans.factory.annotation.Autowired;
11 12 import org.springframework.scheduling.annotation.Scheduled;
... ... @@ -23,52 +24,119 @@ public class CatalogDataCatch {
23 24 private DeferredResultHolder deferredResultHolder;
24 25  
25 26 @Autowired
26   - private IVideoManagerStorager storager;
  27 + private IVideoManagerStorage storager;
27 28  
28   - public void put(String key, int total, Device device, List<DeviceChannel> deviceChannelList) {
29   - CatalogData catalogData = data.get(key);
  29 + public void addReady(Device device, int sn ) {
  30 + CatalogData catalogData = data.get(device.getDeviceId());
  31 + if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
  32 + catalogData = new CatalogData();
  33 + catalogData.setChannelList(new ArrayList<>());
  34 + catalogData.setDevice(device);
  35 + catalogData.setSn(sn);
  36 + catalogData.setStatus(CatalogData.CatalogDataStatus.ready);
  37 + catalogData.setLastTime(new Date(System.currentTimeMillis()));
  38 + data.put(device.getDeviceId(), catalogData);
  39 + }
  40 + }
  41 +
  42 + public void put(String deviceId, int sn, int total, Device device, List<DeviceChannel> deviceChannelList) {
  43 + CatalogData catalogData = data.get(deviceId);
30 44 if (catalogData == null) {
31 45 catalogData = new CatalogData();
  46 + catalogData.setSn(sn);
32 47 catalogData.setTotal(total);
33 48 catalogData.setDevice(device);
34 49 catalogData.setChannelList(new ArrayList<>());
35   - data.put(key, catalogData);
  50 + catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
  51 + catalogData.setLastTime(new Date(System.currentTimeMillis()));
  52 + data.put(deviceId, catalogData);
  53 + }else {
  54 + // 同一个设备的通道同步请求只考虑一个,其他的直接忽略
  55 + if (catalogData.getSn() != sn) {
  56 + return;
  57 + }
  58 + catalogData.setTotal(total);
  59 + catalogData.setDevice(device);
  60 + catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
  61 + catalogData.getChannelList().addAll(deviceChannelList);
  62 + catalogData.setLastTime(new Date(System.currentTimeMillis()));
36 63 }
37   - catalogData.getChannelList().addAll(deviceChannelList);
38   - catalogData.setLastTime(new Date(System.currentTimeMillis()));
39 64 }
40 65  
41   - public List<DeviceChannel> get(String key) {
42   - CatalogData catalogData = data.get(key);
43   - if (catalogData == null) return null;
  66 + public List<DeviceChannel> get(String deviceId) {
  67 + CatalogData catalogData = data.get(deviceId);
  68 + if (catalogData == null) {
  69 + return null;
  70 + }
44 71 return catalogData.getChannelList();
45 72 }
46 73  
47   - public void del(String key) {
48   - data.remove(key);
  74 + public int getTotal(String deviceId) {
  75 + CatalogData catalogData = data.get(deviceId);
  76 + if (catalogData == null) {
  77 + return 0;
  78 + }
  79 + return catalogData.getTotal();
  80 + }
  81 +
  82 + public SyncStatus getSyncStatus(String deviceId) {
  83 + CatalogData catalogData = data.get(deviceId);
  84 + if (catalogData == null) {
  85 + return null;
  86 + }
  87 + SyncStatus syncStatus = new SyncStatus();
  88 + syncStatus.setCurrent(catalogData.getChannelList().size());
  89 + syncStatus.setTotal(catalogData.getTotal());
  90 + syncStatus.setErrorMsg(catalogData.getErrorMsg());
  91 + return syncStatus;
  92 + }
  93 +
  94 + public boolean isSyncRunning(String deviceId) {
  95 + CatalogData catalogData = data.get(deviceId);
  96 + if (catalogData == null) {
  97 + return false;
  98 + }
  99 + return !catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end);
49 100 }
50 101  
51 102 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
52 103 private void timerTask(){
53 104 Set<String> keys = data.keySet();
54   - Calendar calendar = Calendar.getInstance();
55   - calendar.setTime(new Date());
56   - calendar.set(Calendar.SECOND, calendar.get(Calendar.SECOND) - 5);
57   - for (String key : keys) {
58   - CatalogData catalogData = data.get(key);
59   - if (catalogData.getLastTime().before(calendar.getTime())) {
60   -
61   - storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
62   - RequestMessage msg = new RequestMessage();
63   - msg.setKey(key);
64   - WVPResult<Object> result = new WVPResult<>();
65   - result.setCode(0);
66   - result.setMsg("更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条");
67   - result.setData(catalogData.getDevice());
68   - msg.setData(result);
69   - deferredResultHolder.invokeAllResult(msg);
70   - data.remove(key);
  105 + Calendar calendarBefore5S = Calendar.getInstance();
  106 + calendarBefore5S.setTime(new Date());
  107 + calendarBefore5S.set(Calendar.SECOND, calendarBefore5S.get(Calendar.SECOND) - 5);
  108 +
  109 + Calendar calendarBefore30S = Calendar.getInstance();
  110 + calendarBefore30S.setTime(new Date());
  111 + calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30);
  112 + for (String deviceId : keys) {
  113 + CatalogData catalogData = data.get(deviceId);
  114 + if ( catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据
  115 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) {
  116 + storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
  117 + if (catalogData.getTotal() != catalogData.getChannelList().size()) {
  118 + String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条";
  119 + catalogData.setErrorMsg(errorMsg);
  120 + }
  121 + }else if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.ready)) {
  122 + String errorMsg = "同步失败,等待回复超时";
  123 + catalogData.setErrorMsg(errorMsg);
  124 + }
  125 + catalogData.setStatus(CatalogData.CatalogDataStatus.end);
  126 + }
  127 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除
  128 + data.remove(deviceId);
71 129 }
72 130 }
73 131 }
  132 +
  133 +
  134 + public void setChannelSyncEnd(String deviceId, String errorMsg) {
  135 + CatalogData catalogData = data.get(deviceId);
  136 + if (catalogData == null) {
  137 + return;
  138 + }
  139 + catalogData.setStatus(CatalogData.CatalogDataStatus.end);
  140 + catalogData.setErrorMsg(errorMsg);
  141 + }
74 142 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java
... ... @@ -136,4 +136,7 @@ public class SsrcConfig {
136 136 this.notUsed = notUsed;
137 137 }
138 138  
  139 + public boolean checkSsrc(String ssrcInResponse) {
  140 + return !isUsed.contains(ssrcInResponse);
  141 + }
139 142 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
... ... @@ -7,7 +7,7 @@ import javax.sip.ClientTransaction;
7 7 import javax.sip.Dialog;
8 8  
9 9 import com.genersoft.iot.vmp.common.VideoManagerConstants;
10   -import com.genersoft.iot.vmp.conf.UserSetup;
  10 +import com.genersoft.iot.vmp.conf.UserSetting;
11 11 import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
12 12 import com.genersoft.iot.vmp.utils.SerializeUtils;
13 13 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
... ... @@ -28,7 +28,13 @@ public class VideoStreamSessionManager {
28 28 private RedisUtil redisUtil;
29 29  
30 30 @Autowired
31   - private UserSetup userSetup;
  31 + private UserSetting userSetting;
  32 +
  33 + public enum SessionType {
  34 + play,
  35 + playback,
  36 + download
  37 + }
32 38  
33 39 /**
34 40 * 添加一个点播/回放的事务信息
... ... @@ -40,7 +46,7 @@ public class VideoStreamSessionManager {
40 46 * @param mediaServerId 所使用的流媒体ID
41 47 * @param transaction 事务
42 48 */
43   - public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){
  49 + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction, SessionType type){
44 50 SsrcTransaction ssrcTransaction = new SsrcTransaction();
45 51 ssrcTransaction.setDeviceId(deviceId);
46 52 ssrcTransaction.setChannelId(channelId);
... ... @@ -50,10 +56,11 @@ public class VideoStreamSessionManager {
50 56 ssrcTransaction.setCallId(callId);
51 57 ssrcTransaction.setSsrc(ssrc);
52 58 ssrcTransaction.setMediaServerId(mediaServerId);
  59 + ssrcTransaction.setType(type);
53 60  
54   - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  61 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
55 62 + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
56   - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  63 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
57 64 + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
58 65 }
59 66  
... ... @@ -63,7 +70,7 @@ public class VideoStreamSessionManager {
63 70 byte[] dialogByteArray = SerializeUtils.serialize(dialog);
64 71 ssrcTransaction.setDialog(dialogByteArray);
65 72 }
66   - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  73 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
67 74 + "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
68 75 + ssrcTransaction.getStream(), ssrcTransaction);
69 76 }
... ... @@ -71,7 +78,9 @@ public class VideoStreamSessionManager {
71 78  
72 79 public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){
73 80 SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
74   - if (ssrcTransaction == null) return null;
  81 + if (ssrcTransaction == null) {
  82 + return null;
  83 + }
75 84 byte[] transactionByteArray = ssrcTransaction.getTransaction();
76 85 ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
77 86 return clientTransaction;
... ... @@ -79,39 +88,63 @@ public class VideoStreamSessionManager {
79 88  
80 89 public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
81 90 SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
82   - if (ssrcTransaction == null) return null;
  91 + if (ssrcTransaction == null) {
  92 + return null;
  93 + }
83 94 byte[] dialogByteArray = ssrcTransaction.getDialog();
84   - if (dialogByteArray == null) return null;
  95 + if (dialogByteArray == null) {
  96 + return null;
  97 + }
85 98 SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
86 99 return dialog;
87 100 }
88 101  
89 102 public SIPDialog getDialogByCallId(String deviceId, String channelId, String callID){
90 103 SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callID, null);
91   - if (ssrcTransaction == null) return null;
  104 + if (ssrcTransaction == null) {
  105 + return null;
  106 + }
92 107 byte[] dialogByteArray = ssrcTransaction.getDialog();
93   - if (dialogByteArray == null) return null;
  108 + if (dialogByteArray == null) {
  109 + return null;
  110 + }
94 111 SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
95 112 return dialog;
96 113 }
97 114  
98 115 public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
99   - if (StringUtils.isEmpty(callId)) callId ="*";
100   - if (StringUtils.isEmpty(stream)) stream ="*";
101   - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
  116 + if (StringUtils.isEmpty(callId)) {
  117 + callId ="*";
  118 + }
  119 + if (StringUtils.isEmpty(stream)) {
  120 + stream ="*";
  121 + }
  122 + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
102 123 List<Object> scanResult = redisUtil.scan(key);
103   - if (scanResult.size() == 0) return null;
  124 + if (scanResult.size() == 0) {
  125 + return null;
  126 + }
104 127 return (SsrcTransaction)redisUtil.get((String) scanResult.get(0));
105 128 }
106 129  
107 130 public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
108   - if (StringUtils.isEmpty(deviceId)) deviceId ="*";
109   - if (StringUtils.isEmpty(channelId)) channelId ="*";
110   - if (StringUtils.isEmpty(callId)) callId ="*";
111   - if (StringUtils.isEmpty(stream)) stream ="*";
112   - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
  131 + if (StringUtils.isEmpty(deviceId)) {
  132 + deviceId ="*";
  133 + }
  134 + if (StringUtils.isEmpty(channelId)) {
  135 + channelId ="*";
  136 + }
  137 + if (StringUtils.isEmpty(callId)) {
  138 + callId ="*";
  139 + }
  140 + if (StringUtils.isEmpty(stream)) {
  141 + stream ="*";
  142 + }
  143 + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
113 144 List<Object> scanResult = redisUtil.scan(key);
114   - if (scanResult.size() == 0) return null;
  145 + if (scanResult.size() == 0) {
  146 + return null;
  147 + }
115 148 List<SsrcTransaction> result = new ArrayList<>();
116 149 for (Object keyObj : scanResult) {
117 150 result.add((SsrcTransaction)redisUtil.get((String) keyObj));
... ... @@ -121,26 +154,32 @@ public class VideoStreamSessionManager {
121 154  
122 155 public String getMediaServerId(String deviceId, String channelId, String stream){
123 156 SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
124   - if (ssrcTransaction == null) return null;
  157 + if (ssrcTransaction == null) {
  158 + return null;
  159 + }
125 160 return ssrcTransaction.getMediaServerId();
126 161 }
127 162  
128 163 public String getSSRC(String deviceId, String channelId, String stream){
129 164 SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
130   - if (ssrcTransaction == null) return null;
  165 + if (ssrcTransaction == null) {
  166 + return null;
  167 + }
131 168 return ssrcTransaction.getSsrc();
132 169 }
133 170  
134 171 public void remove(String deviceId, String channelId, String stream) {
135 172 SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
136   - if (ssrcTransaction == null) return;
137   - redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_"
  173 + if (ssrcTransaction == null) {
  174 + return;
  175 + }
  176 + redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_"
138 177 + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
139 178 }
140 179  
141 180  
142 181 public List<SsrcTransaction> getAllSsrc() {
143   - List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
  182 + List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId() + "_" ));
144 183 List<SsrcTransaction> result= new ArrayList<>();
145 184 for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
146 185 String key = (String)ssrcTransactionKeys.get(i);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java deleted 100644 → 0
1   -package com.genersoft.iot.vmp.gb28181.task;
2   -
3   -import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4   -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5   -import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
6   -import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
7   -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
8   -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
9   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
10   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
11   -
12   -import java.text.SimpleDateFormat;
13   -import java.util.List;
14   -
15   -public class GPSSubscribeTask implements Runnable{
16   -
17   - private IRedisCatchStorage redisCatchStorage;
18   - private IVideoManagerStorager storager;
19   - private ISIPCommanderForPlatform sipCommanderForPlatform;
20   - private SubscribeHolder subscribeHolder;
21   - private String platformId;
22   - private String sn;
23   - private String key;
24   -
25   - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
26   -
27   - public GPSSubscribeTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorager storager, String platformId, String sn, String key, SubscribeHolder subscribeInfo) {
28   - this.redisCatchStorage = redisCatchStorage;
29   - this.storager = storager;
30   - this.platformId = platformId;
31   - this.sn = sn;
32   - this.key = key;
33   - this.sipCommanderForPlatform = sipCommanderForPlatform;
34   - this.subscribeHolder = subscribeInfo;
35   - }
36   -
37   - @Override
38   - public void run() {
39   -
40   - SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platformId);
41   -
42   - if (subscribe != null) {
43   - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
44   - if (parentPlatform == null || parentPlatform.isStatus()) {
45   - // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
46   - List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platformId);
47   - if (gbStreams.size() > 0) {
48   - for (GbStream gbStream : gbStreams) {
49   - String gbId = gbStream.getGbId();
50   - GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
51   - if (gbStream.isStatus()) {
52   - if (gpsMsgInfo != null) {
53   - // 发送GPS消息
54   - sipCommanderForPlatform.sendNotifyMobilePosition(parentPlatform, gpsMsgInfo, subscribe);
55   - }else {
56   - // 没有在redis找到新的消息就使用数据库的消息
57   - gpsMsgInfo = new GPSMsgInfo();
58   - gpsMsgInfo.setId(gbId);
59   - gpsMsgInfo.setLat(gbStream.getLongitude());
60   - gpsMsgInfo.setLng(gbStream.getLongitude());
61   - // 发送GPS消息
62   - sipCommanderForPlatform.sendNotifyMobilePosition(parentPlatform, gpsMsgInfo, subscribe);
63   - }
64   - }
65   -
66   - }
67   - }
68   - }
69   - }
70   - }
71   -}
src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.task;
  2 +
  3 +import javax.sip.DialogState;
  4 +
  5 +/**
  6 + * @author lin
  7 + */
  8 +public interface ISubscribeTask extends Runnable{
  9 + void stop();
  10 +
  11 + DialogState getDialogState();
  12 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.task.impl;
  2 +
  3 +import com.genersoft.iot.vmp.conf.DynamicTask;
  4 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.scheduling.annotation.Async;
  10 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  11 +
  12 +import javax.sip.Dialog;
  13 +import javax.sip.DialogState;
  14 +import javax.sip.ResponseEvent;
  15 +import java.util.Timer;
  16 +import java.util.TimerTask;
  17 +
  18 +/**
  19 + * 目录订阅任务
  20 + * @author lin
  21 + */
  22 +public class CatalogSubscribeTask implements ISubscribeTask {
  23 + private final Logger logger = LoggerFactory.getLogger(CatalogSubscribeTask.class);
  24 + private Device device;
  25 + private final ISIPCommander sipCommander;
  26 + private Dialog dialog;
  27 +
  28 + private DynamicTask dynamicTask;
  29 +
  30 + private String taskKey = "catalog-subscribe-timeout";
  31 +
  32 +
  33 + public CatalogSubscribeTask(Device device, ISIPCommander sipCommander, DynamicTask dynamicTask) {
  34 + this.device = device;
  35 + this.sipCommander = sipCommander;
  36 + this.dynamicTask = dynamicTask;
  37 + }
  38 +
  39 + @Override
  40 + public void run() {
  41 + if (dynamicTask.get(taskKey) != null) {
  42 + dynamicTask.stop(taskKey);
  43 + }
  44 + sipCommander.catalogSubscribe(device, dialog, eventResult -> {
  45 + if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
  46 + dialog = eventResult.dialog;
  47 + }
  48 + ResponseEvent event = (ResponseEvent) eventResult.event;
  49 + if (event.getResponse().getRawContent() != null) {
  50 + // 成功
  51 + logger.info("[目录订阅]成功: {}", device.getDeviceId());
  52 + }else {
  53 + // 成功
  54 + logger.info("[目录订阅]成功: {}", device.getDeviceId());
  55 + }
  56 + },eventResult -> {
  57 + dialog = null;
  58 + // 失败
  59 + logger.warn("[目录订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  60 + dynamicTask.startDelay(taskKey, CatalogSubscribeTask.this, 2000);
  61 + });
  62 + }
  63 +
  64 + @Override
  65 + public void stop() {
  66 + /**
  67 + * dialog 的各个状态
  68 + * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
  69 + * CONFIRMED-> Confirmed Dialog状态-已确认
  70 + * COMPLETED-> Completed Dialog状态-已完成
  71 + * TERMINATED-> Terminated Dialog状态-终止
  72 + */
  73 + logger.info("取消目录订阅时dialog状态为{}", DialogState.CONFIRMED);
  74 + if (dynamicTask.get(taskKey) != null) {
  75 + dynamicTask.stop(taskKey);
  76 + }
  77 + if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
  78 + device.setSubscribeCycleForCatalog(0);
  79 + sipCommander.catalogSubscribe(device, dialog, eventResult -> {
  80 + ResponseEvent event = (ResponseEvent) eventResult.event;
  81 + if (event.getResponse().getRawContent() != null) {
  82 + // 成功
  83 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  84 + }else {
  85 + // 成功
  86 + logger.info("[取消目录订阅订阅]成功: {}", device.getDeviceId());
  87 + }
  88 + },eventResult -> {
  89 + // 失败
  90 + logger.warn("[取消目录订阅订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  91 + });
  92 + }
  93 + }
  94 +
  95 + @Override
  96 + public DialogState getDialogState() {
  97 + if (dialog == null) {
  98 + return null;
  99 + }
  100 + return dialog.getState();
  101 + }
  102 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.task.impl;
  2 +
  3 +import com.genersoft.iot.vmp.conf.DynamicTask;
  4 +import com.genersoft.iot.vmp.gb28181.bean.*;
  5 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  7 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  8 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  9 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +import org.springframework.scheduling.annotation.Async;
  13 +
  14 +import javax.sip.DialogState;
  15 +import java.util.List;
  16 +
  17 +/**
  18 + * 向已经订阅(移动位置)的上级发送MobilePosition消息
  19 + * @author lin
  20 + */
  21 +public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
  22 +
  23 + private Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeHandlerTask.class);
  24 +
  25 + private IRedisCatchStorage redisCatchStorage;
  26 + private IVideoManagerStorage storager;
  27 + private ISIPCommanderForPlatform sipCommanderForPlatform;
  28 + private SubscribeHolder subscribeHolder;
  29 + private ParentPlatform platform;
  30 +
  31 + private String sn;
  32 + private String key;
  33 +
  34 + public MobilePositionSubscribeHandlerTask(IRedisCatchStorage redisCatchStorage,
  35 + ISIPCommanderForPlatform sipCommanderForPlatform,
  36 + IVideoManagerStorage storager,
  37 + String platformId,
  38 + String sn,
  39 + String key,
  40 + SubscribeHolder subscribeInfo,
  41 + DynamicTask dynamicTask) {
  42 + this.redisCatchStorage = redisCatchStorage;
  43 + this.storager = storager;
  44 + this.platform = storager.queryParentPlatByServerGBId(platformId);
  45 + this.sn = sn;
  46 + this.key = key;
  47 + this.sipCommanderForPlatform = sipCommanderForPlatform;
  48 + this.subscribeHolder = subscribeInfo;
  49 + }
  50 +
  51 + @Override
  52 + public void run() {
  53 +
  54 + if (platform == null) {
  55 + return;
  56 + }
  57 + SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
  58 + if (subscribe != null) {
  59 +
  60 +// if (!parentPlatform.isStatus()) {
  61 +// logger.info("发送订阅时发现平台已经离线:{}", platformId);
  62 +// return;
  63 +// }
  64 + // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
  65 + List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
  66 + if (gbStreams.size() == 0) {
  67 + logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId());
  68 + return;
  69 + }
  70 + for (GbStream gbStream : gbStreams) {
  71 + String gbId = gbStream.getGbId();
  72 + GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
  73 + if (gpsMsgInfo != null) { // 无最新位置不发送
  74 + logger.info("无最新位置不发送");
  75 + // 经纬度都为0不发送
  76 + if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
  77 + continue;
  78 + }
  79 + // 发送GPS消息
  80 + sipCommanderForPlatform.sendNotifyMobilePosition(platform, gpsMsgInfo, subscribe);
  81 + }
  82 + }
  83 + }
  84 + }
  85 +
  86 + @Override
  87 + public void stop() {
  88 +
  89 + }
  90 +
  91 + @Override
  92 + public DialogState getDialogState() {
  93 + return null;
  94 + }
  95 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.task.impl;
  2 +
  3 +import com.genersoft.iot.vmp.conf.DynamicTask;
  4 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  7 +import org.dom4j.Element;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.scheduling.annotation.Async;
  11 +
  12 +import javax.sip.Dialog;
  13 +import javax.sip.DialogState;
  14 +import javax.sip.ResponseEvent;
  15 +import java.util.Timer;
  16 +import java.util.TimerTask;
  17 +
  18 +/**
  19 + * 移动位置订阅的定时更新
  20 + * @author lin
  21 + */
  22 +public class MobilePositionSubscribeTask implements ISubscribeTask {
  23 + private final Logger logger = LoggerFactory.getLogger(MobilePositionSubscribeTask.class);
  24 + private Device device;
  25 + private ISIPCommander sipCommander;
  26 + private Dialog dialog;
  27 + private DynamicTask dynamicTask;
  28 + private String taskKey = "mobile-position-subscribe-timeout";
  29 +
  30 + public MobilePositionSubscribeTask(Device device, ISIPCommander sipCommander, DynamicTask dynamicTask) {
  31 + this.device = device;
  32 + this.sipCommander = sipCommander;
  33 + this.dynamicTask = dynamicTask;
  34 + }
  35 +
  36 + @Override
  37 + public void run() {
  38 + if (dynamicTask.get(taskKey) != null) {
  39 + dynamicTask.stop(taskKey);
  40 + }
  41 + sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
  42 +// if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
  43 +// dialog = eventResult.dialog;
  44 +// }
  45 + ResponseEvent event = (ResponseEvent) eventResult.event;
  46 + if (event.getResponse().getRawContent() != null) {
  47 + // 成功
  48 + logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
  49 + }else {
  50 + // 成功
  51 + logger.info("[移动位置订阅]成功: {}", device.getDeviceId());
  52 + }
  53 + },eventResult -> {
  54 + dialog = null;
  55 + // 失败
  56 + logger.warn("[移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  57 + dynamicTask.startDelay(taskKey, MobilePositionSubscribeTask.this, 2000);
  58 + });
  59 +
  60 + }
  61 +
  62 + @Override
  63 + public void stop() {
  64 + /**
  65 + * dialog 的各个状态
  66 + * EARLY-> Early state状态-初始请求发送以后,收到了一个临时响应消息
  67 + * CONFIRMED-> Confirmed Dialog状态-已确认
  68 + * COMPLETED-> Completed Dialog状态-已完成
  69 + * TERMINATED-> Terminated Dialog状态-终止
  70 + */
  71 + if (dynamicTask.get(taskKey) != null) {
  72 + dynamicTask.stop(taskKey);
  73 + }
  74 + if (dialog != null && dialog.getState().equals(DialogState.CONFIRMED)) {
  75 + logger.info("取消移动订阅时dialog状态为{}", dialog.getState());
  76 + device.setSubscribeCycleForMobilePosition(0);
  77 + sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
  78 + ResponseEvent event = (ResponseEvent) eventResult.event;
  79 + if (event.getResponse().getRawContent() != null) {
  80 + // 成功
  81 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  82 + }else {
  83 + // 成功
  84 + logger.info("[取消移动位置订阅]成功: {}", device.getDeviceId());
  85 + }
  86 + },eventResult -> {
  87 + // 失败
  88 + logger.warn("[取消移动位置订阅]失败,信令发送失败: {}-{} ", device.getDeviceId(), eventResult.msg);
  89 + });
  90 + }
  91 + }
  92 + @Override
  93 + public DialogState getDialogState() {
  94 + if (dialog == null) {
  95 + return null;
  96 + }
  97 + return dialog.getState();
  98 + }
  99 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
... ... @@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
4 4 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
5 5 import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor;
6 6 import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor;
7   -import gov.nist.javax.sip.message.SIPRequest;
8 7 import org.slf4j.Logger;
9 8 import org.slf4j.LoggerFactory;
10 9 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -14,7 +13,6 @@ import org.springframework.stereotype.Component;
14 13 import javax.sip.*;
15 14 import javax.sip.header.CSeqHeader;
16 15 import javax.sip.header.CallIdHeader;
17   -import javax.sip.header.Header;
18 16 import javax.sip.message.Response;
19 17 import java.util.Map;
20 18 import java.util.concurrent.ConcurrentHashMap;
... ... @@ -36,6 +34,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
36 34 @Autowired
37 35 private SipSubscribe sipSubscribe;
38 36  
  37 +
39 38 // @Autowired
40 39 // @Qualifier(value = "taskExecutor")
41 40 // private ThreadPoolTaskExecutor poolTaskExecutor;
... ... @@ -63,7 +62,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
63 62 * @param processor 处理程序
64 63 */
65 64 public void addTimeoutProcessor(ITimeoutProcessor processor) {
66   - this.timeoutProcessor = processor;
  65 + timeoutProcessor = processor;
67 66 }
68 67  
69 68 /**
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
... ... @@ -29,6 +29,7 @@ public class CheckForAllRecordsThread extends Thread {
29 29 this.recordInfo = recordInfo;
30 30 }
31 31  
  32 + @Override
32 33 public void run() {
33 34  
34 35 String cacheKey = this.key;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
... ... @@ -35,7 +35,7 @@ public class DeferredResultHolder {
35 35  
36 36 public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
37 37  
38   - public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAY";
  38 + public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK";
39 39  
40 40 public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
41 41  
... ... @@ -65,12 +65,16 @@ public class DeferredResultHolder {
65 65  
66 66 public DeferredResult get(String key, String id) {
67 67 Map<String, DeferredResult> deferredResultMap = map.get(key);
68   - if (deferredResultMap == null) return null;
  68 + if (deferredResultMap == null) {
  69 + return null;
  70 + }
69 71 return deferredResultMap.get(id);
70 72 }
71 73  
72 74 public boolean exist(String key, String id){
73   - if (key == null) return false;
  75 + if (key == null) {
  76 + return false;
  77 + }
74 78 Map<String, DeferredResult> deferredResultMap = map.get(key);
75 79 if (id == null) {
76 80 return deferredResultMap != null;
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4   -import com.genersoft.iot.vmp.gb28181.bean.Device;
5   -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
  4 +import com.genersoft.iot.vmp.gb28181.bean.*;
6 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
8 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
9 8 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 9  
  10 +import javax.sip.Dialog;
  11 +
11 12 /**
12 13 * @description:设备能力接口,用于定义设备的控制、查询能力
13 14 * @author: swwheihei
... ... @@ -22,7 +23,6 @@ public interface ISIPCommander {
22 23 * @param channelId 预览通道
23 24 * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移
24 25 * @param upDown 镜头上移下移 0:停止 1:上移 2:下移
25   - * @param moveSpeed 镜头移动速度
26 26 */
27 27 boolean ptzdirectCmd(Device device,String channelId,int leftRight, int upDown);
28 28  
... ... @@ -52,7 +52,6 @@ public interface ISIPCommander {
52 52 * @param device 控制设备
53 53 * @param channelId 预览通道
54 54 * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大
55   - * @param zoomSpeed 镜头缩放速度
56 55 */
57 56 boolean ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed);
58 57  
... ... @@ -87,15 +86,15 @@ public interface ISIPCommander {
87 86 * @param channelId 预览通道
88 87 * @param cmdString 前端控制指令串
89 88 */
90   - boolean fronEndCmd(Device device, String channelId, String cmdString);
  89 + boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent);
91 90  
92 91 /**
93 92 * 请求预览视频流
94 93 * @param device 视频设备
95 94 * @param channelId 预览通道
96 95 */
97   - void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
98   -
  96 + void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent);
  97 +
99 98 /**
100 99 * 请求回放视频流
101 100 *
... ... @@ -115,7 +114,9 @@ public interface ISIPCommander {
115 114 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
116 115 * @param downloadSpeed 下载倍速参数
117 116 */
118   - void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, InviteStreamCallback event, SipSubscribe.Event errorEvent);
  117 + void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  118 + String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  119 + SipSubscribe.Event errorEvent);
119 120  
120 121 /**
121 122 * 视频流停止
... ... @@ -179,7 +180,6 @@ public interface ISIPCommander {
179 180 * 报警布防/撤防命令
180 181 *
181 182 * @param device 视频设备
182   - * @param setGuard true: SetGuard, false: ResetGuard
183 183 */
184 184 boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent);
185 185  
... ... @@ -249,7 +249,7 @@ public interface ISIPCommander {
249 249 *
250 250 * @param device 视频设备
251 251 */
252   - boolean catalogQuery(Device device, SipSubscribe.Event errorEvent);
  252 + boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent);
253 253  
254 254 /**
255 255 * 查询录像信息
... ... @@ -303,11 +303,9 @@ public interface ISIPCommander {
303 303 * 订阅、取消订阅移动位置
304 304 *
305 305 * @param device 视频设备
306   - * @param expires 订阅超时时间(值=0时为取消订阅)
307   - * @param interval 上报时间间隔
308 306 * @return true = 命令发送成功
309 307 */
310   - boolean mobilePositionSubscribe(Device device, int expires, int interval);
  308 + boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent);
311 309  
312 310 /**
313 311 * 订阅、取消订阅报警信息
... ... @@ -315,7 +313,6 @@ public interface ISIPCommander {
315 313 * @param expires 订阅过期时间(0 = 取消订阅)
316 314 * @param startPriority 报警起始级别(可选)
317 315 * @param endPriority 报警终止级别(可选)
318   - * @param alarmMethods 报警方式条件(可选)
319 316 * @param alarmType 报警类型
320 317 * @param startTime 报警发生起始时间(可选)
321 318 * @param endTime 报警发生终止时间(可选)
... ... @@ -328,7 +325,7 @@ public interface ISIPCommander {
328 325 * @param device 视频设备
329 326 * @return true = 命令发送成功
330 327 */
331   - boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
  328 + boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent);
332 329  
333 330 /**
334 331 * 拉框控制命令
... ... @@ -338,4 +335,13 @@ public interface ISIPCommander {
338 335 * @param cmdString 前端控制指令串
339 336 */
340 337 boolean dragZoomCmd(Device device, String channelId, String cmdString);
  338 +
  339 +
  340 + /**
  341 + * 向设备发送报警NOTIFY消息, 用于互联结构下,此时将设备当成一个平级平台看待
  342 + * @param device 设备
  343 + * @param deviceAlarm 报警信息信息
  344 + * @return
  345 + */
  346 + boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm);
341 347 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
1 1 package com.genersoft.iot.vmp.gb28181.transmit.cmd;
2 2  
3   -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
4   -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
5   -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
6   -import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
  3 +import com.genersoft.iot.vmp.gb28181.bean.*;
7 4 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
8 5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
9 6  
... ... @@ -46,6 +43,7 @@ public interface ISIPCommanderForPlatform {
46 43 * @return
47 44 */
48 45 boolean catalogQuery(DeviceChannel channel, ParentPlatform parentPlatform, String sn, String fromTag, int size);
  46 + boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag);
49 47  
50 48 /**
51 49 * 向上级回复DeviceInfo查询信息
... ... @@ -75,6 +73,14 @@ public interface ISIPCommanderForPlatform {
75 73 boolean sendNotifyMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo);
76 74  
77 75 /**
  76 + * 向上级回复报警消息
  77 + * @param parentPlatform 平台信息
  78 + * @param deviceAlarm 报警信息信息
  79 + * @return
  80 + */
  81 + boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm);
  82 +
  83 + /**
78 84 * 回复catalog事件-增加/更新
79 85 * @param parentPlatform
80 86 * @param deviceChannels
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
... ... @@ -223,7 +223,7 @@ public class SIPRequestHeaderPlarformProvider {
223 223 CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.MESSAGE), Request.MESSAGE);
224 224 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
225 225 // 设置编码, 防止中文乱码
226   - messageFactory.setDefaultContentEncodingCharset("gb2312");
  226 + messageFactory.setDefaultContentEncodingCharset(parentPlatform.getCharacterSet());
227 227 request = messageFactory.createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
228 228 toHeader, viaHeaders, maxForwards);
229 229 List<String> agentParam = new ArrayList<>();
... ... @@ -235,58 +235,4 @@ public class SIPRequestHeaderPlarformProvider {
235 235 request.setContent(content, contentTypeHeader);
236 236 return request;
237 237 }
238   -
239   -// public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, String fromTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
240   -// Request request = null;
241   -// // sipuri
242   -// SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
243   -// // via
244   -// ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
245   -// ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
246   -// parentPlatform.getTransport(), viaTag);
247   -// viaHeader.setRPort();
248   -// viaHeaders.add(viaHeader);
249   -// // from
250   -// SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
251   -// parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
252   -// Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
253   -// FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
254   -// // to
255   -// SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
256   -// Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
257   -// ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag());
258   -//
259   -// // Forwards
260   -// MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
261   -// // ceq
262   -// CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.NOTIFY), Request.NOTIFY);
263   -// MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
264   -// // 设置编码, 防止中文乱码
265   -// messageFactory.setDefaultContentEncodingCharset("gb2312");
266   -// request = messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
267   -// toHeader, viaHeaders, maxForwards);
268   -// List<String> agentParam = new ArrayList<>();
269   -// agentParam.add("wvp-pro");
270   -// UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
271   -// request.addHeader(userAgentHeader);
272   -//
273   -// EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
274   -// if (subscribeInfo.getEventId() != null) {
275   -// event.setEventId(subscribeInfo.getEventId());
276   -// }
277   -//
278   -// request.addHeader(event);
279   -//
280   -// SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active");
281   -// request.setHeader(active);
282   -//
283   -// String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort();
284   -// Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory()
285   -// .createSipURI(parentPlatform.getDeviceGBId(), sipAddress));
286   -// request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
287   -//
288   -// ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
289   -// request.setContent(content, contentTypeHeader);
290   -// return request;
291   -// }
292 238 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
... ... @@ -225,11 +225,16 @@ public class SIPRequestHeaderProvider {
225 225 return request;
226 226 }
227 227  
228   - public Request createInfoRequest(Device device, StreamInfo streamInfo, String content, Long cseq)
  228 + public Request createInfoRequest(Device device, StreamInfo streamInfo, String content)
229 229 throws PeerUnavailableException, ParseException, InvalidArgumentException {
230 230 Request request = null;
231   - if (streamInfo == null) return null;
  231 + if (streamInfo == null) {
  232 + return null;
  233 + }
232 234 Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
  235 + if (dialog == null) {
  236 + return null;
  237 + }
233 238  
234 239 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
235 240 device.getHostAddress());
... ... @@ -255,9 +260,8 @@ public class SIPRequestHeaderProvider {
255 260  
256 261 // Forwards
257 262 MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
258   - if (cseq == null) {
259   - cseq = redisCatchStorage.getCSEQ(Request.INFO);
260   - }
  263 +
  264 + Long cseq = redisCatchStorage.getCSEQ(Request.INVITE);
261 265 // ceq
262 266 CSeqHeader cSeqHeader = sipFactory.createHeaderFactory()
263 267 .createCSeqHeader(cseq, Request.INFO);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -4,11 +4,8 @@ import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
5 5 import com.genersoft.iot.vmp.conf.DynamicTask;
6 6 import com.genersoft.iot.vmp.conf.SipConfig;
7   -import com.genersoft.iot.vmp.conf.UserSetup;
8   -import com.genersoft.iot.vmp.gb28181.bean.Device;
9   -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
10   -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
11   -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
  7 +import com.genersoft.iot.vmp.conf.UserSetting;
  8 +import com.genersoft.iot.vmp.gb28181.bean.*;
12 9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
13 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
14 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
... ... @@ -20,9 +17,10 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
20 17 import com.genersoft.iot.vmp.service.IMediaServerService;
21 18 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
22 19 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
23   -import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  20 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
24 21 import gov.nist.javax.sip.SipProviderImpl;
25 22 import gov.nist.javax.sip.SipStackImpl;
  23 +import gov.nist.javax.sip.message.MessageFactoryImpl;
26 24 import gov.nist.javax.sip.message.SIPRequest;
27 25 import gov.nist.javax.sip.stack.SIPDialog;
28 26 import org.slf4j.Logger;
... ... @@ -35,8 +33,7 @@ import org.springframework.util.StringUtils;
35 33  
36 34 import javax.sip.*;
37 35 import javax.sip.address.SipURI;
38   -import javax.sip.header.CallIdHeader;
39   -import javax.sip.header.ViaHeader;
  36 +import javax.sip.header.*;
40 37 import javax.sip.message.Request;
41 38 import java.lang.reflect.Field;
42 39 import java.text.ParseException;
... ... @@ -57,6 +54,9 @@ public class SIPCommander implements ISIPCommander {
57 54 private SipConfig sipConfig;
58 55  
59 56 @Autowired
  57 + private SipFactory sipFactory;
  58 +
  59 + @Autowired
60 60 @Qualifier(value="tcpSipProvider")
61 61 private SipProviderImpl tcpSipProvider;
62 62  
... ... @@ -71,13 +71,13 @@ public class SIPCommander implements ISIPCommander {
71 71 private VideoStreamSessionManager streamSession;
72 72  
73 73 @Autowired
74   - private IVideoManagerStorager storager;
  74 + private IVideoManagerStorage storager;
75 75  
76 76 @Autowired
77 77 private IRedisCatchStorage redisCatchStorage;
78 78  
79 79 @Autowired
80   - private UserSetup userSetup;
  80 + private UserSetting userSetting;
81 81  
82 82 @Autowired
83 83 private ZLMHttpHookSubscribe subscribe;
... ... @@ -229,13 +229,15 @@ public class SIPCommander implements ISIPCommander {
229 229 try {
230 230 String cmdStr= cmdString(leftRight, upDown, inOut, moveSpeed, zoomSpeed);
231 231 StringBuffer ptzXml = new StringBuffer(200);
232   - ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
  232 + String charset = device.getCharset();
  233 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
233 234 ptzXml.append("<Control>\r\n");
234 235 ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
235 236 ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
236 237 ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
237 238 ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
238 239 ptzXml.append("<Info>\r\n");
  240 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
239 241 ptzXml.append("</Info>\r\n");
240 242 ptzXml.append("</Control>\r\n");
241 243  
... ... @@ -270,13 +272,15 @@ public class SIPCommander implements ISIPCommander {
270 272 String cmdStr= frontEndCmdString(cmdCode, parameter1, parameter2, combineCode2);
271 273 logger.debug("控制字符串:" + cmdStr);
272 274 StringBuffer ptzXml = new StringBuffer(200);
273   - ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
  275 + String charset = device.getCharset();
  276 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
274 277 ptzXml.append("<Control>\r\n");
275 278 ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
276 279 ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
277 280 ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
278 281 ptzXml.append("<PTZCmd>" + cmdStr + "</PTZCmd>\r\n");
279 282 ptzXml.append("<Info>\r\n");
  283 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
280 284 ptzXml.append("</Info>\r\n");
281 285 ptzXml.append("</Control>\r\n");
282 286  
... ... @@ -301,16 +305,18 @@ public class SIPCommander implements ISIPCommander {
301 305 * @param cmdString 前端控制指令串
302 306 */
303 307 @Override
304   - public boolean fronEndCmd(Device device, String channelId, String cmdString) {
  308 + public boolean fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) {
305 309 try {
306 310 StringBuffer ptzXml = new StringBuffer(200);
307   - ptzXml.append("<?xml version=\"1.0\" ?>\r\n");
  311 + String charset = device.getCharset();
  312 + ptzXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
308 313 ptzXml.append("<Control>\r\n");
309 314 ptzXml.append("<CmdType>DeviceControl</CmdType>\r\n");
310 315 ptzXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
311 316 ptzXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
312 317 ptzXml.append("<PTZCmd>" + cmdString + "</PTZCmd>\r\n");
313 318 ptzXml.append("<Info>\r\n");
  319 + ptzXml.append("<ControlPriority>5</ControlPriority>\r\n");
314 320 ptzXml.append("</Info>\r\n");
315 321 ptzXml.append("</Control>\r\n");
316 322  
... ... @@ -320,7 +326,7 @@ public class SIPCommander implements ISIPCommander {
320 326 : udpSipProvider.getNewCallId();
321 327  
322 328 Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader);
323   - transmitRequest(device, request);
  329 + transmitRequest(device, request, errorEvent, okEvent);
324 330 return true;
325 331 } catch (SipException | ParseException | InvalidArgumentException e) {
326 332 e.printStackTrace();
... ... @@ -334,13 +340,15 @@ public class SIPCommander implements ISIPCommander {
334 340 * @param channelId 预览通道
335 341 * @param event hook订阅
336 342 * @param errorEvent sip错误订阅
337   - */
  343 + */
338 344 @Override
339 345 public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
340   - ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
  346 + ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
341 347 String streamId = ssrcInfo.getStream();
342 348 try {
343   - if (device == null) return;
  349 + if (device == null) {
  350 + return;
  351 + }
344 352 String streamMode = device.getStreamMode().toUpperCase();
345 353  
346 354 logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
... ... @@ -365,7 +373,7 @@ public class SIPCommander implements ISIPCommander {
365 373 content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n");
366 374 content.append("t=0 0\r\n");
367 375  
368   - if (userSetup.isSeniorSdp()) {
  376 + if (userSetting.isSeniorSdp()) {
369 377 if("TCP-PASSIVE".equals(streamMode)) {
370 378 content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
371 379 }else if ("TCP-ACTIVE".equals(streamMode)) {
... ... @@ -428,8 +436,9 @@ public class SIPCommander implements ISIPCommander {
428 436 errorEvent.response(e);
429 437 }), e ->{
430 438 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
431   - streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
  439 + streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
432 440 streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
  441 + okEvent.response(e);
433 442 });
434 443  
435 444  
... ... @@ -465,7 +474,7 @@ public class SIPCommander implements ISIPCommander {
465 474  
466 475 String streamMode = device.getStreamMode().toUpperCase();
467 476  
468   - if (userSetup.isSeniorSdp()) {
  477 + if (userSetting.isSeniorSdp()) {
469 478 if("TCP-PASSIVE".equals(streamMode)) {
470 479 content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
471 480 }else if ("TCP-ACTIVE".equals(streamMode)) {
... ... @@ -537,7 +546,7 @@ public class SIPCommander implements ISIPCommander {
537 546  
538 547 transmitRequest(device, request, errorEvent, okEvent -> {
539 548 ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
540   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction());
  549 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback);
541 550 streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
542 551 });
543 552 if (inviteStreamCallback != null) {
... ... @@ -558,8 +567,9 @@ public class SIPCommander implements ISIPCommander {
558 567 * @param downloadSpeed 下载倍速参数
559 568 */
560 569 @Override
561   - public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, InviteStreamCallback event
562   - , SipSubscribe.Event errorEvent) {
  570 + public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
  571 + String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  572 + SipSubscribe.Event errorEvent) {
563 573 try {
564 574 logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
565 575  
... ... @@ -572,11 +582,9 @@ public class SIPCommander implements ISIPCommander {
572 582 content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
573 583 +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
574 584  
575   -
576   -
577 585 String streamMode = device.getStreamMode().toUpperCase();
578 586  
579   - if (userSetup.isSeniorSdp()) {
  587 + if (userSetting.isSeniorSdp()) {
580 588 if("TCP-PASSIVE".equals(streamMode)) {
581 589 content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
582 590 }else if ("TCP-ACTIVE".equals(streamMode)) {
... ... @@ -639,15 +647,20 @@ public class SIPCommander implements ISIPCommander {
639 647 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
640 648 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
641 649 (MediaServerItem mediaServerItemInUse, JSONObject json)->{
642   - event.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  650 + hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
643 651 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
644 652 });
645 653  
646 654 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
  655 + if (inviteStreamCallback != null) {
  656 + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
  657 + }
  658 + transmitRequest(device, request, errorEvent, okEvent->{
  659 + ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
  660 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.download);
  661 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
  662 + });
647 663  
648   - ClientTransaction transaction = transmitRequest(device, request, errorEvent);
649   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
650   - streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
651 664  
652 665 } catch ( SipException | ParseException | InvalidArgumentException e) {
653 666 e.printStackTrace();
... ... @@ -683,7 +696,9 @@ public class SIPCommander implements ISIPCommander {
683 696 if (callId != null) {
684 697 dialog = streamSession.getDialogByCallId(deviceId, channelId, callId);
685 698 }else {
686   - if (stream == null) return;
  699 + if (stream == null) {
  700 + return;
  701 + }
687 702 dialog = streamSession.getDialogByStream(deviceId, channelId, stream);
688 703 }
689 704 if (ssrcTransaction != null) {
... ... @@ -718,7 +733,7 @@ public class SIPCommander implements ISIPCommander {
718 733 Request byeRequest = dialog.createRequest(Request.BYE);
719 734 SipURI byeURI = (SipURI) byeRequest.getRequestURI();
720 735 SIPRequest request = (SIPRequest)transaction.getRequest();
721   - byeURI.setHost(request.getRemoteAddress().getHostName());
  736 + byeURI.setHost(request.getRemoteAddress().getHostAddress());
722 737 byeURI.setPort(request.getRemotePort());
723 738 ViaHeader viaHeader = (ViaHeader) byeRequest.getHeader(ViaHeader.NAME);
724 739 String protocol = viaHeader.getTransport().toUpperCase();
... ... @@ -762,7 +777,8 @@ public class SIPCommander implements ISIPCommander {
762 777 public boolean audioBroadcastCmd(Device device) {
763 778 try {
764 779 StringBuffer broadcastXml = new StringBuffer(200);
765   - broadcastXml.append("<?xml version=\"1.0\" ?>\r\n");
  780 + String charset = device.getCharset();
  781 + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
766 782 broadcastXml.append("<Notify>\r\n");
767 783 broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
768 784 broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -787,7 +803,8 @@ public class SIPCommander implements ISIPCommander {
787 803 public void audioBroadcastCmd(Device device, SipSubscribe.Event errorEvent) {
788 804 try {
789 805 StringBuffer broadcastXml = new StringBuffer(200);
790   - broadcastXml.append("<?xml version=\"1.0\" ?>\r\n");
  806 + String charset = device.getCharset();
  807 + broadcastXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
791 808 broadcastXml.append("<Notify>\r\n");
792 809 broadcastXml.append("<CmdType>Broadcast</CmdType>\r\n");
793 810 broadcastXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -819,7 +836,8 @@ public class SIPCommander implements ISIPCommander {
819 836 public boolean recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) {
820 837 try {
821 838 StringBuffer cmdXml = new StringBuffer(200);
822   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  839 + String charset = device.getCharset();
  840 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
823 841 cmdXml.append("<Control>\r\n");
824 842 cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
825 843 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -854,7 +872,8 @@ public class SIPCommander implements ISIPCommander {
854 872 public boolean teleBootCmd(Device device) {
855 873 try {
856 874 StringBuffer cmdXml = new StringBuffer(200);
857   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  875 + String charset = device.getCharset();
  876 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
858 877 cmdXml.append("<Control>\r\n");
859 878 cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
860 879 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -886,7 +905,8 @@ public class SIPCommander implements ISIPCommander {
886 905 public boolean guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) {
887 906 try {
888 907 StringBuffer cmdXml = new StringBuffer(200);
889   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  908 + String charset = device.getCharset();
  909 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
890 910 cmdXml.append("<Control>\r\n");
891 911 cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
892 912 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -917,7 +937,8 @@ public class SIPCommander implements ISIPCommander {
917 937 public boolean alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) {
918 938 try {
919 939 StringBuffer cmdXml = new StringBuffer(200);
920   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  940 + String charset = device.getCharset();
  941 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
921 942 cmdXml.append("<Control>\r\n");
922 943 cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
923 944 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -961,7 +982,8 @@ public class SIPCommander implements ISIPCommander {
961 982 public boolean iFrameCmd(Device device, String channelId) {
962 983 try {
963 984 StringBuffer cmdXml = new StringBuffer(200);
964   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  985 + String charset = device.getCharset();
  986 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
965 987 cmdXml.append("<Control>\r\n");
966 988 cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
967 989 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -999,7 +1021,8 @@ public class SIPCommander implements ISIPCommander {
999 1021 public boolean homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) {
1000 1022 try {
1001 1023 StringBuffer cmdXml = new StringBuffer(200);
1002   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1024 + String charset = device.getCharset();
  1025 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1003 1026 cmdXml.append("<Control>\r\n");
1004 1027 cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n");
1005 1028 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1067,7 +1090,8 @@ public class SIPCommander implements ISIPCommander {
1067 1090 String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) {
1068 1091 try {
1069 1092 StringBuffer cmdXml = new StringBuffer(200);
1070   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1093 + String charset = device.getCharset();
  1094 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1071 1095 cmdXml.append("<Control>\r\n");
1072 1096 cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n");
1073 1097 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1120,8 +1144,9 @@ public class SIPCommander implements ISIPCommander {
1120 1144 @Override
1121 1145 public boolean deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) {
1122 1146 try {
  1147 + String charset = device.getCharset();
1123 1148 StringBuffer catalogXml = new StringBuffer(200);
1124   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1149 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1125 1150 catalogXml.append("<Query>\r\n");
1126 1151 catalogXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
1127 1152 catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1153,7 +1178,8 @@ public class SIPCommander implements ISIPCommander {
1153 1178 public boolean deviceInfoQuery(Device device) {
1154 1179 try {
1155 1180 StringBuffer catalogXml = new StringBuffer(200);
1156   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1181 + String charset = device.getCharset();
  1182 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1157 1183 catalogXml.append("<Query>\r\n");
1158 1184 catalogXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
1159 1185 catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1182,13 +1208,14 @@ public class SIPCommander implements ISIPCommander {
1182 1208 * @param device 视频设备
1183 1209 */
1184 1210 @Override
1185   - public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) {
  1211 + public boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) {
1186 1212 try {
1187 1213 StringBuffer catalogXml = new StringBuffer(200);
1188   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1214 + String charset = device.getCharset();
  1215 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1189 1216 catalogXml.append("<Query>\r\n");
1190 1217 catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
1191   - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1218 + catalogXml.append("<SN>" + sn + "</SN>\r\n");
1192 1219 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1193 1220 catalogXml.append("</Query>\r\n");
1194 1221  
... ... @@ -1224,7 +1251,8 @@ public class SIPCommander implements ISIPCommander {
1224 1251 }
1225 1252 try {
1226 1253 StringBuffer recordInfoXml = new StringBuffer(200);
1227   - recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1254 + String charset = device.getCharset();
  1255 + recordInfoXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1228 1256 recordInfoXml.append("<Query>\r\n");
1229 1257 recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
1230 1258 recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
... ... @@ -1277,7 +1305,8 @@ public class SIPCommander implements ISIPCommander {
1277 1305 String startTime, String endTime, SipSubscribe.Event errorEvent) {
1278 1306 try {
1279 1307 StringBuffer cmdXml = new StringBuffer(200);
1280   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1308 + String charset = device.getCharset();
  1309 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1281 1310 cmdXml.append("<Query>\r\n");
1282 1311 cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
1283 1312 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1327,7 +1356,8 @@ public class SIPCommander implements ISIPCommander {
1327 1356 public boolean deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) {
1328 1357 try {
1329 1358 StringBuffer cmdXml = new StringBuffer(200);
1330   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1359 + String charset = device.getCharset();
  1360 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1331 1361 cmdXml.append("<Query>\r\n");
1332 1362 cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n");
1333 1363 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1362,7 +1392,8 @@ public class SIPCommander implements ISIPCommander {
1362 1392 public boolean presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) {
1363 1393 try {
1364 1394 StringBuffer cmdXml = new StringBuffer(200);
1365   - cmdXml.append("<?xml version=\"1.0\" ?>\r\n");
  1395 + String charset = device.getCharset();
  1396 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1366 1397 cmdXml.append("<Query>\r\n");
1367 1398 cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n");
1368 1399 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1396,7 +1427,8 @@ public class SIPCommander implements ISIPCommander {
1396 1427 public boolean mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) {
1397 1428 try {
1398 1429 StringBuffer mobilePostitionXml = new StringBuffer(200);
1399   - mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1430 + String charset = device.getCharset();
  1431 + mobilePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1400 1432 mobilePostitionXml.append("<Query>\r\n");
1401 1433 mobilePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
1402 1434 mobilePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1424,30 +1456,38 @@ public class SIPCommander implements ISIPCommander {
1424 1456 * 订阅、取消订阅移动位置
1425 1457 *
1426 1458 * @param device 视频设备
1427   - * @param expires 订阅超时时间
1428   - * @param interval 上报时间间隔
1429 1459 * @return true = 命令发送成功
1430 1460 */
1431   - public boolean mobilePositionSubscribe(Device device, int expires, int interval) {
  1461 + @Override
  1462 + public boolean mobilePositionSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) {
1432 1463 try {
1433 1464 StringBuffer subscribePostitionXml = new StringBuffer(200);
1434   - subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1465 + String charset = device.getCharset();
  1466 + subscribePostitionXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1435 1467 subscribePostitionXml.append("<Query>\r\n");
1436 1468 subscribePostitionXml.append("<CmdType>MobilePosition</CmdType>\r\n");
1437 1469 subscribePostitionXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1438 1470 subscribePostitionXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1439   - if (expires > 0) {
1440   - subscribePostitionXml.append("<Interval>" + String.valueOf(interval) + "</Interval>\r\n");
  1471 + if (device.getSubscribeCycleForMobilePosition() > 0) {
  1472 + subscribePostitionXml.append("<Interval>" + String.valueOf(device.getMobilePositionSubmissionInterval()) + "</Interval>\r\n");
1441 1473 }
1442 1474 subscribePostitionXml.append("</Query>\r\n");
1443 1475  
1444   - String tm = Long.toString(System.currentTimeMillis());
1445   -
1446   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1447   - : udpSipProvider.getNewCallId();
1448   -
1449   - Request request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, expires, "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
1450   - transmitRequest(device, request);
  1476 + Request request;
  1477 + if (dialog != null) {
  1478 + logger.info("发送移动位置订阅消息时 dialog的状态为: {}", dialog.getState());
  1479 + request = dialog.createRequest(Request.SUBSCRIBE);
  1480 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  1481 + request.setContent(subscribePostitionXml.toString(), contentTypeHeader);
  1482 + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition());
  1483 + request.addHeader(expireHeader);
  1484 + }else {
  1485 + String tm = Long.toString(System.currentTimeMillis());
  1486 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1487 + : udpSipProvider.getNewCallId();
  1488 + request = headerProvider.createSubscribeRequest(device, subscribePostitionXml.toString(), "z9hG4bK-viaPos-" + tm, "fromTagPos" + tm, null, device.getSubscribeCycleForMobilePosition(), "presence" ,callIdHeader); //Position;id=" + tm.substring(tm.length() - 4));
  1489 + }
  1490 + transmitRequest(device, request, errorEvent, okEvent);
1451 1491  
1452 1492 return true;
1453 1493  
... ... @@ -1470,10 +1510,12 @@ public class SIPCommander implements ISIPCommander {
1470 1510 * @param endTime 报警发生终止时间(可选)
1471 1511 * @return true = 命令发送成功
1472 1512 */
  1513 + @Override
1473 1514 public boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
1474 1515 try {
1475 1516 StringBuffer cmdXml = new StringBuffer(200);
1476   - cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1517 + String charset = device.getCharset();
  1518 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1477 1519 cmdXml.append("<Query>\r\n");
1478 1520 cmdXml.append("<CmdType>Alarm</CmdType>\r\n");
1479 1521 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -1515,27 +1557,39 @@ public class SIPCommander implements ISIPCommander {
1515 1557 }
1516 1558  
1517 1559 @Override
1518   - public boolean catalogSubscribe(Device device, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
  1560 + public boolean catalogSubscribe(Device device, Dialog dialog, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
1519 1561 try {
1520 1562 StringBuffer cmdXml = new StringBuffer(200);
1521   - cmdXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  1563 + String charset = device.getCharset();
  1564 + cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1522 1565 cmdXml.append("<Query>\r\n");
1523 1566 cmdXml.append("<CmdType>Catalog</CmdType>\r\n");
1524 1567 cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
1525 1568 cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1526 1569 cmdXml.append("</Query>\r\n");
1527 1570  
1528   - String tm = Long.toString(System.currentTimeMillis());
1529 1571  
1530   - CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
1531   - : udpSipProvider.getNewCallId();
  1572 + Request request;
  1573 + if (dialog != null) {
  1574 + logger.info("发送目录订阅消息时 dialog的状态为: {}", dialog.getState());
  1575 + request = dialog.createRequest(Request.SUBSCRIBE);
  1576 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  1577 + request.setContent(cmdXml.toString(), contentTypeHeader);
  1578 + ExpiresHeader expireHeader = sipFactory.createHeaderFactory().createExpiresHeader(device.getSubscribeCycleForMobilePosition());
  1579 + request.addHeader(expireHeader);
  1580 + }else {
  1581 + String tm = Long.toString(System.currentTimeMillis());
1532 1582  
1533   - // 有效时间默认为60秒以上
1534   - Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm,
1535   - "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" ,
1536   - callIdHeader);
1537   - transmitRequest(device, request, errorEvent, okEvent);
  1583 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1584 + : udpSipProvider.getNewCallId();
1538 1585  
  1586 + // 有效时间默认为60秒以上
  1587 + request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), "z9hG4bK-viaPos-" + tm,
  1588 + "fromTagPos" + tm, null, device.getSubscribeCycleForCatalog(), "Catalog" ,
  1589 + callIdHeader);
  1590 +
  1591 + }
  1592 + transmitRequest(device, request, errorEvent, okEvent);
1539 1593 return true;
1540 1594  
1541 1595 } catch ( NumberFormatException | ParseException | InvalidArgumentException | SipException e) {
... ... @@ -1548,7 +1602,8 @@ public class SIPCommander implements ISIPCommander {
1548 1602 public boolean dragZoomCmd(Device device, String channelId, String cmdString) {
1549 1603 try {
1550 1604 StringBuffer dragXml = new StringBuffer(200);
1551   - dragXml.append("<?xml version=\"1.0\" ?>\r\n");
  1605 + String charset = device.getCharset();
  1606 + dragXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1552 1607 dragXml.append("<Control>\r\n");
1553 1608 dragXml.append("<CmdType>DeviceControl</CmdType>\r\n");
1554 1609 dragXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
... ... @@ -1620,7 +1675,7 @@ public class SIPCommander implements ISIPCommander {
1620 1675 content.append("PAUSE RTSP/1.0\r\n");
1621 1676 content.append("CSeq: " + cseq + "\r\n");
1622 1677 content.append("PauseTime: now\r\n");
1623   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
  1678 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
1624 1679 if (request == null) {
1625 1680 return;
1626 1681 }
... ... @@ -1651,8 +1706,10 @@ public class SIPCommander implements ISIPCommander {
1651 1706 content.append("PLAY RTSP/1.0\r\n");
1652 1707 content.append("CSeq: " + cseq + "\r\n");
1653 1708 content.append("Range: npt=now-\r\n");
1654   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1655   - if (request == null) return;
  1709 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1710 + if (request == null) {
  1711 + return;
  1712 + }
1656 1713 logger.info(request.toString());
1657 1714 ClientTransaction clientTransaction = null;
1658 1715 if ("TCP".equals(device.getTransport())) {
... ... @@ -1680,8 +1737,10 @@ public class SIPCommander implements ISIPCommander {
1680 1737 content.append("CSeq: " + cseq + "\r\n");
1681 1738 content.append("Range: npt=" + Math.abs(seekTime) + "-\r\n");
1682 1739  
1683   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1684   - if (request == null) return;
  1740 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1741 + if (request == null) {
  1742 + return;
  1743 + }
1685 1744 logger.info(request.toString());
1686 1745 ClientTransaction clientTransaction = null;
1687 1746 if ("TCP".equals(device.getTransport())) {
... ... @@ -1708,8 +1767,10 @@ public class SIPCommander implements ISIPCommander {
1708 1767 content.append("PLAY RTSP/1.0\r\n");
1709 1768 content.append("CSeq: " + cseq + "\r\n");
1710 1769 content.append("Scale: " + String.format("%.1f",speed) + "\r\n");
1711   - Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString(), cseq);
1712   - if (request == null) return;
  1770 + Request request = headerProvider.createInfoRequest(device, streamInfo, content.toString());
  1771 + if (request == null) {
  1772 + return;
  1773 + }
1713 1774 logger.info(request.toString());
1714 1775 ClientTransaction clientTransaction = null;
1715 1776 if ("TCP".equals(device.getTransport())) {
... ... @@ -1724,4 +1785,103 @@ public class SIPCommander implements ISIPCommander {
1724 1785 e.printStackTrace();
1725 1786 }
1726 1787 }
  1788 +
  1789 + @Override
  1790 + public boolean sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) {
  1791 + if (device == null) {
  1792 + return false;
  1793 + }
  1794 + logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
  1795 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  1796 + try {
  1797 + String characterSet = device.getCharset();
  1798 + StringBuffer deviceStatusXml = new StringBuffer(600);
  1799 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  1800 + deviceStatusXml.append("<Notify>\r\n");
  1801 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  1802 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1803 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  1804 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  1805 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  1806 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  1807 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  1808 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  1809 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  1810 + deviceStatusXml.append("<info>\r\n");
  1811 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  1812 + deviceStatusXml.append("</info>\r\n");
  1813 + deviceStatusXml.append("</Notify>\r\n");
  1814 +
  1815 + CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  1816 + : udpSipProvider.getNewCallId();
  1817 + String tm = Long.toString(System.currentTimeMillis());
  1818 + Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), "z9hG4bK-ViaPtz-" + tm, "FromPtz" + tm, null, callIdHeader);
  1819 + transmitRequest(device, request);
  1820 +
  1821 +
  1822 + } catch (SipException | ParseException e) {
  1823 + e.printStackTrace();
  1824 + return false;
  1825 + } catch (InvalidArgumentException e) {
  1826 + throw new RuntimeException(e);
  1827 + }
  1828 + return true;
  1829 + }
  1830 +
  1831 + private void sendNotify(Device device, String catalogXmlContent,
  1832 + SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
  1833 + throws NoSuchFieldException, IllegalAccessException, SipException, ParseException {
  1834 + MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  1835 + String characterSet = device.getCharset();
  1836 + // 设置编码, 防止中文乱码
  1837 + messageFactory.setDefaultContentEncodingCharset(characterSet);
  1838 + Dialog dialog = subscribeInfo.getDialog();
  1839 + if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
  1840 + return;
  1841 + }
  1842 + SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
  1843 + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
  1844 + notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
  1845 +
  1846 + SubscriptionStateHeader subscriptionState = sipFactory.createHeaderFactory()
  1847 + .createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
  1848 + notifyRequest.addHeader(subscriptionState);
  1849 +
  1850 + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType());
  1851 + if (subscribeInfo.getEventId() != null) {
  1852 + event.setEventId(subscribeInfo.getEventId());
  1853 + }
  1854 + notifyRequest.addHeader(event);
  1855 +
  1856 + SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
  1857 + if (subscribeInfo.getTransaction() != null) {
  1858 + SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
  1859 + sipURI.setHost(request.getRemoteAddress().getHostAddress());
  1860 + sipURI.setPort(request.getRemotePort());
  1861 + }else {
  1862 + sipURI.setHost(device.getIp());
  1863 + sipURI.setPort(device.getPort());
  1864 + }
  1865 +
  1866 + ClientTransaction transaction = null;
  1867 + if ("TCP".equals(device.getTransport())) {
  1868 + transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
  1869 + } else if ("UDP".equals(device.getTransport())) {
  1870 + transaction = udpSipProvider.getNewClientTransaction(notifyRequest);
  1871 + }
  1872 + // 添加错误订阅
  1873 + if (errorEvent != null) {
  1874 + sipSubscribe.addErrorSubscribe(subscribeInfo.getCallId(), errorEvent);
  1875 + }
  1876 + // 添加订阅
  1877 + if (okEvent != null) {
  1878 + sipSubscribe.addOkSubscribe(subscribeInfo.getCallId(), okEvent);
  1879 + }
  1880 + if (transaction == null) {
  1881 + logger.error("平台{}的Transport错误:{}",device.getDeviceId(), device.getTransport());
  1882 + return;
  1883 + }
  1884 + dialog.sendRequest(transaction);
  1885 +
  1886 + }
1727 1887 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
... ... @@ -32,6 +32,7 @@ import javax.sip.header.*;
32 32 import javax.sip.message.Request;
33 33 import java.lang.reflect.Field;
34 34 import java.text.ParseException;
  35 +import java.util.ArrayList;
35 36 import java.util.HashSet;
36 37 import java.util.List;
37 38 import java.util.UUID;
... ... @@ -145,9 +146,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
145 146 public String keepalive(ParentPlatform parentPlatform) {
146 147 String callId = null;
147 148 try {
148   -
  149 + String characterSet = parentPlatform.getCharacterSet();
149 150 StringBuffer keepaliveXml = new StringBuffer(200);
150   - keepaliveXml.append("<?xml version=\"1.0\"?>\r\n");
  151 + keepaliveXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
151 152 keepaliveXml.append("<Notify>\r\n");
152 153 keepaliveXml.append("<CmdType>Keepalive</CmdType>\r\n");
153 154 keepaliveXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -215,56 +216,110 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
215 216 return false;
216 217 }
217 218 try {
218   - StringBuffer catalogXml = new StringBuffer(600);
219   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
220   - catalogXml.append("<Response>\r\n");
221   - catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
222   - catalogXml.append("<SN>" +sn + "</SN>\r\n");
223   - catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
224   - catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");
225   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
226   - catalogXml.append("<Item>\r\n");
  219 + List<DeviceChannel> channels = new ArrayList<>();
227 220 if (channel != null) {
  221 + channels.add(channel);
  222 + }
  223 + String catalogXml = getCatalogXml(channels, sn, parentPlatform, size);
  224 +
  225 + // callid
  226 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  227 + : udpSipProvider.getNewCallId();
  228 +
  229 + Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, callIdHeader);
  230 + transmitRequest(parentPlatform, request);
  231 +
  232 + } catch (SipException | ParseException | InvalidArgumentException e) {
  233 + e.printStackTrace();
  234 + return false;
  235 + }
  236 + return true;
  237 + }
  238 +
  239 + @Override
  240 + public boolean catalogQuery(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag) {
  241 + if ( parentPlatform ==null) {
  242 + return false;
  243 + }
  244 + sendCatalogResponse(channels, parentPlatform, sn, fromTag, 0);
  245 + return true;
  246 + }
  247 + private String getCatalogXml(List<DeviceChannel> channels, String sn, ParentPlatform parentPlatform, int size) {
  248 + String characterSet = parentPlatform.getCharacterSet();
  249 + StringBuffer catalogXml = new StringBuffer(600);
  250 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet +"\"?>\r\n");
  251 + catalogXml.append("<Response>\r\n");
  252 + catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
  253 + catalogXml.append("<SN>" +sn + "</SN>\r\n");
  254 + catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
  255 + catalogXml.append("<SumNum>" + size + "</SumNum>\r\n");
  256 + catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
  257 + if (channels.size() > 0) {
  258 + for (DeviceChannel channel : channels) {
  259 + catalogXml.append("<Item>\r\n");
228 260 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
229 261 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
230   - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
231   - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
232   - catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
233   - catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
234   - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
235 262 catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
236 263 if (channel.getParentId() != null) {
237 264 catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
238 265 }
239   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
240   - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
241   - catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
242   - catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
243   - catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
244   - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
245   - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
246   - catalogXml.append("<Info>\r\n");
247   - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
248   - catalogXml.append("</Info>\r\n");
249   - }
  266 + if (channel.getChannelId().length() == 20) {
  267 + if (Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织增加BusinessGroupID字段
  268 + catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
  269 + }
  270 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  271 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  272 + catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
  273 + if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下字段
  274 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  275 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  276 + catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
  277 + catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
  278 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  279 + catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
  280 + catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n");
  281 + catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
  282 + catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
  283 + catalogXml.append("<Info>\r\n");
  284 + catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
  285 + catalogXml.append("</Info>\r\n");
  286 + }
  287 + }
250 288  
251 289  
252   - catalogXml.append("</Item>\r\n");
253   - catalogXml.append("</DeviceList>\r\n");
254   - catalogXml.append("</Response>\r\n");
  290 + catalogXml.append("</Item>\r\n");
  291 + }
  292 + }
  293 +
  294 + catalogXml.append("</DeviceList>\r\n");
  295 + catalogXml.append("</Response>\r\n");
  296 + return catalogXml.toString();
  297 + }
255 298  
  299 + private void sendCatalogResponse(List<DeviceChannel> channels, ParentPlatform parentPlatform, String sn, String fromTag, int index) {
  300 + if (index >= channels.size()) {
  301 + return;
  302 + }
  303 + try {
  304 + List<DeviceChannel> deviceChannels;
  305 + if (index + parentPlatform.getCatalogGroup() < channels.size()) {
  306 + deviceChannels = channels.subList(index, index + parentPlatform.getCatalogGroup());
  307 + }else {
  308 + deviceChannels = channels.subList(index, channels.size());
  309 + }
  310 + String catalogXml = getCatalogXml(deviceChannels, sn, parentPlatform, channels.size());
256 311 // callid
257 312 CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
258 313 : udpSipProvider.getNewCallId();
259 314  
260   - Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml.toString(), fromTag, callIdHeader);
261   - transmitRequest(parentPlatform, request);
262   -
  315 + Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, catalogXml, fromTag, callIdHeader);
  316 + transmitRequest(parentPlatform, request, null, eventResult -> {
  317 + int indexNext = index + parentPlatform.getCatalogGroup();
  318 + sendCatalogResponse(channels, parentPlatform, sn, fromTag, indexNext);
  319 + });
263 320 } catch (SipException | ParseException | InvalidArgumentException e) {
264 321 e.printStackTrace();
265   - return false;
266 322 }
267   - return true;
268 323 }
269 324  
270 325 /**
... ... @@ -280,8 +335,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
280 335 return false;
281 336 }
282 337 try {
  338 + String characterSet = parentPlatform.getCharacterSet();
283 339 StringBuffer deviceInfoXml = new StringBuffer(600);
284   - deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  340 + deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
285 341 deviceInfoXml.append("<Response>\r\n");
286 342 deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
287 343 deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
... ... @@ -319,8 +375,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
319 375 return false;
320 376 }
321 377 try {
  378 + String characterSet = parentPlatform.getCharacterSet();
322 379 StringBuffer deviceStatusXml = new StringBuffer(600);
323   - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  380 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
324 381 deviceStatusXml.append("<Response>\r\n");
325 382 deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
326 383 deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
... ... @@ -348,10 +405,11 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
348 405 if (parentPlatform == null) {
349 406 return false;
350 407 }
351   -
  408 + logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
352 409 try {
  410 + String characterSet = parentPlatform.getCharacterSet();
353 411 StringBuffer deviceStatusXml = new StringBuffer(600);
354   - deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  412 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
355 413 deviceStatusXml.append("<Notify>\r\n");
356 414 deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
357 415 deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
... ... @@ -368,7 +426,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
368 426 : udpSipProvider.getNewCallId();
369 427 callIdHeader.setCallId(subscribeInfo.getCallId());
370 428  
371   -//
372 429 sendNotify(parentPlatform, deviceStatusXml.toString(), subscribeInfo, eventResult -> {
373 430 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
374 431 }, null);
... ... @@ -385,6 +442,48 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
385 442 }
386 443  
387 444 @Override
  445 + public boolean sendAlarmMessage(ParentPlatform parentPlatform, DeviceAlarm deviceAlarm) {
  446 + if (parentPlatform == null) {
  447 + return false;
  448 + }
  449 + logger.info("[发送 报警订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
  450 + deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
  451 + try {
  452 + String characterSet = parentPlatform.getCharacterSet();
  453 + StringBuffer deviceStatusXml = new StringBuffer(600);
  454 + deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
  455 + deviceStatusXml.append("<Notify>\r\n");
  456 + deviceStatusXml.append("<CmdType>Alarm</CmdType>\r\n");
  457 + deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  458 + deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
  459 + deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
  460 + deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
  461 + deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n");
  462 + deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
  463 + deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
  464 + deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
  465 + deviceStatusXml.append("<info>\r\n");
  466 + deviceStatusXml.append("<AlarmType>" + deviceAlarm.getAlarmType() + "</AlarmType>\r\n");
  467 + deviceStatusXml.append("</info>\r\n");
  468 + deviceStatusXml.append("</Notify>\r\n");
  469 +
  470 + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
  471 + : udpSipProvider.getNewCallId();
  472 +
  473 + String tm = Long.toString(System.currentTimeMillis());
  474 + Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), "FromPtz" + tm, callIdHeader);
  475 + transmitRequest(parentPlatform, request);
  476 +
  477 + } catch (SipException | ParseException e) {
  478 + e.printStackTrace();
  479 + return false;
  480 + } catch (InvalidArgumentException e) {
  481 + throw new RuntimeException(e);
  482 + }
  483 + return true;
  484 + }
  485 +
  486 + @Override
388 487 public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) {
389 488 if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
390 489 return false;
... ... @@ -395,13 +494,21 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
395 494 if (index >= deviceChannels.size()) {
396 495 return true;
397 496 }
  497 + List<DeviceChannel> channels;
  498 + if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
  499 + channels = deviceChannels.subList(index, index + parentPlatform.getCatalogGroup());
  500 + }else {
  501 + channels = deviceChannels.subList(index, deviceChannels.size());
  502 + }
398 503 try {
399 504 Integer finalIndex = index;
400   - String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index ), deviceChannels.size(), type, subscribeInfo);
  505 + String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
  506 + deviceChannels.size(), type, subscribeInfo);
401 507 sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
402 508 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
403 509 }, (eventResult -> {
404   - sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex + 1);
  510 + sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo,
  511 + finalIndex + parentPlatform.getCatalogGroup());
405 512 }));
406 513 } catch (SipException | ParseException e) {
407 514 e.printStackTrace();
... ... @@ -418,10 +525,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
418 525 SubscribeInfo subscribeInfo, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent )
419 526 throws NoSuchFieldException, IllegalAccessException, SipException, ParseException {
420 527 MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
  528 + String characterSet = parentPlatform.getCharacterSet();
421 529 // 设置编码, 防止中文乱码
422   - messageFactory.setDefaultContentEncodingCharset("gb2312");
  530 + messageFactory.setDefaultContentEncodingCharset(characterSet);
423 531 Dialog dialog = subscribeInfo.getDialog();
424   - if (dialog == null) return;
  532 + if (dialog == null || !dialog.getState().equals(DialogState.CONFIRMED)) {
  533 + return;
  534 + }
425 535 SIPRequest notifyRequest = (SIPRequest)dialog.createRequest(Request.NOTIFY);
426 536 ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml");
427 537 notifyRequest.setContent(catalogXmlContent, contentTypeHeader);
... ... @@ -435,11 +545,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
435 545 event.setEventId(subscribeInfo.getEventId());
436 546 }
437 547 notifyRequest.addHeader(event);
438   -
439 548 SipURI sipURI = (SipURI) notifyRequest.getRequestURI();
440   - SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
441   - sipURI.setHost(request.getRemoteAddress().getHostName());
442   - sipURI.setPort(request.getRemotePort());
  549 + if (subscribeInfo.getTransaction() != null) {
  550 + SIPRequest request = (SIPRequest) subscribeInfo.getTransaction().getRequest();
  551 + sipURI.setHost(request.getRemoteAddress().getHostAddress());
  552 + sipURI.setPort(request.getRemotePort());
  553 + }else {
  554 + sipURI.setHost(parentPlatform.getServerIP());
  555 + sipURI.setPort(parentPlatform.getServerPort());
  556 + }
  557 +
443 558 ClientTransaction transaction = null;
444 559 if ("TCP".equals(parentPlatform.getTransport())) {
445 560 transaction = tcpSipProvider.getNewClientTransaction(notifyRequest);
... ... @@ -462,52 +577,48 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
462 577  
463 578 }
464 579  
465   -// private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type,
466   -// SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException,
467   -// PeerUnavailableException, NoSuchFieldException, IllegalAccessException {
468   -// String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo);
469   -//
470   -// CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
471   -// : udpSipProvider.getNewCallId();
472   -// callIdHeader.setCallId(subscribeInfo.getCallId());
473   -// String tm = Long.toString(System.currentTimeMillis());
474   -//
475   -// Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent,
476   -// callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""),"FromRegister" + tm, subscribeInfo);
477   -// return request;
478   -// }
479   -
480   - private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) {
  580 + private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
481 581 StringBuffer catalogXml = new StringBuffer(600);
482   - if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
483   - channel.setParentId(parentPlatform.getDeviceGBId());
484   - }
485   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  582 +
  583 + String characterSet = parentPlatform.getCharacterSet();
  584 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
486 585 catalogXml.append("<Notify>\r\n");
487 586 catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
488 587 catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
489 588 catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
490 589 catalogXml.append("<SumNum>1</SumNum>\r\n");
491   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
492   - catalogXml.append("<Item>\r\n");
493   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
494   - catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
495   - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
496   - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
497   - catalogXml.append("<Owner>0</Owner>\r\n");
498   - catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
499   - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
500   - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
501   - if (channel.getParentId() != null) {
502   - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
503   - }
504   - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
505   - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
506   - catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
507   - if (!"presence".equals(subscribeInfo.getEventType())) {
508   - catalogXml.append("<Event>" + type + "</Event>\r\n");
509   - }
510   - catalogXml.append("</Item>\r\n");
  590 + catalogXml.append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
  591 + if (channels.size() > 0) {
  592 + for (DeviceChannel channel : channels) {
  593 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  594 + channel.setParentId(parentPlatform.getDeviceGBId());
  595 + }
  596 + catalogXml.append("<Item>\r\n");
  597 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  598 + catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
  599 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  600 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  601 + if (channel.getParentId() != null) {
  602 + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
  603 + }
  604 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  605 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  606 + catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
  607 + if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织增加BusinessGroupID字段
  608 + catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
  609 + }
  610 + if (channel.getChannelType() == 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
  611 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  612 + catalogXml.append("<Owner>0</Owner>\r\n");
  613 + catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
  614 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  615 + }
  616 + if (!"presence".equals(subscribeInfo.getEventType())) {
  617 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  618 + }
  619 + catalogXml.append("</Item>\r\n");
  620 + }
  621 + }
511 622 catalogXml.append("</DeviceList>\r\n");
512 623 catalogXml.append("</Notify>\r\n");
513 624 return catalogXml.toString();
... ... @@ -529,13 +640,20 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
529 640 if (index >= deviceChannels.size()) {
530 641 return true;
531 642 }
  643 + List<DeviceChannel> channels;
  644 + if (index + parentPlatform.getCatalogGroup() < deviceChannels.size()) {
  645 + channels = deviceChannels.subList(index, index + parentPlatform.getCatalogGroup());
  646 + }else {
  647 + channels = deviceChannels.subList(index, deviceChannels.size());
  648 + }
532 649 try {
533 650 Integer finalIndex = index;
534   - String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, deviceChannels.get(index), type);
  651 + String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
535 652 sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
536 653 logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
537 654 }, (eventResult -> {
538   - sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex + 1);
  655 + sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo,
  656 + finalIndex + parentPlatform.getCatalogGroup());
539 657 }));
540 658 } catch (SipException e) {
541 659 e.printStackTrace();
... ... @@ -550,22 +668,28 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
550 668 return true;
551 669 }
552 670  
553   - private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, DeviceChannel channel, String type) {
554   - if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
555   - channel.setParentId(parentPlatform.getDeviceGBId());
556   - }
  671 + private String getCatalogXmlContentForCatalogOther(ParentPlatform parentPlatform, List<DeviceChannel> channels, String type) {
  672 +
  673 + String characterSet = parentPlatform.getCharacterSet();
557 674 StringBuffer catalogXml = new StringBuffer(600);
558   - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  675 + catalogXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
559 676 catalogXml.append("<Notify>\r\n");
560 677 catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
561 678 catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n");
562 679 catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n");
563 680 catalogXml.append("<SumNum>1</SumNum>\r\n");
564   - catalogXml.append("<DeviceList Num=\"1\">\r\n");
565   - catalogXml.append("<Item>\r\n");
566   - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
567   - catalogXml.append("<Event>" + type + "</Event>\r\n");
568   - catalogXml.append("</Item>\r\n");
  681 + catalogXml.append("<DeviceList Num=\" " + channels.size() + " \">\r\n");
  682 + if (channels.size() > 0) {
  683 + for (DeviceChannel channel : channels) {
  684 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  685 + channel.setParentId(parentPlatform.getDeviceGBId());
  686 + }
  687 + catalogXml.append("<Item>\r\n");
  688 + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
  689 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  690 + catalogXml.append("</Item>\r\n");
  691 + }
  692 + }
569 693 catalogXml.append("</DeviceList>\r\n");
570 694 catalogXml.append("</Notify>\r\n");
571 695 return catalogXml.toString();
... ... @@ -576,8 +700,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
576 700 return false;
577 701 }
578 702 try {
  703 + String characterSet = parentPlatform.getCharacterSet();
579 704 StringBuffer recordXml = new StringBuffer(600);
580   - recordXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
  705 + recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
581 706 recordXml.append("<Response>\r\n");
582 707 recordXml.append("<CmdType>RecordInfo</CmdType>\r\n");
583 708 recordXml.append("<SN>" +recordInfo.getSn() + "</SN>\r\n");
... ... @@ -661,7 +786,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
661 786  
662 787 SipURI byeURI = (SipURI) byeRequest.getRequestURI();
663 788 SIPRequest request = (SIPRequest) clientTransaction.getRequest();
664   - byeURI.setHost(request.getRemoteAddress().getHostName());
  789 + byeURI.setHost(request.getRemoteAddress().getHostAddress());
665 790 byeURI.setPort(request.getRemotePort());
666 791 if ("TCP".equals(platform.getTransport())) {
667 792 clientTransaction = tcpSipProvider.getNewClientTransaction(byeRequest);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
... ... @@ -139,7 +139,9 @@ public abstract class SIPRequestProcessorParent {
139 139 serverTransaction.sendResponse(response);
140 140 if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) {
141 141  
142   - if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
  142 + if (serverTransaction.getDialog() != null) {
  143 + serverTransaction.getDialog().delete();
  144 + }
143 145 }
144 146 }
145 147  
... ... @@ -149,7 +151,9 @@ public abstract class SIPRequestProcessorParent {
149 151 ServerTransaction serverTransaction = getServerTransaction(evt);
150 152 serverTransaction.sendResponse(response);
151 153 if (statusCode >= 200 && !"NOTIFY".equals(evt.getRequest().getMethod())) {
152   - if (serverTransaction.getDialog() != null) serverTransaction.getDialog().delete();
  154 + if (serverTransaction.getDialog() != null) {
  155 + serverTransaction.getDialog().delete();
  156 + }
153 157 }
154 158 }
155 159  
... ... @@ -215,7 +219,9 @@ public abstract class SIPRequestProcessorParent {
215 219 return getRootElement(evt, "gb2312");
216 220 }
217 221 public Element getRootElement(RequestEvent evt, String charset) throws DocumentException {
218   - if (charset == null) charset = "gb2312";
  222 + if (charset == null) {
  223 + charset = "gb2312";
  224 + }
219 225 Request request = evt.getRequest();
220 226 SAXReader reader = new SAXReader();
221 227 reader.setEncoding(charset);
... ...