From 8b0ff3767b23f9479a0b3ebe8e343ed6470bd194 Mon Sep 17 00:00:00 2001
From: 648540858 <648540858@qq.com>
Date: 星期二, 09 八月 2022 14:41:21 +0800
Subject: [PATCH] Merge branch 'wvp-28181-2.0'

---
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java                                                                 |   14 
 doc/_content/theory/_media/img_8.png                                                                                                   |    0 
 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java                                                                 |   59 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java                           |   10 
 doc/_content/ability/_media/img_9.png                                                                                                  |    0 
 doc/_sidebar.md                                                                                                                        |   33 
 src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java                                                 |    6 
 src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java                                                                       |    7 
 src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java                                          |   16 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java                                                              |   50 
 doc/_media/weixin.jpg                                                                                                                  |    0 
 doc/_content/ability/_media/img_13.png                                                                                                 |    0 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                                                                  |   45 
 src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java                                                                              |    9 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java           |    2 
 doc/_media/zhifubao.jpg                                                                                                                |    0 
 doc/_content/theory/_media/img_1.png                                                                                                   |    0 
 web_src/src/components/dialog/chooseChannelForStream.vue                                                                               |    1 
 doc/_content/skill/_media/img.png                                                                                                      |    0 
 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java                                                                 |   72 
 doc/_content/ability/user.md                                                                                                           |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java                       |    1 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java                                                            |  120 
 web_src/src/components/dialog/changePasswordForAdmin.vue                                                                               |  121 +
 doc/_content/qa/_media/img_1.png                                                                                                       |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java                                                        |   52 
 pom.xml                                                                                                                                |   18 
 doc/_content/ability/_media/img_16.png                                                                                                 |    0 
 doc/_content/ability/_media/cascade1.png                                                                                               |    0 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java                                                                |   86 
 src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java                                                         |  342 --
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java                                                                        |   23 
 doc/_content/ability/_media/img_6.png                                                                                                  |    0 
 doc/_content/donation.md                                                                                                               |    7 
 doc/README.md                                                                                                                          |  102 
 doc/_content/introduction/deployment.md                                                                                                |   36 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java                                                  |    4 
 doc/_content/theory/register.md                                                                                                        |   21 
 web_src/src/components/UserManager.vue                                                                                                 |  236 ++
 src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java                                                                       |    1 
 web_src/src/components/ParentPlatformList.vue                                                                                          |    2 
 doc/_content/ability/_media/img_2.png                                                                                                  |    0 
 doc/_content/theory/_media/img_4.png                                                                                                   |    0 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java                                                                 |   54 
 doc/_content/qa/_media/img_5.png                                                                                                       |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java                                             |   72 
 src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java                                                              |   34 
 web_src/src/components/dialog/changePushKey.vue                                                                                        |  102 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java                                                        |   29 
 doc/_content/ability/_media/img_10.png                                                                                                 |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java              |   44 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java                                                           |    6 
 doc/_content/theory/_media/img_7.png                                                                                                   |    0 
 doc/index.html                                                                                                                         |   59 
 web_src/src/components/Login.vue                                                                                                       |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java                                       |    2 
 sql/mysql.sql                                                                                                                          |  783 ++++---
 src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java                                            |   18 
 doc/_content/ability/device_use.md                                                                                                     |   35 
 doc/_content/ability/_media/img_8.png                                                                                                  |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java                              |    1 
 doc/_content/ability/cascade.md                                                                                                        |   34 
 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java                                                                  |    4 
 doc/_content/ability/_media/img_14.png                                                                                                 |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java                                    |  101 
 src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java                                                                        |    3 
 doc/_content/ability/proxy.md                                                                                                          |   24 
 web_src/src/router/index.js                                                                                                            |    6 
 src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java                                                                   |   40 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java                                                            |   33 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java                                                                       |   16 
 src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java                                                                    |   39 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java                                                                         |   10 
 doc/_content/qa/bug.md                                                                                                                 |   19 
 doc/_content/skill/_media/img_2.png                                                                                                    |    0 
 web_src/src/components/PushVideoList.vue                                                                                               |   44 
 src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java                                                   |   13 
 src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java                                                                  |    8 
 doc/_content/theory/_media/img_3.png                                                                                                   |    0 
 src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java                                                               |   22 
 doc/_content/qa/start_error.md                                                                                                         |   24 
 web_src/src/components/dialog/devicePlayer.vue                                                                                         |    2 
 doc/_content/qa/img.png                                                                                                                |    0 
 doc/_content/ability/_media/cascade4.png                                                                                               |    0 
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java                                                           |    1 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java     |    1 
 doc/_content/introduction/compile.md                                                                                                   |   95 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java                                                                           |   40 
 src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java                                                                         |  227 +
 doc/_content/ability/_media/img_3.png                                                                                                  |    0 
 doc/_content/qa/_media/img_4.png                                                                                                       |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java                                                                   |   27 
 src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java                                                             |    9 
 src/main/resources/all-application.yml                                                                                                 |    2 
 doc/_content/qa/_media/img.png                                                                                                         |    0 
 src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java                                                              |   16 
 doc/_navbar.md                                                                                                                         |    1 
 web_src/src/components/channelList.vue                                                                                                 |    5 
 doc/_content/about_doc.md                                                                                                              |    5 
 doc/_content/qa/play_error.md                                                                                                          |   57 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java                                                                  |   36 
 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java                                                              |   13 
 web_src/src/components/dialog/chooseChannelForCatalog.vue                                                                              |    5 
 web_src/src/components/dialog/pushStreamEdit.vue                                                                                       |   79 
 doc/_content/theory/channel_tree.md                                                                                                    |   14 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java            |   76 
 doc/_content/disclaimers.md                                                                                                            |    2 
 web_src/src/components/dialog/SyncChannelProgress.vue                                                                                  |   43 
 doc/_content/theory/_media/img_6.png                                                                                                   |    0 
 src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java                                                                   |    5 
 src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java                                                                              |    1 
 doc/_media/favicon.ico                                                                                                                 |    0 
 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java                                                           |   94 
 doc/_content/ability/online_doc.md                                                                                                     |    2 
 web_src/src/components/dialog/platformEdit.vue                                                                                         |   69 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java                                                           |   14 
 src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java                                                                   |    5 
 doc/_content/ability/_media/img_7.png                                                                                                  |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java                                                  |   41 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java                                  |    1 
 doc/_content/qa/regiser_error.md                                                                                                       |    8 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java                                                       |  106 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java                                                 |  115 +
 doc/_content/ability/_media/img_15.png                                                                                                 |    0 
 doc/_content/ability/cloud_record.md                                                                                                   |    8 
 doc/_content/introduction/_media/img_2.png                                                                                             |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java     |   42 
 src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java                                                                 |   35 
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java                                                         |  165 +
 bootstrap.sh                                                                                                                           |    0 
 doc/_content/introduction/_media/img.png                                                                                               |    0 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java                                                    |   43 
 src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java                                                                  |   16 
 doc/_media/logo.png                                                                                                                    |    0 
 doc/_content/ability/_media/cascade3.png                                                                                               |    0 
 doc/_content/ability/continuous_recording.md                                                                                           |   14 
 web_src/src/components/dialog/addUser.vue                                                                                              |  159 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java                                |    6 
 doc/_content/theory/_media/img_2.png                                                                                                   |    0 
 src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java                                                            |   13 
 doc/_content/ability/auto_play.md                                                                                                      |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java              |   76 
 web_src/static/file/推流通道导入.zip                                                                                                         |    0 
 src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java                                                                              |    2 
 doc/_content/qa/_media/img_3.png                                                                                                       |    0 
 src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java                                                                   |    2 
 doc/_content/ability/_media/img_18.png                                                                                                 |    0 
 doc/_content/ability/cascade2.md                                                                                                       |   18 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java        |    9 
 doc/_content/ability/_media/img_4.png                                                                                                  |    0 
 doc/_content/skill/_media/img_1.png                                                                                                    |    0 
 doc/_content/theory/img.png                                                                                                            |    0 
 doc/_content/ability/_media/img.png                                                                                                    |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java                                                                       |   11 
 web_src/src/components/control.vue                                                                                                     |  102 
 doc/_content/ability/_media/img_11.png                                                                                                 |    0 
 src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java                                                                  |   69 
 doc/_content/ability/device.md                                                                                                         |   36 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java |   41 
 src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java                                                                      |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java                                                                      |    8 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java                                                      |   44 
 doc/_content/ability/_media/img_1.png                                                                                                  |    0 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java                                                                  |   28 
 src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java                                                              |    5 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java                                                                  |   35 
 doc/_content/ability/push.md                                                                                                           |   41 
 src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java                                                      |   54 
 src/main/java/com/genersoft/iot/vmp/service/IUserService.java                                                                          |    5 
 README.md                                                                                                                              |    4 
 web_src/src/components/dialog/chooseChannel.vue                                                                                        |    6 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java                                                  |   35 
 doc/_content/theory/_media/img_9.png                                                                                                   |    0 
 web_src/src/layout/UiHeader.vue                                                                                                        |    3 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java                                                                 |  162 -
 sql/update.sql                                                                                                                         |   18 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java                                    |  155 
 doc/_content/ability/node_manger.md                                                                                                    |    9 
 web_src/src/components/dialog/catalogEdit.vue                                                                                          |   37 
 doc/_content/ability/_media/img_5.png                                                                                                  |    0 
 doc/_content/qa/development.md                                                                                                         |   15 
 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java                                                                 |    4 
 doc/_content/introduction/_media/img_1.png                                                                                             |    0 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java                                                           |   20 
 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java                                                           |   21 
 doc/_content/theory/code.md                                                                                                            |   25 
 doc/_content/qa/_media/img_2.png                                                                                                       |    0 
 doc/_content/ability/_media/img_17.png                                                                                                 |    0 
 doc/_content/skill/tcpdump.md                                                                                                          |   62 
 doc/_content/ability/gis.md                                                                                                            |   37 
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java                                                                |   60 
 doc/_content/theory/_media/img.png                                                                                                     |    0 
 doc/_content/theory/_media/img_5.png                                                                                                   |    0 
 doc/_coverpage.md                                                                                                                      |   17 
 doc/_content/ability/_media/img_12.png                                                                                                 |    0 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java                                                   |   44 
 doc/_content/theory/play.md                                                                                                            |   33 
 doc/_media/logo-mini.png                                                                                                               |    0 
 web_src/static/js/jessibuca/decoder.wasm                                                                                               |    0 
 /dev/null                                                                                                                              |   38 
 web_src/src/components/common/jessibuca.vue                                                                                            |   14 
 doc/_content/introduction/config.md                                                                                                    |  119 +
 doc/_content/ability/_media/cascade2.png                                                                                               |    0 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java                                                           |  117 
 204 files changed, 4,646 insertions(+), 1,896 deletions(-)

diff --git a/README.md b/README.md
index 1c5f868..1c131bf 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 ![logo](https://raw.githubusercontent.com/648540858/wvp-GB28181-pro/wvp-28181-2.0/web_src/static/logo.png)
-# 寮�绠卞嵆鐢ㄧ殑鐨�28181鍗忚瑙嗛骞冲彴
+# 寮�绠卞嵆鐢ㄧ殑28181鍗忚瑙嗛骞冲彴
 
 [![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit)
 [![license](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/xia-chu/ZLMediaKit/blob/master/LICENSE)
@@ -25,7 +25,7 @@
 鏃ㄥ湪鎵撻�犱竴涓槗閰嶇疆,鏄撲娇鐢�,渚夸簬缁存姢鐨�28181鍥芥爣淇′护绯荤粺, 渚濇墭浼樼鐨勫紑婧愭祦濯掍綋鏈嶅姟妗嗘灦ZLMediaKit, 瀹炵幇涓�涓畬鏁存槗鐢℅B28181骞冲彴. 
 
 # 閮ㄧ讲鏂囨。
-[https://github.com/648540858/wvp-GB28181-pro/wiki](https://github.com/648540858/wvp-GB28181-pro/wiki)
+[doc.wvp-pro.cn](https://doc.wvp-pro.cn)
 
 # gitee鍚屾浠撳簱
 https://gitee.com/pan648540858/wvp-GB28181-pro.git
diff --git a/bootstrap.sh b/bootstrap.sh
old mode 100755
new mode 100644
diff --git a/doc/README.md b/doc/README.md
new file mode 100644
index 0000000..635a4a5
--- /dev/null
+++ b/doc/README.md
@@ -0,0 +1,102 @@
+# 浠嬬粛
+
+> 寮�绠卞嵆鐢ㄧ殑28181鍗忚瑙嗛骞冲彴
+
+# 姒傝堪
+- WVP-PRO鍩轰簬GB/T 28181-2016鏍囧噯瀹炵幇鐨勬祦濯掍綋骞冲彴锛屼緷鎵樹紭绉�鐨勫紑婧愭祦濯掍綋鏈嶅姟[ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)锛屾彁渚涘畬鍠勪赴瀵岀殑鍔熻兘銆�
+- GB/T 28181-2016 涓枃鏍囧噯鍚嶇О鏄�婂叕鍏卞畨鍏ㄨ棰戠洃鎺ц仈缃戠郴缁熶俊鎭紶杈撱�佷氦鎹€�佹帶鍒舵妧鏈姹傘�嬫槸鐩戞帶棰嗗煙鐨勫浗瀹舵爣鍑嗐�傚ぇ閲忓簲鐢ㄤ簬鏀垮簻瑙嗛骞冲彴銆�
+- 閫氳繃28181鍗忚浣犲彲浠ュ皢IPC鎽勫儚澶存帴鍏ュ钩鍙帮紝鍙互瑙傜湅涔熷彲浠ヤ娇鐢�28181/rtsp/rtmp/flv绛夊崗璁皢瑙嗛娴佸垎鍙戝埌鍏朵粬骞冲彴銆�
+
+# 鐗规��
+- 瀹炵幇鏍囧噯鐨�28181淇′护锛屽吋瀹瑰父瑙佺殑鍝佺墝璁惧锛屾瘮濡傛捣搴枫�佸ぇ鍗庛�佸畤瑙嗙瓑鍝佺墝鐨処PC銆丯VR浠ュ強骞冲彴銆�
+- 鏀寔灏嗗浗鏍囪澶囩骇鑱斿埌鍏朵粬鍥芥爣骞冲彴锛屼篃鏀寔灏嗕笉鏀寔鍥芥爣鐨勮澶囩殑鍥惧儚鎴栬�呯洿鎾帹閫佸埌鍏朵粬鍥芥爣骞冲彴
+- 鍓嶇瀹屽杽锛岃嚜甯﹀畬鏁村墠绔〉闈紝鏃犻渶浜屾寮�鍙戝彲鐩存帴閮ㄧ讲浣跨敤銆�
+- 瀹屽叏寮�婧愶紝涓斾娇鐢∕IT璁稿彲鍗忚銆備繚鐣欑増鏉冪殑鎯呭喌涓嬪彲浠ョ敤浜庡晢涓氶」鐩��
+- 鏀寔澶氭祦濯掍綋鑺傜偣璐熻浇鍧囪 銆�
+
+# 鎴戜滑瀹炵幇浜嗗摢浜涘浗鏍囧姛鑳�
+**浣滀负涓婄骇骞冲彴**
+- [X] 娉ㄥ唽
+- [X] 娉ㄩ攢
+- [X] 瀹炴椂瑙嗛煶棰戠偣鎾�
+- [X] 璁惧鎺у埗
+  - [X] 浜戝彴鎺у埗
+  - [ ] 杩滅▼鍚姩
+  - [ ] 褰曞儚鎺у埗
+  - [ ] 鎶ヨ甯冮槻/鎾ら槻
+  - [ ] 鎶ヨ澶嶄綅
+  - [X] 寮哄埗鍏抽敭甯�
+  - [ ] 鎷夋鏀惧ぇ
+  - [ ] 鎷夋缂╁皬
+  - [ ] 鐪嬪畧浣嶆帶鍒�
+  - [ ] 璁惧閰嶇疆
+- [X] 鎶ヨ浜嬩欢閫氱煡鍜屽垎鍙�
+- [X] 璁惧鐩綍璁㈤槄
+- [X] 缃戠粶璁惧淇℃伅鏌ヨ
+  - [X] 璁惧鐩綍鏌ヨ
+  - [X] 璁惧鐘舵�佹煡璇�
+  - [ ] 璁惧閰嶇疆鏌ヨ
+  - [ ] 璁惧棰勭疆浣嶆煡璇�
+- [X] 鐘舵�佷俊鎭姤閫�
+- [X] 璁惧瑙嗛煶棰戞枃浠舵绱�
+- [X] 鍘嗗彶瑙嗛煶棰戠殑鍥炴斁
+  - [X] 鎾斁
+  - [X] 鏆傚仠
+  - [X] 杩�/閫�
+  - [X] 鍋滄
+- [X] 瑙嗛煶棰戞枃浠朵笅杞�
+- [X] 鏍℃椂
+- [X] 璁㈤槄鍜岄�氱煡
+  - [X] 浜嬩欢璁㈤槄
+    - [X] 绉诲姩璁惧浣嶇疆璁㈤槄
+    - [X] 鎶ヨ璁㈤槄
+    - [X] 鐩綍璁㈤槄
+- [ ] 璇煶骞挎挱
+- [ ] 璇煶瀵硅
+
+**浣滀负涓嬬骇骞冲彴**
+- [X] 娉ㄥ唽
+- [X] 娉ㄩ攢
+- [X] 瀹炴椂瑙嗛煶棰戠偣鎾�
+- [ ] 璁惧鎺у埗
+  - [ ] 浜戝彴鎺у埗
+  - [ ] 杩滅▼鍚姩
+  - [ ] 褰曞儚鎺у埗
+  - [ ] 鎶ヨ甯冮槻/鎾ら槻
+  - [ ] 鎶ヨ澶嶄綅
+  - [ ] 寮哄埗鍏抽敭甯�
+  - [ ] 鎷夋鏀惧ぇ
+  - [ ] 鎷夋缂╁皬
+  - [ ] 鐪嬪畧浣嶆帶鍒�
+  - [ ] 璁惧閰嶇疆
+- [ ] 鎶ヨ浜嬩欢閫氱煡鍜屽垎鍙�
+- [X] 璁惧鐩綍璁㈤槄
+- [X] 缃戠粶璁惧淇℃伅鏌ヨ
+  - [X] 璁惧鐩綍鏌ヨ
+  - [X] 璁惧鐘舵�佹煡璇�
+  - [ ] 璁惧閰嶇疆鏌ヨ
+  - [ ] 璁惧棰勭疆浣嶆煡璇�
+- [X] 鐘舵�佷俊鎭姤閫�
+- [X] 璁惧瑙嗛煶棰戞枃浠舵绱�
+- [X] 鍘嗗彶瑙嗛煶棰戠殑鍥炴斁
+  - [X] 鎾斁
+  - [x] 鏆傚仠
+  - [x] 杩�/閫�
+  - [x] 鍋滄
+- [ ] 瑙嗛煶棰戞枃浠朵笅杞�
+- [ ] ~~鏍℃椂~~
+- [X] 璁㈤槄鍜岄�氱煡
+  - [X] 浜嬩欢璁㈤槄
+    - [X] 绉诲姩璁惧浣嶇疆璁㈤槄
+    - [ ] 鎶ヨ璁㈤槄
+    - [X] 鐩綍璁㈤槄
+- [ ] 璇煶骞挎挱
+- [ ] 璇煶瀵硅
+
+   
+
+
+# 绀惧尯
+浠g爜鐩墠鎵樼鍦℅itHub鍜孏itee锛孏itee鐩墠浣滀负鍔犻�熶粨搴撲娇鐢紝涓嶆帴鍙梚ssue銆�  
+GitHub锛� [https://github.com/648540858/wvp-GB28181-pro](https://github.com/648540858/wvp-GB28181-pro)  
+Gitee锛� [https://gitee.com/pan648540858/wvp-GB28181-pro](https://gitee.com/pan648540858/wvp-GB28181-pro)
\ No newline at end of file
diff --git a/doc/_content/ability/_media/cascade1.png b/doc/_content/ability/_media/cascade1.png
new file mode 100644
index 0000000..9ba8280
--- /dev/null
+++ b/doc/_content/ability/_media/cascade1.png
Binary files differ
diff --git a/doc/_content/ability/_media/cascade2.png b/doc/_content/ability/_media/cascade2.png
new file mode 100644
index 0000000..4dd62cf
--- /dev/null
+++ b/doc/_content/ability/_media/cascade2.png
Binary files differ
diff --git a/doc/_content/ability/_media/cascade3.png b/doc/_content/ability/_media/cascade3.png
new file mode 100644
index 0000000..f95f5d5
--- /dev/null
+++ b/doc/_content/ability/_media/cascade3.png
Binary files differ
diff --git a/doc/_content/ability/_media/cascade4.png b/doc/_content/ability/_media/cascade4.png
new file mode 100644
index 0000000..9db85b5
--- /dev/null
+++ b/doc/_content/ability/_media/cascade4.png
Binary files differ
diff --git a/doc/_content/ability/_media/img.png b/doc/_content/ability/_media/img.png
new file mode 100644
index 0000000..6a0c550
--- /dev/null
+++ b/doc/_content/ability/_media/img.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_1.png b/doc/_content/ability/_media/img_1.png
new file mode 100644
index 0000000..31995c3
--- /dev/null
+++ b/doc/_content/ability/_media/img_1.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_10.png b/doc/_content/ability/_media/img_10.png
new file mode 100644
index 0000000..030502d
--- /dev/null
+++ b/doc/_content/ability/_media/img_10.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_11.png b/doc/_content/ability/_media/img_11.png
new file mode 100644
index 0000000..cb0f3d5
--- /dev/null
+++ b/doc/_content/ability/_media/img_11.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_12.png b/doc/_content/ability/_media/img_12.png
new file mode 100644
index 0000000..d6fe877
--- /dev/null
+++ b/doc/_content/ability/_media/img_12.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_13.png b/doc/_content/ability/_media/img_13.png
new file mode 100644
index 0000000..6be1128
--- /dev/null
+++ b/doc/_content/ability/_media/img_13.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_14.png b/doc/_content/ability/_media/img_14.png
new file mode 100644
index 0000000..2471204
--- /dev/null
+++ b/doc/_content/ability/_media/img_14.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_15.png b/doc/_content/ability/_media/img_15.png
new file mode 100644
index 0000000..f167811
--- /dev/null
+++ b/doc/_content/ability/_media/img_15.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_16.png b/doc/_content/ability/_media/img_16.png
new file mode 100644
index 0000000..f7ce9e7
--- /dev/null
+++ b/doc/_content/ability/_media/img_16.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_17.png b/doc/_content/ability/_media/img_17.png
new file mode 100644
index 0000000..02b303e
--- /dev/null
+++ b/doc/_content/ability/_media/img_17.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_18.png b/doc/_content/ability/_media/img_18.png
new file mode 100644
index 0000000..5ca4faf
--- /dev/null
+++ b/doc/_content/ability/_media/img_18.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_2.png b/doc/_content/ability/_media/img_2.png
new file mode 100644
index 0000000..f9f2f55
--- /dev/null
+++ b/doc/_content/ability/_media/img_2.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_3.png b/doc/_content/ability/_media/img_3.png
new file mode 100644
index 0000000..efe688c
--- /dev/null
+++ b/doc/_content/ability/_media/img_3.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_4.png b/doc/_content/ability/_media/img_4.png
new file mode 100644
index 0000000..f548cec
--- /dev/null
+++ b/doc/_content/ability/_media/img_4.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_5.png b/doc/_content/ability/_media/img_5.png
new file mode 100644
index 0000000..6959c78
--- /dev/null
+++ b/doc/_content/ability/_media/img_5.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_6.png b/doc/_content/ability/_media/img_6.png
new file mode 100644
index 0000000..04c42bc
--- /dev/null
+++ b/doc/_content/ability/_media/img_6.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_7.png b/doc/_content/ability/_media/img_7.png
new file mode 100644
index 0000000..1a8edbf
--- /dev/null
+++ b/doc/_content/ability/_media/img_7.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_8.png b/doc/_content/ability/_media/img_8.png
new file mode 100644
index 0000000..02fa66f
--- /dev/null
+++ b/doc/_content/ability/_media/img_8.png
Binary files differ
diff --git a/doc/_content/ability/_media/img_9.png b/doc/_content/ability/_media/img_9.png
new file mode 100644
index 0000000..708e901
--- /dev/null
+++ b/doc/_content/ability/_media/img_9.png
Binary files differ
diff --git a/doc/_content/ability/auto_play.md b/doc/_content/ability/auto_play.md
new file mode 100644
index 0000000..5259e0b
--- /dev/null
+++ b/doc/_content/ability/auto_play.md
@@ -0,0 +1,2 @@
+<!-- 鑷姩鐐规挱 -->
+# 鑷姩鐐规挱
diff --git a/doc/_content/ability/cascade.md b/doc/_content/ability/cascade.md
new file mode 100644
index 0000000..7942bda
--- /dev/null
+++ b/doc/_content/ability/cascade.md
@@ -0,0 +1,34 @@
+<!-- 鍥芥爣绾ц仈鐨勪娇鐢� -->
+# 鍥芥爣绾ц仈鐨勪娇鐢�
+鍥芥爣28181涓嶅悓骞冲彴涔嬮棿鏀寔涓ょ杩炴帴鏂瑰紡锛屽钩绾у拰涓婁笅绾э紝WVP鐩墠鏀寔鍚戜笂绾х骇鑱斻��
+## 1 鎺ュ叆骞冲彴
+### 1.1 wvp-pro
+#### 1.1.1 wvp-pro绠$悊椤甸潰鐐瑰嚮娣诲姞
+   ![cascade1](_media/cascade1.png)
+#### 1.1.2 濉叆wvp-pro涓婄骇骞冲彴淇℃伅
+   ![cascade1](_media/img_4.png)
+   ![cascade1](_media/img_5.png)
+#### 1.1.3 缂栬緫wvp-pro涓婄骇璁惧淇℃伅锛屽紑鍚闃�
+   ![cascade1](_media/img_6.png)
+### 1.2 澶у崕骞冲彴
+### 1.3 娴峰悍骞冲彴
+### 1.4 liveGBS
+#### 1.4.1. wvp-pro绠$悊椤甸潰鐐瑰嚮娣诲姞  
+   ![娣诲姞](_media/cascade1.png)
+#### 1.4.2. 濉叆liveGBS骞冲彴淇℃伅  
+   ![濉叆liveGBS骞冲彴淇℃伅1](_media/cascade2.png)
+   ![濉叆liveGBS骞冲彴淇℃伅2](_media/cascade3.png)
+#### 1.4.3. 缂栬緫liveGBS璁惧淇℃伅锛屽紑鍚洰褰曡闃�  
+   ![cascade1](_media/cascade4.png)  
+#### 1.4.4. 缂栬緫liveGBS璁惧淇℃伅锛屽紑鍚疓PS璁㈤槄  
+   ![cascade1](_media/img_7.png)
+
+## 2 娣诲姞鐩綍涓庨�氶亾
+1. 绾ц仈骞冲彴娣诲姞鐩綍淇℃伅  
+   ![cascade1](_media/img_1.png)
+2. 涓虹洰褰曟坊鍔犻�氶亾  
+   ![cascade1](_media/img_2.png)
+3. 璁剧疆榛樿娴佺洰褰�   
+濡傛灉闇�瑕佸悗缁嚜鍔ㄧ敓鎴愮殑娴佷俊鎭兘鍦ㄦ煇涓�涓妭鐐逛笅锛屽彲浠ュ湪瀵瑰簲鑺傜偣鍙抽敭璁剧疆涓洪粯璁�  
+   ![cascade1](_media/img_3.png)
+
diff --git a/doc/_content/ability/cascade2.md b/doc/_content/ability/cascade2.md
new file mode 100644
index 0000000..7bd6c79
--- /dev/null
+++ b/doc/_content/ability/cascade2.md
@@ -0,0 +1,18 @@
+<!-- 鍥芥爣绾ц仈鐨勪娇鐢� -->
+# 鍥芥爣绾ц仈鐨勪娇鐢�
+鍥芥爣28181涓嶅悓骞冲彴涔嬮棿鏀寔涓ょ杩炴帴鏂瑰紡锛屽钩绾у拰涓婁笅绾э紝WVP鐩墠鏀寔鍚戜笂绾х骇鑱斻��
+## 娣诲姞涓婄骇骞冲彴
+鍦ㄥ浗鏍囩骇鑱旈〉闈㈢偣鍑烩�滄坊鍔犫�濇寜閽紝浠ユ帹閫佸埌涓婄骇WVP涓轰緥瀛愶紝鍙傜湅[鎺ュ叆璁惧](./_content/ability/device.md)
+![cascade17](_media/img_17.png)
+鐐瑰嚮淇濆瓨鍙互鍦ㄤ笂绾х殑鍥芥爣閫氶亾鍒楄〃鐪嬪埌鏂板鍔犵殑璁惧锛�
+鍥芥爣绾ц仈鍒楄〃鍑虹幇浜嗙骇鑱旂殑杩欎釜骞冲彴锛涘悓鏃剁姸鎬佹樉绀轰负鍦ㄧ嚎锛屽鏋滅姸鎬佷负绂荤嚎閭d箞鍙兘鏄綘鐨勬湇鍔′俊鎭厤缃湁璇垨鑰呯綉缁滀笉閫氥��
+璁㈤槄淇℃伅鍒楁湁涓変釜鍥炬爣锛岃〃绀轰笂绾у紑鍚闃咃紝浠庡乏鍒板彸渚濇鏄細鎶ヨ璁㈤槄锛岀洰褰曡闃咃紝绉诲姩浣嶇疆璁㈤槄銆�
+## 鎺ㄩ�侀�氶亾
+鐐瑰嚮浣犺鎺ㄩ�佺殑骞冲彴鐨勨�滈�夋嫨閫氶亾鈥濇寜閽��
+![cascade18](_media/img_18.png)
+- **椤甸潰缁撴瀯**
+  - 宸︿晶涓虹洰褰曠粨鏋�  
+  閫夋嫨鏈垎閰嶏紝鍒欏彸渚ф樉绀哄緟鍒嗛厤鐨勯�氶亾锛屽彲浠ョ偣鍑烩�滄坊鍔犳寜閽�濓紝鍦ㄥ脊绐椾腑閫夋嫨瑕佹斁缃殑浣嶇疆锛屼繚瀛樺悗鍗冲彲娣诲姞閫氶亾鎴愬姛
+  閫夋嫨鍏朵粬鐨勭洰褰曞彲浠ョ湅鍒板凡缁忓垎閰嶅湪杩欎釜鐩綍涓嬬殑閫氶亾锛屽彲浠ュ鍏惰繘琛屽垹闄ゅ悗閲嶆柊鍦ㄦ湭鍒嗛厤涓幓鍒嗛厤銆�
+  - 鍙充晶涓烘暟鎹睍绀轰互鍙婃搷浣�  
+  鍥芥爣閫氶亾鏍忓唴涓烘潵鑷叾浠栧浗鏍囪澶�/骞冲彴鐨勯�氶亾锛涚洿鎾祦閫氶亾涓烘潵鑷帹娴�/鎷夋祦浠g悊鐨勯�氶亾銆�
\ No newline at end of file
diff --git a/doc/_content/ability/cloud_record.md b/doc/_content/ability/cloud_record.md
new file mode 100644
index 0000000..4ac4f8f
--- /dev/null
+++ b/doc/_content/ability/cloud_record.md
@@ -0,0 +1,8 @@
+<!-- 浜戠褰曞儚 -->
+# 浜戠褰曞儚
+浜戠褰曞儚鏄褰曞埗鍦▃lm鏈嶅姟涓嬬殑褰曞儚鏂囦欢鐨勭鐞嗭紝褰曞儚鐨勬枃浠惰矾寰勯粯璁ゅ湪ZLM/www/record涓嬶紝浣跨敤浜戠褰曞儚鍔熻兘蹇呴』閮ㄧ讲wvp-pro-assist锛屼富瑕侀�氳繃璋冪敤wvp-pro-assist鐨勬帴鍙e畬鎴愬悇绉嶅姛鑳姐��
+濡傛灉浣犻渶瑕�24灏忔椂鐨勫綍鍍忥紝鐩墠鏈変竴涓繖绉嶆柟妗堬紝鍙互鍙傝�僛7*24涓嶉棿鏂綍鍍廬(./_content/ability/continuous_recording.md)銆�
+1. 浜戞褰曞儚鏀寔褰曞儚鏂囦欢鐨勬煡鐪嬶紝鎾斁锛堝彲鑳藉洜涓虹紪鐮佺殑鍘熷洜瀵艰嚧鏃犳硶鎾斁锛夛紱
+2. 鏀寔褰曞儚鐨勪笅杞斤紱
+3. 鏀寔褰曞儚鐨勫悎骞朵笅杞斤紱
+鍔熻兘娌℃湁澶鐗规畩鐨勫湴鏂瑰氨涓嶄竴涓�浠嬬粛浜嗭紝澶у鑷浣撻獙鍚с��
diff --git a/doc/_content/ability/continuous_recording.md b/doc/_content/ability/continuous_recording.md
new file mode 100644
index 0000000..516830f
--- /dev/null
+++ b/doc/_content/ability/continuous_recording.md
@@ -0,0 +1,14 @@
+<!-- 7*24涓嶉棿鏂綍鍍� -->
+# 7*24涓嶉棿鏂綍鍍�
+
+鐩墠濡傛灉瑕佸疄鐜颁笉闂存柇褰曞儚濡傛灉鍙槸鍏抽棴鏃犱汉瑙傜湅鍋滄鎺ㄦ祦鏄笉澶熺殑锛岃澶囧彲鑳界粡鍘嗘柇缃戯紝閲嶅惎锛岄兘浼氬鑷村綍鍍忕殑涓柇锛岀洰鍓嶇粰澶у鎻愪緵涓�绉嶅彲鐢ㄧ殑涓存椂鏂规銆�   
+
+**鍘熺悊锛�** wvp鏀寔浣跨敤娴佸湴鍧�鑷姩鐐规挱锛屽嵆浣犳嬁鍒颁竴涓祦鍦板潃鐩存帴鍘绘挱鏀撅紝鍗充娇璁惧澶勪簬鏈偣鎾姸鎬侊紝wvp浼氳嚜鍔ㄥ府浣犵偣鎾紱ZLM
+鐨勬媺娴佷唬鐞嗘垚鍔熷悗浼氭棤闄愰噸璇曪紝鍙娴佷竴鎭㈠灏卞彲浠ユ媺璧锋潵锛屽熀浜庤繖涓や釜鍘熺悊銆�  
+**鏂规濡備笅锛�**
+1. wvp鐨勯厤缃腑user-settings->auto-apply-play璁剧疆涓哄洟true,寮�鍚嚜鍔ㄧ偣鎾紱
+2. 鐐瑰嚮浣犺褰曞儚鐨勯�氶亾锛岀偣鍑绘挱鏀鹃〉闈㈠乏涓嬭鐨勨�滄洿澶氬湴鍧�鈥濓紝鐐瑰嚮rtsp锛屾鏃跺鍒朵簡rtsp鍦板潃鍒板壀璐存澘锛�
+3. 鍦ㄦ媺娴佷唬鐞嗕腑娣诲姞涓�璺祦锛屽湴鍧�濉啓浣犲鍒剁殑鍦板潃锛屽惎鐢ㄦ垚鍔熷嵆鍙��  
+**鍓嶆彁锛�** 
+1. wvp浣跨敤澶氱鍙f敹娴侊紝涓嶇劧浣犳棤娉曞緱鍒颁竴涓浐瀹氱殑娴佸湴鍧�锛屼篃灏辨棤娉曞疄鐜拌嚜鍔ㄧ偣鎾��
+
diff --git a/doc/_content/ability/device.md b/doc/_content/ability/device.md
new file mode 100644
index 0000000..ceed545
--- /dev/null
+++ b/doc/_content/ability/device.md
@@ -0,0 +1,36 @@
+<!-- 鎺ュ叆璁惧 -->
+# 鎺ュ叆璁惧
+璁惧鎺ュ叆涓昏鏄渶瑕佸湪璁惧涓婇厤缃�28181涓婄骇涔熷氨鏄疻VP-PRO鐨勪俊鎭紝鍙湁淇℃伅涓�鑷寸殑鎯呭喌鎵嶅彲浠ユ敞鍐屾垚鍔熴�傝澶囨敞鍐屾垚鍔熷悗鎵撳紑WVP->鍥芥爣璁惧,鍙互鐪嬪埌鏂板鍔犵殑璁惧锛沎璁惧浣跨敤](./_content/ability/device_use.md)锛�  
+涓昏鏈変互涓嬪瓧娈甸渶瑕侀厤缃細  
+
+- sip->ip  
+鏈満IP锛屼笉瑕佷娇鐢�127.0.0.1/0.0.0.0, 闄ら潪浣犲椤圭洰鍙婂叾鐔熸倝    
+
+- sip->port  
+28181鏈嶅姟鐩戝惉鐨勭鍙�  
+
+- sip->domain  
+domain瀹滈噰鐢↖D缁熶竴缂栫爜鐨勫墠鍗佷綅缂栫爜銆�  
+
+- sip->id  
+28181鏈嶅姟ID
+
+- sip->password  
+28181鏈嶅姟瀵嗙爜    
+
+- 閰嶇疆淇℃伅鍦ㄥ涓嬩綅缃�  
+
+![_media/img_16.png](_media/img_16.png)
+***
+## 澶у崕鎽勫儚澶�
+![_media/img_10.png](_media/img_10.png)
+## 澶у崕NVR
+![_media/img_11.png](_media/img_11.png)
+## 鑹剧濞佽鎽勫儚澶�
+![_media/img_15.png](_media/img_15.png)
+## 姘存槦鎽勫儚澶�
+![_media/img_12.png](_media/img_12.png)
+## 娴峰悍鎽勫儚澶�
+![_media/img_9.png](_media/img_9.png)
+
+[璁惧浣跨敤](_content/ability/device_use.md)
diff --git a/doc/_content/ability/device_use.md b/doc/_content/ability/device_use.md
new file mode 100644
index 0000000..c406b3b
--- /dev/null
+++ b/doc/_content/ability/device_use.md
@@ -0,0 +1,35 @@
+<!-- 璁惧浣跨敤 -->
+# 璁惧浣跨敤  
+### 鏇存柊璁惧閫氶亾  
+  鐐瑰嚮鍒楄〃鏈熬鐨勨�滃埛鏂扳�濇寜閽紝鍙互鐪嬪埌涓�涓渾褰㈣繘搴︽潯锛岀瓑杩涘害缁撴潫鎻愮ず鎴愬姛鍚庡嵆鍙洿鏂板畬鎴愶紝濡傛灉閫氶亾鏁伴噺鏈夊彉鍖栦綘鍙互鐪嬬偣鍑诲乏涓婅鐨�![鍒锋柊](_media/img_14.png)鍗冲彲鐪嬪埌閫氶亾鏁伴噺鐨勫彉鍖栵紱濡傛灉閫氶亾鏁伴噺浠嶆湭0,閭d箞鍙兘鏃跺鏂瑰皻鏈帹閫侀�氶亾缁欎綘銆�
+### 鏌ョ湅璁惧閫氶亾  
+  鐐瑰嚮鍒楄〃鏈熬鐨勨�滈�氶亾鈥濇寜閽紝
+### 鏌ョ湅璁惧瀹氫綅  
+  鐐瑰嚮鍒楄〃鏈熬鐨勨�滃畾浣嶁�濇寜閽紝鍗冲彲璺宠浆鍒板湴鍥鹃〉闈㈢湅鍒拌澶囩殑浣嶇疆
+### 缂栬緫璁惧鍦╓VP涓竴浜涘姛鑳�
+鐐瑰嚮鍒楄〃鏈熬鐨勨�滅紪杈戔�濇寜閽紝鍗冲彲鍦ㄦ墦寮�鐨勫脊绐椾腑瀵硅澶囧姛鑳借繘琛屼慨鏀�
+- 璁惧鍚嶇О  
+  濡備綍鏈兘浠庤澶囬噷璇诲彇鍒拌澶囧悕绉版垨鑰呴渶瑕佽嚜宸遍噸鍛藉悕锛岄偅涔堝彲浠ヤ慨鏀规閫夐」銆�
+- 瀛楃闆�  
+  淇敼璇诲彇璁惧鏁版嵁鏃朵娇鐢ㄧ殑瀛楃闆嗭紝榛樿涓篏B2312,浣嗘槸GB2312鏀跺綍鐨勬眽瀛椾笉鍏紝鎵�浠ユ湁鏃跺�欏洖閬囧埌涔辩爜锛屽彲浠ヤ慨鏀逛负UTF-8鏉ヨВ鍐炽��
+- 鍦扮悊鍧愭爣绯�  
+  灞曠ず姝よ澶囧畾浣嶄俊鎭椂浣跨敤鐨勮鐢ㄤ粈涔堝潗鏍囩郴鏉ヨВ鏋愮粡绾害锛屼竴鑸笉鐢ㄤ慨鏀癸紝濡傛灉閬囧埌瀹氫綅涓嶅噯锛屽彲浠ヤ慨鏀瑰皾璇曚慨鏀规閫夐」瑙e喅銆� 
+- 鐩綍缁撴瀯  
+  灞曠ず璁惧鐨勯�氶亾淇℃伅鏃讹紝浣跨敤璁惧浣滀负鏍戝舰缁撴瀯鐨勪緷鎹紝鍥芥爣28181瀹氫箟浜嗕袱绉嶆爲褰㈢粨鏋勶紝璇︽儏鏌ョ湅[鍥芥爣28181鐨勬爲褰㈢粨鏋刔(./_content/theory/channel_tree.md)锛�
+- 鐩綍璁㈤槄  
+  濉啓璁㈤槄鍛ㄦ湡鍗冲彲瀵硅澶囧紑鍚洰褰曡闃咃紝璁惧濡傛灉鏀寔鐩綍璁㈤槄閭d箞璁惧鍦ㄩ�氶亾淇℃伅鍙戠敓鍙樺寲鏃跺氨浼氶�氱煡WVP鍝簺閫氶亾鍙戠敓浜嗛偅浜涘彉鍖栵紝鍖呮嫭閫氶亾澧炲姞/鍒犻櫎/鏇存柊/涓婄嚎/涓嬬嚎/瑙嗛涓㈠け/鏁呴殰銆�0涓哄彇娑堣闃呫��
+  涓�鑸琋VR鍜屽钩鍙板鎺ュ彲浠ュ紑鍚閫夐」锛岀洿鎺ユ帴鎽勫儚鏈哄紑鍚閫夐」鎰忎箟涓嶅ぇ銆�
+- 绉诲姩浣嶇疆璁㈤槄  
+  瀵硅澶囧紑鍚Щ鍔ㄤ綅缃闃咃紝璁惧濡傛灉鏀寔鐩綍璁㈤槄閭d箞璁惧浣嶇疆鍙戠敓鍙樺寲鏃朵細閫氱煡鍒癢VP,涓�鑸墽娉曡褰曚华鍙互寮�鍚閫夐」锛屽鍥哄畾浣嶇疆鐨勮澶囨剰涔変笉澶с��
+- SSRC鏍¢獙  
+  涓轰簡瑙e喅閮ㄥ垎璁惧鍑虹幇鐨勪覆娴侀棶棰橈紝鍙互鎵撳紑姝ら�夐」銆俍LM浼氫弗鏍兼寜鐓х粰瀹氱殑ssrc澶勭悊瑙嗛娴併�傞儴鍒嗚澶囨祦淇℃伅涓嶆爣鍑嗭紝寮�鍚彲鑳藉鑷存棤娉曠偣鎾��
+### 鍒犻櫎璁惧  
+  鍙互鍒犻櫎WVP涓殑璁惧淇℃伅锛屽鏋滆澶�28181閰嶇疆鏈洿鏀癸紝閭d箞璁惧鍦ㄤ笅涓�娆℃敞鍐屽悗浠嶇劧浼氭敞鍐屼笂鏉ャ��
+### 鐐规挱瑙嗛  
+  杩涘叆閫氶亾鍒楄〃鍚庯紝鐐瑰嚮鍒楄〃鏈熬鐨勨�滄挱鏀锯�濇寜閽紝绋嶇瓑鍗冲彲寮瑰嚭鎾斁椤甸潰
+### 璁惧褰曞儚  
+  杩涘叆閫氶亾鍒楄〃鍚庯紝鐐瑰嚮鍒楄〃鏈熬鐨勨�滆澶囧綍鍍忊�濇寜閽紝涔熷彲浠ュ湪鎾斁椤甸潰鐐瑰嚮褰曞儚鏌ヨ杩涘叆褰曞儚鏌ョ湅椤甸潰锛岄�夋嫨瑕佹煡鐪嬬殑鏃ユ湡鍗冲彲瀵瑰綍鍍忚繘琛屾挱鏀惧拰涓嬭浇銆�
+### 浜戝彴鎺у埗  
+  鍙互瀵规敮鎸佷簯鍙板姛鑳界殑璁惧杩涜涓婁笅宸﹀彸鐨勮浆鍔ㄤ互鍙婃媺杩戞媺杩滅殑鎿嶄綔銆�
+### 鑾峰彇瑙嗛鐨勬挱鏀惧櫒鍦板潃  
+  瑙嗛鐐规挱鎴愬姛鍚庡湪瀹炴椂瑙嗛椤甸潰锛岀偣鍑烩�滄洿澶氬湴鍧�鈥濆彲浠ョ湅鍒版墍鏈夌殑鎾斁鍦板潃锛屽湴鍧�鏄惁鍙互鎾斁涓庝綘鏄惁瀹屾暣缂栬瘧鍚敤zlm鍔熻兘鏈夊叧锛屾洿涓庣綉缁滄湁鍏炽��
\ No newline at end of file
diff --git a/doc/_content/ability/gis.md b/doc/_content/ability/gis.md
new file mode 100644
index 0000000..8796dba
--- /dev/null
+++ b/doc/_content/ability/gis.md
@@ -0,0 +1,37 @@
+<!-- 鐢靛瓙鍦板浘 -->
+# 鐢靛瓙鍦板浘
+WVP鎻愪緵浜嗙畝鍗曠殑鐢靛瓙鍦板浘鐢ㄤ簬璁惧鐨勫畾浣嶄互鍙婄Щ鍔ㄨ澶囩殑杞ㄨ抗淇℃伅锛岀數瀛愬湴鍥惧熀浜庡紑婧愮殑鍦板浘寮曟搸openlayers寮�鍙戙��
+### 鏌ョ湅璁惧瀹氫綅
+1. 鍙互鍦ㄨ澶囧垪琛ㄧ偣鍑烩�滃畾浣嶁�濇寜閽�,鑷姩璺宠浆鍒扮數瀛愬湴鍥鹃〉闈紱 
+2. 鍦ㄧ數瀛愬湴鍥鹃〉闈㈠湪璁惧涓婂彸閿偣鍑烩�滃畾浣嶁�濊幏鍙栬澶�/骞冲彴涓嬬殑鎵�鏈夐�氶亾浣嶇疆銆�
+3. 鍗曞嚮閫氶亾淇℃伅鍙互瀹氫綅鍒板叿浣撶殑閫氶亾 
+
+
+### 鏌ヨ璁惧杞ㄨ抗
+鏌ヨ杞ㄨ抗闇�瑕佹彁鍓嶉厤缃畇ave-position-history閫夐」寮�鍚建杩逛俊鎭殑淇濆瓨锛岀洰鍓峎VP姝ゅ鏈敮鎸佸垎搴撳垎琛紝瀵逛簬澶ф暟鎹噺鐨勮建杩逛俊鎭棤娉曡儨浠伙紝鏈夐渶姹傝鑷浜屾寮�鍙戞垨鑰呭畾鍒跺紑鍙戙��
+鍦ㄧ數瀛愬湴鍥鹃〉闈㈠湪璁惧涓婂彸閿偣鍑烩�滄煡璇㈣建杩光�濊幏鍙栬澶囪建杩逛俊鎭��
+
+PS锛� 鐩墠鐨勫簳鍥句粎鐢ㄧ敤浣滄紨绀哄拰瀛︿範锛屽晢鐢ㄦ儏鍐佃鑷璐拱鎺堟潈浣跨敤銆�
+
+### 鏇存崲搴曞浘浠ュ強搴曞浘閰嶇疆
+鐩墠WVP鏀寔浣跨敤浜嗘洿鎹㈠簳鍥撅紝閰嶇疆鏂囦欢鍦╳eb_src/static/js/mapConfig.js锛岃淇敼鍚庨噸鏂扮紪璇戝墠绔枃浠躲��
+```javascript
+window.mapParam = {
+  // 寮�鍚�/鍏抽棴鍦板浘鍔熻兘
+  enable: true,
+  // 鍧愭爣绯� GCJ-02 WGS-84,
+  coordinateSystem: "GCJ-02",
+  // 鍦板浘鐡︾墖鍦板潃
+  tilesUrl: "http://webrd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
+  // 鐡︾墖澶у皬
+  tileSize: 256,
+  // 榛樿灞傜骇
+  zoom:10,
+  // 榛樿鍦板浘涓績鐐�
+  center:[116.41020, 39.915119],
+  // 鍦板浘鏈�澶у眰绾�
+  maxZoom:18,
+  // 鍦板浘鏈�灏忓眰绾�
+  minZoom: 3
+}
+```
diff --git a/doc/_content/ability/node_manger.md b/doc/_content/ability/node_manger.md
new file mode 100644
index 0000000..1b4aef3
--- /dev/null
+++ b/doc/_content/ability/node_manger.md
@@ -0,0 +1,9 @@
+<!-- 鑺傜偣绠$悊 -->
+# 鑺傜偣绠$悊
+WVP鏀寔鍗曚釜WVP澶氫釜ZLM鐨勬柟妗堟潵鎵╁睍WVP鐨勮棰戝苟鍙戣兘鍔涳紝骞跺彂鐐规挱鏄洜涓哄甫瀹藉拰鎬ц兘鐨勫師鍥狅紝鍗曚釜ZLM鑺傜偣鑳芥敮鎸佺殑璺暟鏈夐檺锛屾墍浠VP澧炲姞浜哯LM闆嗙兢鏉ユ墿灞曞苟鍙戝苟涓斾繚璇乑LM鐨勯珮鍙敤銆�
+## 榛樿鑺傜偣
+WVP涓负浜嗕繚璇佸姛鑳界殑瀹屾暣鎬э紝ZLM鑺傜偣鑷冲皯瑕佹湁涓�涓粯璁よ妭鐐癸紝杩欎釜鑺傜偣涓嶆槸鍦ㄧ鐞嗛〉闈㈡坊鍔犵殑锛岃�屾槸鍦╓VP鐨勯厤缃枃浠朵腑閰嶇疆鐨勶紝杩欎釜鑺傜偣涓嶅彲鍦ㄩ〉闈㈠垹闄ゃ�傛瘡娆″惎鍔ㄤ細鑷姩浠庨厤缃枃浠朵腑璇诲彇閰嶇疆鍐欏叆鏁版嵁搴撳鐢ㄣ��
+## 鏂板鑺傜偣
+鍚姩浣犺娣诲姞鐨剒lm鑺傜偣锛岀劧鍚庣偣鍑烩�滄坊鍔犺妭鐐光�濇寜閽緭鍏lm鐨刬p锛� http绔彛锛孲ECRET銆傜偣鍑绘祴璇曟祴璇曞畬鎴愬垯寮�濮嬪鑺傜偣杩涜璇︾粏鐨勮缃紝濡傛灉浣犵殑zlm鏄娇鐢╠ocker鍚姩鐨勶紝鍙兘瀛樺湪zlm浣跨敤鐨勭鍙d笌瀹夸富鏈虹鍙d笉涓�鑷寸殑鎯呭喌锛岄渶瑕佸湪杩欓噷涓�涓�閰嶇疆銆�
+## wvp浣跨敤澶氫釜鑺傜偣鐨勫師鐞�
+wvp浼氭妸杩炴帴鐨勮妭鐐圭粺涓�璁板綍鍦╮edis涓紝骞惰褰晍lm鐨勮礋杞芥儏鍐碉紝褰撴柊鐨勮姹傚埌鏉ユ椂锛屼細鍙栧嚭璐熻浇鏈�浣庣殑閭d釜zlm杩涜浣跨敤銆備互姝や繚璇佽妭鐐硅礋杞藉潎琛°��
diff --git a/doc/_content/ability/online_doc.md b/doc/_content/ability/online_doc.md
new file mode 100644
index 0000000..55ecb26
--- /dev/null
+++ b/doc/_content/ability/online_doc.md
@@ -0,0 +1,2 @@
+<!-- 鍦ㄧ嚎鏂囨。 -->
+# 鍦ㄧ嚎鏂囨。
diff --git a/doc/_content/ability/proxy.md b/doc/_content/ability/proxy.md
new file mode 100644
index 0000000..74e632d
--- /dev/null
+++ b/doc/_content/ability/proxy.md
@@ -0,0 +1,24 @@
+<!-- 鎷夋祦浠g悊 -->
+# 鎷夋祦浠g悊
+涓嶆槸鎵�鏈夌殑鎽勫儚鏈洪兘鏀寔鍥芥爣鎴栬�呮帹娴佺殑锛屼絾鏄繖浜涜澶囧彲浠ュ緱鍒颁竴涓棰戞挱鏀惧湴鍧�锛岄�氬父涓簉tsp鍗忚锛�
+浠ュぇ鍗庝负渚嬶細
+```text
+rtsp://{user}:{passwd}@{ipc_ip}:{rtsp_port}/cam/realmonitor?channel=1&subtype=0
+```
+鍙互寰楀埌杩欐牱涓�涓祦鍦板潃锛屽彲浠ョ洿鎺ョ敤vlc杩涜鎾斁锛屾鏃舵垜浠彲浠ラ�氳繃鎷夋祦浠g悊鍔熻兘灏嗚繖涓澶囨帹閫佺粰鍏朵粬鍥芥爣骞冲彴浜嗐��
+娴佺▼濡備笅锛�
+```plantuml
+@startuml
+"鎽勫儚鏈�"  <- "ZLMediaKit": 1. 娴佸幓娴佷俊鎭埌ZLM
+"ZLMediaKit"  -> "WVP-PRO": 2. 鏀跺埌hook閫氱煡寰楀埌娴佷俊鎭�
+"涓婄骇鍥芥爣骞冲彴"  -> "WVP-PRO": 3. 鐐规挱杩欒矾瑙嗛
+"WVP-PRO" -> "ZLMediaKit": 4. 閫氱煡鎺ㄦ祦鍒颁笂绾у浗鏍囧钩鍙�
+@enduml
+```
+## 娣诲姞浠g悊
+鎷夋祦浠g悊鏀寔涓ょ鏂瑰紡锛�
+1. ZLM涓洿鎺ヤ唬鐞嗘祦锛屾敮鎸丷TSP/RTMP锛屼笉鏀寔杞爜锛�
+2. 鍊熷姪ffmpeg瀹屾垚鎷夎浆锛屽彲浠ラ�氳繃淇敼ffmpeg鎷夎浆鍙傛暟瀹屾垚杞爜銆�  
+鐐瑰嚮椤甸潰鐨勨�滄坊鍔犱唬鐞嗏�濓紝瀹夎鎻愮ず鎿嶄綔鍗冲彲锛屼繚瀛樺苟鍚敤鎴愬姛鍚庯紝鍙互鍦ㄥ浗鏍囩骇鑱斾腑[娣诲姞閫氶亾鎺ㄩ�佺粰涓婄骇骞冲彴](./_content/ability/cascade?id=_2-%e6%b7%bb%e5%8a%a0%e7%9b%ae%e5%bd%95%e4%b8%8e%e9%80%9a%e9%81%93)
+
+PS锛� ffmpeg榛樿妯℃澘涓嶉渶淇敼锛岄渶瑕佷慨鏀瑰弬鏁拌嚜琛屽幓ZLM閰嶇疆鏂囦欢涓坊鍔犱竴涓嵆鍙��
diff --git a/doc/_content/ability/push.md b/doc/_content/ability/push.md
new file mode 100644
index 0000000..ef50182
--- /dev/null
+++ b/doc/_content/ability/push.md
@@ -0,0 +1,41 @@
+<!-- 鎺ㄦ祦鍒楄〃 -->
+# 鎺ㄦ祦鍒楄〃
+## 鍔熻兘璇存槑
+
+WVP鏀寔涓夌鍥惧儚杈撳叆鏂瑰紡锛岀洿鎾紝[鎷夋祦浠g悊](_content/ability/proxy.md)锛孾鍥芥爣](_content/ability/device.md),鐩存挱璁惧鎺ュ叆娴佺▼濡備笅
+```plantuml
+@startuml
+"鐩存挱璁惧"  -> "ZLMediaKit": 1. 鍙戣捣鎺ㄦ祦
+"ZLMediaKit"  -> "WVP-PRO": 2. 鏀跺埌hook閫氱煡寰楀埌娴佷俊鎭�
+"涓婄骇鍥芥爣骞冲彴"  -> "WVP-PRO": 3. 鐐规挱杩欒矾瑙嗛
+"WVP-PRO" -> "ZLMediaKit": 4. 閫氱煡鎺ㄦ祦鍒颁笂绾у浗鏍囧钩鍙�
+@enduml
+```
+1. 榛樿鎯呭喌涓媁VP鏀跺埌鎺ㄦ祦淇℃伅鍚庯紝鍒楄〃涓嚭鐜拌繖鏉℃帹娴佷俊鎭紝姝ゆ椂浣犲彲浠ョ偣鍑烩�滃姞鍏ュ浗鏍団�濇寜閽负姝よ矾鎺ㄦ祦閰嶇疆鍚嶇О浠ュ強鍥芥爣缂栧彿锛屽彧鏈夋湁鍥芥爣缂栧彿鐨勬帹娴佹墠鍙互娣诲姞鍒扮骇鑱斿钩鍙帮紝淇濆瓨鎴愬姛鍚庡彲浠ュ湪鍥芥爣绾ц仈涓璠娣诲姞閫氶亾鎺ㄩ�佺粰涓婄骇骞冲彴](_content/ability/cascade?id=_2-%e6%b7%bb%e5%8a%a0%e7%9b%ae%e5%bd%95%e4%b8%8e%e9%80%9a%e9%81%93)
+2. WVP涔熸敮鎸佹帹娴佸墠瀵煎叆澶ч噺閫氶亾鐩存帴鎺ㄩ�佺粰涓婄骇锛岀偣鍑烩�滀笅杞芥ā鏉库�濇寜閽紝鏍规嵁绀轰緥淇敼妯℃澘鍚庯紝鐐瑰嚮鈥滈�氶亾瀵煎叆鈥濇寜閽鍏ラ�氶亾鏁版嵁锛屼繚瀛樻垚鍔熷悗鍙互鍦ㄥ浗鏍囩骇鑱斾腑[娣诲姞閫氶亾鎺ㄩ�佺粰涓婄骇骞冲彴](_content/ability/cascade?id=_2-%e6%b7%bb%e5%8a%a0%e7%9b%ae%e5%bd%95%e4%b8%8e%e9%80%9a%e9%81%93)
+
+## 鎺ㄦ媺娴侀壌鏉冭鍒�
+涓轰簡淇濇姢鏈嶅姟鍣ㄧ殑WVP榛樿寮�鍚帹娴侀壌鏉冿紙鐩墠涓嶆敮鎸佸叧闂鍔熻兘锛�
+
+### 鎺ㄦ祦瑙勫垯
+鎺ㄦ祦鏃堕渶瑕佹惡甯︽帹娴侀壌鏉冪殑绛惧悕sign锛宻ign=md5(pushKey),pushKey鏉ヨ嚜鐢ㄦ埛琛紝姣忎釜鐢ㄦ埛浼氭湁涓�涓笉鍚岀殑pushKey.
+渚嬪app=test锛宻tream=live锛宲ushKey=1000锛宨p=192.168.1.4, port=10554 閭d箞鎺ㄦ祦鍦板潃涓猴細
+```
+rtsp://192.168.1.4:10554/test/live?sign=a9b7ba70783b617e9998dc4dd82eb3c5
+```
+鏀寔鎺ㄦ祦鏃惰嚜瀹氫箟鎾斁閴存潈Id锛屽弬鏁板悕涓篶allId锛屾鏃秙ign=md5(callId_pushKey)
+渚嬪app=test锛宻tream=live锛宲ushKey=1000锛宑allId=12345678, ip=192.168.1.4, port=10554 閭d箞鎺ㄦ祦鍦板潃涓猴細
+```
+rtsp://192.168.1.4:10554/test/live?callId=12345678&sign=c8e6e01dde2d60c66dcea8d2498ffef1
+```
+### 鎾斁瑙勫垯
+榛樿鎯呭喌鎾斁涓嶉渶瑕侀壌鏉冿紝浣嗘槸濡傛灉鎺ㄦ祦鏃舵惡甯︿簡callId锛岄偅涔堟挱鏀炬椂蹇呴』鎼哄甫callId
+渚嬪app=test锛宻tream=live锛屾棤callId, ip=192.168.1.4, port=10554 閭d箞鎾斁鍦板潃涓猴細
+```
+rtsp://192.168.1.4:10554/test/live
+```
+渚嬪app=test锛宻tream=live锛宑allId=12345678, ip=192.168.1.4, port=10554 閭d箞鎾斁鍦板潃涓猴細
+```
+rtsp://192.168.1.4:10554/test/live?callId=12345678
+```
+
diff --git a/doc/_content/ability/user.md b/doc/_content/ability/user.md
new file mode 100644
index 0000000..0c47238
--- /dev/null
+++ b/doc/_content/ability/user.md
@@ -0,0 +1,2 @@
+<!-- 鐢ㄦ埛绠$悊 -->
+# 鐢ㄦ埛绠$悊
diff --git a/doc/_content/about_doc.md b/doc/_content/about_doc.md
new file mode 100644
index 0000000..f727264
--- /dev/null
+++ b/doc/_content/about_doc.md
@@ -0,0 +1,5 @@
+<!-- 鍏充簬鏈枃妗� -->
+
+# 鍏充簬鏈枃妗�
+鏈枃妗e紑婧愬湪gitee涓婏紝[https://gitee.com/pan648540858/wvp-pro-doc.git](https://gitee.com/pan648540858/wvp-pro-doc.git),濡傛灉鏂囨。鍑虹幇浠讳綍閿欒鎴栬�呬笉鏄撶悊瑙g殑璇彞锛岃澶у鎻怚SSUE甯姪鎴戝強鏃舵洿姝c�傛杩庡ぇ瀹舵彁浜R涓�璧风淮鎶よ繖浠芥枃妗o紝璁╂洿澶氱殑浜哄彲浠ヤ娇鐢ㄥ埌杩欎釜寮�婧愮殑瑙嗛骞冲彴銆�
+
diff --git a/doc/_content/disclaimers.md b/doc/_content/disclaimers.md
new file mode 100644
index 0000000..94412ec
--- /dev/null
+++ b/doc/_content/disclaimers.md
@@ -0,0 +1,2 @@
+# 鍏嶈矗澹版槑
+WVP-PRO鑷湁浠g爜浣跨敤瀹芥澗鐨凪IT鍗忚锛屽湪淇濈暀鐗堟潈淇℃伅鐨勬儏鍐典笅鍙互鑷敱搴旂敤浜庡悇鑷晢鐢ㄣ�侀潪鍟嗕笟鐨勯」鐩�� 浣嗘槸鏈」鐩篃闆剁鐨勪娇鐢ㄤ簡涓�浜涘叾浠栫殑寮�婧愪唬鐮侊紝鍦ㄥ晢鐢ㄧ殑鎯呭喌涓嬭鑷鏇夸唬鎴栧墧闄わ紱 鐢变簬浣跨敤鏈」鐩�屼骇鐢熺殑鍟嗕笟绾犵悍鎴栦镜鏉冭涓轰竴姒備笌鏈」鐩強寮�鍙戣�呮棤鍏筹紝璇疯嚜琛屾壙鎷呮硶寰嬮闄┿�� 鍦ㄤ娇鐢ㄦ湰椤圭洰浠g爜鏃讹紝涔熷簲璇ュ湪鎺堟潈鍗忚涓悓鏃惰〃鏄庢湰椤圭洰渚濊禆鐨勭涓夋柟搴撶殑鍗忚
\ No newline at end of file
diff --git a/doc/_content/donation.md b/doc/_content/donation.md
new file mode 100644
index 0000000..959eee8
--- /dev/null
+++ b/doc/_content/donation.md
@@ -0,0 +1,7 @@
+# 鎹愯禒
+椤圭洰鐩墠浠嶅湪绉瀬寮�鍙戙�傚ぇ瀹剁殑鎹愯禒浠ュ強start鍙互璁╂垜鐪嬪埌澶у鐨勬敮鎸佷簬鍏虫敞銆傛洿鍔犳湁鍔ㄥ姏鎶婇」鐩淮鎶や笅鍘汇��
+
+<div align="left">
+<img src=_media/weixin.jpg style="height: 500px; border: 1px solid #e2e2e2"/>
+<img src=_media/zhifubao.jpg style="height: 500px; border: 1px solid #e2e2e2; margin-left: 20px"/>
+</div>
\ No newline at end of file
diff --git a/doc/_content/introduction/_media/img.png b/doc/_content/introduction/_media/img.png
new file mode 100644
index 0000000..48f8d8e
--- /dev/null
+++ b/doc/_content/introduction/_media/img.png
Binary files differ
diff --git a/doc/_content/introduction/_media/img_1.png b/doc/_content/introduction/_media/img_1.png
new file mode 100644
index 0000000..aad1859
--- /dev/null
+++ b/doc/_content/introduction/_media/img_1.png
Binary files differ
diff --git a/doc/_content/introduction/_media/img_2.png b/doc/_content/introduction/_media/img_2.png
new file mode 100644
index 0000000..e786900
--- /dev/null
+++ b/doc/_content/introduction/_media/img_2.png
Binary files differ
diff --git a/doc/_content/introduction/compile.md b/doc/_content/introduction/compile.md
new file mode 100644
index 0000000..b208685
--- /dev/null
+++ b/doc/_content/introduction/compile.md
@@ -0,0 +1,95 @@
+<!-- 缂栬瘧 -->
+# 缂栬瘧
+WVP-PRO涓嶅彧鏄疄鐜颁簡鍥芥爣28181鐨勫崗璁紝鏈韩涔熸槸涓�涓畬鏁寸殑瑙嗛骞冲彴銆傛墍浠ュ浜庢柊鎵嬫潵璇达紝浣犲彲鑳介渶瑕佷竴浜涜�愬績鏉ュ畬鎴愩�傞亣鍒伴棶棰樹笉瑕佺劍韬侊紝浣犲彲浠�
+1. 鐧惧害
+2. 濡傛灉韬竟鏈夌啛鎮塲ava鐨勬湅鍙嬶紝鍙互鍜ㄨ涓嬫湅鍙嬶紱
+3. 鏉ョ兢閲岋紙901799015锛夊挩璇㈢兢鍙嬶紱
+4. 鍚戜綔鑰呭彂閫侀偖浠�648540858@qq.com锛�
+5. 浣滆�呰繙绋嬫敮鎸侊紙鏈夊伩锛夈��   
+   濡傛灉杩欎簺浠嶄笉鑳借В鍐充綘鐨勯棶棰橈紝閭d箞浣犲彲鑳介渶瑕佷笌浣滆�呮垜涓�璧峰悎浣滃畬鎴愯繖涓」鐩紝瑙e喅浣犻亣鍒扮殑闂銆�
+
+
+WVP-PRO浣跨敤Spring boot寮�鍙戯紝maven绠$悊渚濊禆銆傚浜庣啛鎮塻pring寮�鍙戠殑鏈嬪弸鏄緢瀹规槗杩涜缂栬瘧閮ㄧ讲浠ュ強杩愯鐨勩��  
+涓嬮潰灏嗘彁渚涗竴绉嶉�氱敤鏂规硶鏂逛究澶у杩愯椤圭洰銆�
+## 1 鏈嶅姟浠嬬粛
+| 鏈嶅姟             | 浣滅敤                                       | 鏄惁蹇呴』                    |
+|----------------|------------------------------------------|-------------------------|
+| WVP-PRO        | 瀹炵幇鍥芥爣28181鐨勪俊浠や互鍙婅棰戝钩鍙扮浉鍏崇殑鍔熻兘                  | 鏄�                       |
+| ZLMediaKit     | 涓篧VP-PRO鎻愪緵鍥芥爣28181鐨勫獟浣撻儴鍒嗙殑瀹炵幇锛屼互鍙婂悇绉嶈棰戞祦鏍煎紡鐨勫垎鍙戞敮鎸� | 鏄�                       |
+| wvp-pro-assist | wvp鐨勮緟鍔╁綍鍍忕▼搴忥紝涔熷彲鍗曠嫭璺焭lm涓�璧蜂娇鐢紝鎻愪緵褰曞儚鎺у埗,褰曞儚鍚堝苟涓嬭浇鎺ュ彛  | 鍚︼紙涓嶅畨瑁呭彧鏄奖鍝嶄簯绔綍鍍忓姛鑳藉拰鍥芥爣褰曞儚涓嬭浇锛� |
+
+## 2 瀹夎渚濊禆
+| 渚濊禆     | 鐗堟湰         | 鐢ㄩ��          | 寮�鍙戠幆澧冮渶瑕� | 鐢熶骇鐜闇�瑕� |
+|--------|------------|-------------|--------|--------|
+| jdk    | >=1.8      | 杩愯涓庣紪璇慾ava浠g爜 | 鏄�      | 鏄�      |  
+| maven  | >=3.3      | 绠$悊java浠g爜渚濊禆  | 鍚�      | 鍚�      |
+| git    || 涓嬭浇/鏇存柊/鎻愪氦浠g爜 | 鍚�           | 鍚�      |
+| nodejs || 缂栬瘧浜庤繍琛屽墠绔枃浠�  | 鍚�           | 鍚�      |
+| npm    || 绠$悊鍓嶇鏂囦欢渚濊禆   | 鍚�           | 鍚�      |
+
+濡傛灉浣犳槸涓�涓柊鎵嬶紝寤鸿浣犱娇鐢╨inux鎴栬�卪acOS骞冲彴銆倃indows涓嶆帹鑽愩��
+
+ubuntu鐜锛屼互ubuntu 18涓轰緥锛�
+``` bash
+apt-get install -y openjdk-11-jre git maven nodejs npm
+```
+centos鐜,浠entos 8涓轰緥锛�
+```bash
+yum install -y java-1.8.0-openjdk.x86_64 git maven nodejs npm
+```
+window鐜锛屼互windows10涓轰緥锛�
+```bash
+杩欓噷涓嶇粏璇翠簡锛岀櫨搴︽垨鑰呰胺姝屼竴鎼滀竴澶ф妸锛屽熀鏈兘鏄笅涓�姝ヤ笅涓�姝ワ紝鐒跺悗閰嶇疆鐜鍙橀噺銆�
+```
+## 3 瀹夎mysql浠ュ強redis
+杩欓噷渚濈劧鏄弬鑰冪綉涓婃暀绋嬶紝鑷瀹夎鍚с��
+
+## 4 缂栬瘧ZLMediaKit
+鍙傝�僙LMediaKit[WIKI](https://github.com/ZLMediaKit/ZLMediaKit/wiki)锛屾埅鍙栦竴涓嬪叧閿楠わ細
+```bash
+# 鍥藉唴鐢ㄦ埛鎺ㄨ崘浠庡悓姝ラ暅鍍忕綉绔檊itee涓嬭浇 
+git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
+cd ZLMediaKit
+# 鍗冧竾涓嶈蹇樿鎵ц杩欏彞鍛戒护
+git submodule update --init
+```
+## 5 缂栬瘧WVP-PRO
+### 5.1 鍙互閫氳繃git鍏嬮殕锛屼篃鍙互鍦ㄩ」鐩笅杞界偣鍑讳笅杞�
+![鐐瑰嚮涓嬭浇](_media/img_1.png)
+![鐐瑰嚮涓嬭浇](_media/img_2.png)
+浠巊itee鍏嬮殕
+```bash
+git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
+```
+浠巊ithub鍏嬮殕
+```bash
+git clone https://github.com/648540858/wvp-GB28181-pro.git
+```
+
+### 5.2 缂栬瘧鍓嶇椤甸潰
+```shell script
+cd wvp-GB28181-pro/web_src/
+npm --registry=https://registry.npm.taobao.org install
+npm run build
+```
+缂栬瘧濡傛灉鎶ラ敊, 涓�鑸兘鏄綉缁滈棶棰�, 瀵艰嚧鐨勪緷璧栧寘涓嬭浇澶辫触  
+缂栬瘧瀹屾垚鍚庡湪src/main/resources涓嬪嚭鐜皊tatic鐩綍
+**缂栬瘧瀹屾垚涓�鑸槸杩欎釜鏍峰瓙锛屼腑闂存病鏈夋姤绾㈢殑閿欒淇℃伅**
+![缂栬瘧鎴愬姛](_media/img.png)
+
+### 5.3 鎵撳寘椤圭洰, 鐢熸垚鍙墽琛宩ar
+```bash
+cd wvp-GB28181-pro
+mvn package
+```
+缂栬瘧濡傛灉鎶ラ敊, 涓�鑸兘鏄綉缁滈棶棰�, 瀵艰嚧鐨勪緷璧栧寘涓嬭浇澶辫触  
+缂栬瘧瀹屾垚鍚庡湪target鐩綍涓嬪嚭鐜皐vp-pro-***.jar銆�  
+鎺ヤ笅鏉閰嶇疆鏈嶅姟](./_content/introduction/config.md)
+
+  
+
+
+
+
+
+
diff --git a/doc/_content/introduction/config.md b/doc/_content/introduction/config.md
new file mode 100644
index 0000000..feb7487
--- /dev/null
+++ b/doc/_content/introduction/config.md
@@ -0,0 +1,119 @@
+<!-- 閰嶇疆 -->
+# 閰嶇疆
+瀵逛簬棣栨娴嬭瘯鎴栬�呮柊鎵嬪悓瀛︼紝鎴戝缓璁湪灞�鍩熺綉娴嬭瘯锛屽苟涓斿叧闂湇鍔″櫒涓庡鎴锋満鐨勯槻鐏娴嬭瘯銆傚缓璁儴缃插湪linux杩涜娴嬭瘯銆�
+
+```plantuml
+@startuml
+"WVP-PRO" -> "ZLMediaKit": RESTful 鎺ュ彛
+"WVP-PRO" <-- "ZLMediaKit": Web Hook 鎺ュ彛
+@enduml
+```
+WVP-PRO閫氳繃璋冪敤ZLMediaKit鐨凴ESTful鎺ュ彛瀹炵幇瀵筞LMediaKit琛屼负鐨勬帶鍒�; ZLMediaKit閫氳繃Web Hook 鎺ュ彛鎶婃秷鎭�氱煡WVP-PRO銆傞�氳繃杩欑鏂瑰紡锛屽疄鐜颁簡涓よ�呯殑浜掗�氥��
+瀵逛簬鏈�绠�鍗曠殑閰嶇疆锛屼綘涓嶉渶瑕佷慨鏀筞LMediaKit鐨勪换浣曢粯璁ら厤缃�備綘鍙渶瑕佸湪WVP-PRO涓厤缃殑ZLMediaKit淇℃伅鍗冲彲
+## 1 WVP閰嶇疆鏂囦欢浣嶇疆
+鍩轰簬spring boot鐨勫紑鍙戞柟寮忥紝閰嶇疆鏂囦欢鐨勫姞杞芥槸寰堢伒娲荤殑銆傞粯璁ゅ湪src/main/resources/application.yml锛岄儴鍒嗛厤缃」鏄彲閫夛紝浣犱笉闇�瑕佸叏閮ㄩ厤缃湪閰嶇疆鏂囦欢涓紝
+瀹屽叏鐨勯厤缃鏄庡彲浠ュ弬鐪媋ll-application.yml銆�
+### 1.1 榛樿鍔犺浇閰嶇疆鏂囦欢鏂瑰紡
+浣跨敤maven鎵撳寘鍚庣殑jar鍖呴噷锛屽凡缁忓瓨鍦ㄤ簡閰嶇疆鏂囦欢锛屼絾鏄瘡娆℃墦寮�jar鍖呬慨鏀归厤缃枃浠舵垨鑰呬慨鏀瑰悗鍐嶆墦鍖呴兘鏄瘮杈冮夯鐑︾殑锛屾墍浠ュぇ瀹跺彲閫氳繃鎸囧畾閰嶇疆鏂囦欢璺緞鏉ュ姞杞芥寚瀹氫綅缃殑閰嶇疆鏂囦欢銆�
+```shell
+cd wvp-GB28181-pro/target
+java -jar wvp-pro-*.jar --spring.config.location=../src/main/resources/application.yml
+```
+### 1.2 杩佺Щ閰嶇疆鏂囦欢浠ユ柟渚垮惎鍔�
+鐢变簬閰嶇疆鏂囦欢鐨勫懡浠ゆ瘮杈冮暱锛屾墍浠ヤ负浜嗗惎鍔ㄦ柟渚块�氬父鎴戜細鎶婇厤缃枃浠舵斁鍒癹ar鍖呯殑鍚岀骇鐩綍锛岀被浼艰繖鏍�,
+绉婚櫎jar鍖呭唴/BOOT-INF/classes/涓嬫墍鏈変互application寮�澶寸殑鏂囦欢锛屼娇鐢ㄨВ鍘嬬缉宸ュ叿鎵撳紑jar鍗冲彲锛屼笉闇�瑕佽В鍘嬪嚭鏉ャ��
+```shell
+cd wvp-GB28181-pro/target
+mv ../src/main/resources/application-dev.yml application.yml 
+java -jar wvp-pro-*.jar 
+```
+杩欎篃鏄垜鑷繁鏈�甯哥敤鐨勬柟寮忋��
+## 2 閰嶇疆WVP-PRO
+### 2.1 Mysql鏁版嵁搴撻厤缃�
+棣栧厛浣犻渶瑕佸垱寤轰竴涓悕涓簑vp锛堜篃鍙娇鐢ㄥ叾浠栧悕瀛楋級鐨勬暟鎹簱锛屽苟浣跨敤sql/mysql.sql瀵煎叆鏁版嵁搴擄紝鍒濆鍖栨暟鎹簱缁撴瀯銆�
+鍦╝pplication-dev.yml涓厤缃紙浣跨敤1.2鏂瑰紡鐨勬槸鍦╦ar鍖呯殑鍚岀骇鐩綍鐨刟pplication.yml锛夐厤缃暟鎹簱杩炴帴锛屽寘鎷暟鎹簱杩炴帴淇℃伅锛屽瘑鐮併��
+### 2.2 Redis鏁版嵁搴撻厤缃�
+閰嶇疆wvp涓殑redis杩炴帴淇℃伅锛屽缓璁畐vp鑷繁鍗曠嫭浣跨敤涓�涓猟b銆�
+### 2.3 閰嶇疆鏈嶅姟鍚姩绔彛锛堝彲鐩存帴浣跨敤榛樿閰嶇疆锛�
+```yaml
+# [鍙�塢 WVP鐩戝惉鐨凥TTP绔彛, 缃戦〉鍜屾帴鍙h皟鐢ㄩ兘鏄繖涓鍙�
+server:
+    port: 18080
+```
+### 2.4 閰嶇疆28181鐩稿叧淇℃伅锛堝彲鐩存帴浣跨敤榛樿閰嶇疆锛�
+```yaml
+# 浣滀负28181鏈嶅姟鍣ㄧ殑閰嶇疆
+sip:
+    # [蹇呴』淇敼] 鏈満鐨処P
+    ip: 192.168.1.3
+    # [鍙�塢 28181鏈嶅姟鐩戝惉鐨勭鍙�
+    port: 5060
+    # 鏍规嵁鍥芥爣6.1.2涓瀹氾紝domain瀹滈噰鐢↖D缁熶竴缂栫爜鐨勫墠鍗佷綅缂栫爜銆傚浗鏍囬檮褰旸涓畾涔夊墠8浣嶄负涓績缂栫爜锛堢敱鐪佺骇銆佸競绾с�佸尯绾с�佸熀灞傜紪鍙风粍鎴愶紝鍙傜収GB/T 2260-2007锛�
+    # 鍚庝袱浣嶄负琛屼笟缂栫爜锛屽畾涔夊弬鐓ч檮褰旸.3
+    # 3701020049鏍囪瘑灞变笢娴庡崡鍘嗕笅鍖� 淇℃伅琛屼笟鎺ュ叆
+    # [鍙�塢
+    domain: 3402000000
+    # [鍙�塢
+    id: 34020000002000000001
+    # [鍙�塢 榛樿璁惧璁よ瘉瀵嗙爜锛屽悗缁墿灞曚娇鐢ㄨ澶囧崟鐙瘑鐮�, 绉婚櫎瀵嗙爜灏嗕笉杩涜鏍¢獙
+    password: 12345678
+```
+### 2.5 閰嶇疆ZLMediaKit杩炴帴淇℃伅
+```yaml
+#zlm 榛樿鏈嶅姟鍣ㄩ厤缃�
+media:
+    # ZLMediaKit鐨勬湇鍔D锛屽繀椤婚厤缃�
+    id: FQ3TF8yT83wh5Wvz
+    # [蹇呴』淇敼] zlm鏈嶅姟鍣ㄧ殑鍐呯綉IP锛宻dp-ip涓巗tream-ip浣跨敤榛樿鍊肩殑鎯呭喌涓嬶紝杩欓噷涓嶈浣跨敤127.0.0.1/0.0.0.0
+    ip: 192.168.1.3
+    # [蹇呴』淇敼] zlm鏈嶅姟鍣ㄧ殑http.port
+    http-port: 6080
+    # [鍙�塢 zlm鏈嶅姟鍣ㄧ殑hook.admin_params=secret
+    secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
+    # 鍚敤澶氱鍙fā寮�, 澶氱鍙fā寮忎娇鐢ㄧ鍙e尯鍒嗘瘡璺祦锛屽吋瀹规�ф洿濂姐�� 鍗曠鍙d娇鐢ㄦ祦鐨剆src鍖哄垎锛� 鐐规挱瓒呮椂寤鸿浣跨敤澶氱鍙f祴璇�
+    rtp:
+        # [鍙�塢 鏄惁鍚敤澶氱鍙fā寮�, 寮�鍚悗浼氬湪portRange鑼冨洿鍐呴�夋嫨绔彛鐢ㄤ簬濯掍綋娴佷紶杈�
+        enable: true
+        # [鍙�塢 鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鐢ㄤ簬濯掍綋娴佷紶杈�,
+        port-range: 30000,30500 # 绔彛鑼冨洿
+        # [鍙�塢 鍥芥爣绾ц仈鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鍙戦�佸獟浣撴祦,
+        send-port-range: 30000,30500 # 绔彛鑼冨洿
+    # 褰曞儚杈呭姪鏈嶅姟锛� 閮ㄧ讲姝ゆ湇鍔″彲浠ュ疄鐜皕lm褰曞儚鐨勭鐞嗕笌涓嬭浇锛� 0 琛ㄧず涓嶄娇鐢�
+    record-assist-port: 18081
+```
+### 2.4 涓�у寲瀹氬埗淇℃伅閰嶇疆
+```yaml
+# [鏍规嵁涓氬姟闇�姹傞厤缃甝
+user-settings:
+    # [鍙�塢 鏈嶅姟ID锛屼笉鍐欏垯涓�000000
+    server-id:
+    # [鍙�塢 鑷姩鐐规挱锛� 浣跨敤鍥哄畾娴佸湴鍧�杩涜鎾斁鏃讹紝濡傛灉鏈偣鎾垯鑷姩杩涜鐐规挱, 闇�瑕乺tp.enable=true
+    auto-apply-play: false
+    # [鍙�塢 閮ㄥ垎璁惧闇�瑕佹墿灞昐DP锛岄渶瑕佹墦寮�姝よ缃�
+    senior-sdp: false
+    # 淇濆瓨绉诲姩浣嶇疆鍘嗗彶杞ㄨ抗锛歵rue:淇濈暀鍘嗗彶鏁版嵁锛宖alse:浠呬繚鐣欐渶鍚庣殑浣嶇疆(榛樿)
+    save-position-history: false
+    # 鐐规挱绛夊緟瓒呮椂鏃堕棿,鍗曚綅锛氭绉�
+    play-timeout: 3000
+    # 绛夊緟闊宠棰戠紪鐮佷俊鎭啀杩斿洖锛� true锛� 鍙互鏍规嵁缂栫爜閫夋嫨鍚堥�傜殑鎾斁鍣紝false锛� 鍙互鏇村揩鐐规挱
+    wait-track: false
+    # 鏄惁寮�鍚帴鍙i壌鏉�
+    interface-authentication: true
+    # 鑷姩閰嶇疆redis 鍙互杩囨湡浜嬩欢
+    redis-config: true
+    # 鎺ュ彛閴存潈渚嬪鐨勬帴鍙�, 鍗充笉杩涜鎺ュ彛閴存潈鐨勬帴鍙�,灏介噺璇︾粏涔﹀啓锛屽敖閲忎笉鐢�/**锛岃嚦灏戜袱绾х洰褰�
+    interface-authentication-excludes:
+        - /api/v1/**
+    # 鎺ㄦ祦鐩存挱鏄惁褰曞埗
+    record-push-live: true
+    # 鍥芥爣鏄惁褰曞埗
+    record-sip: true
+    # 鏄惁灏嗘棩蹇楀瓨鍌ㄨ繘鏁版嵁搴�
+    logInDatebase: true
+    # 绗笁鏂瑰尮閰嶏紝鐢ㄤ簬浠巗tream閽熻幏鍙栨湁鏁堜俊鎭�
+    thirdPartyGBIdReg: [\s\S]*
+```
+
+
+濡傛灉閰嶇疆淇℃伅鏃犺锛屼綘鍙互鍚姩zlm锛屽啀鍚姩wvp鏉ユ祴璇曚簡锛屽惎鍔ㄦ垚鍔熺殑璇濓紝浣犲彲浠ュ湪wvp鐨勬棩蹇椾笅鐪嬪埌zlm宸茶繛鎺ョ殑鎻愮ず銆�
+鎺ヤ笅鏉閮ㄧ讲鍒版湇鍔″櫒](./_content/introduction/deployment.md)锛� 濡備綍浣犲彧鏄湰鍦拌繍琛岀洿鎺ュ啀鏈湴杩愯鍗冲彲銆�
\ No newline at end of file
diff --git a/doc/_content/introduction/deployment.md b/doc/_content/introduction/deployment.md
new file mode 100644
index 0000000..cdc1568
--- /dev/null
+++ b/doc/_content/introduction/deployment.md
@@ -0,0 +1,36 @@
+<!-- 閮ㄧ讲 -->
+
+# 閮ㄧ讲
+**璇蜂粩缁嗛槄璇讳互涓嬪唴瀹�**
+1. WVP-PRO涓嶼LM鏀寔鍒嗗紑閮ㄧ讲锛屼絾鏄痺vp-pro-assist蹇呴』涓巣lm閮ㄧ讲鍦ㄥ悓涓�鍙颁富鏈�;
+2. 闇�瑕佸紑鏀剧殑绔彛
+| 鏈嶅姟  | 绔彛                       | 绫诲瀷          | 蹇呴��    |
+|-----|:-------------------------|-------------|-------|
+| wvp | server.port              | tcp         | 鏄�     |
+| wvp | sip.port                 | udp and tcp | 鏄�     |
+| zlm | http.port                | tcp         | 鏄�     |
+| zlm | http.sslport             | tcp         | 鍚�     |
+| zlm | rtmp.port                | tcp         | 鍚�     |
+| zlm | rtmp.sslport             | tcp         | 鍚�     |
+| zlm | rtsp.port                | udp and tcp | 鍚�     |
+| zlm | rtsp.sslport             | udp and tcp | 鍚�     |
+| zlm | rtp_proxy.port           | udp and tcp | 鍗曠鍙e紑鏀� |
+| zlm | rtp.port-range(鍦╳vp涓厤缃�)  | udp and tcp | 澶氱鍙e紑鏀� |
+
+3. 娴嬭瘯鐜閮ㄧ讲寤鸿鎵�鏈夋湇鍔¢儴缃插湪涓�鍙颁富鏈猴紝鍏抽棴闃茬伀澧欙紝鍑忓皯鍥犵綉缁滃嚭鐜伴棶棰樼殑鍙兘;
+4. WVP-PRO涓嶼LM鏀寔鍒嗗紑閮ㄧ讲锛屼絾鏄痺vp-pro-assist蹇呴』涓巣lm閮ㄧ讲鍦ㄥ悓涓�鍙颁富鏈�;
+5. 鐢熶骇鐜鎸夐渶寮�鏀剧鍙o紝浣嗘槸寤鸿淇敼榛樿绔彛锛屽挨鍏舵槸5060绔彛锛屾槗鍙楀埌鏀诲嚮;
+6. zlm浣跨敤docker閮ㄧ讲鐨勬儏鍐碉紝瑕佹眰绔彛鏄犲皠涓�鑷达紝姣斿鏄犲皠5060,搴斿皢澶栭儴绔彛涔熸槧灏勪负5060绔彛;
+7. 鍚姩鏈嶅姟锛屼互linux涓轰緥
+**鍚姩WVP-PRO**
+```shell
+nohup java -jar java -jar wvp-pro-*.jar &
+```
+
+**鍚姩ZLM**
+```shell
+nohup ./MediaServer -d -m 3 &
+```
+
+[鎺ュ叆璁惧](./_content/ability/device.md)
+
diff --git a/doc/_content/qa/_media/img.png b/doc/_content/qa/_media/img.png
new file mode 100644
index 0000000..d6c29d7
--- /dev/null
+++ b/doc/_content/qa/_media/img.png
Binary files differ
diff --git a/doc/_content/qa/_media/img_1.png b/doc/_content/qa/_media/img_1.png
new file mode 100644
index 0000000..5b74d95
--- /dev/null
+++ b/doc/_content/qa/_media/img_1.png
Binary files differ
diff --git a/doc/_content/qa/_media/img_2.png b/doc/_content/qa/_media/img_2.png
new file mode 100644
index 0000000..4aaa7fe
--- /dev/null
+++ b/doc/_content/qa/_media/img_2.png
Binary files differ
diff --git a/doc/_content/qa/_media/img_3.png b/doc/_content/qa/_media/img_3.png
new file mode 100644
index 0000000..27f8a96
--- /dev/null
+++ b/doc/_content/qa/_media/img_3.png
Binary files differ
diff --git a/doc/_content/qa/_media/img_4.png b/doc/_content/qa/_media/img_4.png
new file mode 100644
index 0000000..aa3b88e
--- /dev/null
+++ b/doc/_content/qa/_media/img_4.png
Binary files differ
diff --git a/doc/_content/qa/_media/img_5.png b/doc/_content/qa/_media/img_5.png
new file mode 100644
index 0000000..76e6faf
--- /dev/null
+++ b/doc/_content/qa/_media/img_5.png
Binary files differ
diff --git a/doc/_content/qa/bug.md b/doc/_content/qa/bug.md
new file mode 100644
index 0000000..f452161
--- /dev/null
+++ b/doc/_content/qa/bug.md
@@ -0,0 +1,19 @@
+<!-- 鍙嶉bug -->
+# 鍙嶉bug
+浠g爜鏄湪涓嶆柇鐨勫畬鍠勭殑锛屼笉鏂慨鏀逛細淇鏃х殑闂涔熸湁鍙兘寮曞叆鏂扮殑闂锛屾墍浠ラ亣鍒癇UG鏄緢姝e父鐨勪竴浠朵簨銆傛墍浠ラ亣鍒伴棶棰樹笉瑕佺儲鐕ワ紝鍜变滑灏变簨璁轰簨灏卞ソ浜嗐��
+## 濡備綍鍙嶉
+1. 鏇存柊浠g爜锛屽緢鍙兘浣犻亣鍒伴棶棰樺埆浜哄凡缁忔洿鏃╃殑閬囧埌浜嗭紝鎴栬�呮槸浣滆�呰嚜宸卞彂鐜颁簡锛屽凡缁忚В鍐充簡锛屾墍浠ヤ綘鍙互鏇存柊浠g爜鍐嶆杩涜娴嬭瘯;
+2. 鍙互鍦╣ithub鎻怚SSUE锛屾垜鍑犱箮姣忓ぉ閮戒細鍘荤湅issue锛屼綘鐨勯棶棰樻垜浼氬敖蹇粰浜堢瓟澶�;
+3. 浣犲彲浠ユ潵鎴戠殑QQ缇ら噷锛岃闂兢鍙嬬湅鐪嬫槸鍚﹂亣鍒颁簡鍚屾牱鐨勯棶棰�;
+4. 浣犲彲浠ョ鑱婃垜鐨凲Q锛屽鏋滄垜鏈夋椂闂存垜浼氱粰浣犵瓟澶嶏紝浣嗘槸闄ら潪浣犳湁鏄庣‘鐨勫鐜版楠ゆ垨鑰呬慨澶嶆柟妗堬紝鍚﹀垯浣犲彲鑳界瓑涓嶅埌鎴戠殑绛斿銆�
+
+## 濡備綍蹇�熻В鍐矪UG
+鐩墠瑙e喅BUG鏈変笁绉嶆柟寮�:
+1. 浣滆�呴獙璇佷互鍙婁慨澶�;
+2. 鐑績寮�鍙戣�呮彁鏉ョ殑PR;
+3. 浣跨敤杩愮淮鎵嬫灞忚斀BUG鐨勫奖鍝嶃��
+
+- 瀵逛簬绗竴绉嶏細璇︾粏鐨勫鐜版楠わ紝瀹屾暣鐨勬姄鍖呮枃浠讹紝鏈夋潯鐞嗙殑閿欒鍒嗘瀽閮藉彲浠ュ府鍔╀綔鑰呭鐜伴棶棰橈紝杩涜�岃В鍐抽棶棰樸�傝В鍐抽棶棰樺線寰�涓嶆槸鏈�闅剧殑锛屽鐜版墠鏄��
+- 瀵逛簬绗簩绉嶏細濡傛灉浣犳槸寮�鍙戣�咃紝浣犲凡缁忓彂鐜颁簡閫犳垚BUG鐨勫師鍥犱互鍙婄煡閬撳浣曟纭殑淇锛岄偅涔堟垜寰堝笇鏈涗綘PR锛孲RS鐨勫ぇ浣粡甯歌鐨勶紝寮�婧愪笉鏄竴涓汉鐨勪簨銆傛墍浠ヤ綘鐨勫弬涓庡氨鏄渶澶х殑榧撳姳銆�
+- 瀵逛簬绗笁绉嶏細濡傛灉浣犳湁涓�涓湁缁忛獙鐨勮繍缁翠紮浼达紝閭d箞閮ㄥ垎闂鏄彲浠ラ�氳繃杩愮淮鐨勬墜娈垫殏鏃跺睆钄界殑锛屽湪绛夊緟淇鐨勮繖娈垫椂闂翠簡浠ヤ繚璇侀」鐩殑杩愯銆�
+
diff --git a/doc/_content/qa/development.md b/doc/_content/qa/development.md
new file mode 100644
index 0000000..fec7b70
--- /dev/null
+++ b/doc/_content/qa/development.md
@@ -0,0 +1,15 @@
+<!-- 鍙備笌寮�鍙� -->
+# 鍙備笌鍒板紑鍙戜腑鏉�
+闈炲父娆㈣繋鏈夊叴瓒g殑灏忎紮浼翠竴璧锋潵缁存姢杩欎釜椤圭洰
+## 涓庡紑鍙戞湁鍏崇殑淇℃伅
+- 寮�鍙戣瑷�锛氬悗绔痡ava + 鍓嶇vue锛�
+- jdk鐗堟湰锛� 1.8锛�
+- 浣滆�呰嚜鐢ㄥ紑鍙慽de锛� jetbrains intellij idea锛�
+- nodejs/npm鐗堟湰锛歷10.19.0/6.14.4锛�
+- 鍚庣浣跨敤Spring boot妗嗘灦寮�鍙戯紱
+- 椤圭洰澶ч噺浣跨敤浜嗗紓姝ユ搷浣滐紱
+- 璺熶唬鐮佸娴佺▼闇�瑕佸弬鑰�28181鏂囨。锛屽彧鐪嬩唬鐮佷綘浼氬緢鎳电殑锛�
+- 蹇呴』瀛︿細[鎶撳寘](_content/skill/tcpdump.md),杩欐槸蹇呴』鐨�  
+
+## 鎻愪氦浠g爜
+澶у鍙互閫氳繃fork椤圭洰鐨勬柟寮忔彁浜よ嚜宸辩殑浠g爜锛岀劧鍚庢彁浜R锛屾垜鏉ュ悎骞跺埌涓荤嚎銆傛彁浜や唬鐮佺殑杩囩▼涓垜浠渶瑕侀伒寰��**闃块噷缂栫爜瑙勭害**鈥濓紝鐜版湁浠g爜涔熸湁寰堝浠g爜娌℃湁鍋氬埌锛屼絾鏄垜浠湪鏈濊繖涓柟鍚戝姫鍔涖��
\ No newline at end of file
diff --git a/doc/_content/qa/img.png b/doc/_content/qa/img.png
new file mode 100644
index 0000000..d6c29d7
--- /dev/null
+++ b/doc/_content/qa/img.png
Binary files differ
diff --git a/doc/_content/qa/play_error.md b/doc/_content/qa/play_error.md
new file mode 100644
index 0000000..8c9e759
--- /dev/null
+++ b/doc/_content/qa/play_error.md
@@ -0,0 +1,57 @@
+<!-- 鐐规挱閿欒 -->
+# 鐐规挱閿欒
+鎺掓煡鐐规挱閿欒浣犻鍏堣娓呴櫎[鐐规挱鐨勫熀鏈祦绋媇(_content/theory/play.md),涓�鑸殑娴佺▼濡備笅锛�
+```plantuml
+@startuml
+"WEB鐢ㄦ埛"  -> "WVP-PRO": 1. 鍙戣捣鐐规挱璇锋眰
+"璁惧" <-  "WVP-PRO": 2. Invite(鎼哄甫SDP娑堟伅浣�)
+"璁惧" --> "WVP-PRO": 3. 200OK(鎼哄甫SDP娑堟伅浣�)
+"璁惧" <-- "WVP-PRO": 4. Ack
+"璁惧" -> "ZLMediaKit": 5. 鍙戦�佸疄鏃舵祦
+"WVP-PRO" <- "ZLMediaKit": 6. 娴佹敼鍙樹簨浠�
+"WEB鐢ㄦ埛"  <-- "WVP-PRO": 7. 鍥炲娴佹挱鏀惧湴鍧�锛堟惡甯︽祦鍦板潃锛�
+"WVP-PRO" <- "ZLMediaKit": 8. 鏃犱汉瑙傜湅浜嬩欢
+"璁惧" <-  "WVP-PRO": 9 Bye娑堟伅
+"璁惧" -->  "WVP-PRO": 10 200OK
+@enduml
+```
+閽堝鍑犵甯歌鐨勯敊璇紝鎴戜滑鏉ュ垎鏋愪竴涓嬶紝涔熸柟渚垮ぇ瀹跺鍙峰叆搴цВ鍐冲父瑙佺殑闂
+## 鐐规挱鏀跺埌閿欒鐮�
+杩欎釜閿欒涓�鑸〃鐜颁负鐐瑰嚮"鎾斁"鎸夐挳鍚庡緢蹇緱鍒颁竴涓敊璇��
+1. **400閿欒鐮�**  
+鍑虹幇400閿欒鐜涙椂涓�鑸槸杩欐牱鐨勬祦绋嬫槸杩欐牱鐨�
+```plantuml
+@startuml
+"WEB鐢ㄦ埛"  -> "WVP-PRO": 1. 鍙戣捣鐐规挱璇锋眰
+"璁惧" <-  "WVP-PRO": 2. Invite(鎼哄甫SDP娑堟伅浣�)
+"璁惧" --> "WVP-PRO": 3. 400閿欒
+@enduml
+```
+姝ゆ椂閫氬父鏄澶囪涓篧VP鍙戦�佷簡閿欒鐨勬秷鎭粰瀹冿紝瀹冭涓烘秷鎭笉鍏ㄦ垨鑰呴敊璇墍浠ョ洿鎺ヨ繑鍥�400閿欒锛屾鏃舵垜浠渶瑕乕鎶撳寘](_content/skill/tcpdump.md)鏉ュ垎鏋愭槸鍚︾己澶变簡鍐呭锛屼篃鍙互鐩存帴鑱旂郴瀵规柟璇㈤棶涓轰粈涔堣繑鍥炰簡400銆�
+WVP涓嶈兘淇濊瘉鍏煎鎵�鏈夌殑璁惧锛屾湁浜涘疄鐜颁笉瑙勮寖鐨勮澶囧彲鑳藉湪瀵规帴鏃跺氨浼氬嚭鐜颁笂杩伴棶棰橈紝浣犲彲浠ヨ仈绯讳綔鑰呭府蹇欏鎺ャ��
+2. **500閿欒鐮�**  
+500鎴栬�呭ぇ浜�500灏忎簬600鐨勯敊璇爜涓�鑸鏄澶囧唴閮ㄥ嚭浜嗛棶棰橈紝瑙e喅鏂瑰紡鏈変袱涓紝绗竴绉嶇洿鎺ヨ仈绯昏澶�/骞冲彴瀹㈡湇瀵绘眰瑙e喅锛涚浜岀锛屽鏋滀綘鏈夌‘瀹氬彲浠ュ鎺ヨ繖涓澶囩殑骞冲彴閭d箞鍙互鎶婂鎺ヨ繖涓钩鍙扮殑鎶撳寘鍜屽鎺vp鐨勬姄鍖呭悓鏃跺彂閫佺粰鎴戯紝鎴戞潵灏濊瘯瑙e喅銆�
+
+
+## 鐐规挱瓒呮椂
+鐐规挱瓒呮椂鐨勬儏鍐靛ぇ鑷村垎涓轰袱绉嶏細鐐规挱瓒呮椂鍜屾敹娴佽秴鏃�
+1. **鐐规挱瓒呮椂**  
+鐐规挱瓒呮椂閿欒涓�鑸负淇′护鐨勮秴鏃讹紝姣斿闀挎椂闂翠负鏀跺埌瀵规柟鐨勫洖澶嶏紝鍙兘鍑虹幇鍦ㄦ祦绋嬩腑 鈥�3. 200OK(鎼哄甫SDP娑堟伅浣�)鈥濊繖涓綅缃紝鍗虫垜浠彂閫佺偣鎾秷鎭紝浣嗘槸璁惧娌℃湁鍥炲锛屽彲鑳界殑鍘熷洜锛�
+> 1. 璁惧鍐呴儴閿欒锛屾湭鑳藉洖澶嶆秷鎭�
+> 2. 缃戠粶鍘熷洜娑堟伅鏈埌鍒拌揪璁惧  
+
+澶ч儴鍒嗘椂鍊欐槸鍘熷洜2锛屾墍浠ラ亣鍒拌繖涓敊璇垜浠鍏堣鎺掓煡鎴戜滑鎴戠殑缃戣矾锛屽鏋滀綘鏄叕缃戦儴缃诧紝閭d箞涔熷彲鑳芥椂蹇冭烦鍛ㄦ湡澶暱锛屽鑷寸殑璺敱NAT澶辨晥锛學VP鐨勬秷鎭棤娉曢�氶亾鍘熸潵鐨処P绔彛鍙峰彂閫佺粰璁惧銆�
+
+2. **鏀舵祦瓒呮椂**  
+鏀舵祦瓒呮椂鍙兘鍙戠敓鍦ㄦ祦绋嬩腑鐨�5鍜�6,鍙兘鐨勫師鍥犳湁锛�
+> 1. 璁惧鍙戦�佷簡娴佷絾鏄彂閫佸埌浜嗛敊璇殑ip鍜岀鍙d笂锛岃�岃繖涓俊鎭槸鍦╥nvite娑堟伅鐨剆dp涓寚瀹氱殑锛屽氨鏄祦绋�2Invite(鎼哄甫SDP娑堟伅浣�)涓紝鑰岃繖涓敊璇緢鍙兘鏉ヨ嚜浣犵殑閰嶇疆閿欒锛屾瘮濡備綘璁剧疆浜�127.0.0.1瀵艰嚧璁惧缃�127.0.0.1涓婂彂娴侊紝鎴栬�呮槸浣燱VP鍦ㄥ叕缃戯紝浣嗘槸浣犵粰璁惧浜嗕竴涓唴缃慽p锛屽鑷磋澶囨棤娉曟妸娴佸彂閫佽繃鏉ワ紱
+> 2. 璁惧鍐呴儴閿欒鏈彂閫佹祦锛�
+> 2. 璁惧鍙戦�佷簡娴侊紝浣嗘槸娴佹棤娉曡瘑鍒紝鍙兘瀛樺湪浜庢祦涓嶈鑼冨拰缃戠粶寰堝樊鐨勬儏鍐典笅锛�
+> 3. 璁惧鍙戦�佷簡娴侊紝zlm涔熸敹鍒颁簡锛屼絾鏄痾lm鏃犳硶閫氳繃hook閫氱煡鍒皐vp锛屾鏃跺師鍥犳槸浣犲彲浠ユ鏌lm鐨勯厤缃枃浠朵腑鐨刪ook閰嶇疆锛岀湅鐪嬫槸鍚︽棤娉曚粠zlm杩炴帴鍒皐vp锛�
+> 4. 璁惧鍙戦�佷簡娴侊紝浣嗘槸寮�鍚疭SRC鏍¢獙锛岃澶囩殑娴佷笉澶熻鑼冮噰鐢ㄩ敊璇殑ssrc锛屽鑷磟lm閫夋嫨涓㈠純锛�
+ 
+閽堝杩欎簺鍙兘鐨勯敊璇師鍥犳垜寤鸿鐨勬帓鏌ラ『搴忥細  
+- 鍏抽棴ssrc鏍¢獙锛�
+- 鏌ョ湅zlm閰嶇疆鐨刪ook鏄惁鍙互杩炴帴鍒皕lm锛�
+- 鏌ョ湅zlm鏃ュ織鏄惁鏈夋祦娉ㄥ唽锛�
+- 鎶撳寘鏌ョ湅娴佺殑淇℃伅锛岀湅鐪嬫祦鏄惁姝e父鍙戦�侊紝鐢氳嚦鍙互瀵煎嚭鍙戦�佸師濮嬫祦锛岀敤vlc鎾斁锛岀湅鐪嬫槸鍚﹀彲浠ユ挱鏀俱��
diff --git a/doc/_content/qa/regiser_error.md b/doc/_content/qa/regiser_error.md
new file mode 100644
index 0000000..d18459c
--- /dev/null
+++ b/doc/_content/qa/regiser_error.md
@@ -0,0 +1,8 @@
+<!-- 璁惧娉ㄥ唽涓嶄笂鏉ョ殑瑙e喅鍔炴硶 -->
+# 璁惧娉ㄥ唽涓嶄笂鏉ョ殑瑙e喅鍔炴硶
+涓�鑸殑鍘熷洜鏈変袱涓�
+1. 淇℃伅濉啓閿欒锛屾瘮濡傚瘑鐮侀敊璇紱 
+2. 缃戠粶涓嶉�氬鑷存敞鍐屾秷鎭棤娉曞彂閫佸埌WVP锛� 
+
+
+閬囧埌闂棣栧厛浠旂粏鏍¢獙濉啓淇℃伅锛屼緥濡傛捣搴峰彲鑳介渶瑕佸嬀閫夐壌鏉冩墠鍙互杈撳叆瀵嗙爜銆傜綉缁滈棶棰樿鑷娴嬭瘯銆�
\ No newline at end of file
diff --git a/doc/_content/qa/start_error.md b/doc/_content/qa/start_error.md
new file mode 100644
index 0000000..1dd533f
--- /dev/null
+++ b/doc/_content/qa/start_error.md
@@ -0,0 +1,24 @@
+<!-- 鍚姩鏃舵姤閿� -->
+# 鍚姩鏃舵姤閿�
+鍚姩鏃剁殑鎶ラ敊澶ч儴鍒嗘椂鍊欐槸鍥犱负浣犵殑閰嶇疆鏈夐棶棰橈紝姣斿mysql娌¤繛鎺ヤ笂锛宺edis娌¤繛鎺ヤ笂锛�18080/15060绔彛鍗犵敤浜嗭紝杩欎簺閮戒細瀵艰嚧鍚姩鏄姤閿欙紝淇敼閰嶇疆閰嶇疆涔嬪悗閮藉彲浠ヨВ鍐筹紱
+涓嬮潰鎴戞暣鐞嗙殑涓�浜涘父瑙佺殑閿欒锛屽ぇ瀹跺彲浠ュ厛瀵瑰彿鍏ュ骇鐨勭畝鍗曟帓鏌ヤ笅銆�
+> **甯歌閿欒**  
+
+![_media/img.png](_media/img.png)
+**閿欒鍘熷洜锛�** redis閰嶇疆閿欒锛屽彲鑳藉師鍥狅細 redis鏈惎鍔�/ip閿欒/绔彛閿欒/缃戠粶涓嶉��  
+---
+![_media/img_1.png](_media/img_1.png)
+**閿欒鍘熷洜锛�** redis閰嶇疆閿欒锛屽彲鑳藉師鍥狅細 瀵嗙爜閿欒
+---
+![_media/img_2.png](_media/img_2.png)
+**閿欒鍘熷洜锛�** mysql閰嶇疆閿欒锛屽彲鑳藉師鍥狅細 mysql鏈惎鍔�/ip閿欒/绔彛閿欒/缃戠粶涓嶉��  
+---
+![_media/img_3.png](_media/img_3.png)
+**閿欒鍘熷洜锛�** mysql閰嶇疆閿欒锛屽彲鑳藉師鍥狅細 鐢ㄦ埛鍚�/瀵嗙爜閿欒
+---
+![_media/img_4.png](_media/img_4.png)
+**閿欒鍘熷洜锛�** SIP閰嶇疆閿欒锛屽彲鑳藉師鍥狅細 SIP绔彛琚崰鐢�
+---
+![_media/img_5.png](_media/img_5.png)
+**閿欒鍘熷洜锛�** WVP Tomcat绔彛閰嶇疆閿欒锛屽彲鑳藉師鍥狅細 server.port绔彛琚崰鐢�
+---
\ No newline at end of file
diff --git a/doc/_content/skill/_media/img.png b/doc/_content/skill/_media/img.png
new file mode 100644
index 0000000..a9bc95f
--- /dev/null
+++ b/doc/_content/skill/_media/img.png
Binary files differ
diff --git a/doc/_content/skill/_media/img_1.png b/doc/_content/skill/_media/img_1.png
new file mode 100644
index 0000000..e08e4e1
--- /dev/null
+++ b/doc/_content/skill/_media/img_1.png
Binary files differ
diff --git a/doc/_content/skill/_media/img_2.png b/doc/_content/skill/_media/img_2.png
new file mode 100644
index 0000000..2af0ecc
--- /dev/null
+++ b/doc/_content/skill/_media/img_2.png
Binary files differ
diff --git a/doc/_content/skill/tcpdump.md b/doc/_content/skill/tcpdump.md
new file mode 100644
index 0000000..7dd270d
--- /dev/null
+++ b/doc/_content/skill/tcpdump.md
@@ -0,0 +1,62 @@
+<!-- 鎶撳寘 -->
+# 鎶撳寘
+濡傛灉璇村浜庣綉缁滅紪绋嬶紝鏈変粈涔堝伐鍏锋槸蹇呬細鐨勶紝鎴戣寰楁姄鍖呰偗瀹氭槸鍏朵腑涔嬩竴浜嗐�備綔涓篏B/T 28181璋冭瘯杩囩▼涓渶閲嶈鐨勬墜娈碉紝鎴戣寰楀鏋滀綘鐪熷浠栨湁鍏磋叮锛屾垨鑰呯郴缁熼亣鍒伴棶棰樺彲浠ユ渶蹇殑寰楀埌瑙e喅锛岄偅涔堟姄鍖呬綘灏变竴瀹氳瀛︿細浜嗐��
+
+## 鎶撳寘宸ュ叿鐨勯�夋嫨
+### 1. Wireshark
+鍦ㄥ叿澶囧浘褰㈢晫闈㈢殑绯荤粺涓婏紝姣斿windows锛宭inux鍙戣鐗坲buntu锛宱pensuse绛夛紝鎴戜竴鑸洿鎺ヤ娇鐢╓ireshark鐩存帴杩涜鎶撳寘锛屼篃鏂逛究杩涜鍐呭鐨勬煡鐪嬨��
+### 2. Tcpdump
+鍦ㄤ娇鐢ㄥ懡浠よ鐨勭郴缁燂紝姣斿linux鏈嶅姟鍣紝鎴戜竴鑸娇鐢═cpdump杩涜鎶撳寘锛屾棤闇�棰濆瀹夎锛岀郴缁熶竴鑸嚜甯︼紝鎶撳寘鐨勫埌鐨勬枃浠讹紝鍙互浣跨敤Wireshark鎵撳紑锛屽湪鍥惧舰鐣岄潰涓嬫柟渚挎煡鐪嬪唴瀹广��
+
+## 宸ュ叿瀹夎
+Wireshark鐨勫畨瑁呭緢绠�鍗曪紝鏍规嵁鎻愮ず涓�姝ユ鐐瑰嚮灏卞ソ浜嗭紝鍦╨inux闇�瑕佽В鍐虫潈闄愮殑闂锛屽鏋滃拰鎴戜竴鏍蜂娇鐢ㄥ浘褰㈢晫闈㈢殑linux鍙戣鐗堢殑璇濓紝鍙互鍙傜湅濡備笅姝ラ; windows鐨勫皬浼欎即鐩存帴鐣ヨ繃鍗冲彲
+```shell
+# 1. 娣诲姞wireshark鐢ㄦ埛缁�
+sudo groupadd wireshark
+# 2. 灏哾umpcap鏇存敼涓簑ireshark鐢ㄦ埛缁�
+sudo chgrp wireshark /usr/bin/dumpcap
+# 3. 璁﹚ireshark鐢ㄦ埛缁勬湁root鏉冮檺浣跨敤dumpcap
+sudo chmod 4755 /usr/bin/dumpcap
+# 4. 灏嗛渶瑕佷娇鐢ㄧ殑鐢ㄦ埛鍚嶅姞鍏ireshark鐢ㄦ埛缁�
+sudo gpasswd -a $USER wireshark
+```
+tcpdump涓�鑸琹inux閮芥槸鑷甫锛屾棤闇�瀹夎锛屽彲浠ヨ繖鏍烽獙璇�;鏄剧ず鐗堟湰淇℃伅鍗虫槸宸插畨瑁�
+```shell
+tcpdump --version
+```
+## 寮�濮嬫姄鍖�
+### 浣跨敤Wireshark
+鍦�28181涓垜涓�鑸彧鍏虫敞sip鍖呭拰rtp鍖咃紝鎵�浠ユ垜涓�鑸槸鐩存帴杩囨护sip鍜宺tp锛屽彲浠ヨ緭鍏ユ杈撳叆 `sip or rtp`杩欐牱鍗冲彲锛屽鏋滆澶囨潵婧愭瘮杈冨杩樺彲浠ュ姞涓奿p鍜岀鍙e彿鐨勮繃婊(sip or rtp )and ip.addr==192.168.1.3 and udp.port==5060`
+璇︾粏鐨勮繃婊よ鍒欏彲浠ヨ嚜琛岀櫨搴︼紝鎴戝彲浠ユ彁渚涗竴浜涘父鐢ㄧ殑缁欏ぇ瀹跺弬鑰�
+![img.png](_media/img.png)  
+**鍙繃婊IP锛�**
+```shell
+sip
+```
+**鍙幏鍙杛tp鏁版嵁锛�**
+```shell
+rtp
+```
+**榛樿鏂瑰紡锛�**
+```shell
+sip or rtp
+```
+**杩囨护IP锛�**
+```shell
+ sip and ip.addr==192.168.1.3
+```
+**杩囨护绔彛锛�**
+```shell
+ sip and udp.port==5060
+```
+杈撳叆鍛戒护寮�鍚姄鍖呭悗锛屾鏃跺彲浠ヨ繘琛屾搷浣滐紝姣斿鐐规挱锛屽綍鍍忓洖璁跨瓑锛屾搷浣滃畬鎴愬洖鍒癢ireshark鐐瑰嚮绾㈣壊鐨勫仠姝㈠嵆鍙紝闇�瑕佷繚瀛樻枃浠跺彲浠ョ偣鍑籤鏂囦欢->瀵煎嚭鐗瑰畾鍒嗙粍`瀵煎嚭杩囨护鍚庣殑鏁版嵁锛屼篃鍙互鐩存帴`鏂囦欢->鍙﹀瓨涓篳淇濆瓨鏈繃婊ょ殑鏁版嵁銆�
+### 浣跨敤tcpdump
+瀵逛簬鏈嶅姟鍣ㄦ姄鍖咃紝涓轰簡寰楀埌瓒冲瀹屾暣鐨勬暟鎹紝鎴戜竴鑸細瑕佹眰鐩存帴鎶撳彇缃戝崱鏁版嵁鑰屼笉杩囨护锛屽涓嬶細
+鎶撳彇缃戝崱棣栧厛闇�瑕佽幏鍙栫綉鍗″悕锛屽湪linux鎴戜竴鑸娇鐢╜ip addr`鑾峰彇缃戝崱淇℃伅锛屽涓嬫墍绀猴細
+![img_1.png](_media/img_1.png)
+```shell
+sudo tcpdump -i wlp3s0 -w demo.pcap
+```
+![img_2.png](_media/img_2.png)  
+鍛戒护琛屼細鍋滅暀鍦ㄨ繖涓綅缃紝姝ゆ椂鍙互杩涜鎿嶄綔锛屾瘮濡傜偣鎾紝褰曞儚鍥炴斁绛夛紝鎿嶄綔瀹屾垚鍥炲埌鍛戒护琛屼娇鐢╜Ctrl+C`缁撴潫鍛戒护琛岋紝鍦ㄥ綋鍓嶇洰褰曚笅寰楀埌demo.pcap锛屽皢杩欎釜鏂囦欢涓嬭浇鍒板浘褰㈢晫闈㈡搷浣滅郴缁熼噷锛屽嵆鍙娇鐢╓ireshark鏌ョ湅浜�
+鏇村鐨勬搷浣滃彲浠ュ弬鑰冿細 [https://www.cnblogs.com/jiujuan/p/9017495.html](https://www.cnblogs.com/jiujuan/p/9017495.html)
diff --git a/doc/_content/theory/_media/img.png b/doc/_content/theory/_media/img.png
new file mode 100644
index 0000000..ecf62e9
--- /dev/null
+++ b/doc/_content/theory/_media/img.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_1.png b/doc/_content/theory/_media/img_1.png
new file mode 100644
index 0000000..2dc8cc8
--- /dev/null
+++ b/doc/_content/theory/_media/img_1.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_2.png b/doc/_content/theory/_media/img_2.png
new file mode 100644
index 0000000..7e2ddde
--- /dev/null
+++ b/doc/_content/theory/_media/img_2.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_3.png b/doc/_content/theory/_media/img_3.png
new file mode 100644
index 0000000..5fc5ef4
--- /dev/null
+++ b/doc/_content/theory/_media/img_3.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_4.png b/doc/_content/theory/_media/img_4.png
new file mode 100644
index 0000000..d5df7ce
--- /dev/null
+++ b/doc/_content/theory/_media/img_4.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_5.png b/doc/_content/theory/_media/img_5.png
new file mode 100644
index 0000000..47daffc
--- /dev/null
+++ b/doc/_content/theory/_media/img_5.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_6.png b/doc/_content/theory/_media/img_6.png
new file mode 100644
index 0000000..6c67ef4
--- /dev/null
+++ b/doc/_content/theory/_media/img_6.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_7.png b/doc/_content/theory/_media/img_7.png
new file mode 100644
index 0000000..fc204aa
--- /dev/null
+++ b/doc/_content/theory/_media/img_7.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_8.png b/doc/_content/theory/_media/img_8.png
new file mode 100644
index 0000000..9b43641
--- /dev/null
+++ b/doc/_content/theory/_media/img_8.png
Binary files differ
diff --git a/doc/_content/theory/_media/img_9.png b/doc/_content/theory/_media/img_9.png
new file mode 100644
index 0000000..c3aa1ff
--- /dev/null
+++ b/doc/_content/theory/_media/img_9.png
Binary files differ
diff --git a/doc/_content/theory/channel_tree.md b/doc/_content/theory/channel_tree.md
new file mode 100644
index 0000000..c4c1b09
--- /dev/null
+++ b/doc/_content/theory/channel_tree.md
@@ -0,0 +1,14 @@
+<!-- 閫氶亾鐨勬爲褰㈢粨鏋� -->
+
+# 閫氶亾鐨勬爲褰㈢粨鏋�
+
+鍥芥爣28181瑙勫畾浜嗕袱绉嶇粍缁囪澶囨爲鐨勬柟寮�
+1. **琛屾斂鍖哄垝**  
+   琛屾斂鍖哄垝妯″紡涓嬩富瑕佹槸浠ヨ鏀垮尯鍒掍綔涓虹洰褰曡妭鐐逛緥濡傦細娌冲寳鐪�->閭兏甯�->骞垮钩鍘�  
+   ![_media/img_8.png](_media/img_8.png)  
+2. **涓氬姟鍒嗙粍**  
+   涓氬姟鍒嗙粍涓昏鑷畾涔夌殑鐩綍鏍戠殑涓�绉嶇粍缁囧舰寮忥紝浣嗘槸瀵瑰畾涔夌殑鐩綍鐨勫浗鏍囩紪鍙锋湁涓�瀹氱殑瑕佹眰銆�  
+   绗竴绾у埆闇�瑕佹槸涓氬姟鍒嗙粍绫诲瀷锛屽嵆鍥芥爣缂栫爜涓殑11銆�12銆�13鏄�215,渚嬪锛�65010200002150000001锛�  
+   涓氬姟鍒嗙粍涓嬫槸铏氭嫙缁勭粐锛屽嵆鍥芥爣缂栫爜涓殑11銆�12銆�13鏄�216,渚嬪锛�65010200002160000002銆�  
+   铏氭嫙缁勭粐涓嬩笉鍙槸涓氬姟鍒嗙粍锛岃櫄鎷熺粍缁囦笅鍙互缁х画娣诲姞铏氭嫙缁勭粐銆�  
+   ![_media/img_9.png](_media/img_9.png)
diff --git a/doc/_content/theory/code.md b/doc/_content/theory/code.md
new file mode 100644
index 0000000..d5a892e
--- /dev/null
+++ b/doc/_content/theory/code.md
@@ -0,0 +1,25 @@
+<!-- 缁熶竴缂栫爜瑙勫垯 -->
+
+# 缁熶竴缂栫爜瑙勫垯
+## D.1 缂栫爜瑙勫垯 A
+>&emsp;&emsp;缂栫爜瑙勫垯 A 鐢变腑蹇冪紪鐮�(8浣�)銆佽涓氱紪鐮�(2浣�)銆佺被鍨嬬紪鐮�(3浣�)鍜屽簭鍙�(7浣�)鍥涗釜鐮佹鍏�20浣嶅崄
+>杩涘埗鏁板瓧瀛楃鏋勬垚,鍗崇郴缁熺紪鐮� =涓績缂栫爜 + 琛屼笟缂栫爜 + 绫诲瀷缂栫爜 + 搴忓彿銆�  
+>&emsp;&emsp;缂栫爜瑙勫垯 A 鐨勮缁嗚鏄庤琛� D.1銆傚叾涓�,涓績缂栫爜鎸囩敤鎴锋垨璁惧鎵�褰掑睘鐨勭洃鎺т腑蹇冪殑缂栫爜,鎸夌収鐩戞帶涓績鎵�鍦ㄥ湴鐨勮鏀垮尯鍒掍唬鐮佺‘瀹�,
+> 褰撲笉鏄熀灞傚崟浣嶆椂绌轰綑浣嶄负0銆傝鏀垮尯鍒掍唬鐮侀噰鐢� GB/T2260鈥� 2007瑙勫畾鐨勮鏀垮尯鍒掍唬鐮佽〃绀恒�傝涓氱紪鐮佹槸鎸囩敤鎴锋垨璁惧鎵�褰掑睘鐨勮涓�,琛屼笟缂栫爜瀵圭収琛ㄨ D.3銆�
+> 绫诲瀷缂栫爜鎸囧畾浜嗚澶囨垨鐢ㄦ埛鐨勫叿浣撶被鍨�,鍏朵腑鐨勫墠绔澶囧寘鍚叕瀹夌郴缁熷拰闈炲叕瀹夌郴缁熺殑鍓嶇璁惧,缁堢鐢� 鎴峰寘鍚叕瀹夌郴缁熷拰闈炲叕瀹夌郴缁熺殑缁堢鐢ㄦ埛銆�   
+![img_7.png](_media/img_7.png)
+![img_1.png](_media/img_1.png)
+![img_2.png](_media/img_2.png)  
+
+
+## D.2 缂栫爜瑙勫垯 B
+>&emsp;&emsp;缂栫爜瑙勫垯 B鐢变腑蹇冪紪鐮�(8浣�)銆佽涓氱紪鐮�(2浣�)銆佸簭鍙�(4浣�)鍜岀被鍨嬬紪鐮�(2浣�)鍥涗釜鐮佹鏋勬垚,鍗崇郴
+>缁熺紪鐮� =涓績缂栫爜 + 琛屼笟缂栫爜 +搴忓彿+绫诲瀷缂栫爜銆傜紪鐮佽鍒� B鐨勮缁嗚鏄庤琛� D.2銆�
+![img_3.png](_media/img_3.png)
+![img_4.png](_media/img_4.png)
+
+
+## D.3 琛屼笟缂栫爜瀵圭収琛�
+>&emsp;&emsp;琛屼笟缂栫爜瀵圭収琛ㄨ琛� D.3銆�  
+![img_5.png](_media/img_5.png)
+![img_6.png](_media/img_6.png)
\ No newline at end of file
diff --git a/doc/_content/theory/img.png b/doc/_content/theory/img.png
new file mode 100644
index 0000000..9b43641
--- /dev/null
+++ b/doc/_content/theory/img.png
Binary files differ
diff --git a/doc/_content/theory/play.md b/doc/_content/theory/play.md
new file mode 100644
index 0000000..fbfdcc6
--- /dev/null
+++ b/doc/_content/theory/play.md
@@ -0,0 +1,33 @@
+<!-- 鐐规挱娴佺▼ -->
+
+# 鐐规挱娴佺▼
+> 浠ヤ笅涓篧VP-PRO鐐规挱娴佺▼銆傜偣鎾垚鍔熷墠鐨勪换浣曚竴涓幆鑺傚嚭鐜伴棶棰橀兘鍙兘鍑虹幇鐐规挱瓒呮椂锛岃繖涔熸槸鎺掓煡鐐规挱瓒呮椂鐨勪緷鎹��
+
+```plantuml
+@startuml
+"WEB鐢ㄦ埛"  -> "WVP-PRO": 1. 鍙戣捣鐐规挱璇锋眰
+"璁惧" <-  "WVP-PRO": 2. Invite(鎼哄甫SDP娑堟伅浣�)
+"璁惧" --> "WVP-PRO": 3. 200OK(鎼哄甫SDP娑堟伅浣�)
+"璁惧" <-- "WVP-PRO": 4. Ack
+"璁惧" -> "ZLMediaKit": 5. 鍙戦�佸疄鏃舵祦
+"WVP-PRO" <- "ZLMediaKit": 6. 娴佹敼鍙樹簨浠�
+"WEB鐢ㄦ埛"  <-- "WVP-PRO": 7. 鍥炲娴佹挱鏀惧湴鍧�锛堟惡甯︽祦鍦板潃锛�
+"WVP-PRO" <- "ZLMediaKit": 8. 鏃犱汉瑙傜湅浜嬩欢
+"璁惧" <-  "WVP-PRO": 9 Bye娑堟伅
+"璁惧" -->  "WVP-PRO": 10 200OK
+@enduml
+```
+
+
+##  娉ㄥ唽娴佺▼鎻忚堪濡備笅:  
+1. 鐢ㄦ埛浠庣綉椤垫垨璋冪敤鎺ュ彛鍙戣捣鐐规挱璇锋眰;  
+2. WVP-PRO鍚戞憚鍍忔満鍙戦�両nvite娑堟伅,娑堟伅澶村煙涓惡甯� Subject瀛楁,琛ㄦ槑鐐规挱鐨勮棰戞簮ID銆佸彂閫佹柟濯掍綋娴佸簭鍒楀彿銆乑LMediaKit鎺ユ敹娴佷娇鐢ㄧ殑IP銆佺鍙e彿銆�
+ 鎺ユ敹绔獟浣撴祦搴忓垪鍙风瓑鍙傛暟,SDP娑堟伅浣撲腑 s瀛楁涓衡�淧lay鈥濅唬琛ㄥ疄鏃剁偣鎾紝y瀛楁鎻忚堪SSRC鍊�,f瀛楁鎻忚堪濯掍綋鍙傛暟銆�
+3. 鎽勫儚鏈哄悜WVP-PRO鍥炲200OK锛屾秷鎭綋涓弿杩颁簡濯掍綋娴佸彂閫佽�呭彂閫佸獟浣撴祦鐨処P銆佺鍙c�佸獟浣撴牸寮忋�丼SRC瀛楁绛夊唴瀹广��
+4. WVP-PRO鍚戣澶囧洖澶岮ck锛� 浼氳瘽寤虹珛鎴愬姛銆�
+5. 璁惧鍚慫LMediaKit鍙戦�佸疄鏃舵祦銆�
+6. ZLMediaKit鍚慦VP-PRO鍙戦�佹祦鏀瑰彉浜嬩欢銆�
+7. WVP-PRO鍚慦EB鐢ㄦ埛鍥炲鎾斁鍦板潃銆�
+8. ZLMediaKit鍚慦VP鍙戦�佹祦鏃犱汉瑙傜湅浜嬩欢銆�
+9. WVP-PRO鍚戣澶囧洖澶岯ye锛� 缁撴潫浼氳瘽銆�
+10. 璁惧鍥炲200OK锛屼細璇濈粨鏉熸垚鍔熴��
diff --git a/doc/_content/theory/register.md b/doc/_content/theory/register.md
new file mode 100644
index 0000000..fad9589
--- /dev/null
+++ b/doc/_content/theory/register.md
@@ -0,0 +1,21 @@
+<!-- 娉ㄥ唽娴佺▼ -->
+
+# 娉ㄥ唽娴佺▼
+WVP-PRO鐩墠浠呮敮鎸佸浗鏍囦腑鎻忚堪鐨勫熀鏈敞鍐屾祦绋嬶紝涔熸槸鏈�甯哥敤鐨勶紝
+> 鍩烘湰娉ㄥ唽鍗抽噰鐢↖ETFRFC3261瑙勫畾鐨勫熀浜庢暟瀛楁憳瑕佺殑鎸戞垬搴旂瓟寮忓畨鍏ㄦ妧鏈繘琛屾敞鍐�.
+
+```plantuml
+@startuml
+"璁惧"  -> "WVP-PRO": 1. Register
+"璁惧" <-- "WVP-PRO": 2. 401 Unauthorized
+"璁惧"  -> "WVP-PRO": 3. Register
+"璁惧" <-- "WVP-PRO": 4. 200 OK
+@enduml
+```
+
+
+> 娉ㄥ唽娴佺▼鎻忚堪濡備笅:  
+> 1. 鎽勫儚鏈哄悜WVP-PRO鏈嶅姟鍣ㄥ彂閫� Register璇锋眰;  
+> 2. WVP-PRO鍚戞憚鍍忔満鍙戦�佸搷搴�401,骞跺湪鍝嶅簲鐨勬秷鎭ご WWW_Authenticate瀛楁涓粰鍑洪�傚悎鎽勫儚鏈虹殑璁よ瘉浣撳埗鍜屽弬鏁�;
+> 3. 鎽勫儚鏈洪噸鏂板悜WVP-PRO鍙戦�� Register璇锋眰,鍦ㄨ姹傜殑 Authorization瀛楁缁欏嚭淇′换涔�, 鍖呭惈璁よ瘉淇℃伅;
+> 4. WVP-PRO瀵硅姹傝繘琛岄獙璇�,濡傛灉妫�鏌ュ嚭 鎽勫儚鏈鸿韩浠藉悎娉�,鍚戞憚鍍忔満鍙戦�佹垚鍔熷搷搴� 200OK,濡傛灉韬唤涓嶅悎娉曞垯鍙戦�佹嫆缁濇湇鍔″簲绛斻��
diff --git a/doc/_coverpage.md b/doc/_coverpage.md
new file mode 100644
index 0000000..eb3524f
--- /dev/null
+++ b/doc/_coverpage.md
@@ -0,0 +1,17 @@
+<!-- 灏侀潰 -->
+![logo](_media/logo-mini.png)
+
+# WVP-PRO <small>2.0</small>
+
+> 寮�绠卞嵆鐢ㄧ殑28181鍗忚瑙嗛骞冲彴銆�
+
+- 鍩轰簬GB/T28181-2016鏍囧噯淇′护瀹炵幇锛屽吋瀹笹B/T28181-2011銆�  
+- 鑷甫瀹屾暣鍓嶇椤甸潰锛屽紑绠卞嵆鐢ㄣ��  
+- 瀹屽叏寮�婧愶紝涓斾娇鐢∕IT璁稿彲鍗忚銆傚彲浠ュ湪淇濈暀鐗堟潈淇℃伅鐨勫熀纭�涓婂晢鐢ㄣ��
+
+[GitHub](https://github.com/648540858/wvp-GB28181-pro)
+[Gitee](https://gitee.com/pan648540858/wvp-GB28181-pro)
+
+<!-- 鑳屾櫙鑹� -->
+
+[//]: # ([comment]: <> &#40;![color]&#40;#f0f0f0&#41;&#41;)
diff --git a/doc/_media/favicon.ico b/doc/_media/favicon.ico
new file mode 100644
index 0000000..bc5f8e6
--- /dev/null
+++ b/doc/_media/favicon.ico
Binary files differ
diff --git a/doc/_media/logo-mini.png b/doc/_media/logo-mini.png
new file mode 100644
index 0000000..cc8078d
--- /dev/null
+++ b/doc/_media/logo-mini.png
Binary files differ
diff --git a/doc/_media/logo.png b/doc/_media/logo.png
new file mode 100644
index 0000000..c5da2d4
--- /dev/null
+++ b/doc/_media/logo.png
Binary files differ
diff --git a/doc/_media/weixin.jpg b/doc/_media/weixin.jpg
new file mode 100644
index 0000000..eda1260
--- /dev/null
+++ b/doc/_media/weixin.jpg
Binary files differ
diff --git a/doc/_media/zhifubao.jpg b/doc/_media/zhifubao.jpg
new file mode 100644
index 0000000..973996b
--- /dev/null
+++ b/doc/_media/zhifubao.jpg
Binary files differ
diff --git a/doc/_navbar.md b/doc/_navbar.md
new file mode 100644
index 0000000..22ac93a
--- /dev/null
+++ b/doc/_navbar.md
@@ -0,0 +1 @@
+<!-- 瀵艰埅鏍� -->
diff --git a/doc/_sidebar.md b/doc/_sidebar.md
new file mode 100644
index 0000000..eb0c96c
--- /dev/null
+++ b/doc/_sidebar.md
@@ -0,0 +1,33 @@
+<!-- 渚ц竟鏍� -->
+
+* **缂栬瘧涓庨儴缃�**
+  * [缂栬瘧](_content/introduction/compile.md)
+  * [閰嶇疆](_content/introduction/config.md)
+  * [閮ㄧ讲](_content/introduction/deployment.md)
+* **鍔熻兘涓庝娇鐢�**
+  * [鎺ュ叆璁惧](_content/ability/device.md)
+  * [璁惧浣跨敤](_content/ability/device_use.md)
+  * [鍥芥爣绾ц仈](_content/ability/cascade2.md)
+  * [鎺ㄦ祦鍒楄〃](_content/ability/push.md)
+  * [鎷夋祦浠g悊](_content/ability/proxy.md)
+  * [鐢靛瓙鍦板浘](_content/ability/gis.md)
+  * [鑺傜偣绠$悊](_content/ability/node_manger.md)
+  * [浜戠褰曞儚](_content/ability/cloud_record.md)
+  * [涓嶉棿鏂綍鍍廬(_content/ability/continuous_recording.md)
+* **娴佺▼涓庡師鐞�**
+  * [缁熶竴缂栫爜瑙勫垯](_content/theory/code.md)
+  * [鏍戝舰缁撴瀯](_content/theory/channel_tree.md)
+  * [娉ㄥ唽娴佺▼](_content/theory/register.md)
+  * [鐐规挱娴佺▼](_content/theory/play.md)
+* **蹇呭鎶�宸�**
+  * [鎶撳寘](_content/skill/tcpdump.md)
+
+* **甯歌闂瓟**
+  - [濡備綍鍙嶉BUG](_content/qa/bug.md)
+  - [濡備綍鍙備笌寮�鍙慮(_content/qa/development.md)
+  - [鍚姩鎶ラ敊鐨勮В鍐冲姙娉昡(_content/qa/start_error.md)
+  - [璁惧娉ㄥ唽涓嶄笂鏉ョ殑瑙e喅鍔炴硶](_content/qa/regiser_error.md)
+  - [鐐规挱瓒呮椂/鎶ラ敊鐨勮В鍐冲姙娉昡(_content/qa/play_error.md)
+* [**鍏嶈矗澹版槑**](_content/disclaimers.md)
+* [**鎹愯禒**](_content/donation.md)
+* [**鍏充簬鏈枃妗�**](_content/about_doc.md)
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..1048d92
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>WVP-PRO鏂囨。</title>
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+  <meta name="description" content="Description">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
+  <link rel="icon" href="_media/favicon.ico" type="image/x-icon" />
+  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
+<!--  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/dark.css">-->
+  <style>
+    .cover{
+      background: linear-gradient(to left bottom, hsl(82, 100%, 85%) 0%,hsl(199, 100%, 85%) 100%) !important;
+    }
+  </style>
+</head>
+<body>
+  <div id="app">鍔犺浇涓�</div>
+  <script>
+    window.$docsify = {
+      name: 'WVP-RPO浣跨敤鏂囨。',
+      repo: 'https://github.com/648540858/wvp-GB28181-pro',
+      loadSidebar: true, // 寮�鍚晶杈规爮
+      loadNavbar: true, // 寮�鍚鑸爮
+      coverpage: true, // 寮�鍚皝闈�
+
+      subMaxLevel: 3,
+      plantuml: {
+        skin: 'default',
+      },
+      search: {
+        maxAge: 86400000, // 杩囨湡鏃堕棿锛屽崟浣嶆绉掞紝榛樿涓�澶�
+        paths: 'auto', // or 'auto'
+        placeholder: '鎼滅储',
+        noData: '鎵句笉鍒扮粨鏋�',
+        // 鎼滅储鏍囬鐨勬渶澶у眰绾�, 1 - 6
+        depth: 4,
+        hideOtherSidebarContent: false, // 鏄惁闅愯棌鍏朵粬渚ц竟鏍忓唴瀹�
+      },
+      copyCode: {
+        buttonText : '澶嶅埗',
+        errorText  : '閿欒',
+        successText: '宸插鍒�'
+      },
+      // disqus: 'shortname'
+    }
+  </script>
+  <!-- Docsify v4 -->
+  <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
+  <script src="//unpkg.com/docsify-plantuml/dist/docsify-plantuml.min.js"></script>
+  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
+  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
+  <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
+
+  </script>
+<!--  <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/disqus.min.js"></script>-->
+</body>
+</html>
diff --git a/pom.xml b/pom.xml
index 1209124..41be567 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,13 @@
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-data-redis</artifactId>
+			 <exclusions>
+                <!-- 鍘绘帀  Lettuce 鐨勪緷璧栵紝  Spring Boot 浼樺厛浣跨敤 Lettuce 浣滀负 Redis 瀹㈡埛绔� -->
+                <exclusion>
+                    <groupId>io.lettuce</groupId>
+                    <artifactId>lettuce-core</artifactId>
+                </exclusion>
+            </exclusions>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
@@ -75,6 +82,12 @@
 			<groupId>org.mybatis.spring.boot</groupId>
 			<artifactId>mybatis-spring-boot-starter</artifactId>
 			<version>2.1.4</version>
+			<exclusions>
+				<exclusion>
+					<groupId>com.zaxxer</groupId>
+					<artifactId>HikariCP</artifactId>
+				</exclusion>
+			</exclusions>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
@@ -84,7 +97,6 @@
 		<dependency>
 			<groupId>redis.clients</groupId>
 			<artifactId>jedis</artifactId>
-			<version>${jedis-version}</version>
 		</dependency>
 
 		<!-- druid鏁版嵁搴撹繛鎺ユ睜 -->
@@ -265,14 +277,14 @@
 				</configuration>
 			</plugin>
 
-			<plugin>
+	<!--		<plugin>
 				<groupId>pl.project13.maven</groupId>
 				<artifactId>git-commit-id-plugin</artifactId>
 				<version>3.0.1</version>
 				<configuration>
 					<offline>true</offline>
 				</configuration>
-			</plugin>
+			</plugin>-->
 
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
diff --git a/sql/mysql.sql b/sql/mysql.sql
index 9d2e117..e494990 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -2,55 +2,60 @@
 --
 -- Host: 127.0.0.1    Database: wvp2
 -- ------------------------------------------------------
--- Server version	8.0.29-0ubuntu0.22.04.2
+-- Server version	8.0.29-0ubuntu0.22.04.3
 
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT = @@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS = @@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION = @@COLLATION_CONNECTION */;
 /*!50503 SET NAMES utf8mb4 */;
-/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
-/*!40103 SET TIME_ZONE='+00:00' */;
-/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+/*!40103 SET @OLD_TIME_ZONE = @@TIME_ZONE */;
+/*!40103 SET TIME_ZONE = ' + 00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS = @@UNIQUE_CHECKS, UNIQUE_CHECKS = 0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS = 0 */;
+/*!40101 SET @OLD_SQL_MODE = @@SQL_MODE, SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES = @@SQL_NOTES, SQL_NOTES = 0 */;
 
 --
 -- Table structure for table `device`
 --
 
 DROP TABLE IF EXISTS `device`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `device` (
-                          `id` int NOT NULL AUTO_INCREMENT,
-                          `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                          `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `manufacturer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `firmware` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                          `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                          `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                          `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                          `port` int NOT NULL,
-                          `expires` int NOT NULL,
-                          `subscribeCycleForCatalog` int NOT NULL,
-                          `hostAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                          `charset` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                          `subscribeCycleForMobilePosition` int DEFAULT NULL,
-                          `mobilePositionSubmissionInterval` int DEFAULT '5',
-                          `subscribeCycleForAlarm` int DEFAULT NULL,
-                          `ssrcCheck` int DEFAULT '0',
-                          `geoCoordSys` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
-                          `treeType` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
-                          PRIMARY KEY (`id`) USING BTREE,
-                          UNIQUE KEY `device_deviceId_uindex` (`deviceId`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `device`
+(
+    `id`                               int                                                          NOT NULL AUTO_INCREMENT,
+    `deviceId`                         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `name`                             varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `manufacturer`                     varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `model`                            varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `firmware`                         varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `transport`                        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `streamMode`                       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `online`                           varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `registerTime`                     varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `keepaliveTime`                    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `ip`                               varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `createTime`                       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `updateTime`                       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `port`                             int                                                          NOT NULL,
+    `expires`                          int                                                          NOT NULL,
+    `subscribeCycleForCatalog`         int                                                          NOT NULL,
+    `hostAddress`                      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `charset`                          varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `subscribeCycleForMobilePosition`  int                                                           DEFAULT NULL,
+    `mobilePositionSubmissionInterval` int                                                           DEFAULT '5 ',
+    `subscribeCycleForAlarm`           int                                                           DEFAULT NULL,
+    `ssrcCheck`                        int                                                           DEFAULT '0 ',
+    `geoCoordSys`                      varchar(50) COLLATE utf8mb4_general_ci                       NOT NULL,
+    `treeType`                         varchar(50) COLLATE utf8mb4_general_ci                       NOT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `device_deviceId_uindex` (`deviceId`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 53
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -58,8 +63,10 @@
 --
 
 LOCK TABLES `device` WRITE;
-/*!40000 ALTER TABLE `device` DISABLE KEYS */;
-/*!40000 ALTER TABLE `device` ENABLE KEYS */;
+/*!40000 ALTER TABLE `device`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `device`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -67,22 +74,26 @@
 --
 
 DROP TABLE IF EXISTS `device_alarm`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `device_alarm` (
-                                `id` int NOT NULL AUTO_INCREMENT,
-                                `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `longitude` double DEFAULT NULL,
-                                `latitude` double DEFAULT NULL,
-                                `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `device_alarm`
+(
+    `id`               int                                                          NOT NULL AUTO_INCREMENT,
+    `deviceId`         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `channelId`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `alarmPriority`    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `alarmMethod`      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `alarmTime`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `longitude`        double                                                        DEFAULT NULL,
+    `latitude`         double                                                        DEFAULT NULL,
+    `alarmType`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `createTime`       varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -90,8 +101,10 @@
 --
 
 LOCK TABLES `device_alarm` WRITE;
-/*!40000 ALTER TABLE `device_alarm` DISABLE KEYS */;
-/*!40000 ALTER TABLE `device_alarm` ENABLE KEYS */;
+/*!40000 ALTER TABLE `device_alarm`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `device_alarm`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -99,50 +112,55 @@
 --
 
 DROP TABLE IF EXISTS `device_channel`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `device_channel` (
-                                  `id` int NOT NULL AUTO_INCREMENT,
-                                  `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `safetyWay` int DEFAULT NULL,
-                                  `registerWay` int DEFAULT NULL,
-                                  `certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `certifiable` int DEFAULT NULL,
-                                  `errCode` int DEFAULT NULL,
-                                  `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `port` int DEFAULT NULL,
-                                  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `PTZType` int DEFAULT NULL,
-                                  `status` int DEFAULT NULL,
-                                  `longitude` double DEFAULT NULL,
-                                  `latitude` double DEFAULT NULL,
-                                  `streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                  `parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `hasAudio` bit(1) DEFAULT NULL,
-                                  `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                  `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                  `subCount` int DEFAULT '0',
-                                  `longitudeGcj02` double DEFAULT NULL,
-                                  `latitudeGcj02` double DEFAULT NULL,
-                                  `longitudeWgs84` double DEFAULT NULL,
-                                  `latitudeWgs84` double DEFAULT NULL,
-                                  `businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  `gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                  PRIMARY KEY (`id`) USING BTREE,
-                                  UNIQUE KEY `device_channel_id_uindex` (`id`) USING BTREE,
-                                  UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=19331 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `device_channel`
+(
+    `id`              int                                                          NOT NULL AUTO_INCREMENT,
+    `channelId`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `name`            varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `manufacture`     varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `model`           varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `owner`           varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `civilCode`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `block`           varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `address`         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `parentId`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `safetyWay`       int                                                           DEFAULT NULL,
+    `registerWay`     int                                                           DEFAULT NULL,
+    `certNum`         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `certifiable`     int                                                           DEFAULT NULL,
+    `errCode`         int                                                           DEFAULT NULL,
+    `endTime`         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `secrecy`         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `ipAddress`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `port`            int                                                           DEFAULT NULL,
+    `password`        varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `PTZType`         int                                                           DEFAULT NULL,
+    `status`          int                                                           DEFAULT NULL,
+    `longitude`       double                                                        DEFAULT NULL,
+    `latitude`        double                                                        DEFAULT NULL,
+    `streamId`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `deviceId`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `parental`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `hasAudio`        bit(1)                                                        DEFAULT NULL,
+    `createTime`      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `updateTime`      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `subCount`        int                                                           DEFAULT '0 ',
+    `longitudeGcj02`  double                                                        DEFAULT NULL,
+    `latitudeGcj02`   double                                                        DEFAULT NULL,
+    `longitudeWgs84`  double                                                        DEFAULT NULL,
+    `latitudeWgs84`   double                                                        DEFAULT NULL,
+    `businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `gpsTime`         varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `device_channel_id_uindex` (`id`) USING BTREE,
+    UNIQUE KEY `device_channel_pk` (`channelId`, `deviceId`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 19496
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -150,8 +168,10 @@
 --
 
 LOCK TABLES `device_channel` WRITE;
-/*!40000 ALTER TABLE `device_channel` DISABLE KEYS */;
-/*!40000 ALTER TABLE `device_channel` ENABLE KEYS */;
+/*!40000 ALTER TABLE `device_channel`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `device_channel`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -159,27 +179,32 @@
 --
 
 DROP TABLE IF EXISTS `device_mobile_position`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `device_mobile_position` (
-                                          `id` int NOT NULL AUTO_INCREMENT,
-                                          `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                          `channelId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                          `deviceName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                          `time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                          `longitude` double NOT NULL,
-                                          `latitude` double NOT NULL,
-                                          `altitude` double DEFAULT NULL,
-                                          `speed` double DEFAULT NULL,
-                                          `direction` double DEFAULT NULL,
-                                          `reportSource` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                          `longitudeGcj02` double DEFAULT NULL,
-                                          `latitudeGcj02` double DEFAULT NULL,
-                                          `longitudeWgs84` double DEFAULT NULL,
-                                          `latitudeWgs84` double DEFAULT NULL,
-                                          `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                          PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=6751 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `device_mobile_position`
+(
+    `id`             int                                                          NOT NULL AUTO_INCREMENT,
+    `deviceId`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `channelId`      varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    `deviceName`     varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `time`           varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `longitude`      double                                                       NOT NULL,
+    `latitude`       double                                                       NOT NULL,
+    `altitude`       double                                                        DEFAULT NULL,
+    `speed`          double                                                        DEFAULT NULL,
+    `direction`      double                                                        DEFAULT NULL,
+    `reportSource`   varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `longitudeGcj02` double                                                        DEFAULT NULL,
+    `latitudeGcj02`  double                                                        DEFAULT NULL,
+    `longitudeWgs84` double                                                        DEFAULT NULL,
+    `latitudeWgs84`  double                                                        DEFAULT NULL,
+    `createTime`     varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 6956
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -187,8 +212,10 @@
 --
 
 LOCK TABLES `device_mobile_position` WRITE;
-/*!40000 ALTER TABLE `device_mobile_position` DISABLE KEYS */;
-/*!40000 ALTER TABLE `device_mobile_position` ENABLE KEYS */;
+/*!40000 ALTER TABLE `device_mobile_position`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `device_mobile_position`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -196,24 +223,29 @@
 --
 
 DROP TABLE IF EXISTS `gb_stream`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `gb_stream` (
-                             `gbStreamId` int NOT NULL AUTO_INCREMENT,
-                             `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             `gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                             `longitude` double DEFAULT NULL,
-                             `latitude` double DEFAULT NULL,
-                             `streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                             `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                             `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                             `gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                             PRIMARY KEY (`gbStreamId`) USING BTREE,
-                             UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
-                             UNIQUE KEY `gbId` (`gbId`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=301681 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `gb_stream`
+(
+    `gbStreamId`    int                                                           NOT NULL AUTO_INCREMENT,
+    `app`           varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `stream`        varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `gbId`          varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `name`          varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `longitude`     double                                                        DEFAULT NULL,
+    `latitude`      double                                                        DEFAULT NULL,
+    `streamType`    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `createTime`    varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    `gpsTime`       varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    PRIMARY KEY (`gbStreamId`) USING BTREE,
+    UNIQUE KEY `app` (`app`, `stream`) USING BTREE,
+    UNIQUE KEY `gbId` (`gbId`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 301754
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -221,8 +253,10 @@
 --
 
 LOCK TABLES `gb_stream` WRITE;
-/*!40000 ALTER TABLE `gb_stream` DISABLE KEYS */;
-/*!40000 ALTER TABLE `gb_stream` ENABLE KEYS */;
+/*!40000 ALTER TABLE `gb_stream`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `gb_stream`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -230,20 +264,25 @@
 --
 
 DROP TABLE IF EXISTS `log`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `log` (
-                       `id` int NOT NULL AUTO_INCREMENT,
-                       `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       `result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       `timing` bigint NOT NULL,
-                       `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                       PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=34997 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `log`
+(
+    `id`         int                                                           NOT NULL AUTO_INCREMENT,
+    `name`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `type`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `uri`        varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `address`    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `result`     varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `timing`     bigint                                                        NOT NULL,
+    `username`   varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 42703
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -251,8 +290,10 @@
 --
 
 LOCK TABLES `log` WRITE;
-/*!40000 ALTER TABLE `log` DISABLE KEYS */;
-/*!40000 ALTER TABLE `log` ENABLE KEYS */;
+/*!40000 ALTER TABLE `log`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `log`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -260,35 +301,39 @@
 --
 
 DROP TABLE IF EXISTS `media_server`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `media_server` (
-                                `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `httpPort` int NOT NULL,
-                                `httpSSlPort` int NOT NULL,
-                                `rtmpPort` int NOT NULL,
-                                `rtmpSSlPort` int NOT NULL,
-                                `rtpProxyPort` int NOT NULL,
-                                `rtspPort` int NOT NULL,
-                                `rtspSSLPort` int NOT NULL,
-                                `autoConfig` int NOT NULL,
-                                `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `streamNoneReaderDelayMS` int NOT NULL,
-                                `rtpEnable` int NOT NULL,
-                                `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `recordAssistPort` int NOT NULL,
-                                `defaultServer` int NOT NULL,
-                                `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `hookAliveInterval` int NOT NULL,
-                                PRIMARY KEY (`id`) USING BTREE,
-                                UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `media_server`
+(
+    `id`                      varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `ip`                      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `hookIp`                  varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `sdpIp`                   varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `streamIp`                varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `httpPort`                int                                                           NOT NULL,
+    `httpSSlPort`             int                                                           NOT NULL,
+    `rtmpPort`                int                                                           NOT NULL,
+    `rtmpSSlPort`             int                                                           NOT NULL,
+    `rtpProxyPort`            int                                                           NOT NULL,
+    `rtspPort`                int                                                           NOT NULL,
+    `rtspSSLPort`             int                                                           NOT NULL,
+    `autoConfig`              int                                                           NOT NULL,
+    `secret`                  varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `streamNoneReaderDelayMS` int                                                           NOT NULL,
+    `rtpEnable`               int                                                           NOT NULL,
+    `rtpPortRange`            varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `sendRtpPortRange`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `recordAssistPort`        int                                                           NOT NULL,
+    `defaultServer`           int                                                           NOT NULL,
+    `createTime`              varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `updateTime`              varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `hookAliveInterval`       int                                                           NOT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `media_server_i` (`ip`, `httpPort`) USING BTREE
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -296,8 +341,10 @@
 --
 
 LOCK TABLES `media_server` WRITE;
-/*!40000 ALTER TABLE `media_server` DISABLE KEYS */;
-/*!40000 ALTER TABLE `media_server` ENABLE KEYS */;
+/*!40000 ALTER TABLE `media_server`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `media_server`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -305,39 +352,44 @@
 --
 
 DROP TABLE IF EXISTS `parent_platform`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `parent_platform` (
-                                   `id` int NOT NULL AUTO_INCREMENT,
-                                   `enable` int DEFAULT NULL,
-                                   `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                   `serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `serverPort` int DEFAULT NULL,
-                                   `deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                   `deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                   `ptz` int DEFAULT NULL,
-                                   `rtcp` int DEFAULT NULL,
-                                   `status` bit(1) DEFAULT NULL,
-                                   `shareAllLiveStream` int DEFAULT NULL,
-                                   `startOfflinePush` int DEFAULT '0',
-                                   `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                   `catalogGroup` int DEFAULT '1',
-                                   `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                   PRIMARY KEY (`id`) USING BTREE,
-                                   UNIQUE KEY `parent_platform_id_uindex` (`id`) USING BTREE,
-                                   UNIQUE KEY `parent_platform_pk` (`serverGBId`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `parent_platform`
+(
+    `id`                     int                                                          NOT NULL AUTO_INCREMENT,
+    `enable`                 int                                                           DEFAULT NULL,
+    `name`                   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `serverGBId`             varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `serverGBDomain`         varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `serverIP`               varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `serverPort`             int                                                           DEFAULT NULL,
+    `deviceGBId`             varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `deviceIp`               varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `devicePort`             varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `username`               varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `password`               varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `expires`                varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `keepTimeout`            varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `transport`              varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `characterSet`           varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `catalogId`              varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `ptz`                    int                                                           DEFAULT NULL,
+    `rtcp`                   int                                                           DEFAULT NULL,
+    `status`                 bit(1)                                                        DEFAULT NULL,
+    `startOfflinePush`       int                                                           DEFAULT '0 ',
+    `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `catalogGroup`           int                                                           DEFAULT '1 ',
+    `createTime`             varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    `updateTime`             varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    `treeType`               varchar(50) COLLATE utf8mb4_general_ci                       NOT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `parent_platform_id_uindex` (`id`) USING BTREE,
+    UNIQUE KEY `parent_platform_pk` (`serverGBId`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 40
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -345,8 +397,10 @@
 --
 
 LOCK TABLES `parent_platform` WRITE;
-/*!40000 ALTER TABLE `parent_platform` DISABLE KEYS */;
-/*!40000 ALTER TABLE `parent_platform` ENABLE KEYS */;
+/*!40000 ALTER TABLE `parent_platform`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `parent_platform`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -354,15 +408,21 @@
 --
 
 DROP TABLE IF EXISTS `platform_catalog`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `platform_catalog` (
-                                    `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                    `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                    `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                    `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                    PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `platform_catalog`
+(
+    `id`              varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `platformId`      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `name`            varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `parentId`        varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `civilCode`       varchar(50) COLLATE utf8mb4_general_ci                       DEFAULT NULL,
+    `businessGroupId` varchar(50) COLLATE utf8mb4_general_ci                       DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -370,8 +430,10 @@
 --
 
 LOCK TABLES `platform_catalog` WRITE;
-/*!40000 ALTER TABLE `platform_catalog` DISABLE KEYS */;
-/*!40000 ALTER TABLE `platform_catalog` ENABLE KEYS */;
+/*!40000 ALTER TABLE `platform_catalog`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `platform_catalog`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -379,15 +441,20 @@
 --
 
 DROP TABLE IF EXISTS `platform_gb_channel`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `platform_gb_channel` (
-                                       `id` int NOT NULL AUTO_INCREMENT,
-                                       `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                       `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                       `deviceChannelId` int NOT NULL,
-                                       PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=4889 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `platform_gb_channel`
+(
+    `id`              int                                                          NOT NULL AUTO_INCREMENT,
+    `platformId`      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `catalogId`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `deviceChannelId` int                                                          NOT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 4915
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -395,8 +462,10 @@
 --
 
 LOCK TABLES `platform_gb_channel` WRITE;
-/*!40000 ALTER TABLE `platform_gb_channel` DISABLE KEYS */;
-/*!40000 ALTER TABLE `platform_gb_channel` ENABLE KEYS */;
+/*!40000 ALTER TABLE `platform_gb_channel`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `platform_gb_channel`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -404,16 +473,21 @@
 --
 
 DROP TABLE IF EXISTS `platform_gb_stream`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `platform_gb_stream` (
-                                      `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                      `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                      `gbStreamId` int NOT NULL,
-                                      `id` int NOT NULL AUTO_INCREMENT,
-                                      PRIMARY KEY (`id`) USING BTREE,
-                                      UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=302077 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `platform_gb_stream`
+(
+    `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `catalogId`  varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `gbStreamId` int                                                          NOT NULL,
+    `id`         int                                                          NOT NULL AUTO_INCREMENT,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `platform_gb_stream_pk` (`platformId`, `catalogId`, `gbStreamId`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 302149
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -421,8 +495,10 @@
 --
 
 LOCK TABLES `platform_gb_stream` WRITE;
-/*!40000 ALTER TABLE `platform_gb_stream` DISABLE KEYS */;
-/*!40000 ALTER TABLE `platform_gb_stream` ENABLE KEYS */;
+/*!40000 ALTER TABLE `platform_gb_stream`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `platform_gb_stream`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -430,31 +506,36 @@
 --
 
 DROP TABLE IF EXISTS `stream_proxy`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `stream_proxy` (
-                                `id` int NOT NULL AUTO_INCREMENT,
-                                `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `src_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `dst_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `timeout_ms` int DEFAULT NULL,
-                                `ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `enable_hls` bit(1) DEFAULT NULL,
-                                `enable_mp4` bit(1) DEFAULT NULL,
-                                `enable` bit(1) NOT NULL,
-                                `status` bit(1) NOT NULL,
-                                `enable_remove_none_reader` bit(1) NOT NULL,
-                                `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                                `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                                PRIMARY KEY (`id`) USING BTREE,
-                                UNIQUE KEY `stream_proxy_pk` (`app`,`stream`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `stream_proxy`
+(
+    `id`                        int                                                           NOT NULL AUTO_INCREMENT,
+    `type`                      varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `app`                       varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `stream`                    varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `url`                       varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `src_url`                   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `dst_url`                   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `timeout_ms`                int                                                           DEFAULT NULL,
+    `ffmpeg_cmd_key`            varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `rtp_type`                  varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `mediaServerId`             varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  DEFAULT NULL,
+    `enable_hls`                bit(1)                                                        DEFAULT NULL,
+    `enable_mp4`                bit(1)                                                        DEFAULT NULL,
+    `enable`                    bit(1)                                                        NOT NULL,
+    `status`                    bit(1)                                                        NOT NULL,
+    `enable_remove_none_reader` bit(1)                                                        NOT NULL,
+    `createTime`                varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `name`                      varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `updateTime`                varchar(50) COLLATE utf8mb4_general_ci                        DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `stream_proxy_pk` (`app`, `stream`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 66
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -462,8 +543,10 @@
 --
 
 LOCK TABLES `stream_proxy` WRITE;
-/*!40000 ALTER TABLE `stream_proxy` DISABLE KEYS */;
-/*!40000 ALTER TABLE `stream_proxy` ENABLE KEYS */;
+/*!40000 ALTER TABLE `stream_proxy`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `stream_proxy`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -471,25 +554,32 @@
 --
 
 DROP TABLE IF EXISTS `stream_push`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `stream_push` (
-                               `id` int NOT NULL AUTO_INCREMENT,
-                               `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                               `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                               `totalReaderCount` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                               `originType` int DEFAULT NULL,
-                               `originTypeStr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                               `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                               `aliveSecond` int DEFAULT NULL,
-                               `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
-                               `serverId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
-                               `pushTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                               `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                               `status` int DEFAULT NULL,
-                               PRIMARY KEY (`id`) USING BTREE,
-                               UNIQUE KEY `stream_push_pk` (`app`,`stream`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=305315 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `stream_push`
+(
+    `id`               int                                                           NOT NULL AUTO_INCREMENT,
+    `app`              varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `stream`           varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `totalReaderCount` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `originType`       int                                                          DEFAULT NULL,
+    `originTypeStr`    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `createTime`       varchar(50) COLLATE utf8mb4_general_ci                       DEFAULT NULL,
+    `aliveSecond`      int                                                          DEFAULT NULL,
+    `mediaServerId`    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
+    `serverId`         varchar(50) COLLATE utf8mb4_general_ci                        NOT NULL,
+    `pushTime`         varchar(50) COLLATE utf8mb4_general_ci                       DEFAULT NULL,
+    `updateTime`       varchar(50) COLLATE utf8mb4_general_ci                       DEFAULT NULL,
+    `status`           int                                                          DEFAULT NULL,
+    `pushIng`          int                                                          DEFAULT NULL,
+    `self`             int                                                          DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `stream_push_pk` (`app`, `stream`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 305415
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -497,8 +587,10 @@
 --
 
 LOCK TABLES `stream_push` WRITE;
-/*!40000 ALTER TABLE `stream_push` DISABLE KEYS */;
-/*!40000 ALTER TABLE `stream_push` ENABLE KEYS */;
+/*!40000 ALTER TABLE `stream_push`
+    DISABLE KEYS */;
+/*!40000 ALTER TABLE `stream_push`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -506,19 +598,24 @@
 --
 
 DROP TABLE IF EXISTS `user`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `user` (
-                        `id` int NOT NULL AUTO_INCREMENT,
-                        `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                        `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                        `roleId` int NOT NULL,
-                        `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                        `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                        `pushKey` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
-                        PRIMARY KEY (`id`) USING BTREE,
-                        UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `user`
+(
+    `id`         int                                                           NOT NULL AUTO_INCREMENT,
+    `username`   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `password`   varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `roleId`     int                                                           NOT NULL,
+    `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci  NOT NULL,
+    `pushKey`    varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
+    PRIMARY KEY (`id`) USING BTREE,
+    UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 2
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -526,9 +623,13 @@
 --
 
 LOCK TABLES `user` WRITE;
-/*!40000 ALTER TABLE `user` DISABLE KEYS */;
-INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57','453df297a57a5a7438934sda801fc3');
-/*!40000 ALTER TABLE `user` ENABLE KEYS */;
+/*!40000 ALTER TABLE `user`
+    DISABLE KEYS */;
+INSERT INTO `user`
+VALUES (1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 1, '2021 - 04 - 13 14:14:57', '2021 - 04 - 13 14:14:57',
+        '01685cb9573ae25ec6c52142402da7c5');
+/*!40000 ALTER TABLE `user`
+    ENABLE KEYS */;
 UNLOCK TABLES;
 
 --
@@ -536,16 +637,21 @@
 --
 
 DROP TABLE IF EXISTS `user_role`;
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
 /*!50503 SET character_set_client = utf8mb4 */;
-CREATE TABLE `user_role` (
-                             `id` int NOT NULL AUTO_INCREMENT,
-                             `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
-                             PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+CREATE TABLE `user_role`
+(
+    `id`         int                                                          NOT NULL AUTO_INCREMENT,
+    `name`       varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `authority`  varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB
+  AUTO_INCREMENT = 2
+  DEFAULT CHARSET = utf8mb4
+  COLLATE = utf8mb4_general_ci
+  ROW_FORMAT = DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -553,18 +659,21 @@
 --
 
 LOCK TABLES `user_role` WRITE;
-/*!40000 ALTER TABLE `user_role` DISABLE KEYS */;
-INSERT INTO `user_role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
-/*!40000 ALTER TABLE `user_role` ENABLE KEYS */;
+/*!40000 ALTER TABLE `user_role`
+    DISABLE KEYS */;
+INSERT INTO `user_role`
+VALUES (1, 'admin', '0 ', '2021 - 04 - 13 14:14:57', '2021 - 04 - 13 14:14:57');
+/*!40000 ALTER TABLE `user_role`
+    ENABLE KEYS */;
 UNLOCK TABLES;
-/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+/*!40103 SET TIME_ZONE = @OLD_TIME_ZONE */;
 
-/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+/*!40101 SET SQL_MODE = @OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS = @OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS = @OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT = @OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS = @OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION = @OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES = @OLD_SQL_NOTES */;
 
--- Dump completed on 2022-07-11 17:32:51
+-- Dump completed on 2022-07-27 14:51:08
diff --git a/sql/update.sql b/sql/update.sql
index f3ca465..c04cd92 100644
--- a/sql/update.sql
+++ b/sql/update.sql
@@ -71,6 +71,8 @@
 alter table stream_push
     add updateTime varchar(50) default null;
 alter table stream_push
+    add pushIng int DEFAULT NULL;
+alter table stream_push
     change createStamp createTime varchar(50) default null;
 
 alter table gb_stream
@@ -78,4 +80,20 @@
 
 alter table user
     add pushKey varchar(50) default null;
+update user set pushKey='453df297a57a5a7438934sda801fc3' where id=1;
+
+alter table parent_platform
+    add treeType varchar(50) not null;
+update parent_platform set parent_platform.treeType='BusinessGroup';
+alter table parent_platform drop shareAllLiveStream;
+
+alter table platform_catalog
+    add civilCode varchar(50) default null;
+alter table platform_catalog
+    add businessGroupId varchar(50) default null;
+
+/********************* ADD ***************************/
+alter table stream_push
+    add self int DEFAULT NULL;
+
 
diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
index 8ff2efb..3bac82d 100644
--- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
+++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
@@ -11,7 +11,7 @@
 import springfox.documentation.oas.annotations.EnableOpenApi;
 
 /**
- *
+ * 鍚姩绫�
  */
 @ServletComponentScan("com.genersoft.iot.vmp.conf")
 @SpringBootApplication
diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
index 702e357..40a7352 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -104,6 +104,10 @@
 	// 璁惧鐘舵�佽闃呯殑閫氱煡
 	public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
 
+
+
+
+
 	//**************************    绗笁鏂�  ****************************************
 	public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
 	public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
index ec1f9ba..6a862ae 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
@@ -1,10 +1,7 @@
 package com.genersoft.iot.vmp.conf;
 
 import com.genersoft.iot.vmp.common.VideoManagerConstants;
-import com.genersoft.iot.vmp.service.impl.RedisAlarmMsgListener;
-import com.genersoft.iot.vmp.service.impl.RedisGpsMsgListener;
-import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener;
-import com.genersoft.iot.vmp.service.impl.RedisStreamMsgListener;
+import com.genersoft.iot.vmp.service.impl.*;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -60,6 +57,9 @@
 	@Autowired
 	private RedisGbPlayMsgListener redisGbPlayMsgListener;
 
+	@Autowired
+	private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
+
 	@Bean
 	public JedisPool jedisPool() {
 		if (StringUtils.isBlank(password)) {
@@ -108,6 +108,7 @@
 		container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
 		container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH"));
 		container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY));
+		container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
         return container;
     }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
index c0fcf01..d28ddeb 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
@@ -1,6 +1,5 @@
 package com.genersoft.iot.vmp.conf;
 
-import io.swagger.models.auth.In;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
index 63569ef..509a1e0 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
@@ -1,9 +1,7 @@
 package com.genersoft.iot.vmp.conf.security;
 
-import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
-import com.genersoft.iot.vmp.service.IUserService;
-import com.genersoft.iot.vmp.storager.dao.dto.User;
-import com.github.xiaoymin.knife4j.core.util.StrUtil;
+import java.time.LocalDateTime;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -12,7 +10,10 @@
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Component;
 
-import java.time.LocalDateTime;
+import com.alibaba.excel.util.StringUtils;
+import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
+import com.genersoft.iot.vmp.service.IUserService;
+import com.genersoft.iot.vmp.storager.dao.dto.User;
 
 /**
  * 鐢ㄦ埛鐧诲綍璁よ瘉閫昏緫
@@ -27,7 +28,7 @@
 
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-        if (StrUtil.isBlank(username)) {
+        if (StringUtils.isBlank(username)) {
             logger.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�", username);
             throw new UsernameNotFoundException("鐧诲綍鐢ㄦ埛锛�" + username + " 涓嶅瓨鍦�");
         }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
index 8a96d35..965d7f2 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
@@ -3,8 +3,14 @@
 import java.time.Instant;
 import java.util.List;
 
+/**
+ * @author lin
+ */
 public class CatalogData {
-    private int sn; // 鍛戒护搴忓垪鍙�
+    /**
+     * 鍛戒护搴忓垪鍙�
+     */
+    private int sn;
     private int total;
     private List<DeviceChannel> channelList;
     private Instant lastTime;
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
index 4377282..61e777a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -105,11 +105,6 @@
     private int channelCount;
 
     /**
-     * 鍏变韩鎵�鏈夌殑鐩存挱娴�
-     */
-    private boolean shareAllLiveStream;
-
-    /**
      * 榛樿鐩綍Id,鑷姩娣诲姞鐨勯�氶亾澶氭斁鍦ㄨ繖涓洰褰曚笅
      */
     private String catalogId;
@@ -153,6 +148,11 @@
      * 鍒涘缓鏃堕棿
      */
     private String createTime;
+
+    /**
+     * 鏍戠被鍨� 鍥芥爣瑙勫畾浜嗕袱绉嶆爲鐨勫睍鐜版柟寮� 琛屾斂鍖哄垝 CivilCode 鍜屼笟鍔″垎缁�:BusinessGroup
+     */
+    private String treeType;
 
     public Integer getId() {
         return id;
@@ -314,15 +314,6 @@
         this.channelCount = channelCount;
     }
 
-
-    public boolean isShareAllLiveStream() {
-        return shareAllLiveStream;
-    }
-
-    public void setShareAllLiveStream(boolean shareAllLiveStream) {
-        this.shareAllLiveStream = shareAllLiveStream;
-    }
-
     public String getCatalogId() {
         return catalogId;
     }
@@ -394,4 +385,12 @@
     public void setCreateTime(String createTime) {
         this.createTime = createTime;
     }
+
+    public String getTreeType() {
+        return treeType;
+    }
+
+    public void setTreeType(String treeType) {
+        this.treeType = treeType;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
index 065971d..58a9cbb 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
@@ -1,12 +1,28 @@
 package com.genersoft.iot.vmp.gb28181.bean;
 
+/**
+ * 鍥芥爣绾ц仈-鐩綍
+ * @author lin
+ */
 public class PlatformCatalog {
     private String id;
     private String name;
     private String platformId;
     private String parentId;
-    private int childrenCount; // 瀛愯妭鐐规暟
-    private int type; // 0 鐩綍, 1 鍥芥爣閫氶亾, 2 鐩存挱娴�
+
+    private String civilCode;
+
+    private String businessGroupId;
+
+    /**
+     * 瀛愯妭鐐规暟
+     */
+    private int childrenCount;
+
+    /**
+     * 0 鐩綍, 1 鍥芥爣閫氶亾, 2 鐩存挱娴�
+     */
+    private int type;
 
     public String getId() {
         return id;
@@ -68,4 +84,19 @@
         this.type = 2;
     }
 
+    public String getCivilCode() {
+        return civilCode;
+    }
+
+    public void setCivilCode(String civilCode) {
+        this.civilCode = civilCode;
+    }
+
+    public String getBusinessGroupId() {
+        return businessGroupId;
+    }
+
+    public void setBusinessGroupId(String businessGroupId) {
+        this.businessGroupId = businessGroupId;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
index 2ae50e6..f3a197c 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
@@ -2,11 +2,14 @@
 
 /**
  * 鎽勫儚鏈哄悓姝ョ姸鎬�
+ * @author lin
  */
 public class SyncStatus {
     private int total;
     private int current;
     private String errorMsg;
+
+    private boolean syncIng;
 
     public int getTotal() {
         return total;
@@ -31,4 +34,12 @@
     public void setErrorMsg(String errorMsg) {
         this.errorMsg = errorMsg;
     }
+
+    public boolean isSyncIng() {
+        return syncIng;
+    }
+
+    public void setSyncIng(boolean syncIng) {
+        this.syncIng = syncIng;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java
new file mode 100644
index 0000000..bb684e1
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java
@@ -0,0 +1,10 @@
+package com.genersoft.iot.vmp.gb28181.bean;
+
+/**
+ * 鐩綍缁撴瀯绫诲瀷
+ * @author lin
+ */
+public class TreeType {
+    public static final String BUSINESS_GROUP = "BusinessGroup";
+    public static final String CIVIL_CODE = "CivilCode";
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
index 14ed76a..56bdeb5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
@@ -65,7 +65,6 @@
         }
         // 鏌ヨ鏄惁鏈夋帹娴侊紝 濡傛灉鏈夊垯閮藉仠姝�
         List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID());
-        logger.info("[ 骞冲彴鏈敞鍐屼簨浠� ] 鍋滄[ {} ]鐨勬墍鏈夋帹娴乻ize", sendRtpItems.size());
         if (sendRtpItems != null && sendRtpItems.size() > 0) {
             logger.info("[ 骞冲彴鏈敞鍐屼簨浠� ] 鍋滄[ {} ]鐨勬墍鏈夋帹娴�", event.getPlatformGbID());
             for (SendRtpItem sendRtpItem : sendRtpItems) {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
index c035b80..5c064f7 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
@@ -11,13 +11,40 @@
         super(source);
     }
 
-    public static final String ON = "ON";         // 涓婄嚎
-    public static final String OFF = "OFF";       // 绂荤嚎
-    public static final String VLOST = "VLOST";   // 瑙嗛涓㈠け
-    public static final String DEFECT = "DEFECT"; // 鏁呴殰
-    public static final String ADD = "ADD";       // 澧炲姞
-    public static final String DEL = "DEL";       // 鍒犻櫎
-    public static final String UPDATE = "UPDATE";       // 鏇存柊
+    /**
+     * 涓婄嚎
+     */
+    public static final String ON = "ON";
+
+    /**
+     * 绂荤嚎
+     */
+    public static final String OFF = "OFF";
+
+    /**
+     * 瑙嗛涓㈠け
+     */
+    public static final String VLOST = "VLOST";
+
+    /**
+     * 鏁呴殰
+     */
+    public static final String DEFECT = "DEFECT";
+
+    /**
+     * 澧炲姞
+     */
+    public static final String ADD = "ADD";
+
+    /**
+     * 鍒犻櫎
+     */
+    public static final String DEL = "DEL";
+
+    /**
+     * 鏇存柊
+     */
+    public static final String UPDATE = "UPDATE";
 
     private List<DeviceChannel> deviceChannels;
     private List<GbStream> gbStreams;
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
index e38733d..224fa1e 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -58,17 +58,16 @@
         ParentPlatform parentPlatform = null;
 
         Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
-        if (event.getPlatformId() != null) {
+        if (!StringUtils.isEmpty(event.getPlatformId())) {
+            subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
+            if (subscribe == null) {
+                return;
+            }
             parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
             if (parentPlatform != null && !parentPlatform.isStatus()) {
                 return;
             }
-            subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
 
-            if (subscribe == null) {
-                logger.info("鍙戦�佽闃呮秷鎭椂鍙戠幇璁㈤槄淇℃伅宸茬粡涓嶅瓨鍦�: {}", event.getPlatformId());
-                return;
-            }
         }else {
             // 鑾峰彇鎵�鐢ㄨ闃�
             List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform();
@@ -144,11 +143,8 @@
                      }
                     if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
                         for (GbStream gbStream : event.getGbStreams()) {
-                            DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
-                            if (deviceChannelByStream.getParentId().length() <= 10) { // 鐖惰妭鐐规槸琛屾斂鍖哄垝,鍒欒缃瓹ivilCode浣跨敤姝よ鏀垮尯鍒�
-                                deviceChannelByStream.setCivilCode(deviceChannelByStream.getParentId());
-                            }
-                            deviceChannelList.add(deviceChannelByStream);
+                            deviceChannelList.add(
+                                    gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform));
                         }
                     }
                     if (deviceChannelList.size() > 0) {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
index 7ed3c11..732a87a 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
@@ -84,6 +84,11 @@
         syncStatus.setCurrent(catalogData.getChannelList().size());
         syncStatus.setTotal(catalogData.getTotal());
         syncStatus.setErrorMsg(catalogData.getErrorMsg());
+        if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
+            syncStatus.setSyncIng(false);
+        }else {
+            syncStatus.setSyncIng(true);
+        }
         return syncStatus;
     }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
index 66b57fe..7edee4d 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
@@ -57,23 +57,17 @@
         SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
         if (subscribe != null) {
 
-//            if (!parentPlatform.isStatus()) {
-//                logger.info("鍙戦�佽闃呮椂鍙戠幇骞冲彴宸茬粡绂荤嚎锛歿}", platformId);
-//                return;
-//            }
             // TODO 鏆傛椂鍙鐞嗚棰戞祦鐨勫洖澶�,鍚庣画澧炲姞瀵瑰浗鏍囪澶囩殑鏀寔
-            List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
+            List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
             if (gbStreams.size() == 0) {
                 logger.info("鍙戦�佽闃呮椂鍙戠幇骞冲彴宸茬粡娌℃湁鍏宠仈鐨勭洿鎾祦锛歿}", platform.getServerGBId());
                 return;
             }
-            for (GbStream gbStream : gbStreams) {
-                String gbId = gbStream.getGbId();
+            for (DeviceChannel deviceChannel : gbStreams) {
+                String gbId = deviceChannel.getChannelId();
                 GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
-                if (gpsMsgInfo != null) { // 鏃犳渶鏂颁綅缃笉鍙戦��
-                   if (logger.isDebugEnabled()) {
-                       logger.debug("鏃犳渶鏂颁綅缃笉鍙戦��");
-                   }
+                // 鏃犳渶鏂颁綅缃笉鍙戦��
+                if (gpsMsgInfo != null) {
                     // 缁忕含搴﹂兘涓�0涓嶅彂閫�
                     if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
                         continue;
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
index cf1f7cf..e43e59b 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
@@ -39,9 +39,9 @@
             dynamicTask.stop(taskKey);
         }
         sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
-//            if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
-//                dialog = eventResult.dialog;
-//            }
+            if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
+                dialog = eventResult.dialog;
+            }
             ResponseEvent event = (ResponseEvent) eventResult.event;
             if (event.getResponse().getRawContent() != null) {
                 // 鎴愬姛
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 832f716..96b92e9 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -10,6 +10,9 @@
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
+import com.genersoft.iot.vmp.media.zlm.dto.HookType;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -348,25 +351,19 @@
 	@Override
 	public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
 							  ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
-		String streamId = ssrcInfo.getStream();
+		String stream = ssrcInfo.getStream();
 		try {
 			if (device == null) {
 				return;
 			}
 			String streamMode = device.getStreamMode().toUpperCase();
 
-			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
-			// 娣诲姞璁㈤槄
-			JSONObject subscribeKey = new JSONObject();
-			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", streamId);
-			subscribeKey.put("regist", true);
-			subscribeKey.put("schema", "rtmp");
-			subscribeKey.put("mediaServerId", mediaServerItem.getId());
-			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
+			logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
+			HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId());
+			subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
 				if (event != null) {
 					event.response(mediaServerItemInUse, json);
+					subscribe.removeSubscribe(hookSubscribe);
 				}
 			});
 			//
@@ -440,7 +437,7 @@
 				errorEvent.response(e);
 			}), e ->{
 				// 杩欓噷涓轰緥閬垮厤涓�涓�氶亾鐨勭偣鎾彧鏈変竴涓猚allID杩欎釜鍙傛暟浣跨敤涓�涓浐瀹氬��
-				streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
+				streamSession.put(device.getDeviceId(), channelId ,"play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
 				streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
 				okEvent.response(e);
 			});
@@ -530,21 +527,14 @@
 
 			CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
 					: udpSipProvider.getNewCallId();
-
+			HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtmp", mediaServerItem.getId());
 			// 娣诲姞璁㈤槄
-			JSONObject subscribeKey = new JSONObject();
-			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", ssrcInfo.getStream());
-			subscribeKey.put("regist", true);
-			subscribeKey.put("schema", "rtmp");
-			subscribeKey.put("mediaServerId", mediaServerItem.getId());
-			logger.debug("褰曞儚鍥炴斁娣诲姞璁㈤槄锛岃闃呭唴瀹癸細" + subscribeKey);
-			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
+			subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
 						if (hookEvent != null) {
 							InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());
 							hookEvent.call(inviteStreamInfo);
 						}
+						subscribe.removeSubscribe(hookSubscribe);
 					});
 	        Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
 
@@ -643,21 +633,15 @@
 			CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
 					: udpSipProvider.getNewCallId();
 
+			HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
 			// 娣诲姞璁㈤槄
-			JSONObject subscribeKey = new JSONObject();
-			subscribeKey.put("app", "rtp");
-			subscribeKey.put("stream", ssrcInfo.getStream());
-			subscribeKey.put("regist", true);
-			subscribeKey.put("mediaServerId", mediaServerItem.getId());
-			logger.debug("褰曞儚鍥炴斁娣诲姞璁㈤槄锛岃闃呭唴瀹癸細" + subscribeKey.toString());
-			subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-					(MediaServerItem mediaServerItemInUse, JSONObject json)->{
+			subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
 						hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
-						subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
-						subscribeKey.put("regist", false);
-						subscribeKey.put("schema", "rtmp");
+						subscribe.removeSubscribe(hookSubscribe);
+						hookSubscribe.getContent().put("regist", false);
+						hookSubscribe.getContent().put("schema", "rtmp");
 						// 娣诲姞娴佹敞閿�鐨勮闃咃紝娉ㄩ攢浜嗗悗鍚戣澶囧彂閫乥ye
-						subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
+						subscribe.addSubscribe(hookSubscribe,
 								(MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{
 									ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
 									if (transaction != null) {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
index 2d4913e..c87b554 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -257,37 +257,37 @@
         catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
         if (channels.size() > 0) {
             for (DeviceChannel channel : channels) {
+                if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
+                    channel.setParentId(parentPlatform.getDeviceGBId());
+                }
                 catalogXml.append("<Item>\r\n");
+                // 琛屾斂鍖哄垝鍒嗙粍鍙渶瑕佽繖涓ら」灏卞彲浠�
                 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
                 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
-                catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
                 if (channel.getParentId() != null) {
+                    // 涓氬姟鍒嗙粍鍔犱笂杩欎竴椤瑰嵆鍙紝鎻愰珮鍏煎鎬э紝
                     catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
                 }
-                if (channel.getChannelId().length() == 20) {
-                    if (Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 铏氭嫙缁勭粐澧炲姞BusinessGroupID瀛楁
-                        catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
-                    }
+                if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
+                    // 铏氭嫙缁勭粐澧炲姞BusinessGroupID瀛楁
+                    catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
+                }
+                catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
+                if (channel.getParental() == 0) {
+                    // 閫氶亾椤�
                     catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
+                    catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
                     catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
-                    catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
-                    if (channel.getChannelType() != 2) { // 涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝 涓嶈缃互涓嬪瓧娈�
-                        catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
+                    catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
+
+                    if (channel.getChannelType() != 2) {  // 涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝 涓嶈缃互涓嬪睘鎬�
                         catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
-                        catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n");
+                        catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
                         catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
                         catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
-                        catalogXml.append("<Longitude>" + channel.getLongitudeWgs84() + "</Longitude>\r\n");
-                        catalogXml.append("<Latitude>" + channel.getLatitudeWgs84() + "</Latitude>\r\n");
-                        catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
-                        catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
-                        catalogXml.append("<Info>\r\n");
-                        catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
-                        catalogXml.append("</Info>\r\n");
                     }
+
                 }
-
-
                 catalogXml.append("</Item>\r\n");
             }
         }
@@ -592,27 +592,35 @@
                     channel.setParentId(parentPlatform.getDeviceGBId());
                 }
                 catalogXml.append("<Item>\r\n");
+                // 琛屾斂鍖哄垝鍒嗙粍鍙渶瑕佽繖涓ら」灏卞彲浠�
                 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
                 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
-                catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
-                catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
                 if (channel.getParentId() != null) {
+                    // 涓氬姟鍒嗙粍鍔犱笂杩欎竴椤瑰嵆鍙紝鎻愰珮鍏煎鎬э紝
                     catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
                 }
-                catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
-                catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
-                catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
-                if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 铏氭嫙缁勭粐澧炲姞BusinessGroupID瀛楁
+                if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
+                    // 铏氭嫙缁勭粐澧炲姞BusinessGroupID瀛楁
                     catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
                 }
-                if (channel.getChannelType() == 2) {  // 涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝 涓嶈缃互涓嬪睘鎬�
-                    catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
-                    catalogXml.append("<Owner>0</Owner>\r\n");
-                    catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");
-                    catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
-                }
-                if (!"presence".equals(subscribeInfo.getEventType())) {
-                    catalogXml.append("<Event>" + type + "</Event>\r\n");
+                catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
+                if (channel.getParental() == 0) {
+                    // 閫氶亾椤�
+                    catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
+                    catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
+                    catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
+                    catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
+
+                    if (channel.getChannelType() != 2) {  // 涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝 涓嶈缃互涓嬪睘鎬�
+                        catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
+                        catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
+                        catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
+                        catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
+                    }
+                    if (!"presence".equals(subscribeInfo.getEventType())) {
+                        catalogXml.append("<Event>" + type + "</Event>\r\n");
+                    }
+
                 }
                 catalogXml.append("</Item>\r\n");
             }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
index 12083ed..9c45788 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -133,7 +133,7 @@
 					SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
 					if (ssrcTransactionForPlay != null){
 						SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
-						if (dialogForPlay.getCallId().equals(callIdHeader.getCallId())){
+						if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
 							// 閲婃斁ssrc
 							MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
 							if (mediaServerItem != null) {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
index 4023219..5e6e8d7 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -30,6 +30,7 @@
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.service.IPlayService;
+import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -81,6 +82,9 @@
     private IStreamPushService streamPushService;
 
     @Autowired
+    private IStreamProxyService streamProxyService;
+
+    @Autowired
     private IRedisCatchStorage redisCatchStorage;
 
     @Autowired
@@ -94,7 +98,7 @@
 
     @Autowired
     private ISIPCommander commander;
-	
+
 	@Autowired
 	private AudioBroadcastManager audioBroadcastManager;
 
@@ -153,10 +157,7 @@
         //  Invite Request娑堟伅瀹炵幇锛屾娑堟伅涓�鑸负绾ц仈娑堟伅锛屼笂绾х粰涓嬬骇鍙戦�佽姹傝棰戞寚浠�
         try {
             Request request = evt.getRequest();
-            SipURI sipUri = (SipURI) request.getRequestURI();
-            //浠巗ubject璇诲彇channelId,涓嶅啀浠巖equest-line璇诲彇銆� 鏈変簺骞冲彴request-line鏄钩鍙板浗鏍囩紪鐮侊紝涓嶆槸璁惧鍥芥爣缂栫爜銆�
-            //String channelId = sipURI.getUser();
-            String channelId = SipUtils.getChannelIdFromHeader(request);
+            String channelId = SipUtils.getChannelIdFromRequest(request);
             String requesterId = SipUtils.getUserIdFromFromHeader(request);
             CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
             if (requesterId == null || channelId == null) {
@@ -178,6 +179,7 @@
 
                 MediaServerItem mediaServerItem = null;
                 StreamPushItem streamPushItem = null;
+                StreamProxyItem proxyByAppAndStream =null;
                 // 涓嶆槸閫氶亾鍙兘鏄洿鎾祦
                 if (channel != null && gbStream == null) {
                     if (channel.getStatus() == 0) {
@@ -207,6 +209,13 @@
                         if ("push".equals(gbStream.getStreamType())) {
                             streamPushItem = streamPushService.getPush(gbStream.getApp(), gbStream.getStream());
                             if (streamPushItem == null) {
+                                logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
+                                responseAck(evt, Response.GONE);
+                                return;
+                            }
+                        }else if("proxy".equals(gbStream.getStreamType())){
+                            proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
+                            if (proxyByAppAndStream == null) {
                                 logger.info("[ app={}, stream={} ]鎵句笉鍒皕lm {}锛岃繑鍥�410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
                                 responseAck(evt, Response.GONE);
                                 return;
@@ -452,18 +461,35 @@
                         }
                     }
                 } else if (gbStream != null) {
-                    if (streamPushItem.isStatus()) {
-                        // 鍦ㄧ嚎鐘舵��
-                        pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
-                                mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
-                    } else {
-                        // 涓嶅湪绾� 鎷夎捣
-                        notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
-                                mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                    if("push".equals(gbStream.getStreamType())) {
+                        if (streamPushItem != null && streamPushItem.isPushIng()) {
+                            // 鎺ㄦ祦鐘舵��
+                            pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                        } else {
+                            // 鏈帹娴� 鎷夎捣
+                            notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                        }
+                    }else if ("proxy".equals(gbStream.getStreamType())){
+                        if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){
+                            pushProxyStream(evt, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                    mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                        }else{
+                            //寮�鍚唬鐞嗘媺娴�
+                            boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
+                            if(start1) {
+                                pushProxyStream(evt, gbStream,  platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                            }else{
+                                //澶辫触鍚庨�氱煡
+                                notifyStreamOnline(evt, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
+                                        mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
+                            }
+                        }
+
                     }
-
                 }
-
             }
 
         } catch (SipException | InvalidArgumentException | ParseException e) {
@@ -480,13 +506,45 @@
     /**
      * 瀹夋帓鎺ㄦ祦
      */
+    private void pushProxyStream(RequestEvent evt, GbStream gbStream, ParentPlatform platform,
+                            CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
+                            int port, Boolean tcpActive, boolean mediaTransmissionTCP,
+                            String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
+            Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
+            if (streamReady) {
+                // 鑷钩鍙板唴瀹�
+                SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
+                        gbStream.getApp(), gbStream.getStream(), channelId,
+                        mediaTransmissionTCP);
 
+                if (sendRtpItem == null) {
+                    logger.warn("鏈嶅姟鍣ㄧ鍙h祫婧愪笉瓒�");
+                    responseAck(evt, Response.BUSY_HERE);
+                    return;
+                }
+                if (tcpActive != null) {
+                    sendRtpItem.setTcpActive(tcpActive);
+                }
+                sendRtpItem.setPlayType(InviteStreamType.PUSH);
+                // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶�
+                sendRtpItem.setStatus(1);
+                sendRtpItem.setCallId(callIdHeader.getCallId());
+                byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
+                sendRtpItem.setDialog(dialogByteArray);
+                byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
+                sendRtpItem.setTransaction(transactionByteArray);
+                redisCatchStorage.updateSendRTPSever(sendRtpItem);
+                sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
+
+        }
+
+    }
     private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
                             CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
                             int port, Boolean tcpActive, boolean mediaTransmissionTCP,
                             String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
         // 鎺ㄦ祦
-        if (streamPushItem.getServerId().equals(userSetting.getServerId())) {
+        if (streamPushItem.isSelf()) {
             Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
             if (streamReady) {
                 // 鑷钩鍙板唴瀹�
@@ -525,7 +583,6 @@
         }
 
     }
-
     /**
      * 閫氱煡娴佷笂绾�
      */
@@ -535,7 +592,7 @@
                                     String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
         if ("proxy".equals(gbStream.getStreamType())) {
             // TODO 鎺у埗鍚敤浠ヤ娇璁惧涓婄嚎
-            logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽惎鐢ㄦ祦鍚庡紑濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
+            logger.info("[ app={}, stream={} ]閫氶亾鏈帹娴侊紝鍚敤娴佸悗寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
             responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
         } else if ("push".equals(gbStream.getStreamType())) {
             if (!platform.isStartOfflinePush()) {
@@ -543,7 +600,7 @@
                 return;
             }
             // 鍙戦�乺edis娑堟伅浠ヤ娇璁惧涓婄嚎
-            logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛屽彂閫乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
+            logger.info("[ app={}, stream={} ]閫氶亾鏈帹娴侊紝鍙戦�乺edis淇℃伅鎺у埗璁惧寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream());
 
             MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(1,
                     gbStream.getApp(), gbStream.getStream(), gbStream.getGbId(), gbStream.getPlatformId(),
@@ -553,7 +610,7 @@
             dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
                 logger.info("[ app={}, stream={} ] 绛夊緟璁惧寮�濮嬫帹娴佽秴鏃�", gbStream.getApp(), gbStream.getStream());
                 try {
-                    mediaListManager.removedChannelOnlineEventLister(gbStream.getGbId());
+                    mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
                     responseAck(evt, Response.REQUEST_TIMEOUT); // 瓒呮椂
                 } catch (SipException e) {
                     e.printStackTrace();
@@ -568,7 +625,7 @@
             Boolean finalTcpActive = tcpActive;
 
             // 娣诲姞鍦ㄦ湰鏈轰笂绾跨殑閫氱煡
-            mediaListManager.addChannelOnlineEventLister(gbStream.getGbId(), (app, stream, serverId) -> {
+            mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> {
                 dynamicTask.stop(callIdHeader.getCallId());
                 if (serverId.equals(userSetting.getServerId())) {
                     SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
@@ -656,7 +713,7 @@
                             // 绂荤嚎
                             // 鏌ヨ鏄惁鍦ㄦ湰鏈轰笂绾夸簡
                             StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
-                            if (currentStreamPushItem.isStatus()) {
+                            if (currentStreamPushItem.isPushIng()) {
                                 // 鍦ㄧ嚎鐘舵��
                                 pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
                                         mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
index 376d74b..4ce30a2 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -15,6 +15,7 @@
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -71,6 +72,9 @@
 	@Autowired
 	private SIPProcessorObserver sipProcessorObserver;
 
+	@Autowired
+	private IDeviceChannelService deviceChannelService;
+
 	private boolean taskQueueHandlerRun = false;
 
 	private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
@@ -88,39 +92,36 @@
 	@Override
 	public void process(RequestEvent evt) {
 		try {
-
 			taskQueue.offer(new HandlerCatchData(evt, null, null));
 			responseAck(evt, Response.OK);
 			if (!taskQueueHandlerRun) {
 				taskQueueHandlerRun = true;
 				taskExecutor.execute(()-> {
-							while (!taskQueue.isEmpty()) {
-								try {
-									HandlerCatchData take = taskQueue.poll();
-									Element rootElement = getRootElement(take.getEvt());
-									String cmd = XmlUtil.getText(rootElement, "CmdType");
+					while (!taskQueue.isEmpty()) {
+						try {
+							HandlerCatchData take = taskQueue.poll();
+							Element rootElement = getRootElement(take.getEvt());
+							String cmd = XmlUtil.getText(rootElement, "CmdType");
 
-									if (CmdType.CATALOG.equals(cmd)) {
-										logger.info("鎺ユ敹鍒癈atalog閫氱煡");
-										processNotifyCatalogList(take.getEvt());
-									} else if (CmdType.ALARM.equals(cmd)) {
-										logger.info("鎺ユ敹鍒癆larm閫氱煡");
-										processNotifyAlarm(take.getEvt());
-									} else if (CmdType.MOBILE_POSITION.equals(cmd)) {
-										logger.info("鎺ユ敹鍒癕obilePosition閫氱煡");
-										processNotifyMobilePosition(take.getEvt());
-									} else {
-										logger.info("鎺ユ敹鍒版秷鎭細" + cmd);
-									}
-								} catch (DocumentException e) {
-									throw new RuntimeException(e);
-								}
+							if (CmdType.CATALOG.equals(cmd)) {
+								logger.info("鎺ユ敹鍒癈atalog閫氱煡");
+								processNotifyCatalogList(take.getEvt());
+							} else if (CmdType.ALARM.equals(cmd)) {
+								logger.info("鎺ユ敹鍒癆larm閫氱煡");
+								processNotifyAlarm(take.getEvt());
+							} else if (CmdType.MOBILE_POSITION.equals(cmd)) {
+								logger.info("鎺ユ敹鍒癕obilePosition閫氱煡");
+								processNotifyMobilePosition(take.getEvt());
+							} else {
+								logger.info("鎺ユ敹鍒版秷鎭細" + cmd);
 							}
-						taskQueueHandlerRun = false;
-						});
+						} catch (DocumentException e) {
+							throw new RuntimeException(e);
+						}
+					}
+				taskQueueHandlerRun = false;
+				});
 			}
-
-
 		} catch (SipException | InvalidArgumentException | ParseException e) {
 			e.printStackTrace();
 		}
@@ -170,31 +171,10 @@
 			} else {
 				mobilePosition.setAltitude(0.0);
 			}
-			logger.info("[鏀跺埌 绉诲姩浣嶇疆璁㈤槄]锛歿}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
+			logger.info("[鏀跺埌绉诲姩浣嶇疆璁㈤槄閫氱煡]锛歿}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
 					mobilePosition.getLongitude(), mobilePosition.getLatitude());
 			mobilePosition.setReportSource("Mobile Position");
-			// 榛樿鏉ユ簮鍧愭爣绯讳负WGS-84澶勭悊
-			if ("WGS84".equals(device.getGeoCoordSys())) {
-				mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
-				mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
-				Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-				mobilePosition.setLongitudeGcj02(position[0]);
-				mobilePosition.setLatitudeGcj02(position[1]);
-			}else if ("GCJ02".equals(device.getGeoCoordSys())) {
-				mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
-				mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
-				Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-				mobilePosition.setLongitudeWgs84(position[0]);
-				mobilePosition.setLatitudeWgs84(position[1]);
-			}else {
-				mobilePosition.setLongitudeGcj02(0.00);
-				mobilePosition.setLatitudeGcj02(0.00);
-				mobilePosition.setLongitudeWgs84(0.00);
-				mobilePosition.setLatitudeWgs84(0.00);
-			}
-			if (userSetting.getSavePositionHistory()) {
-				storager.insertMobilePosition(mobilePosition);
-			}
+
 
 			// 鏇存柊device channel 鐨勭粡绾害
 			DeviceChannel deviceChannel = new DeviceChannel();
@@ -202,11 +182,18 @@
 			deviceChannel.setChannelId(channelId);
 			deviceChannel.setLongitude(mobilePosition.getLongitude());
 			deviceChannel.setLatitude(mobilePosition.getLatitude());
-			deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
-			deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
-			deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
-			deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
 			deviceChannel.setGpsTime(mobilePosition.getTime());
+			deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
+
+			mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
+			mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
+			mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
+			mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
+
+			if (userSetting.getSavePositionHistory()) {
+				storager.insertMobilePosition(mobilePosition);
+			}
+
 			storager.updateChannelPosition(deviceChannel);
 			// 鍙戦�乺edis娑堟伅銆� 閫氱煡浣嶇疆淇℃伅鐨勫彉鍖�
 			JSONObject jsonObject = new JSONObject();
@@ -281,38 +268,28 @@
 				mobilePosition.setLongitude(deviceAlarm.getLongitude());
 				mobilePosition.setLatitude(deviceAlarm.getLatitude());
 				mobilePosition.setReportSource("GPS Alarm");
-				if ("WGS84".equals(device.getGeoCoordSys())) {
-					mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
-					mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
-					Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-					mobilePosition.setLongitudeGcj02(position[0]);
-					mobilePosition.setLatitudeGcj02(position[1]);
-				}else if ("GCJ02".equals(device.getGeoCoordSys())) {
-					mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
-					mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
-					Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-					mobilePosition.setLongitudeWgs84(position[0]);
-					mobilePosition.setLatitudeWgs84(position[1]);
-				}else {
-					mobilePosition.setLongitudeGcj02(0.00);
-					mobilePosition.setLatitudeGcj02(0.00);
-					mobilePosition.setLongitudeWgs84(0.00);
-					mobilePosition.setLatitudeWgs84(0.00);
-				}
-				if (userSetting.getSavePositionHistory()) {
-					storager.insertMobilePosition(mobilePosition);
-				}
+
+
+
 				// 鏇存柊device channel 鐨勭粡绾害
 				DeviceChannel deviceChannel = new DeviceChannel();
 				deviceChannel.setDeviceId(device.getDeviceId());
 				deviceChannel.setChannelId(channelId);
 				deviceChannel.setLongitude(mobilePosition.getLongitude());
 				deviceChannel.setLatitude(mobilePosition.getLatitude());
-				deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
-				deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
-				deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
-				deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
 				deviceChannel.setGpsTime(mobilePosition.getTime());
+
+				deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
+
+				mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
+				mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
+				mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
+				mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
+
+				if (userSetting.getSavePositionHistory()) {
+					storager.insertMobilePosition(mobilePosition);
+				}
+
 				storager.updateChannelPosition(deviceChannel);
 			}
 			// TODO: 闇�瑕佸疄鐜板瓨鍌ㄦ姤璀︿俊鎭�佹姤璀﹀垎绫�
@@ -338,7 +315,7 @@
 
 			Device device = redisCatchStorage.getDevice(deviceId);
 			if (device == null || device.getOnline() == 0) {
-				logger.warn("[鏀跺埌 鐩綍璁㈤槄]锛歿}, 浣嗘槸璁惧宸茬粡绂荤嚎", (device != null ? device.getDeviceId():"" ));
+				logger.warn("[鏀跺埌鐩綍璁㈤槄]锛歿}, 浣嗘槸璁惧宸茬粡绂荤嚎", (device != null ? device.getDeviceId():"" ));
 				return;
 			}
 			Element rootElement = getRootElement(evt, device.getCharset());
@@ -359,28 +336,28 @@
 					Element eventElement = itemDevice.element("Event");
 					String event;
 					if (eventElement == null) {
-						logger.warn("[鏀跺埌 鐩綍璁㈤槄]锛歿}, 浣嗘槸Event涓虹┖, 璁句负榛樿鍊� ADD", (device != null ? device.getDeviceId():"" ));
+						logger.warn("[鏀跺埌鐩綍璁㈤槄]锛歿}, 浣嗘槸Event涓虹┖, 璁句负榛樿鍊� ADD", (device != null ? device.getDeviceId():"" ));
 						event = CatalogEvent.ADD;
 					}else {
 						event = eventElement.getText().toUpperCase();
 					}
-					DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device);
+					DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
 					channel.setDeviceId(device.getDeviceId());
-					logger.info("[鏀跺埌 鐩綍璁㈤槄]锛歿}/{}", device.getDeviceId(), channel.getChannelId());
+					logger.info("[鏀跺埌鐩綍璁㈤槄]锛歿}/{}", device.getDeviceId(), channel.getChannelId());
 					switch (event) {
 						case CatalogEvent.ON:
 							// 涓婄嚎
-							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾銆恵}銆戜笂绾块�氱煡", device.getDeviceId(), channel.getChannelId());
+							logger.info("[鏀跺埌閫氶亾涓婄嚎閫氱煡] 鏉ヨ嚜璁惧: {}, 閫氶亾 {}", device.getDeviceId(), channel.getChannelId());
 							storager.deviceChannelOnline(deviceId, channel.getChannelId());
 							break;
 						case CatalogEvent.OFF :
 							// 绂荤嚎
-							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾銆恵}銆戠绾块�氱煡", device.getDeviceId(), channel.getChannelId());
+							logger.info("[鏀跺埌閫氶亾绂荤嚎閫氱煡] 鏉ヨ嚜璁惧: {}, 閫氶亾 {}", device.getDeviceId(), channel.getChannelId());
 							storager.deviceChannelOffline(deviceId, channel.getChannelId());
 							break;
 						case CatalogEvent.VLOST:
 							// 瑙嗛涓㈠け
-							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾銆恵}銆戣棰戜涪澶遍�氱煡", device.getDeviceId(), channel.getChannelId());
+							logger.info("[鏀跺埌閫氶亾瑙嗛涓㈠け閫氱煡] 鏉ヨ嚜璁惧: {}, 閫氶亾 {}", device.getDeviceId(), channel.getChannelId());
 							storager.deviceChannelOffline(deviceId, channel.getChannelId());
 							break;
 						case CatalogEvent.DEFECT:
@@ -388,18 +365,18 @@
 							break;
 						case CatalogEvent.ADD:
 							// 澧炲姞
-							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑澧炲姞閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId());
-							storager.updateChannel(deviceId, channel);
+							logger.info("[鏀跺埌澧炲姞閫氶亾閫氱煡] 鏉ヨ嚜璁惧: {}, 閫氶亾 {}", device.getDeviceId(), channel.getChannelId());
+							deviceChannelService.updateChannel(deviceId, channel);
 							break;
 						case CatalogEvent.DEL:
 							// 鍒犻櫎
-							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑鍒犻櫎閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId());
+							logger.info("[鏀跺埌鍒犻櫎閫氶亾閫氱煡] 鏉ヨ嚜璁惧: {}, 閫氶亾 {}", device.getDeviceId(), channel.getChannelId());
 							storager.delChannel(deviceId, channel.getChannelId());
 							break;
 						case CatalogEvent.UPDATE:
 							// 鏇存柊
-							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑鏇存柊閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId());
-							storager.updateChannel(deviceId, channel);
+							logger.info("[鏀跺埌鏇存柊閫氶亾閫氱煡] 鏉ヨ嚜璁惧: {}, 閫氶亾 {}", device.getDeviceId(), channel.getChannelId());
+							deviceChannelService.updateChannel(deviceId, channel);
 							break;
 						default:
 							logger.warn("[ NotifyCatalog ] event not found 锛� {}", event );
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
index 622cf07..351b79c 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -143,6 +143,7 @@
                 device.setGeoCoordSys("WGS84");
                 device.setTreeType("CivilCode");
                 device.setDeviceId(deviceId);
+                device.setOnline(0);
             }
             device.setIp(received);
             device.setPort(rPort);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
index cd85889..e004b89 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
@@ -27,6 +27,7 @@
 import javax.sip.address.SipURI;
 import javax.sip.header.CSeqHeader;
 import javax.sip.header.CallIdHeader;
+import javax.sip.message.Request;
 import javax.sip.message.Response;
 import java.text.ParseException;
 import java.util.Map;
@@ -68,22 +69,23 @@
 
     @Override
     public void process(RequestEvent evt) {
+        SIPRequest sipRequest = (SIPRequest)evt.getRequest();
         logger.debug("鎺ユ敹鍒版秷鎭細" + evt.getRequest());
         String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
-        CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
+        CallIdHeader callIdHeader = sipRequest.getCallIdHeader();
         // 鍏堜粠浼氳瘽鍐呮煡鎵�
         SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
-        if (ssrcTransaction != null) { // 鍏煎娴峰悍 濯掍綋閫氱煡 娑堟伅from瀛楁涓嶆槸璁惧ID鐨勯棶棰�
+        // 鍏煎娴峰悍 濯掍綋閫氱煡 娑堟伅from瀛楁涓嶆槸璁惧ID鐨勯棶棰�
+        if (ssrcTransaction != null) {
             deviceId = ssrcTransaction.getDeviceId();
         }
         // 鏌ヨ璁惧鏄惁瀛樺湪
-        CSeqHeader cseqHeader = (CSeqHeader) evt.getRequest().getHeader(CSeqHeader.NAME);
-        String method = cseqHeader.getMethod();
         Device device = redisCatchStorage.getDevice(deviceId);
         // 鏌ヨ涓婄骇骞冲彴鏄惁瀛樺湪
         ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
         try {
             if (device != null && parentPlatform != null) {
+
                 logger.warn("[閲嶅]骞冲彴涓庤澶囩紪鍙烽噸澶嶏細{}", deviceId);
                 SIPRequest request = (SIPRequest) evt.getRequest();
                 String hostAddress = request.getRemoteAddress().getHostAddress();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java
index c546057..c8be504 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java
@@ -9,6 +9,7 @@
 /**
  * 鍛戒护绫诲瀷锛� 閫氱煡鍛戒护
  * 鍛戒护绫诲瀷锛� 鐘舵�佷俊鎭�(蹇冭烦)鎶ラ��, 鎶ヨ閫氱煡, 濯掍綋閫氱煡, 绉诲姩璁惧浣嶇疆鏁版嵁锛岃闊冲箍鎾�氱煡(TODO), 璁惧棰勭疆浣�(TODO)
+ * @author lin
  */
 @Component
 public class NotifyMessageHandler extends MessageHandlerAbstract implements InitializingBean  {
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
index 8dfd233..20316e7 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
@@ -11,6 +11,7 @@
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -58,6 +59,9 @@
     @Autowired
     private IDeviceAlarmService deviceAlarmService;
 
+    @Autowired
+    private IDeviceChannelService deviceChannelService;
+
     @Override
     public void afterPropertiesSet() throws Exception {
         notifyMessageHandler.addHandler(cmdType, this);
@@ -65,7 +69,7 @@
 
     @Override
     public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
-        logger.info("鏀跺埌鏉ヨ嚜璁惧[{}]鐨勬姤璀﹂�氱煡", device.getDeviceId());
+        logger.info("[鏀跺埌鎶ヨ閫氱煡]璁惧锛歿}", device.getDeviceId());
         // 鍥炲200 OK
         try {
             responseAck(evt, Response.OK);
@@ -119,38 +123,26 @@
                 mobilePosition.setLongitude(deviceAlarm.getLongitude());
                 mobilePosition.setLatitude(deviceAlarm.getLatitude());
                 mobilePosition.setReportSource("GPS Alarm");
-                if ("WGS84".equals(device.getGeoCoordSys())) {
-                    mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
-                    mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
-                    Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-                    mobilePosition.setLongitudeGcj02(position[0]);
-                    mobilePosition.setLatitudeGcj02(position[1]);
-                }else if ("GCJ02".equals(device.getGeoCoordSys())) {
-                    mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
-                    mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
-                    Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-                    mobilePosition.setLongitudeWgs84(position[0]);
-                    mobilePosition.setLatitudeWgs84(position[1]);
-                }else {
-                    mobilePosition.setLongitudeGcj02(0.00);
-                    mobilePosition.setLatitudeGcj02(0.00);
-                    mobilePosition.setLongitudeWgs84(0.00);
-                    mobilePosition.setLatitudeWgs84(0.00);
-                }
-                if (userSetting.getSavePositionHistory()) {
-                    storager.insertMobilePosition(mobilePosition);
-                }
+
+
                 // 鏇存柊device channel 鐨勭粡绾害
                 DeviceChannel deviceChannel = new DeviceChannel();
                 deviceChannel.setDeviceId(device.getDeviceId());
                 deviceChannel.setChannelId(channelId);
                 deviceChannel.setLongitude(mobilePosition.getLongitude());
                 deviceChannel.setLatitude(mobilePosition.getLatitude());
-                deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
-                deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
-                deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
-                deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
                 deviceChannel.setGpsTime(mobilePosition.getTime());
+
+                deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
+
+                mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
+                mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
+                mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
+                mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
+
+                if (userSetting.getSavePositionHistory()) {
+                    storager.insertMobilePosition(mobilePosition);
+                }
                 storager.updateChannelPosition(deviceChannel);
             }
         }
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
index d714ee4..0b27855 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
@@ -58,85 +58,21 @@
             // 鍑嗗鍥炲閫氶亾淇℃伅
             List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
             // 鏌ヨ鍏宠仈鐨勭洿鎾�氶亾
-            List<GbStream> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
+            List<DeviceChannel> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
+            // 鍥炲鐩綍淇℃伅
+            List<DeviceChannel> catalogs =  storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
 
             List<DeviceChannel> allChannels = new ArrayList<>();
-            // 鍥炲鐩綍淇℃伅
-            List<PlatformCatalog> catalogs =  storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
             if (catalogs.size() > 0) {
-                for (PlatformCatalog catalog : catalogs) {
-                    if (catalog.getParentId().equals(catalog.getPlatformId())) {
-                        catalog.setParentId(parentPlatform.getDeviceGBId());
-                    }
-                    DeviceChannel deviceChannel = new DeviceChannel();
-                    deviceChannel.setChannelId(catalog.getId());
-                    deviceChannel.setName(catalog.getName());
-                    deviceChannel.setLongitude(0.0);
-                    deviceChannel.setLatitude(0.0);
-                    deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
-                    deviceChannel.setManufacture("wvp-pro");
-                    deviceChannel.setStatus(1);
-                    deviceChannel.setParental(1);
-                    deviceChannel.setParentId(catalog.getParentId());
-                    deviceChannel.setRegisterWay(1);
-                    if (catalog.getParentId() != null && catalog.getParentId().length() <= 10) {
-                        deviceChannel.setCivilCode(catalog.getParentId());
-                    }else {
-                        deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    }
-                    deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    deviceChannel.setModel("live");
-                    deviceChannel.setOwner("wvp-pro");
-                    deviceChannel.setSecrecy("0");
-                    allChannels.add(deviceChannel);
-                }
+                allChannels.addAll(catalogs);
             }
             // 鍥炲绾ц仈鐨勯�氶亾
             if (deviceChannels.size() > 0) {
-                for (DeviceChannelInPlatform channel : deviceChannels) {
-                    if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {
-                        channel.setCatalogId(parentPlatform.getDeviceGBId());
-                    }
-                    DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());
-                    deviceChannel.setParental(0);
-                    deviceChannel.setParentId(channel.getCatalogId());
-                    if (channel.getCatalogId() != null &&  channel.getCatalogId().length() <= 10) {
-                        channel.setCivilCode(channel.getCatalogId());
-                    }else {
-                        deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    }
-
-                    allChannels.add(deviceChannel);
-                }
+                allChannels.addAll(deviceChannels);
             }
             // 鍥炲鐩存挱鐨勯�氶亾
             if (gbStreams.size() > 0) {
-                for (GbStream gbStream : gbStreams) {
-                    if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
-                        gbStream.setCatalogId(null);
-                    }
-                    DeviceChannel deviceChannel = new DeviceChannel();
-                    deviceChannel.setChannelId(gbStream.getGbId());
-                    deviceChannel.setName(gbStream.getName());
-                    deviceChannel.setLongitude(gbStream.getLongitude());
-                    deviceChannel.setLatitude(gbStream.getLatitude());
-                    deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
-                    deviceChannel.setManufacture("wvp-pro");
-//                    deviceChannel.setStatus(gbStream.isStatus()?1:0);
-                    deviceChannel.setStatus(1);
-    				deviceChannel.setParentId(gbStream.getCatalogId());
-                    deviceChannel.setRegisterWay(1);
-                    if (gbStream.getCatalogId() != null && gbStream.getCatalogId().length() <= 10) {
-                        deviceChannel.setCivilCode(gbStream.getCatalogId());
-                    }else {
-                        deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    }
-                    deviceChannel.setModel("live");
-                    deviceChannel.setOwner("wvp-pro");
-                    deviceChannel.setParental(0);
-                    deviceChannel.setSecrecy("0");
-                    allChannels.add(deviceChannel);
-                }
+                allChannels.addAll(gbStreams);
             }
             if (allChannels.size() > 0) {
                 cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
index aa91556..2402494 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
@@ -7,6 +7,7 @@
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.utils.GpsUtil;
@@ -41,6 +42,9 @@
 
     @Autowired
     private IVideoManagerStorage storager;
+
+    @Autowired
+    private IDeviceChannelService deviceChannelService;
 
     @Override
     public void afterPropertiesSet() throws Exception {
@@ -79,38 +83,26 @@
                 mobilePosition.setAltitude(0.0);
             }
             mobilePosition.setReportSource("Mobile Position");
-            if ("WGS84".equals(device.getGeoCoordSys())) {
-                mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
-                mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
-                Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-                mobilePosition.setLongitudeGcj02(position[0]);
-                mobilePosition.setLatitudeGcj02(position[1]);
-            }else if ("GCJ02".equals(device.getGeoCoordSys())) {
-                mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
-                mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
-                Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-                mobilePosition.setLongitudeWgs84(position[0]);
-                mobilePosition.setLatitudeWgs84(position[1]);
-            }else {
-                mobilePosition.setLongitudeGcj02(0.00);
-                mobilePosition.setLatitudeGcj02(0.00);
-                mobilePosition.setLongitudeWgs84(0.00);
-                mobilePosition.setLatitudeWgs84(0.00);
-            }
-            if (userSetting.getSavePositionHistory()) {
-                storager.insertMobilePosition(mobilePosition);
-            }
+
+
             // 鏇存柊device channel 鐨勭粡绾害
             DeviceChannel deviceChannel = new DeviceChannel();
             deviceChannel.setDeviceId(device.getDeviceId());
             deviceChannel.setChannelId(mobilePosition.getChannelId());
             deviceChannel.setLongitude(mobilePosition.getLongitude());
             deviceChannel.setLatitude(mobilePosition.getLatitude());
-            deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
-            deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
-            deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
-            deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
             deviceChannel.setGpsTime(mobilePosition.getTime());
+
+            deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
+
+            mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
+            mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
+            mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
+            mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
+
+            if (userSetting.getSavePositionHistory()) {
+                storager.insertMobilePosition(mobilePosition);
+            }
             storager.updateChannelPosition(deviceChannel);
             //鍥炲 200 OK
             responseAck(evt, Response.OK);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
index 0e97961..7f6f817 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
@@ -70,86 +70,24 @@
             Element snElement = rootElement.element("SN");
             String sn = snElement.getText();
             // 鍑嗗鍥炲閫氶亾淇℃伅
-            List<DeviceChannelInPlatform> deviceChannelInPlatforms = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
+            List<DeviceChannel> deviceChannelInPlatforms = storager.queryChannelWithCatalog(parentPlatform.getServerGBId());
             // 鏌ヨ鍏宠仈鐨勭洿鎾�氶亾
-            List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
+            List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
             // 鍥炲鐩綍淇℃伅
-            List<PlatformCatalog> catalogs =  storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
+            List<DeviceChannel> catalogs =  storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
 
             List<DeviceChannel> allChannels = new ArrayList<>();
+
             if (catalogs.size() > 0) {
-                for (PlatformCatalog catalog : catalogs) {
-                    if (catalog.getParentId().equals(catalog.getPlatformId())) {
-                        catalog.setParentId(parentPlatform.getDeviceGBId());
-                    }
-                    DeviceChannel deviceChannel = new DeviceChannel();
-                    // 閫氶亾鐨勭被鍨嬶紝0->鍥芥爣閫氶亾 1->鐩存挱娴侀�氶亾 2->涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝
-                    deviceChannel.setChannelType(2);
-                    deviceChannel.setChannelId(catalog.getId());
-                    deviceChannel.setName(catalog.getName());
-                    deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
-                    deviceChannel.setManufacture("wvp-pro");
-                    deviceChannel.setStatus(1);
-                    deviceChannel.setParental(1);
-                    deviceChannel.setParentId(catalog.getParentId());
-                    deviceChannel.setRegisterWay(1);
-                    if (catalog.getParentId() != null &&  catalog.getParentId().length() < 10) {
-                        deviceChannel.setCivilCode(catalog.getParentId());
-                    }else {
-                        deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    }
-                    allChannels.add(deviceChannel);
-                }
+                allChannels.addAll(catalogs);
             }
             // 鍥炲绾ц仈鐨勯�氶亾
             if (deviceChannelInPlatforms.size() > 0) {
-                for (DeviceChannelInPlatform channel : deviceChannelInPlatforms) {
-                    if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {
-                        channel.setCatalogId(parentPlatform.getDeviceGBId());
-                    }
-                    DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());
-                    // 閫氶亾鐨勭被鍨嬶紝0->鍥芥爣閫氶亾 1->鐩存挱娴侀�氶亾 2->涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝
-                    deviceChannel.setChannelType(0);
-                    deviceChannel.setParental(0);
-                    deviceChannel.setParentId(channel.getCatalogId());
-                    if (channel.getCatalogId() != null && channel.getCatalogId().length() < 10) {
-                        deviceChannel.setCivilCode(channel.getCatalogId());
-                    }else {
-                        deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    }
-                    allChannels.add(deviceChannel);
-                }
+                allChannels.addAll(deviceChannelInPlatforms);
             }
             // 鍥炲鐩存挱鐨勯�氶亾
             if (gbStreams.size() > 0) {
-                for (GbStream gbStream : gbStreams) {
-                    if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {
-                        gbStream.setCatalogId(null);
-                    }
-                    DeviceChannel deviceChannel = new DeviceChannel();
-                    // 閫氶亾鐨勭被鍨嬶紝0->鍥芥爣閫氶亾 1->鐩存挱娴侀�氶亾 2->涓氬姟鍒嗙粍/铏氭嫙缁勭粐/琛屾斂鍖哄垝
-                    deviceChannel.setChannelType(1);
-                    deviceChannel.setChannelId(gbStream.getGbId());
-                    deviceChannel.setName(gbStream.getName());
-                    deviceChannel.setLongitude(gbStream.getLongitude());
-                    deviceChannel.setLatitude(gbStream.getLatitude());
-                    deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
-                    deviceChannel.setManufacture("wvp-pro");
-//                    deviceChannel.setStatus(gbStream.isStatus()?1:0);
-                    deviceChannel.setStatus(1);
-                    deviceChannel.setParentId(gbStream.getCatalogId());
-                    deviceChannel.setRegisterWay(1);
-                    if (gbStream.getCatalogId() != null && gbStream.getCatalogId().length() < 10) {
-                        deviceChannel.setCivilCode(gbStream.getCatalogId());
-                    }else {
-                        deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());
-                    }
-                    deviceChannel.setModel("live");
-                    deviceChannel.setOwner("wvp-pro");
-                    deviceChannel.setParental(0);
-                    deviceChannel.setSecrecy("0");
-                    allChannels.add(deviceChannel);
-                }
+                allChannels.addAll(gbStreams);
             }
             if (allChannels.size() > 0) {
                 cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
index 8234cb1..19183e0 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
@@ -44,7 +44,7 @@
 
     @Override
     public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
-        logger.info("鎺ユ敹鍒癉eviceInfo鏌ヨ娑堟伅");
+        logger.info("[DeviceInfo鏌ヨ]娑堟伅");
         FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
         try {
             // 鍥炲200 OK
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
index 2766474..ff71a92 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -111,6 +111,7 @@
                         int sumNum = Integer.parseInt(sumNumElement.getText());
 
                         if (sumNum == 0) {
+                            logger.info("[鏀跺埌閫氶亾]璁惧:{}鐨�: 0涓�", take.getDevice().getDeviceId());
                             // 鏁版嵁宸茬粡瀹屾暣鎺ユ敹
                             storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
                             catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
@@ -125,18 +126,14 @@
                                     if (channelDeviceElement == null) {
                                         continue;
                                     }
-                                    //by brewswang
-    //                        if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//濡傛灉鍖呭惈浣嶇疆淇℃伅锛屽氨鏇存柊涓�涓嬩綅缃�
-    //                            processNotifyMobilePosition(evt, itemDevice);
-    //                        }
-                                    DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device);
+                                    DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
                                     deviceChannel.setDeviceId(take.getDevice().getDeviceId());
 
                                     channelList.add(deviceChannel);
                                 }
                                 int sn = Integer.parseInt(snElement.getText());
                                 catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
-                                logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑閫氶亾: {}涓紝{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
+                                logger.info("[鏀跺埌閫氶亾]璁惧: {} -> {}涓紝{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
                                 if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
                                     // 鏁版嵁宸茬粡瀹屾暣鎺ユ敹
                                     boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
index eb2c7b8..f5d04be 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
@@ -87,7 +87,6 @@
                 device.setStreamMode("UDP");
             }
             deviceService.updateDevice(device);
-//            storager.updateDevice(device);
 
             RequestMessage msg = new RequestMessage();
             msg.setKey(key);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
index e562fa4..4c723ab 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
@@ -7,6 +7,7 @@
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.utils.GpsUtil;
@@ -41,6 +42,9 @@
 
     @Autowired
     private IVideoManagerStorage storager;
+
+    @Autowired
+    private IDeviceChannelService deviceChannelService;
 
     @Override
     public void afterPropertiesSet() throws Exception {
@@ -79,38 +83,25 @@
                 mobilePosition.setAltitude(0.0);
             }
             mobilePosition.setReportSource("Mobile Position");
-            if ("WGS84".equals(device.getGeoCoordSys())) {
-                mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());
-                mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());
-                Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-                mobilePosition.setLongitudeGcj02(position[0]);
-                mobilePosition.setLatitudeGcj02(position[1]);
-            }else if ("GCJ02".equals(device.getGeoCoordSys())) {
-                mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());
-                mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());
-                Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
-                mobilePosition.setLongitudeWgs84(position[0]);
-                mobilePosition.setLatitudeWgs84(position[1]);
-            }else {
-                mobilePosition.setLongitudeGcj02(0.00);
-                mobilePosition.setLatitudeGcj02(0.00);
-                mobilePosition.setLongitudeWgs84(0.00);
-                mobilePosition.setLatitudeWgs84(0.00);
-            }
-            if (userSetting.getSavePositionHistory()) {
-                storager.insertMobilePosition(mobilePosition);
-            }
+
             // 鏇存柊device channel 鐨勭粡绾害
             DeviceChannel deviceChannel = new DeviceChannel();
             deviceChannel.setDeviceId(device.getDeviceId());
             deviceChannel.setChannelId(mobilePosition.getChannelId());
             deviceChannel.setLongitude(mobilePosition.getLongitude());
             deviceChannel.setLatitude(mobilePosition.getLatitude());
-            deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());
-            deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());
-            deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());
-            deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());
             deviceChannel.setGpsTime(mobilePosition.getTime());
+
+            deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
+
+            mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
+            mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
+            mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
+            mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
+
+            if (userSetting.getSavePositionHistory()) {
+                storager.insertMobilePosition(mobilePosition);
+            }
             storager.updateChannelPosition(deviceChannel);
             //鍥炲 200 OK
             responseAck(evt, Response.OK);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
index f3a9f65..a48dd20 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
@@ -26,7 +26,7 @@
 @Component
 public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
 
-	private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class);
+	private final Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class);
 	private final String method = "REGISTER";
 
 	@Autowired
@@ -69,11 +69,11 @@
 
 		ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId);
 		if (parentPlatformCatch == null) {
-			logger.warn(String.format("鏀跺埌 %s 鐨勬敞鍐�/娉ㄩ攢%S璇锋眰, 浣嗘槸骞冲彴缂撳瓨淇℃伅鏈煡璇㈠埌!!!", platformGBId, response.getStatusCode()));
+			logger.warn(String.format("[鏀跺埌娉ㄥ唽/娉ㄩ攢%S璇锋眰]骞冲彴锛�%s锛屼絾鏄钩鍙扮紦瀛樹俊鎭湭鏌ヨ鍒�!!!", response.getStatusCode(),platformGBId));
 			return;
 		}
 		String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "娉ㄩ攢" : "娉ㄥ唽";
-		logger.info(String.format("鏀跺埌 %s %s鐨�%S鍝嶅簲", platformGBId, action, response.getStatusCode() ));
+		logger.info(String.format("[%s %S鍝嶅簲]%s ", action, response.getStatusCode(), platformGBId ));
 		ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform();
 		if (parentPlatform == null) {
 			logger.warn(String.format("鏀跺埌 %s %s鐨�%S璇锋眰, 浣嗘槸骞冲彴淇℃伅鏈煡璇㈠埌!!!", platformGBId, action, response.getStatusCode()));
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
index 35ec640..44e1337 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
@@ -23,9 +23,10 @@
     /**
      * 浠巗ubject璇诲彇channelId
      * */
-    public static String getChannelIdFromHeader(Request request) {
+    public static String getChannelIdFromRequest(Request request) {
         Header subject = request.getHeader("subject");
         if (subject == null) {
+            // 濡傛灉缂哄けsubject
             return null;
         }
         return ((Subject) subject).getSubject().split(":")[0];
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
index 72206d8..ced97ef 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -4,6 +4,8 @@
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.gb28181.bean.Device;
 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+import com.genersoft.iot.vmp.gb28181.bean.TreeType;
+import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import org.dom4j.Attribute;
 import org.dom4j.Document;
@@ -29,7 +31,7 @@
     /**
      * 鏃ュ織鏈嶅姟
      */
-    private static Logger LOG = LoggerFactory.getLogger(XmlUtil.class);
+    private static Logger logger = LoggerFactory.getLogger(XmlUtil.class);
 
     /**
      * 瑙f瀽XML涓篋ocument瀵硅薄
@@ -46,7 +48,7 @@
         try {
             document = saxReader.read(sr);
         } catch (DocumentException e) {
-            LOG.error("瑙f瀽澶辫触", e);
+            logger.error("瑙f瀽澶辫触", e);
         }
         return null == document ? null : document.getRootElement();
     }
@@ -182,47 +184,69 @@
         return xml.getRootElement();
     }
 
-    public static DeviceChannel channelContentHander(Element itemDevice, Device device){
-        Element channdelNameElement = itemDevice.element("Name");
-        String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";
-        Element statusElement = itemDevice.element("Status");
-        String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON";
+    private enum ChannelType{
+        CivilCode, BusinessGroup,VirtualOrganization,Other
+    }
+
+    public static DeviceChannel channelContentHander(Element itemDevice, Device device, String event){
         DeviceChannel deviceChannel = new DeviceChannel();
-        deviceChannel.setName(channelName);
+        deviceChannel.setDeviceId(device.getDeviceId());
         Element channdelIdElement = itemDevice.element("DeviceID");
-        String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : "";
-        deviceChannel.setChannelId(channelId);
-        // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR鐨勫吋瀹规�у鐞�
-        if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
-            deviceChannel.setStatus(1);
+        if (channdelIdElement == null) {
+            logger.warn("瑙f瀽Catalog娑堟伅鏃跺彂鐜扮己灏� DeviceID");
+            return null;
         }
-        if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
-            deviceChannel.setStatus(0);
+        String channelId = channdelIdElement.getTextTrim();
+        if (StringUtils.isEmpty(channelId)) {
+            logger.warn("瑙f瀽Catalog娑堟伅鏃跺彂鐜扮己灏� DeviceID");
+            return null;
+        }
+        deviceChannel.setChannelId(channelId);
+        if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) {
+            // 闄や簡ADD鍜寀pdate鎯呭喌涓嬮渶瑕佽瘑鍒叏閮ㄥ唴瀹癸紝
+            return deviceChannel;
         }
 
-        deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
-        deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
-        deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
-        deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));
-        deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
-        deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
-        String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
-        if (XmlUtil.getText(itemDevice, "Parental") == null
-                || XmlUtil.getText(itemDevice, "Parental").equals("")) {
-            if (deviceChannel.getChannelId().length() <= 10
-                    || (deviceChannel.getChannelId().length() == 20 && (
-                            Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 215
-                                    || Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216
-                            )
-                        )
-            ) {
-                deviceChannel.setParental(1);
-            }else {
-                deviceChannel.setParental(0);
+        ChannelType channelType = ChannelType.Other;
+        if (channelId.length() <= 8) {
+            channelType = ChannelType.CivilCode;
+        }else {
+            if (channelId.length() == 20) {
+                int code = Integer.parseInt(channelId.substring(10, 13));
+                switch (code){
+                    case 215:
+                        channelType = ChannelType.BusinessGroup;
+                        break;
+                    case 216:
+                        channelType = ChannelType.VirtualOrganization;
+                        break;
+                    default:
+                        break;
+
+                }
             }
-        } else {
-            // 鐢变簬娴峰悍浼氶敊璇殑鍙戦��65535浣滀负杩欓噷鐨勫彇鍊�,鎵�浠ヨ繖閲岄櫎闈炴槸0鍚﹀垯璁や负鏄�1
-            deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")) == 1?1:0);
+        }
+
+        Element channdelNameElement = itemDevice.element("Name");
+        String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim() : "";
+        deviceChannel.setName(channelName);
+
+        String civilCode = XmlUtil.getText(itemDevice, "CivilCode");
+        deviceChannel.setCivilCode(civilCode);
+        if (channelType == ChannelType.CivilCode && civilCode == null) {
+            deviceChannel.setParental(1);
+            // 琛屾斂鍖哄垝濡傛灉娌℃湁浼犻�掑叿浣撳�硷紝鍒欐帹娴嬩竴涓�
+            if (channelId.length() > 2) {
+                deviceChannel.setCivilCode(channelId.substring(0, channelId.length() - 2));
+            }
+        }
+        if (channelType.equals(ChannelType.CivilCode)) {
+            // 琛屾斂鍖哄垝鍏朵粬瀛楁娌″繀瑕佽瘑鍒簡锛岄粯璁ゅ湪绾垮嵆鍙�
+            deviceChannel.setStatus(1);
+            deviceChannel.setParental(1);
+            deviceChannel.setCreateTime(DateUtil.getNow());
+            deviceChannel.setUpdateTime(DateUtil.getNow());
+            return deviceChannel;
         }
         /**
          * 琛屾斂鍖哄垝灞曠ず璁惧鏍戜笌涓氬姟鍒嗙粍灞曠ず璁惧鏍戞槸涓ょ涓嶅悓鐨勬ā寮�
@@ -230,7 +254,17 @@
          * 娌冲寳鐪�
          *    --> 鐭冲搴勫競
          *          --> 鎽勫儚澶�
-         *          --> 姝e畾鍘�
+         *String parentId = XmlUtil.getText(itemDevice, "ParentID");
+         if (parentId != null) {
+         if (parentId.contains("/")) {
+         String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
+         String businessGroup = parentId.substring(0, parentId.indexOf("/"));
+         deviceChannel.setParentId(lastParentId);
+         }else {
+         deviceChannel.setParentId(parentId);
+         }
+         }
+         deviceCh          --> 姝e畾鍘�
          *                  --> 鎽勫儚澶�
          *                  --> 鎽勫儚澶�
          *
@@ -243,59 +277,88 @@
          *             --> 鎽勫儚澶�
          */
         String parentId = XmlUtil.getText(itemDevice, "ParentID");
+        String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
         if (parentId != null) {
             if (parentId.contains("/")) {
                 String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
+                if (businessGroupID == null) {
+                    businessGroupID = parentId.substring(0, parentId.indexOf("/"));
+                }
                 deviceChannel.setParentId(lastParentId);
             }else {
                 deviceChannel.setParentId(parentId);
             }
         }
         deviceChannel.setBusinessGroupId(businessGroupID);
+        if (channelType.equals(ChannelType.BusinessGroup) || channelType.equals(ChannelType.VirtualOrganization)) {
+            // 涓氬姟鍒嗙粍鍜岃櫄鎷熺粍缁� 鍏朵粬瀛楁娌″繀瑕佽瘑鍒簡锛岄粯璁ゅ湪绾垮嵆鍙�
+            deviceChannel.setStatus(1);
+            deviceChannel.setParental(1);
+            deviceChannel.setCreateTime(DateUtil.getNow());
+            deviceChannel.setUpdateTime(DateUtil.getNow());
+            return deviceChannel;
+        }
 
-//        else {
-//            if (deviceChannel.getChannelId().length() <= 10) { // 姝ゆ椂涓鸿鏀垮尯鍒�, 涓婁笅绾ц鏀垮尯鍒掍娇鐢―eviceId鍏宠仈
-//                deviceChannel.setParentId(deviceChannel.getChannelId().substring(0, deviceChannel.getChannelId().length() - 2));
-//            }else if (deviceChannel.getChannelId().length() == 20) {
-//                if (Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216) { // 铏氭嫙缁勭粐
-//                    deviceChannel.setBusinessGroupId(businessGroupID);
-//                }else if (Integer.parseInt(device.getDeviceId().substring(10, 13) )== 118) {//NVR 濡傛灉涓婄骇璁惧缂栧彿鏄疦VR鍒欑洿鎺ュ皢NVR鐨勭紪鍙疯缃粰閫氶亾鐨勪笂绾х紪鍙�
-//                    deviceChannel.setParentId(device.getDeviceId());
-//                }else if (deviceChannel.getCivilCode() != null) {
-//                    // 璁惧锛� 鏃爌arentId鐨�20浣嶆槸浣跨敤CivilCode琛ㄧず涓婄骇鐨勮澶囷紝
-//                    // 娉細215 涓氬姟鍒嗙粍鏄渶瑕佹湁parentId鐨�
-//                    deviceChannel.setParentId(deviceChannel.getCivilCode());
-//                }
-//            }else {
-//                deviceChannel.setParentId(deviceChannel.getDeviceId());
-//            }
-//        }
+        Element statusElement = itemDevice.element("Status");
 
-        if (XmlUtil.getText(itemDevice, "SafetyWay") == null
-                || XmlUtil.getText(itemDevice, "SafetyWay") == "") {
+        if (statusElement != null) {
+            String status = statusElement.getTextTrim().trim();
+            // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR鐨勫吋瀹规�у鐞�
+            if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
+                deviceChannel.setStatus(1);
+            }
+            if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
+                deviceChannel.setStatus(0);
+            }
+        }else {
+            deviceChannel.setStatus(1);
+        }
+        // 璇嗗埆鑷甫鐨勭洰褰曟爣璇�
+        String parental = XmlUtil.getText(itemDevice, "Parental");
+        // 鐢变簬娴峰悍浼氶敊璇殑鍙戦��65535浣滀负杩欓噷鐨勫彇鍊�,鎵�浠ヨ繖閲岄櫎闈炴槸0鍚﹀垯璁や负鏄�1
+        if (!StringUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
+            deviceChannel.setParental(0);
+        }else {
+            deviceChannel.setParental(1);
+        }
+
+
+        deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
+        deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
+        deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
+        deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
+        deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
+        deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
+        deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
+
+        String safetyWay = XmlUtil.getText(itemDevice, "SafetyWay");
+        if (StringUtils.isEmpty(safetyWay)) {
             deviceChannel.setSafetyWay(0);
         } else {
-            deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay")));
+            deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
         }
-        if (XmlUtil.getText(itemDevice, "RegisterWay") == null
-                || XmlUtil.getText(itemDevice, "RegisterWay") == "") {
+
+        String registerWay = XmlUtil.getText(itemDevice, "RegisterWay");
+        if (StringUtils.isEmpty(registerWay)) {
             deviceChannel.setRegisterWay(1);
         } else {
-            deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay")));
+            deviceChannel.setRegisterWay(Integer.parseInt(registerWay));
         }
-        deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
+
         if (XmlUtil.getText(itemDevice, "Certifiable") == null
                 || XmlUtil.getText(itemDevice, "Certifiable") == "") {
             deviceChannel.setCertifiable(0);
         } else {
             deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
         }
+
         if (XmlUtil.getText(itemDevice, "ErrCode") == null
                 || XmlUtil.getText(itemDevice, "ErrCode") == "") {
             deviceChannel.setErrCode(0);
         } else {
             deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
         }
+
         deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
         deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
         deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
@@ -304,43 +367,23 @@
         } else {
             deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
         }
-        deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
-        if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {
-            deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude")));
+
+
+        String longitude = XmlUtil.getText(itemDevice, "Longitude");
+        if (NumericUtil.isDouble(longitude)) {
+            deviceChannel.setLongitude(Double.parseDouble(longitude));
         } else {
             deviceChannel.setLongitude(0.00);
         }
-        if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {
-            deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude")));
+        String latitude = XmlUtil.getText(itemDevice, "Latitude");
+        if (NumericUtil.isDouble(latitude)) {
+            deviceChannel.setLatitude(Double.parseDouble(latitude));
         } else {
             deviceChannel.setLatitude(0.00);
         }
         deviceChannel.setGpsTime(DateUtil.getNow());
-        if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {
-            if ("WGS84".equals(device.getGeoCoordSys())) {
-                deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
-                deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
-                Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
-                deviceChannel.setLongitudeGcj02(position[0]);
-                deviceChannel.setLatitudeGcj02(position[1]);
-            }else if ("GCJ02".equals(device.getGeoCoordSys())) {
-                deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
-                deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
-                Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
-                deviceChannel.setLongitudeWgs84(position[0]);
-                deviceChannel.setLatitudeWgs84(position[1]);
-            }else {
-                deviceChannel.setLongitudeGcj02(0.00);
-                deviceChannel.setLatitudeGcj02(0.00);
-                deviceChannel.setLongitudeWgs84(0.00);
-                deviceChannel.setLatitudeWgs84(0.00);
-            }
-        }else {
-            deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
-            deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
-            deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
-            deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
-        }
+
+
         if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
             //鍏煎INFO涓殑淇℃伅
             Element info = itemDevice.element("Info");
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
index 249ec03..c8f9040 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -136,4 +136,12 @@
         return sendGet(mediaServerItem, "api/record/file/duration",param, callback);
     }
 
+    public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){
+        Map<String, Object> param = new HashMap<>();
+        param.put("app",app);
+        param.put("stream",stream);
+        param.put("callId",callId);
+        return sendGet(mediaServerItem, "api/record/addStreamCallInfo",param, callback);
+    }
+
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
index 95c035f..0dc6bd3 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -87,6 +87,9 @@
 	@Autowired
 	private VideoStreamSessionManager sessionManager;
 
+	@Autowired
+	private AssistRESTfulUtils assistRESTfulUtils;
+
 	/**
 	 * 鏈嶅姟鍣ㄥ畾鏃朵笂鎶ユ椂闂达紝涓婃姤闂撮殧鍙厤缃紝榛樿10s涓婃姤涓�娆�
 	 *
@@ -99,12 +102,13 @@
 			logger.debug("[ ZLM HOOK ] on_server_keepalive API璋冪敤锛屽弬鏁帮細" + json.toString());
 		}
 		String mediaServerId = json.getString("mediaServerId");
-		List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_keepalive);
+		List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
 		if (subscribes != null  && subscribes.size() > 0) {
 			for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
 				subscribe.response(null, json);
 			}
 		}
+		mediaServerService.updateMediaServerKeepalive(mediaServerId, json.getJSONObject("data"));
 
 		JSONObject ret = new JSONObject();
 		ret.put("code", 0);
@@ -164,7 +168,7 @@
 			logger.debug("[ ZLM HOOK ]on_play API璋冪敤锛屽弬鏁帮細" + JSON.toJSONString(param));
 		}
 		String mediaServerId = param.getMediaServerId();
-		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
+		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json);
 		if (subscribe != null ) {
 			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
@@ -200,7 +204,9 @@
 
 		logger.info("[ ZLM HOOK ]on_publish API璋冪敤锛屽弬鏁帮細" + json.toString());
 		JSONObject ret = new JSONObject();
-		if (!"rtp".equals(param.getApp()) && !"broadcast".equals(param.getApp())) {
+		String mediaServerId = json.getString("mediaServerId");
+		MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
+		if (!"rtp".equals(param.getApp())) {
 			// 鎺ㄦ祦閴存潈
 			if (param.getParams() == null) {
 				logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯涓嶈鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)");
@@ -231,6 +237,12 @@
 			streamAuthorityInfo.setSign(sign);
 			// 閴存潈閫氳繃
 			redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
+			// 閫氱煡assist鏂扮殑callId
+			if (mediaInfo != null) {
+				assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
+			}
+		}else {
+			zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId());
 		}
 
 		ret.put("code", 0);
@@ -240,10 +252,9 @@
 			ret.put("enable_audio", true);
 		}
 
-		String mediaServerId = json.getString("mediaServerId");
-		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
+
+		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
 		if (subscribe != null) {
-			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 			}else {
@@ -270,8 +281,10 @@
 				ret.put("mp4_max_second", 10);
 				ret.put("enable_mp4", true);
 				ret.put("enable_audio", true);
+
 			}
 		}
+
 
 
 		return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
@@ -364,7 +377,7 @@
 			logger.debug("[ ZLM HOOK ]on_shell_login API璋冪敤锛屽弬鏁帮細" + json.toString());
 		}
 		String mediaServerId = json.getString("mediaServerId");
-		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
+		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_shell_login, json);
 		if (subscribe != null ) {
 			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
@@ -390,7 +403,7 @@
 		logger.info("[ ZLM HOOK ]on_stream_changed API璋冪敤锛屽弬鏁帮細" + JSONObject.toJSONString(item));
 		String mediaServerId = item.getMediaServerId();
 		JSONObject json = (JSONObject) JSON.toJSON(item);
-		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json);
+		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json);
 		if (subscribe != null ) {
 			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
@@ -438,7 +451,6 @@
 						redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(),
 								streamInfo.getStream(), null);
 					}
-
 				}
 			}else {
 				if (!"rtp".equals(app)){
@@ -451,7 +463,6 @@
 							StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
 									app, stream, tracks, streamAuthorityInfo.getCallId());
 							item.setStreamInfo(streamInfoByAppAndStream);
-
 							redisCatchStorage.addStream(mediaServerItem, type, app, stream, item);
 							if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
 									|| item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
@@ -459,20 +470,6 @@
 								item.setSeverId(userSetting.getServerId());
 								zlmMediaListManager.addPush(item);
 							}
-
-//							List<GbStream> gbStreams = new ArrayList<>();
-//							if (streamPushItem == null || streamPushItem.getGbId() == null) {
-//								GbStream gbStream = storager.getGbStream(app, streamId);
-//								gbStreams.add(gbStream);
-//							}else {
-//								if (streamPushItem.getGbId() != null) {
-//									gbStreams.add(streamPushItem);
-//								}
-//							}
-//							if (gbStreams.size() > 0) {
-//								eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON);
-//							}
-
 						}else {
 							// 鍏煎娴佹敞閿�鏃剁被鍨嬩粠redis璁板綍鑾峰彇
 							MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, stream, mediaServerId);
@@ -616,16 +613,21 @@
 		}
 		String remoteAddr = request.getRemoteAddr();
 		jsonObject.put("ip", remoteAddr);
-		List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started);
+		List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started);
 		if (subscribes != null  && subscribes.size() > 0) {
 			for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
 				subscribe.response(null, jsonObject);
 			}
 		}
+
+		ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(jsonObject, ZLMServerConfig.class);
+		if (zlmServerConfig !=null ) {
+			mediaServerService.zlmServerOnline(zlmServerConfig);
+		}
 		JSONObject ret = new JSONObject();
 		ret.put("code", 0);
 		ret.put("msg", "success");
-		return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
+		return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
 	}
 
 	private Map<String, String> urlParamToMap(String params) {
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
index ffd8ec9..57b6d81 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
@@ -1,12 +1,16 @@
 package com.genersoft.iot.vmp.media.zlm;
 
 import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.media.zlm.dto.HookType;
+import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
+import java.time.Instant;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @description:閽堝 ZLMediaServer鐨刪ook浜嬩欢璁㈤槄
@@ -16,51 +20,39 @@
 @Component
 public class ZLMHttpHookSubscribe {
 
-    public enum HookType{
-        on_flow_report,
-        on_http_access,
-        on_play,
-        on_publish,
-        on_record_mp4,
-        on_rtsp_auth,
-        on_rtsp_realm,
-        on_shell_login,
-        on_stream_changed,
-        on_stream_none_reader,
-        on_stream_not_found,
-        on_server_started,
-        on_server_keepalive
-    }
-
     @FunctionalInterface
     public interface Event{
         void response(MediaServerItem mediaServerItem, JSONObject response);
     }
 
-    private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
+    private Map<HookType, Map<IHookSubscribe, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
 
-    public void addSubscribe(HookType type, JSONObject hookResponse, ZLMHttpHookSubscribe.Event event) {
-        allSubscribes.computeIfAbsent(type, k -> new ConcurrentHashMap<>()).put(hookResponse, event);
+    public void addSubscribe(IHookSubscribe hookSubscribe, ZLMHttpHookSubscribe.Event event) {
+        if (hookSubscribe.getExpires() == null) {
+            // 榛樿5鍒嗛挓杩囨湡
+            Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(5));
+            hookSubscribe.setExpires(expiresInstant);
+        }
+        allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event);
     }
 
-    public ZLMHttpHookSubscribe.Event getSubscribe(HookType type, JSONObject hookResponse) {
+    public ZLMHttpHookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) {
         ZLMHttpHookSubscribe.Event event= null;
-        Map<JSONObject, Event> eventMap = allSubscribes.get(type);
+        Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
         if (eventMap == null) {
             return null;
         }
-        for (JSONObject key : eventMap.keySet()) {
+        for (IHookSubscribe key : eventMap.keySet()) {
             Boolean result = null;
-            for (String s : key.keySet()) {
+            for (String s : key.getContent().keySet()) {
                 if (result == null) {
-                    result = key.getString(s).equals(hookResponse.getString(s));
+                    result = key.getContent().getString(s).equals(hookResponse.getString(s));
                 }else {
-                    if (key.getString(s) == null) {
+                    if (key.getContent().getString(s) == null) {
                         continue;
                     }
-                    result = result && key.getString(s).equals(hookResponse.getString(s));
+                    result = result && key.getContent().getString(s).equals(hookResponse.getString(s));
                 }
-
             }
             if (null != result && result) {
                 event = eventMap.get(key);
@@ -69,26 +61,30 @@
         return event;
     }
 
-    public void removeSubscribe(HookType type, JSONObject hookResponse) {
-        Map<JSONObject, Event> eventMap = allSubscribes.get(type);
+    public void removeSubscribe(IHookSubscribe hookSubscribe) {
+        Map<IHookSubscribe, Event> eventMap = allSubscribes.get(hookSubscribe.getHookType());
         if (eventMap == null) {
             return;
         }
 
-        Set<Map.Entry<JSONObject, Event>> entries = eventMap.entrySet();
+        Set<Map.Entry<IHookSubscribe, Event>> entries = eventMap.entrySet();
         if (entries.size() > 0) {
-            List<Map.Entry<JSONObject, ZLMHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>();
-            for (Map.Entry<JSONObject, ZLMHttpHookSubscribe.Event> entry : entries) {
-                JSONObject key = entry.getKey();
+            List<Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>();
+            for (Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event> entry : entries) {
+                JSONObject content = entry.getKey().getContent();
+                if (content == null || content.size() == 0) {
+                    entriesToRemove.add(entry);
+                    continue;
+                }
                 Boolean result = null;
-                for (String s : key.keySet()) {
+                for (String s : content.keySet()) {
                     if (result == null) {
-                        result = key.getString(s).equals(hookResponse.getString(s));
+                        result = content.getString(s).equals(hookSubscribe.getContent().getString(s));
                     }else {
-                        if (key.getString(s) == null) {
+                        if (content.getString(s) == null) {
                             continue;
                         }
-                        result = result && key.getString(s).equals(hookResponse.getString(s));
+                        result = result && content.getString(s).equals(hookSubscribe.getContent().getString(s));
                     }
                 }
                 if (null != result && result){
@@ -97,7 +93,7 @@
             }
 
             if (!CollectionUtils.isEmpty(entriesToRemove)) {
-                for (Map.Entry<JSONObject, ZLMHttpHookSubscribe.Event> entry : entriesToRemove) {
+                for (Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event> entry : entriesToRemove) {
                     entries.remove(entry);
                 }
             }
@@ -111,17 +107,25 @@
      * @return
      */
     public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) {
-        // ZLMHttpHookSubscribe.Event event= null;
-        Map<JSONObject, Event> eventMap = allSubscribes.get(type);
+        Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
         if (eventMap == null) {
             return null;
         }
         List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>();
-        for (JSONObject key : eventMap.keySet()) {
+        for (IHookSubscribe key : eventMap.keySet()) {
             result.add(eventMap.get(key));
         }
         return result;
     }
 
+    public List<IHookSubscribe> getAll(){
+        ArrayList<IHookSubscribe> result = new ArrayList<>();
+        Collection<Map<IHookSubscribe, Event>> values = allSubscribes.values();
+        for (Map<IHookSubscribe, Event> value : values) {
+            result.addAll(value.keySet());
+        }
+        return result;
+    }
+
 
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
index 693dda1..a8b4a8d 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -4,6 +4,7 @@
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.media.zlm.dto.*;
+import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
@@ -63,124 +64,48 @@
     @Autowired
     private UserSetting userSetting;
 
-    private Map<String, ChannelOnlineEvent> channelOnlineEvents = new ConcurrentHashMap<>();
+    @Autowired
+    private ZLMRTPServerFactory zlmrtpServerFactory;
 
+    @Autowired
+    private IMediaServerService mediaServerService;
 
-    public void updateMediaList(MediaServerItem mediaServerItem) {
-        storager.clearMediaList();
-
-        // 浣跨敤寮傛鐨勫綋鏃舵洿鏂板獟浣撴祦鍒楄〃
-        zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{
-            if (mediaList == null) {
-                return;
-            }
-            String dataStr = mediaList.getString("data");
-
-            Integer code = mediaList.getInteger("code");
-            Map<String, StreamPushItem> result = new HashMap<>();
-            List<StreamPushItem> streamPushItems = null;
-            // 鑾峰彇鎵�鏈夌殑鍥芥爣鍏宠仈
-//            List<GbStream> gbStreams = gbStreamMapper.selectAllByMediaServerId(mediaServerItem.getId());
-            if (code == 0 ) {
-                if (dataStr != null) {
-                    streamPushItems = streamPushService.handleJSON(dataStr, mediaServerItem);
-                }
-            }else {
-                logger.warn("鏇存柊瑙嗛娴佸け璐ワ紝閿欒code锛� " + code);
-            }
-
-            if (streamPushItems != null) {
-                storager.updateMediaList(streamPushItems);
-                for (StreamPushItem streamPushItem : streamPushItems) {
-                    JSONObject jsonObject = new JSONObject();
-                    jsonObject.put("app", streamPushItem.getApp());
-                    jsonObject.put("stream", streamPushItem.getStream());
-                    jsonObject.put("mediaServerId", mediaServerItem.getId());
-                    subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,
-                            (MediaServerItem mediaServerItemInuse, JSONObject response)->{
-                                updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));
-                            }
-                    );
-                }
-            }
-        }));
-
-    }
-
-    public void addMedia(MediaServerItem mediaServerItem, String app, String streamId) {
-        //浣跨敤寮傛鏇存柊鎺ㄦ祦
-        updateMedia(mediaServerItem, app, streamId);
-    }
+    private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
 
     public StreamPushItem addPush(MediaItem mediaItem) {
         // 鏌ユ壘姝ょ洿鎾祦鏄惁瀛樺湪redis棰勮gbId
         StreamPushItem transform = streamPushService.transform(mediaItem);
         StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
+        transform.setPushIng(mediaItem.isRegist());
         transform.setUpdateTime(DateUtil.getNow());
         transform.setPushTime(DateUtil.getNow());
+        transform.setSelf(userSetting.getServerId().equals(mediaItem.getSeverId()));
         if (pushInDb == null) {
             transform.setCreateTime(DateUtil.getNow());
             streamPushMapper.add(transform);
         }else {
             streamPushMapper.update(transform);
-
-
-//            if (!StringUtils.isEmpty(pushInDb.getGbId())) {
-//                List<GbStream> gbStreamList = gbStreamMapper.selectByGBId(transform.getGbId());
-//                if (gbStreamList != null && gbStreamList.size() == 1) {
-//                    transform.setGbStreamId(gbStreamList.get(0).getGbStreamId());
-//                    transform.setPlatformId(gbStreamList.get(0).getPlatformId());
-//                    transform.setCatalogId(gbStreamList.get(0).getCatalogId());
-//                    transform.setGbId(gbStreamList.get(0).getGbId());
-//                    gbStreamMapper.update(transform);
-//                    streamPushMapper.del(gbStreamList.get(0).getApp(), gbStreamList.get(0).getStream());
-//                }else {
-//                    transform.setCreateTime(DateUtil.getNow());
-//                    transform.setUpdateTime(DateUtil.getNow());
-//                    gbStreamMapper.add(transform);
-//                }
-                // 閫氱煡閫氶亾涓婄嚎
-//            if (transform != null) {
-//                if (channelOnlineEvents.get(transform.getGbId()) != null)  {
-//                    channelOnlineEvents.get(transform.getGbId()).run(transform.getApp(), transform.getStream(), transform.getServerId());
-//                    channelOnlineEvents.remove(transform.getGbId());
-//                }
-//            }
-//            }
+            gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId());
         }
-
-
-
+        if (transform != null) {
+            if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null)  {
+                getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
+                removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
+            }
+        }
         return transform;
     }
 
-
-    public void updateMedia(MediaServerItem mediaServerItem, String app, String streamId) {
-        //浣跨敤寮傛鏇存柊鎺ㄦ祦
-        zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{
-
-            if (json == null) {
-                return;
+    public void sendStreamEvent(String app, String stream, String mediaServerId) {
+        MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+        // 鏌ョ湅鎺ㄦ祦鐘舵��
+        if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
+            if (getChannelOnlineEventLister(app, stream) != null)  {
+                getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
+                removedChannelOnlineEventLister(app, stream);
             }
-            String dataStr = json.getString("data");
-
-            Integer code = json.getInteger("code");
-            Map<String, StreamPushItem> result = new HashMap<>();
-            List<StreamPushItem> streamPushItems = null;
-            if (code == 0 ) {
-                if (dataStr != null) {
-                    streamPushItems = streamPushService.handleJSON(dataStr, mediaServerItem);
-                }
-            }else {
-                logger.warn("鏇存柊瑙嗛娴佸け璐ワ紝閿欒code锛� " + code);
-            }
-
-            if (streamPushItems != null && streamPushItems.size() == 1) {
-                storager.updateMedia(streamPushItems.get(0));
-            }
-        });
+        }
     }
-
 
     public int removeMedia(String app, String streamId) {
         // 鏌ユ壘鏄惁鍏宠仈浜嗗浗鏍囷紝 鍏宠仈浜嗕笉鍒犻櫎锛� 缃负绂荤嚎
@@ -189,48 +114,21 @@
         if (gbStream == null) {
             result = storager.removeMedia(app, streamId);
         }else {
-            // TODO 鏆備笉璁剧疆涓虹绾�
             result =storager.mediaOffline(app, streamId);
         }
         return result;
     }
 
-    public void addChannelOnlineEventLister(String key, ChannelOnlineEvent callback) {
-        this.channelOnlineEvents.put(key,callback);
+    public void addChannelOnlineEventLister(String app, String stream, ChannelOnlineEvent callback) {
+        this.channelOnPublishEvents.put(app + "_" + stream, callback);
     }
 
-    public void removedChannelOnlineEventLister(String key) {
-        this.channelOnlineEvents.remove(key);
+    public void removedChannelOnlineEventLister(String app, String stream) {
+        this.channelOnPublishEvents.remove(app + "_" + stream);
     }
 
+    public ChannelOnlineEvent getChannelOnlineEventLister(String app, String stream) {
+        return this.channelOnPublishEvents.get(app + "_" + stream);
+    }
 
-
-//    public void clearAllSessions() {
-//        logger.info("娓呯┖鎵�鏈夊浗鏍囩浉鍏崇殑session");
-//        JSONObject allSessionJSON = zlmresTfulUtils.getAllSession();
-//        ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
-//        HashSet<String> allLocalPorts = new HashSet();
-//        if (allSessionJSON.getInteger("code") == 0) {
-//            JSONArray data = allSessionJSON.getJSONArray("data");
-//            if (data.size() > 0) {
-//                for (int i = 0; i < data.size(); i++) {
-//                    JSONObject sessionJOSN = data.getJSONObject(i);
-//                    Integer local_port = sessionJOSN.getInteger("local_port");
-//                    if (!local_port.equals(Integer.valueOf(mediaInfo.getHttpPort())) &&
-//                        !local_port.equals(Integer.valueOf(mediaInfo.getHttpSSLport())) &&
-//                        !local_port.equals(Integer.valueOf(mediaInfo.getRtmpPort())) &&
-//                        !local_port.equals(Integer.valueOf(mediaInfo.getRtspPort())) &&
-//                        !local_port.equals(Integer.valueOf(mediaInfo.getRtspSSlport())) &&
-//                        !local_port.equals(Integer.valueOf(mediaInfo.getHookOnFlowReport()))){
-//                        allLocalPorts.add(sessionJOSN.getInteger("local_port") + "");
-//                     }
-//                }
-//            }
-//        }
-//        if (allLocalPorts.size() > 0) {
-//            List<String> result = new ArrayList<>(allLocalPorts);
-//            String localPortSStr = String.join(",", result);
-//            zlmresTfulUtils.kickSessions(localPortSStr);
-//        }
-//    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
index 60e79f7..6c3ad90 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -87,7 +87,7 @@
         return result;
     }
 
-    public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc) {
+    public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port) {
         int result = -1;
         // 鏌ヨ姝tp server 鏄惁宸茬粡瀛樺湪
         JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
@@ -105,7 +105,11 @@
         param.put("enable_tcp", 1);
         param.put("stream_id", streamId);
         // 鎺ㄦ祦绔彛璁剧疆0鍒欎娇鐢ㄩ殢鏈虹鍙�
-        param.put("port", 0);
+        if (port == null) {
+            param.put("port", 0);
+        }else {
+            param.put("port", port);
+        }
         param.put("ssrc", ssrc);
         JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
 
@@ -280,8 +284,10 @@
      * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁�
      */
     public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
-        JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId);
-        return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online") != null && mediaInfo.getBoolean("online"));
+        JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId);
+        return (mediaInfo.getInteger("code") == 0
+                && mediaInfo.getJSONArray("data") != null
+                && mediaInfo.getJSONArray("data").size() > 0);
     }
 
     /**
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
index 138af7a..b24d0a1 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -6,22 +6,22 @@
 import com.genersoft.iot.vmp.conf.DynamicTask;
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForServerStarted;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.service.IStreamProxyService;
-import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.core.annotation.Order;
 import org.springframework.scheduling.annotation.Async;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
 
+import java.time.Instant;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 @Component
 @Order(value=1)
@@ -38,16 +38,10 @@
     private ZLMHttpHookSubscribe hookSubscribe;
 
     @Autowired
-    private IStreamProxyService streamProxyService;
-
-    @Autowired
     private EventPublisher publisher;
 
     @Autowired
     private IMediaServerService mediaServerService;
-
-    @Autowired
-    private IRedisCatchStorage redisCatchStorage;
 
     @Autowired
     private MediaConfig mediaConfig;
@@ -67,26 +61,24 @@
             mediaServerService.updateToDatabase(mediaSerItem);
         }
         mediaServerService.syncCatchFromDatabase();
+        HookSubscribeForServerStarted hookSubscribeForServerStarted = HookSubscribeFactory.on_server_started();
+//        Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.SECONDS.toSeconds(60));
+//        hookSubscribeForStreamChange.setExpires(expiresInstant);
         // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁�
-        hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,new JSONObject(),
+        hookSubscribe.addSubscribe(hookSubscribeForServerStarted,
                 (MediaServerItem mediaServerItem, JSONObject response)->{
             ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
             if (zlmServerConfig !=null ) {
                 if (startGetMedia != null) {
                     startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
+                    if (startGetMedia.size() == 0) {
+                        hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started());
+                    }
                 }
-                mediaServerService.zlmServerOnline(zlmServerConfig);
             }
         });
 
-        // 璁㈤槄 zlm淇濇椿浜嬩欢, 褰搝lm绂荤嚎鏃跺仛涓氬姟鐨勫鐞�
-        hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_keepalive,new JSONObject(),
-                (MediaServerItem mediaServerItem, JSONObject response)->{
-                    String mediaServerId = response.getString("mediaServerId");
-                    if (mediaServerId !=null ) {
-                        mediaServerService.updateMediaServerKeepalive(mediaServerId, response.getJSONObject("data"));
-                    }
-                });
+
 
         // 鑾峰彇zlm淇℃伅
         logger.info("[zlm] 绛夊緟榛樿zlm涓�...");
@@ -125,6 +117,9 @@
             zlmServerConfigFirst.setIp(mediaServerItem.getIp());
             zlmServerConfigFirst.setHttpPort(mediaServerItem.getHttpPort());
             startGetMedia.remove(mediaServerItem.getId());
+            if (startGetMedia.size() == 0) {
+                hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started());
+            }
             mediaServerService.zlmServerOnline(zlmServerConfigFirst);
         }else {
             logger.info("[ {} ]-[ {}:{} ]涓诲姩杩炴帴澶辫触, 娓呯悊鐩稿叧璧勬簮锛� 寮�濮嬪皾璇曢噸璇曡繛鎺�",
@@ -139,6 +134,9 @@
                 zlmServerConfig.setIp(mediaServerItem.getIp());
                 zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
                 startGetMedia.remove(mediaServerItem.getId());
+                if (startGetMedia.size() == 0) {
+                    hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started());
+                }
                 mediaServerService.zlmServerOnline(zlmServerConfig);
             }
         }, 2000);
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java
new file mode 100644
index 0000000..92172f3
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java
@@ -0,0 +1,33 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * hook 璁㈤槄宸ュ巶
+ * @author lin
+ */
+public class HookSubscribeFactory {
+
+    public static HookSubscribeForStreamChange on_stream_changed(String app, String stream, boolean regist, String scheam, String mediaServerId) {
+        HookSubscribeForStreamChange hookSubscribe = new HookSubscribeForStreamChange();
+        JSONObject subscribeKey = new com.alibaba.fastjson.JSONObject();
+        subscribeKey.put("app", app);
+        subscribeKey.put("stream", stream);
+        subscribeKey.put("regist", regist);
+        if (scheam != null) {
+            subscribeKey.put("schema", scheam);
+        }
+        subscribeKey.put("mediaServerId", mediaServerId);
+        hookSubscribe.setContent(subscribeKey);
+
+        return hookSubscribe;
+    }
+
+    public static HookSubscribeForServerStarted on_server_started() {
+        HookSubscribeForServerStarted hookSubscribe = new HookSubscribeForServerStarted();
+        hookSubscribe.setContent(new JSONObject());
+
+        return hookSubscribe;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java
new file mode 100644
index 0000000..0b781e6
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java
@@ -0,0 +1,44 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONField;
+
+import java.time.Instant;
+
+/**
+ * hook璁㈤槄-娴佸彉鍖�
+ * @author lin
+ */
+public class HookSubscribeForServerStarted implements IHookSubscribe{
+
+    private HookType hookType = HookType.on_server_started;
+
+    private JSONObject content;
+
+    @JSONField(format="yyyy-MM-dd HH:mm:ss")
+    private Instant expires;
+
+    @Override
+    public HookType getHookType() {
+        return hookType;
+    }
+
+    @Override
+    public JSONObject getContent() {
+        return content;
+    }
+
+    public void setContent(JSONObject content) {
+        this.content = content;
+    }
+
+    @Override
+    public Instant getExpires() {
+        return expires;
+    }
+
+    @Override
+    public void setExpires(Instant expires) {
+        this.expires = expires;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java
new file mode 100644
index 0000000..d5b2fb8
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java
@@ -0,0 +1,43 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.annotation.JSONField;
+
+import java.time.Instant;
+
+/**
+ * hook璁㈤槄-娴佸彉鍖�
+ * @author lin
+ */
+public class HookSubscribeForStreamChange implements IHookSubscribe{
+
+    private HookType hookType = HookType.on_stream_changed;
+
+    private JSONObject content;
+
+    private Instant expires;
+
+    @Override
+    public HookType getHookType() {
+        return hookType;
+    }
+
+    @Override
+    public JSONObject getContent() {
+        return content;
+    }
+
+    public void setContent(JSONObject content) {
+        this.content = content;
+    }
+
+    @Override
+    public Instant getExpires() {
+        return expires;
+    }
+
+    @Override
+    public void setExpires(Instant expires) {
+        this.expires = expires;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java
new file mode 100644
index 0000000..797ab81
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java
@@ -0,0 +1,23 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+/**
+ * hook绫诲瀷
+ * @author lin
+ */
+
+public enum HookType {
+
+    on_flow_report,
+    on_http_access,
+    on_play,
+    on_publish,
+    on_record_mp4,
+    on_rtsp_auth,
+    on_rtsp_realm,
+    on_shell_login,
+    on_stream_changed,
+    on_stream_none_reader,
+    on_stream_not_found,
+    on_server_started,
+    on_server_keepalive
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java
new file mode 100644
index 0000000..5f2ca33
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java
@@ -0,0 +1,36 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.time.Instant;
+
+/**
+ * zlm hook浜嬩欢鐨勫弬鏁�
+ * @author lin
+ */
+public interface IHookSubscribe {
+
+    /**
+     * 鑾峰彇hook绫诲瀷
+     * @return hook绫诲瀷
+     */
+    HookType getHookType();
+
+    /**
+     * 鑾峰彇hook鐨勫叿浣撳唴瀹�
+     * @return hook鐨勫叿浣撳唴瀹�
+     */
+    JSONObject getContent();
+
+    /**
+     * 璁剧疆杩囨湡鏃堕棿
+     * @param instant 杩囨湡鏃堕棿
+     */
+    void setExpires(Instant instant);
+
+    /**
+     * 鑾峰彇杩囨湡鏃堕棿
+     * @return 杩囨湡鏃堕棿
+     */
+    Instant getExpires();
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java
index 8abac5b..96cbfbd 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java
@@ -4,6 +4,9 @@
 
 import java.util.List;
 
+/**
+ * @author lin
+ */
 public class MediaItem {
 
     /**
@@ -20,6 +23,11 @@
      * 娴乮d
      */
     private String stream;
+
+    /**
+     * 鎺ㄦ祦閴存潈Id
+     */
+    private String callId;
 
     /**
      * 瑙傜湅鎬讳汉鏁帮紝鍖呮嫭hls/rtsp/rtmp/http-flv/ws-flv
@@ -427,4 +435,12 @@
     public void setSeverId(String severId) {
         this.severId = severId;
     }
+
+    public String getCallId() {
+        return callId;
+    }
+
+    public void setCallId(String callId) {
+        this.callId = callId;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java
index 91fa619..ff63f6f 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java
@@ -103,6 +103,18 @@
      */
     private String createTime;
 
+    /**
+     * 鏄惁姝e湪鎺ㄦ祦
+     */
+    private boolean pushIng;
+
+    /**
+     * 鏄惁鑷繁骞冲彴鐨勬帹娴�
+     */
+    private boolean self;
+
+
+
     public String getVhost() {
         return vhost;
     }
@@ -277,5 +289,21 @@
     public void setCreateTime(String createTime) {
         this.createTime = createTime;
     }
+
+    public boolean isPushIng() {
+        return pushIng;
+    }
+
+    public void setPushIng(boolean pushIng) {
+        this.pushIng = pushIng;
+    }
+
+    public boolean isSelf() {
+        return self;
+    }
+
+    public void setSelf(boolean self) {
+        this.self = self;
+    }
 }
 
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
new file mode 100644
index 0000000..9629e3a
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
@@ -0,0 +1,35 @@
+package com.genersoft.iot.vmp.service;
+
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+
+import java.util.List;
+
+/**
+ * 鍥芥爣閫氶亾涓氬姟绫�
+ * @author lin
+ */
+public interface IDeviceChannelService {
+
+    /**
+     * 鏇存柊gps淇℃伅
+     */
+    DeviceChannel updateGps(DeviceChannel deviceChannel, Device device);
+
+    /**
+     * 娣诲姞璁惧閫氶亾
+     *
+     * @param deviceId 璁惧id
+     * @param channel 閫氶亾
+     */
+    void updateChannel(String deviceId, DeviceChannel channel);
+
+    /**
+     * 鎵归噺娣诲姞璁惧閫氶亾
+     *
+     * @param deviceId 璁惧id
+     * @param channels 澶氫釜閫氶亾
+     */
+    int updateChannels(String deviceId, List<DeviceChannel> channels);
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java b/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
index abdde6d..0a39206 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
@@ -18,7 +18,7 @@
      * @param count
      * @return
      */
-    PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,Boolean pushing,String mediaServerId);
+    PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,String mediaServerId);
 
 
     /**
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
index 1a9c8c7..03dbd0b 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -47,6 +47,8 @@
 
     SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
 
+    SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port);
+
     void closeRTPServer(String deviceId, String channelId, String ssrc);
 
     void clearRTPServer(MediaServerItem mediaServerItem);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java
new file mode 100644
index 0000000..739e6b8
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java
@@ -0,0 +1,22 @@
+package com.genersoft.iot.vmp.service;
+
+import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
+
+import java.util.List;
+
+/**
+ * 骞冲彴鍏宠仈閫氶亾绠$悊
+ * @author lin
+ */
+public interface IPlatformChannelService {
+
+    /**
+     * 鏇存柊鐩綍涓嬬殑閫氶亾
+     * @param platformId 骞冲彴缂栧彿
+     * @param channelReduces 閫氶亾淇℃伅
+     * @param catalogId 鐩綍缂栧彿
+     * @return
+     */
+    int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
index ac10000..1dd74ee 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
@@ -101,4 +101,9 @@
     void zlmServerOffline(String mediaServerId);
 
     void clean();
+
+    /**
+     * 鏇存柊浠g悊娴�
+     */
+    boolean updateStreamProxy(StreamProxyItem streamProxyItem);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
index acf0d27..b95ec48 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
@@ -5,6 +5,7 @@
 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
+import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
 import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
 import com.github.pagehelper.PageInfo;
 
@@ -44,31 +45,59 @@
      * 鍋滄涓�璺帹娴�
      * @param app 搴旂敤鍚�
      * @param streamId 娴両D
-     * @return
      */
     boolean stop(String app, String streamId);
 
     /**
      * 鏂扮殑鑺傜偣鍔犲叆
-     * @param mediaServerId
-     * @return
      */
     void zlmServerOnline(String mediaServerId);
 
     /**
      * 鑺傜偣绂荤嚎
-     * @param mediaServerId
-     * @return
      */
     void zlmServerOffline(String mediaServerId);
 
+    /**
+     * 娓呯┖
+     */
     void clean();
+
 
     boolean saveToRandomGB();
 
+    /**
+     * 鎵归噺娣诲姞
+     */
     void batchAdd(List<StreamPushItem> streamPushExcelDtoList);
 
+    /**
+     * 涓澶氫釜鎺ㄦ祦
+     */
     boolean batchStop(List<GbStream> streamPushItems);
 
+    /**
+     * 瀵煎叆鏃舵壒閲忓鍔�
+     */
     void batchAddForUpload(List<StreamPushItem> streamPushItems, Map<String, List<String[]>> streamPushItemsForAll);
+
+    /**
+     * 鍏ㄩ儴绂荤嚎
+     */
+    void allStreamOffline();
+
+    /**
+     * 鎺ㄦ祦绂荤嚎
+     */
+    void offline(List<StreamPushItemFromRedis> offlineStreams);
+
+    /**
+     * 鎺ㄦ祦涓婄嚎
+     */
+    void online(List<StreamPushItemFromRedis> onlineStreams);
+
+    /**
+     * 澧炲姞鎺ㄦ祦
+     */
+    boolean add(StreamPushItem stream);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IUserService.java b/src/main/java/com/genersoft/iot/vmp/service/IUserService.java
index e362605..7e2a839 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IUserService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IUserService.java
@@ -1,6 +1,7 @@
 package com.genersoft.iot.vmp.service;
 
 import com.genersoft.iot.vmp.storager.dao.dto.User;
+import com.github.pagehelper.PageInfo;
 
 import java.util.List;
 
@@ -21,4 +22,8 @@
     int updateUsers(User user);
 
     boolean checkPushAuthority(String callId, String sign);
+
+    PageInfo<User> getUsers(int page, int count);
+
+    int changePushKey(int id, String pushKey);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java
deleted file mode 100644
index 9d15c1f..0000000
--- a/src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.genersoft.iot.vmp.service;
-
-import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
-import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-
-/**
- * 瀹氭椂鏌ユ壘redis涓殑GPS鎺ㄩ�佹秷鎭紝骞朵繚瀛樺埌瀵瑰簲鐨勬祦涓�
- */
-@Component
-public class StreamGPSSubscribeTask {
-
-    @Autowired
-    private IRedisCatchStorage redisCatchStorage;
-
-    @Autowired
-    private IVideoManagerStorage storager;
-
-
-    @Scheduled(fixedRate = 30 * 1000)   //姣�30绉掓墽琛屼竴娆�
-    public void execute(){
-        List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();
-        if (gpsMsgInfo.size() > 0) {
-            storager.updateStreamGPS(gpsMsgInfo);
-            for (GPSMsgInfo msgInfo : gpsMsgInfo) {
-                msgInfo.setStored(true);
-                redisCatchStorage.updateGpsMsgInfo(msgInfo);
-            }
-        }
-
-    }
-}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java
index ead291c..8c55986 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java
@@ -17,7 +17,6 @@
     @Autowired
     private DeviceAlarmMapper deviceAlarmMapper;
 
-
     @Override
     public PageInfo<DeviceAlarm> getAllAlarm(int page, int count, String deviceId, String alarmPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
         PageHelper.startPage(page, count);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
new file mode 100644
index 0000000..99ad3de
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
@@ -0,0 +1,165 @@
+package com.genersoft.iot.vmp.service.impl;
+
+import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
+import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
+import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
+import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
+import com.genersoft.iot.vmp.utils.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * @author lin
+ */
+@Service
+public class DeviceChannelServiceImpl implements IDeviceChannelService {
+
+    private final static Logger logger = LoggerFactory.getLogger(DeviceChannelServiceImpl.class);
+
+    @Autowired
+    private IRedisCatchStorage redisCatchStorage;
+
+    @Autowired
+    private DeviceChannelMapper channelMapper;
+
+    @Autowired
+    private DeviceMapper deviceMapper;
+
+    @Override
+    public DeviceChannel updateGps(DeviceChannel deviceChannel, Device device) {
+        if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {
+            if (device == null) {
+                device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
+            }
+
+            if ("WGS84".equals(device.getGeoCoordSys())) {
+                deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
+                deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
+                Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
+                deviceChannel.setLongitudeGcj02(position[0]);
+                deviceChannel.setLatitudeGcj02(position[1]);
+            }else if ("GCJ02".equals(device.getGeoCoordSys())) {
+                deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
+                deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
+                Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
+                deviceChannel.setLongitudeWgs84(position[0]);
+                deviceChannel.setLatitudeWgs84(position[1]);
+            }else {
+                deviceChannel.setLongitudeGcj02(0.00);
+                deviceChannel.setLatitudeGcj02(0.00);
+                deviceChannel.setLongitudeWgs84(0.00);
+                deviceChannel.setLatitudeWgs84(0.00);
+            }
+        }else {
+            deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
+            deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
+            deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
+            deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
+        }
+        return deviceChannel;
+    }
+
+    @Override
+    public void updateChannel(String deviceId, DeviceChannel channel) {
+        String channelId = channel.getChannelId();
+        channel.setDeviceId(deviceId);
+        StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
+        if (streamInfo != null) {
+            channel.setStreamId(streamInfo.getStream());
+        }
+        String now = DateUtil.getNow();
+        channel.setUpdateTime(now);
+        DeviceChannel deviceChannel = channelMapper.queryChannel(deviceId, channelId);
+        channel = updateGps(channel, null);
+        if (deviceChannel == null) {
+            channel.setCreateTime(now);
+            channelMapper.add(channel);
+        }else {
+            channelMapper.update(channel);
+        }
+        channelMapper.updateChannelSubCount(deviceId,channel.getParentId());
+    }
+
+    @Override
+    public int updateChannels(String deviceId, List<DeviceChannel> channels) {
+        List<DeviceChannel> addChannels = new ArrayList<>();
+        List<DeviceChannel> updateChannels = new ArrayList<>();
+        HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
+        Device device = deviceMapper.getDeviceByDeviceId(deviceId);
+        if (channels != null && channels.size() > 0) {
+            List<DeviceChannel> channelList = channelMapper.queryChannels(deviceId, null, null, null, null);
+            if (channelList.size() == 0) {
+                for (DeviceChannel channel : channels) {
+                    channel.setDeviceId(deviceId);
+                    StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
+                    if (streamInfo != null) {
+                        channel.setStreamId(streamInfo.getStream());
+                    }
+                    String now = DateUtil.getNow();
+                    channel.setUpdateTime(now);
+                    channel.setCreateTime(now);
+                    channel = updateGps(channel, device);
+                    addChannels.add(channel);
+                }
+            }else {
+                for (DeviceChannel deviceChannel : channelList) {
+                    channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
+                }
+                for (DeviceChannel channel : channels) {
+                    channel.setDeviceId(deviceId);
+                    StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
+                    if (streamInfo != null) {
+                        channel.setStreamId(streamInfo.getStream());
+                    }
+                    String now = DateUtil.getNow();
+                    channel.setUpdateTime(now);
+                    channel = updateGps(channel, device);
+                    if (channelsInStore.get(channel.getChannelId()) != null) {
+                        updateChannels.add(channel);
+                    }else {
+                        addChannels.add(channel);
+                        channel.setCreateTime(now);
+                    }
+                }
+            }
+            int limitCount = 300;
+            if (addChannels.size() > 0) {
+                if (addChannels.size() > limitCount) {
+                    for (int i = 0; i < addChannels.size(); i += limitCount) {
+                        int toIndex = i + limitCount;
+                        if (i + limitCount > addChannels.size()) {
+                            toIndex = addChannels.size();
+                        }
+                        channelMapper.batchAdd(addChannels.subList(i, toIndex));
+                    }
+                }else {
+                    channelMapper.batchAdd(addChannels);
+                }
+            }
+            if (updateChannels.size() > 0) {
+                if (updateChannels.size() > limitCount) {
+                    for (int i = 0; i < updateChannels.size(); i += limitCount) {
+                        int toIndex = i + limitCount;
+                        if (i + limitCount > updateChannels.size()) {
+                            toIndex = updateChannels.size();
+                        }
+                        channelMapper.batchUpdate(updateChannels.subList(i, toIndex));
+                    }
+                }else {
+                    channelMapper.batchUpdate(updateChannels);
+                }
+            }
+        }
+        return addChannels.size() + updateChannels.size();
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
index 9d376fb..66f678a 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -7,6 +7,7 @@
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
@@ -56,6 +57,9 @@
     private DeviceMapper deviceMapper;
 
     @Autowired
+    private IDeviceChannelService deviceChannelService;
+
+    @Autowired
     private DeviceChannelMapper deviceChannelMapper;
 
     @Autowired
@@ -82,10 +86,10 @@
             redisCatchStorage.clearCatchByDeviceId(device.getDeviceId());
         }
         device.setUpdateTime(now);
-        device.setOnline(1);
 
-        // 绗竴娆′笂绾�
+        // 绗竴娆′笂绾� 鎴栧垯璁惧涔嬪墠鏄绾跨姸鎬�--杩涜閫氶亾鍚屾鍜岃澶囦俊鎭煡璇�
         if (device.getCreateTime() == null) {
+            device.setOnline(1);
             device.setCreateTime(now);
             logger.info("[璁惧涓婄嚎,棣栨娉ㄥ唽]: {}锛屾煡璇㈣澶囦俊鎭互鍙婇�氶亾淇℃伅", device.getDeviceId());
             deviceMapper.add(device);
@@ -93,8 +97,19 @@
             commander.deviceInfoQuery(device);
             sync(device);
         }else {
-            deviceMapper.update(device);
-            redisCatchStorage.updateDevice(device);
+            if(device.getOnline() == 0){
+                device.setOnline(1);
+                device.setCreateTime(now);
+                logger.info("[璁惧涓婄嚎,绂荤嚎鐘舵�佷笅閲嶆柊娉ㄥ唽]: {}锛屾煡璇㈣澶囦俊鎭互鍙婇�氶亾淇℃伅", device.getDeviceId());
+                deviceMapper.update(device);
+                redisCatchStorage.updateDevice(device);
+                commander.deviceInfoQuery(device);
+                sync(device);
+            }else {
+                deviceMapper.update(device);
+                redisCatchStorage.updateDevice(device);
+            }
+
         }
 
         // 涓婄嚎娣诲姞璁㈤槄
@@ -121,6 +136,8 @@
         device.setOnline(0);
         redisCatchStorage.updateDevice(device);
         deviceMapper.update(device);
+        //杩涜閫氶亾绂荤嚎
+        deviceChannelMapper.offlineByDeviceId(deviceId);
         // 绂荤嚎閲婃斁鎵�鏈塻src
         List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null);
         if (ssrcTransactions != null && ssrcTransactions.size() > 0) {
@@ -143,7 +160,7 @@
         logger.info("[娣诲姞鐩綍璁㈤槄] 璁惧{}", device.getDeviceId());
         // 娣诲姞鐩綍璁㈤槄
         CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander, dynamicTask);
-        // 鎻愬墠寮�濮嬪埛鏂拌闃�
+        // 鍒锋柊璁㈤槄
         int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
         // 璁剧疆鏈�灏忓�间负30
         dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000);
@@ -178,8 +195,8 @@
         MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander, dynamicTask);
         // 璁剧疆鏈�灏忓�间负30
         int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
-        // 鎻愬墠寮�濮嬪埛鏂拌闃�
-        dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog -1 ) * 1000);
+        // 鍒锋柊璁㈤槄
+        dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog) * 1000);
         return true;
     }
 
@@ -324,23 +341,12 @@
     private void updateDeviceChannelGeoCoordSys(Device device) {
        List<DeviceChannel> deviceChannels =  deviceChannelMapper.getAllChannelWithCoordinate(device.getDeviceId());
        if (deviceChannels.size() > 0) {
+           List<DeviceChannel> deviceChannelsForStore = new ArrayList<>();
            for (DeviceChannel deviceChannel : deviceChannels) {
-               if ("WGS84".equals(device.getGeoCoordSys())) {
-                   deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
-                   deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
-                   Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
-                   deviceChannel.setLongitudeGcj02(position[0]);
-                   deviceChannel.setLatitudeGcj02(position[1]);
-               }else if ("GCJ02".equals(device.getGeoCoordSys())) {
-                   deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
-                   deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
-                   Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
-                   deviceChannel.setLongitudeWgs84(position[0]);
-                   deviceChannel.setLatitudeWgs84(position[1]);
-               }
+               deviceChannelsForStore.add(deviceChannelService.updateGps(deviceChannel, device));
            }
+           deviceChannelService.updateChannels(device.getDeviceId(), deviceChannelsForStore);
        }
-        storage.updateChannels(device.getDeviceId(), deviceChannels);
     }
 
 
@@ -352,11 +358,11 @@
         }
         if (parentId == null || parentId.equals(deviceId)) {
             // 瀛楁牴鑺傜偣寮�濮嬫煡璇�
-            List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), true, !onlyCatalog);
+            List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), true, !onlyCatalog);
             return transportChannelsToTree(rootNodes, "");
         }
 
-        if ("CivilCode".equals(device.getTreeType())) {
+        if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
             if (parentId.length()%2 != 0) {
                 return null;
             }
@@ -386,7 +392,7 @@
 
         }
         // 浣跨敤涓氬姟鍒嗙粍灞曠ず鏍�
-        if ("BusinessGroup".equals(device.getTreeType())) {
+        if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
             if (parentId.length() < 14 ) {
                 return null;
             }
@@ -406,11 +412,11 @@
         }
         if (parentId == null || parentId.equals(deviceId)) {
             // 瀛楁牴鑺傜偣寮�濮嬫煡璇�
-            List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), false, true);
+            List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), false, true);
             return rootNodes;
         }
 
-        if ("CivilCode".equals(device.getTreeType())) {
+        if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
             if (parentId.length()%2 != 0) {
                 return null;
             }
@@ -431,7 +437,7 @@
 
         }
         // 浣跨敤涓氬姟鍒嗙粍灞曠ず鏍�
-        if ("BusinessGroup".equals(device.getTreeType())) {
+        if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
             if (parentId.length() < 14 ) {
                 return null;
             }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
index 4a965a0..8734882 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
@@ -1,14 +1,13 @@
 package com.genersoft.iot.vmp.service.impl;
 
 import com.genersoft.iot.vmp.conf.SipConfig;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
-import com.genersoft.iot.vmp.gb28181.bean.GbStream;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
+import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
+import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
 import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.github.pagehelper.PageHelper;
@@ -46,15 +45,15 @@
     private ParentPlatformMapper platformMapper;
 
     @Autowired
-    private SipConfig sipConfig;
+    private PlatformCatalogMapper catalogMapper;
 
     @Autowired
     private EventPublisher eventPublisher;
 
     @Override
-    public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, Boolean pushing, String mediaServerId) {
+    public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, String mediaServerId) {
         PageHelper.startPage(page, count);
-        List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, pushing, mediaServerId);
+        List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, mediaServerId);
         return new PageInfo<>(all);
     }
 
@@ -102,16 +101,25 @@
         deviceChannel.setLatitude(gbStream.getLatitude());
         deviceChannel.setDeviceId(platform.getDeviceGBId());
         deviceChannel.setManufacture("wvp-pro");
-//        deviceChannel.setStatus(gbStream.isStatus()?1:0);
-        deviceChannel.setStatus(1);
-        deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId);
+        deviceChannel.setStatus(gbStream.isStatus()?1:0);
+
         deviceChannel.setRegisterWay(1);
-        if (catalogId.length() > 0 && catalogId.length() <= 10) {
-            // 鐖惰妭鐐规槸琛屾斂鍖哄垝,鍒欒缃瓹ivilCode浣跨敤姝よ鏀垮尯鍒�
+        deviceChannel.setCivilCode(platform.getAdministrativeDivision());
+
+        if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
             deviceChannel.setCivilCode(catalogId);
-        }else {
-            deviceChannel.setCivilCode(platform.getAdministrativeDivision());
+        }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
+            PlatformCatalog catalog = catalogMapper.select(catalogId);
+            if (catalog == null) {
+                deviceChannel.setParentId(platform.getDeviceGBId());
+                deviceChannel.setBusinessGroupId(null);
+            }else {
+                deviceChannel.setParentId(catalog.getId());
+                deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
+            }
+
         }
+
         deviceChannel.setModel("live");
         deviceChannel.setOwner("wvp-pro");
         deviceChannel.setParental(0);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
index 1285397..b1c6a9a 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -1,5 +1,26 @@
 package com.genersoft.iot.vmp.service.impl;
 
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.genersoft.iot.vmp.media.zlm.ZLMRunner;
+import com.genersoft.iot.vmp.service.IStreamProxyService;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.util.StringUtils;
+
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -14,25 +35,16 @@
 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.utils.redis.JedisUtil;
 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
-import okhttp3.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.jdbc.datasource.DataSourceTransactionManager;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.TransactionDefinition;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.util.StringUtils;
 
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
 import java.time.LocalDateTime;
 import java.util.*;
 
@@ -46,6 +58,9 @@
 
     @Autowired
     private SipConfig sipConfig;
+
+    @Autowired
+    private ZLMRunner zlmRunner;
 
     @Value("${server.ssl.enabled:false}")
     private boolean sslEnabled;
@@ -120,7 +135,7 @@
     }
 
     @Override
-    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback) {
+    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback, Integer port) {
         if (mediaServerItem == null || mediaServerItem.getId() == null) {
             return null;
         }
@@ -148,11 +163,16 @@
             }
             int rtpServerPort = mediaServerItem.getRtpProxyPort();
             if (mediaServerItem.isRtpEnable()) {
-                rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0);
+                rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
             }
             redisUtil.set(key, mediaServerItem);
             return new SSRCInfo(rtpServerPort, ssrc, streamId);
         }
+    }
+
+    @Override
+    public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
+        return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null);
     }
 
     @Override
@@ -271,7 +291,13 @@
             return null;
         }
         String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
-        return (MediaServerItem)redisUtil.get(key);
+        MediaServerItem serverItem=(MediaServerItem)redisUtil.get(key);
+        if(null==serverItem){
+            //zlm鏈嶅姟涓嶅湪绾匡紝鍚姩閲嶈繛
+            reloadZlm();
+            serverItem=(MediaServerItem)redisUtil.get(key);
+        }
+        return serverItem;
     }
 
     @Override
@@ -351,14 +377,15 @@
      */
     @Override
     public void zlmServerOnline(ZLMServerConfig zlmServerConfig) {
-        logger.info("[ZLM] 姝e湪杩炴帴 : {} -> {}:{}",
-                zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
 
         MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
         if (serverItem == null) {
             logger.warn("[鏈敞鍐岀殑zlm] 鎷掓帴鎺ュ叆锛歿}鏉ヨ嚜{}锛歿}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
             logger.warn("璇锋鏌LM鐨�<general.mediaServerId>閰嶇疆鏄惁涓嶹VP鐨�<media.id>涓�鑷�");
             return;
+        }else {
+            logger.info("[ZLM] 姝e湪杩炴帴 : {} -> {}:{}",
+                    zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
         }
         serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval());
         if (serverItem.getHttpPort() == 0) {
@@ -463,8 +490,13 @@
         String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
 
         if (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
-            logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣");
-            return null;
+            logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣锛屽惎鍔ㄩ噸杩炴満鍒�");
+            //鍚姩閲嶈繛
+            reloadZlm();
+            if (redisUtil.zSize(key)  == null || redisUtil.zSize(key) == 0) {
+                logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣");
+                return null;
+            }
         }
 
         // 鑾峰彇鍒嗘暟鏈�浣庣殑锛屽強骞跺彂鏈�浣庣殑
@@ -595,9 +627,6 @@
         boolean result = false;
         OkHttpClient client = new OkHttpClient();
         String url = String.format("http://%s:%s/index/api/record",  ip, port);
-
-        FormBody.Builder builder = new FormBody.Builder();
-
         Request request = new Request.Builder()
                 .get()
                 .url(url)
@@ -629,9 +658,14 @@
         MediaServerItem mediaServerItem = getOne(mediaServerId);
         if (mediaServerItem == null) {
             // zlm杩炴帴閲嶈瘯
-
-            logger.warn("[鏇存柊ZLM 淇濇椿淇℃伅]澶辫触锛屾湭鎵惧埌娴佸獟浣撲俊鎭�");
-            return;
+            logger.warn("[鏇存柊ZLM 淇濇椿淇℃伅]澶辫触锛屾湭鎵惧埌娴佸獟浣撲俊鎭�,灏濊瘯閲嶈繛zlm");
+            reloadZlm();
+            mediaServerItem = getOne(mediaServerId);
+            if (mediaServerItem == null) {
+                // zlm杩炴帴閲嶈瘯
+                logger.warn("[鏇存柊ZLM 淇濇椿淇℃伅]澶辫触锛屾湭鎵惧埌娴佸獟浣撲俊鎭�");
+                return;
+            }
         }
         String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
         int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2;
@@ -648,10 +682,18 @@
             mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem);
         }
         for (MediaServerItem mediaServerItem : allInCatch) {
-            if (mediaServerItemMap.get(mediaServerItem) == null) {
+            if (!mediaServerItemMap.containsKey(mediaServerItem.getId())) {
                 delete(mediaServerItem.getId());
             }
         }
     }
 
+    public void reloadZlm(){
+        try {
+            zlmRunner.run();
+            Thread.sleep(500);//寤惰繜0.5绉掔紦鍐叉椂闂�
+        } catch (Exception e) {
+            logger.warn("灏濊瘯閲嶈繛zlm澶辫触锛�",e);
+        }
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
index e1f54d4..5a277d7 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -67,9 +67,9 @@
                 JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
                 JSONArray tracks = mediaJSON.getJSONArray("tracks");
                 if (authority) {
-                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, streamAuthorityInfo.getCallId(), true);
+                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,streamAuthorityInfo.getCallId(), true);
                 }else {
-                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
+                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null);
                 }
 
             }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
new file mode 100644
index 0000000..d024550
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
@@ -0,0 +1,106 @@
+package com.genersoft.iot.vmp.service.impl;
+
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
+import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
+import com.genersoft.iot.vmp.gb28181.bean.TreeType;
+import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
+import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
+import com.genersoft.iot.vmp.service.IPlatformChannelService;
+import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
+import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
+import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
+import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
+import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author lin
+ */
+@Service
+public class PlatformChannelServiceImpl implements IPlatformChannelService {
+
+    private final static Logger logger = LoggerFactory.getLogger(PlatformChannelServiceImpl.class);
+
+    @Autowired
+    private PlatformChannelMapper platformChannelMapper;
+
+    @Autowired
+    private DeviceChannelMapper deviceChannelMapper;
+
+    @Autowired
+    private PlatformCatalogMapper catalogManager;
+
+    @Autowired
+    private ParentPlatformMapper platformMapper;
+
+    @Autowired
+    EventPublisher eventPublisher;
+
+    @Override
+    public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
+        ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
+        if (platform == null) {
+            logger.warn("鏇存柊绾ц仈閫氶亾淇℃伅鏃舵湭鎵惧埌骞冲彴{}鐨勪俊鎭�", platformId);
+            return 0;
+        }
+        Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
+        for (ChannelReduce channelReduce : channelReduces) {
+            channelReduce.setCatalogId(catalogId);
+            deviceAndChannels.put(channelReduce.getId(), channelReduce);
+        }
+        List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
+        // 鏌ヨ褰撳墠宸茬粡瀛樺湪鐨�
+        List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
+        if (deviceAndChannelList != null) {
+            deviceAndChannelList.removeAll(channelIds);
+        }
+        for (Integer channelId : channelIds) {
+            deviceAndChannels.remove(channelId);
+        }
+        List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
+        // 瀵瑰墿涓嬬殑鏁版嵁杩涜瀛樺偍
+        int result = 0;
+        if (channelReducesToAdd.size() > 0) {
+            result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
+            // TODO 鍚庣画缁欏钩鍙板鍔犳帶鍒跺紑鍏充互鎺у埗鏄惁鍝嶅簲鐩綍璁㈤槄
+            List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
+            eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
+        }
+
+        return result;
+    }
+
+    private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) {
+        List<DeviceChannel> deviceChannelList = new ArrayList<>();
+        if (channelReduces.size() > 0){
+            PlatformCatalog catalog = catalogManager.select(catalogId);
+            if (catalog == null && !catalogId.equals(platform.getServerGBId())) {
+                logger.warn("鏈煡璇㈠埌鐩綍{}鐨勪俊鎭�", catalogId);
+                return null;
+            }
+            for (ChannelReduce channelReduce : channelReduces) {
+                DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
+                deviceChannel.setParental(0);
+                deviceChannelList.add(deviceChannel);
+                if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
+                    deviceChannel.setCivilCode(catalogId);
+                }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
+                    deviceChannel.setParentId(catalogId);
+                    if (catalog != null) {
+                        deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
+                    }
+                }
+            }
+        }
+        return deviceChannelList;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index a3b40bb..5ae0103 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -1,5 +1,21 @@
 package com.genersoft.iot.vmp.service.impl;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+
+import javax.sip.ResponseEvent;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.web.context.request.async.DeferredResult;
+
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -7,7 +23,13 @@
 import com.genersoft.iot.vmp.conf.DynamicTask;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
-import com.genersoft.iot.vmp.gb28181.bean.*;
+import com.genersoft.iot.vmp.gb28181.bean.Device;
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
+import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
+import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
+import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
+import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
+import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -16,6 +38,9 @@
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
+import com.genersoft.iot.vmp.media.zlm.dto.HookType;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -32,9 +57,11 @@
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
+import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
+
 import gov.nist.javax.sip.stack.SIPDialog;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -313,16 +340,10 @@
                     // 鍗曠鍙fā寮弒treamId涔熸湁鍙樺寲锛岄渶瑕侀噸鏂拌缃洃鍚�
                     if (!mediaServerItem.isRtpEnable()) {
                         // 娣诲姞璁㈤槄
-                        JSONObject subscribeKey = new JSONObject();
-                        subscribeKey.put("app", "rtp");
-                        subscribeKey.put("stream", stream);
-                        subscribeKey.put("regist", true);
-                        subscribeKey.put("schema", "rtmp");
-                        subscribeKey.put("mediaServerId", mediaServerItem.getId());
-                        subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed,subscribeKey);
-                        subscribeKey.put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
-                        subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-                                (MediaServerItem mediaServerItemInUse, JSONObject response)->{
+                        HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId());
+                        subscribe.removeSubscribe(hookSubscribe);
+                        hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
+                        subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
                                     logger.info("[ZLM HOOK] ssrc淇鍚庢敹鍒拌闃呮秷鎭細 " + response.toJSONString());
                                     dynamicTask.stop(timeOutTaskKey);
                                     // hook鍝嶅簲
@@ -333,7 +354,7 @@
                     // 鍏抽棴rtp server
                     mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
                     // 閲嶆柊寮�鍚痵src server
-                    mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false);
+                    mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
 
                 }
             }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java
index 638ea41..a4fa635 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java
@@ -8,6 +8,9 @@
 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
+import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
+import com.genersoft.iot.vmp.media.zlm.dto.HookType;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.bean.*;
@@ -270,14 +273,9 @@
             }, userSetting.getPlatformPlayTimeout());
 
             // 娣诲姞璁㈤槄
-            JSONObject subscribeKey = new JSONObject();
-            subscribeKey.put("app", content.getApp());
-            subscribeKey.put("stream", content.getStream());
-            subscribeKey.put("regist", true);
-            subscribeKey.put("schema", "rtmp");
-            subscribeKey.put("mediaServerId", mediaServerItem.getId());
-            subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
-                    (MediaServerItem mediaServerItemInUse, JSONObject json)->{
+            HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(content.getApp(), content.getStream(), true, "rtmp", mediaServerItem.getId());
+
+            subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
                         dynamicTask.stop(taskKey);
                         responseSendItem(mediaServerItem, content, toId, serial);
                     });
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java
index be21401..4e94d68 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java
@@ -1,15 +1,23 @@
 package com.genersoft.iot.vmp.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.data.redis.connection.Message;
 import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
  * 鎺ユ敹鏉ヨ嚜redis鐨凣PS鏇存柊閫氱煡
@@ -20,12 +28,50 @@
 
     private final static Logger logger = LoggerFactory.getLogger(RedisGpsMsgListener.class);
 
+    private boolean taskQueueHandlerRun = false;
+
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
 
+    @Autowired
+    private IVideoManagerStorage storager;
+
+    private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
+
+    @Qualifier("taskExecutor")
+    @Autowired
+    private ThreadPoolTaskExecutor taskExecutor;
+
+
     @Override
     public void onMessage(@NotNull Message message, byte[] bytes) {
-        GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
-        redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
+        taskQueue.offer(message);
+        if (!taskQueueHandlerRun) {
+            taskQueueHandlerRun = true;
+            taskExecutor.execute(() -> {
+                while (!taskQueue.isEmpty()) {
+                    Message msg = taskQueue.poll();
+                    GPSMsgInfo gpsMsgInfo = JSON.parseObject(msg.getBody(), GPSMsgInfo.class);
+                    // 鍙槸鏀惧叆redis缂撳瓨璧锋潵
+                    redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
+                }
+                taskQueueHandlerRun = false;
+            });
+        }
+    }
+
+    /**
+     * 瀹氭椂灏嗙粡绾害鏇存柊鍒版暟鎹簱
+     */
+    @Scheduled(fixedRate = 2 * 1000)   //姣�2绉掓墽琛屼竴娆�
+    public void execute(){
+        List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();
+        if (gpsMsgInfo.size() > 0) {
+            storager.updateStreamGPS(gpsMsgInfo);
+            for (GPSMsgInfo msgInfo : gpsMsgInfo) {
+                msgInfo.setStored(true);
+                redisCatchStorage.updateGpsMsgInfo(msgInfo);
+            }
+        }
     }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java
new file mode 100644
index 0000000..50e894a
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java
@@ -0,0 +1,115 @@
+package com.genersoft.iot.vmp.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.common.VideoManagerConstants;
+import com.genersoft.iot.vmp.conf.DynamicTask;
+import com.genersoft.iot.vmp.conf.UserSetting;
+import com.genersoft.iot.vmp.gb28181.bean.GbStream;
+import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
+import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
+import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
+import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
+import com.genersoft.iot.vmp.service.IStreamPushService;
+import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
+import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto;
+import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
+import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
+import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+
+/**
+ * 鎺ユ敹redis鍙戦�佺殑鎺ㄦ祦璁惧涓婄嚎涓嬬嚎閫氱煡
+ * @author lin
+ */
+@Component
+public class RedisPushStreamStatusMsgListener implements MessageListener, ApplicationRunner {
+
+    private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusMsgListener.class);
+
+    private boolean taskQueueHandlerRun = false;
+
+    @Autowired
+    private IRedisCatchStorage redisCatchStorage;
+
+    @Autowired
+    private IStreamPushService streamPushService;
+
+    @Autowired
+    private DynamicTask dynamicTask;
+
+
+
+    private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
+
+    @Qualifier("taskExecutor")
+    @Autowired
+    private ThreadPoolTaskExecutor taskExecutor;
+
+    @Override
+    public void onMessage(Message message, byte[] bytes) {
+        // TODO 澧炲姞闃熷垪
+        logger.warn("[REDIS娑堟伅-鎺ㄦ祦璁惧鐘舵�佸彉鍖朷锛� {}", new String(message.getBody()));
+        taskQueue.offer(message);
+
+        if (!taskQueueHandlerRun) {
+            taskQueueHandlerRun = true;
+            taskExecutor.execute(() -> {
+                while (!taskQueue.isEmpty()) {
+                    Message msg = taskQueue.poll();
+                    PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(msg.getBody(), PushStreamStatusChangeFromRedisDto.class);
+                    if (statusChangeFromPushStream == null) {
+                        logger.warn("[REDIS娑堟伅]鎺ㄦ祦璁惧鐘舵�佸彉鍖栨秷鎭В鏋愬け璐�");
+                        return;
+                    }
+                    // 鍙栨秷瀹氭椂浠诲姟
+                    dynamicTask.stop(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED);
+                    if (statusChangeFromPushStream.isSetAllOffline()) {
+                        // 鎵�鏈夎澶囩绾�
+                        streamPushService.allStreamOffline();
+                    }
+                    if (statusChangeFromPushStream.getOfflineStreams() != null
+                            && statusChangeFromPushStream.getOfflineStreams().size() > 0) {
+                        // 鏇存柊閮ㄥ垎璁惧绂荤嚎
+                        streamPushService.offline(statusChangeFromPushStream.getOfflineStreams());
+                    }
+                    if (statusChangeFromPushStream.getOnlineStreams() != null &&
+                            statusChangeFromPushStream.getOnlineStreams().size() > 0) {
+                        // 鏇存柊閮ㄥ垎璁惧涓婄嚎
+                        streamPushService.online(statusChangeFromPushStream.getOnlineStreams());
+                    }
+                }
+                taskQueueHandlerRun = false;
+            });
+        }
+    }
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        //  鍚姩鏃惰缃墍鏈夋帹娴侀�氶亾绂荤嚎锛屽彂璧锋煡璇㈣姹�
+        redisCatchStorage.sendStreamPushRequestedMsgForStatus();
+        dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{
+            logger.info("[REDIS娑堟伅]鏈敹鍒皉edis鍥炲鎺ㄦ祦璁惧鐘舵�侊紝鎵ц鎺ㄦ祦璁惧绂荤嚎");
+            // 浜旂鏀朵笉鍒拌姹傚氨璁剧疆閫氶亾绂荤嚎锛岀劧鍚庨�氱煡涓婄骇绂荤嚎
+            streamPushService.allStreamOffline();
+        }, 5000);
+    }
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java
index 07fffdc..fe024c0 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java
@@ -3,16 +3,12 @@
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.UserSetting;
-import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
-import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
+
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
-import com.genersoft.iot.vmp.utils.DateUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +18,7 @@
 
 
 /**
+ * 鎺ユ敹鍏朵粬wvp鍙戦�佹祦鍙樺寲閫氱煡
  * @author lin
  */
 @Component
@@ -49,7 +46,7 @@
 
         JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class);
         if (steamMsgJson == null) {
-            logger.warn("[REDIS鐨凙LARM閫氱煡]娑堟伅瑙f瀽澶辫触");
+            logger.warn("[鏀跺埌redis 娴佸彉鍖朷娑堟伅瑙f瀽澶辫触");
             return;
         }
         String serverId = steamMsgJson.getString("serverId");
@@ -58,7 +55,7 @@
             // 鑷繁鍙戦�佺殑娑堟伅蹇界暐鍗冲彲
             return;
         }
-        logger.info("[REDIS閫氱煡] 娴佸彉鍖栵細 {}", new String(message.getBody()));
+        logger.info("[鏀跺埌redis 娴佸彉鍖朷锛� {}", new String(message.getBody()));
         String app = steamMsgJson.getString("app");
         String stream = steamMsgJson.getString("stream");
         boolean register = steamMsgJson.getBoolean("register");
@@ -75,9 +72,10 @@
         mediaItem.setOriginType(0);
         mediaItem.setOriginTypeStr("0");
         mediaItem.setOriginTypeStr("unknown");
-
-        zlmMediaListManager.addPush(mediaItem);
-
-
+        if (register) {
+            zlmMediaListManager.addPush(mediaItem);
+        }else {
+            zlmMediaListManager.removeMedia(app, stream);
+        }
     }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
index b9bb96b..40c37c2 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -3,10 +3,10 @@
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
+import com.genersoft.iot.vmp.gb28181.bean.TreeType;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
@@ -23,14 +23,19 @@
 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
 import com.genersoft.iot.vmp.service.IStreamProxyService;
+import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import com.github.pagehelper.PageInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
 import org.springframework.util.StringUtils;
 
+import java.net.InetAddress;
 import java.util.*;
 
 /**
@@ -48,7 +53,7 @@
     private IMediaService mediaService;
 
     @Autowired
-    private ZLMRESTfulUtils zlmresTfulUtils;;
+    private ZLMRESTfulUtils zlmresTfulUtils;
 
     @Autowired
     private StreamProxyMapper streamProxyMapper;
@@ -61,9 +66,6 @@
 
     @Autowired
     private UserSetting userSetting;
-
-    @Autowired
-    private SipConfig sipConfig;
 
     @Autowired
     private GbStreamMapper gbStreamMapper;
@@ -83,6 +85,12 @@
     @Autowired
     private IMediaServerService mediaServerService;
 
+    @Autowired
+    DataSourceTransactionManager dataSourceTransactionManager;
+
+    @Autowired
+    TransactionDefinition transactionDefinition;
+
 
     @Override
     public WVPResult<StreamInfo> save(StreamProxyItem param) {
@@ -99,6 +107,7 @@
             wvpResult.setMsg("淇濆瓨澶辫触");
             return wvpResult;
         }
+
         String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
                 param.getStream() );
         param.setDst_url(dstUrl);
@@ -108,9 +117,9 @@
         boolean saveResult;
         // 鏇存柊
         if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
-            saveResult = videoManagerStorager.updateStreamProxy(param);
+            saveResult = updateStreamProxy(param);
         }else { // 鏂板
-            saveResult = videoManagerStorager.addStreamProxy(param);
+            saveResult = addStreamProxy(param);
         }
         if (saveResult) {
             result.append("淇濆瓨鎴愬姛");
@@ -124,7 +133,7 @@
                     if (param.isEnable_remove_none_reader()) {
                         del(param.getApp(), param.getStream());
                     }else {
-                        videoManagerStorager.updateStreamProxy(param);
+                        updateStreamProxy(param);
                     }
 
                 }else {
@@ -147,25 +156,79 @@
                 result.append(",  鍏宠仈鍥芥爣骞冲彴[ " + param.getPlatformGbId() + " ]澶辫触");
             }
         }
-        if (!StringUtils.isEmpty(param.getGbId())) {
-            // 鏌ユ壘寮�鍚簡鍏ㄩ儴鐩存挱娴佸叡浜殑涓婄骇骞冲彴
-            List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
-            if (parentPlatforms.size() > 0) {
-                for (ParentPlatform parentPlatform : parentPlatforms) {
-                    param.setPlatformId(parentPlatform.getServerGBId());
-                    param.setCatalogId(parentPlatform.getCatalogId());
-                    String stream = param.getStream();
-                    StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(param.getApp(), stream, parentPlatform.getServerGBId());
-                    if (streamProxyItems == null) {
-                        platformGbStreamMapper.add(param);
-                        eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), param, CatalogEvent.ADD);
-                    }
-                }
-            }
-        }
-
         wvpResult.setMsg(result.toString());
         return wvpResult;
+    }
+
+    /**
+     * 鏂板浠g悊娴�
+     * @param streamProxyItem
+     * @return
+     */
+    private boolean addStreamProxy(StreamProxyItem streamProxyItem) {
+        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+        boolean result = false;
+        streamProxyItem.setStreamType("proxy");
+        streamProxyItem.setStatus(true);
+        String now = DateUtil.getNow();
+        streamProxyItem.setCreateTime(now);
+        try {
+            if (streamProxyMapper.add(streamProxyItem) > 0) {
+                if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
+                    if (gbStreamMapper.add(streamProxyItem) < 0) {
+                        //浜嬪姟鍥炴粴
+                        dataSourceTransactionManager.rollback(transactionStatus);
+                        return false;
+                    }
+                }
+            }else {
+                //浜嬪姟鍥炴粴
+                dataSourceTransactionManager.rollback(transactionStatus);
+                return false;
+            }
+            result = true;
+            dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
+        }catch (Exception e) {
+            logger.error("鍚戞暟鎹簱娣诲姞娴佷唬鐞嗗け璐ワ細", e);
+            dataSourceTransactionManager.rollback(transactionStatus);
+        }
+
+
+        return result;
+    }
+
+    /**
+     * 鏇存柊浠g悊娴�
+     * @param streamProxyItem
+     * @return
+     */
+    @Override
+    public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
+        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+        boolean result = false;
+        streamProxyItem.setStreamType("proxy");
+        try {
+            if (streamProxyMapper.update(streamProxyItem) > 0) {
+                if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
+                    if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
+                        //浜嬪姟鍥炴粴
+                        dataSourceTransactionManager.rollback(transactionStatus);
+                        return false;
+                    }
+                }
+            } else {
+                //浜嬪姟鍥炴粴
+                dataSourceTransactionManager.rollback(transactionStatus);
+                return false;
+            }
+
+            dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
+            result = true;
+        }catch (Exception e) {
+            e.printStackTrace();
+            dataSourceTransactionManager.rollback(transactionStatus);
+        }
+        return result;
     }
 
     @Override
@@ -239,7 +302,7 @@
             if (jsonObject.getInteger("code") == 0) {
                 result = true;
                 streamProxy.setEnable(true);
-                videoManagerStorager.updateStreamProxy(streamProxy);
+                updateStreamProxy(streamProxy);
             }
         }
         return result;
@@ -253,7 +316,7 @@
             JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
             if (jsonObject != null && jsonObject.getInteger("code") == 0) {
                 streamProxyDto.setEnable(false);
-                result = videoManagerStorager.updateStreamProxy(streamProxyDto);
+                result = updateStreamProxy(streamProxyDto);
             }
         }
         return result;
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
index 837e135..6c6c04b 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
@@ -4,6 +4,7 @@
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
+import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
@@ -13,6 +14,7 @@
 import com.genersoft.iot.vmp.service.IGbStreamService;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
+import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.dao.*;
 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -21,7 +23,10 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
 import org.springframework.util.StringUtils;
 
 import java.util.*;
@@ -67,6 +72,16 @@
 
     @Autowired
     private IMediaServerService mediaServerService;
+
+    @Autowired
+    DataSourceTransactionManager dataSourceTransactionManager;
+
+    @Autowired
+    TransactionDefinition transactionDefinition;
+
+    @Autowired
+    private MediaConfig mediaConfig;
+
 
     @Override
     public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
@@ -132,30 +147,9 @@
         stream.setStreamType("push");
         stream.setStatus(true);
         stream.setCreateTime(DateUtil.getNow());
+        stream.setStreamType("push");
+        stream.setMediaServerId(mediaConfig.getId());
         int add = gbStreamMapper.add(stream);
-
-        // 鏌ユ壘寮�鍚簡鍏ㄩ儴鐩存挱娴佸叡浜殑涓婄骇骞冲彴
-        List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
-        if (parentPlatforms.size() > 0) {
-            for (ParentPlatform parentPlatform : parentPlatforms) {
-                stream.setCatalogId(parentPlatform.getCatalogId());
-                stream.setPlatformId(parentPlatform.getServerGBId());
-                String streamId = stream.getStream();
-                StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
-                if (streamProxyItem == null) {
-                    platformGbStreamMapper.add(stream);
-                    eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
-                }else {
-                    if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
-                        // 姝ゆ祦浣跨敤鍙︿竴涓浗鏍嘔d宸茬粡涓庤骞冲彴鍏宠仈锛岀Щ闄ゆ璁板綍
-                        platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
-                        platformGbStreamMapper.add(stream);
-                        eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
-                    }
-                }
-            }
-        }
-
         return add > 0;
     }
 
@@ -181,7 +175,6 @@
 
     @Override
     public StreamPushItem getPush(String app, String streamId) {
-
         return streamPushMapper.selectOne(app, streamId);
     }
 
@@ -345,31 +338,6 @@
     public void batchAdd(List<StreamPushItem> streamPushItems) {
         streamPushMapper.addAll(streamPushItems);
         gbStreamMapper.batchAdd(streamPushItems);
-        // 鏌ユ壘寮�鍚簡鍏ㄩ儴鐩存挱娴佸叡浜殑涓婄骇骞冲彴
-        List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
-        if (parentPlatforms.size() > 0) {
-            for (StreamPushItem stream : streamPushItems) {
-                for (ParentPlatform parentPlatform : parentPlatforms) {
-                    stream.setCatalogId(parentPlatform.getCatalogId());
-                    stream.setPlatformId(parentPlatform.getServerGBId());
-                    String streamId = stream.getStream();
-                    StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
-                    if (streamProxyItem == null) {
-                        platformGbStreamMapper.add(stream);
-                        eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
-                    }else {
-                        if (!streamProxyItem.getGbId().equals(stream.getGbId())) {
-                            // 姝ゆ祦浣跨敤鍙︿竴涓浗鏍嘔d宸茬粡涓庤骞冲彴鍏宠仈锛岀Щ闄ゆ璁板綍
-                            platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());
-                            platformGbStreamMapper.add(stream);
-                            eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);
-                            stream.setGbId(streamProxyItem.getGbId());
-                            eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.DEL);
-                        }
-                    }
-                }
-            }
-        }
     }
 
     @Override
@@ -481,4 +449,58 @@
         }
         return true;
     }
+
+    @Override
+    public void allStreamOffline() {
+        List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGb();
+        if (onlinePushers.size() == 0) {
+            return;
+        }
+        streamPushMapper.setAllStreamOffline();
+
+        // 鍙戦�侀�氱煡
+        eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
+    }
+
+    @Override
+    public void offline(List<StreamPushItemFromRedis> offlineStreams) {
+        // 鏇存柊閮ㄥ垎璁惧绂荤嚎
+        List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGbInList(offlineStreams);
+        streamPushMapper.offline(offlineStreams);
+        // 鍙戦�侀�氱煡
+        eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
+    }
+
+    @Override
+    public void online(List<StreamPushItemFromRedis> onlineStreams) {
+        // 鏇存柊閮ㄥ垎璁惧涓婄嚎streamPushService
+        List<GbStream> onlinePushers = streamPushMapper.getOfflinePusherForGbInList(onlineStreams);
+        streamPushMapper.online(onlineStreams);
+        // 鍙戦�侀�氱煡
+        eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.ON);
+    }
+
+    @Override
+    public boolean add(StreamPushItem stream) {
+        stream.setUpdateTime(DateUtil.getNow());
+        stream.setCreateTime(DateUtil.getNow());
+        stream.setServerId(userSetting.getServerId());
+
+        // 鏀惧湪浜嬪姟鍐呮墽琛�
+        boolean result = false;
+        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
+        try {
+            int addStreamResult = streamPushMapper.add(stream);
+            if (!StringUtils.isEmpty(stream.getGbId())) {
+                stream.setStreamType("push");
+                gbStreamMapper.add(stream);
+            }
+            dataSourceTransactionManager.commit(transactionStatus);
+            result = true;
+        }catch (Exception e) {
+            logger.error("鎵归噺绉婚櫎娴佷笌骞冲彴鐨勫叧绯绘椂閿欒", e);
+            dataSourceTransactionManager.rollback(transactionStatus);
+        }
+        return result;
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
index 45cbcf6..0baad96 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
@@ -14,38 +14,60 @@
 
 public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPushExcelDto> {
 
-    // 閿欒鏁版嵁鐨勫洖璋冿紝鐢ㄤ簬灏嗛敊璇暟鎹彂閫佺粰椤甸潰
+    /**
+     * 閿欒鏁版嵁鐨勫洖璋冿紝鐢ㄤ簬灏嗛敊璇暟鎹彂閫佺粰椤甸潰
+     */
     private ErrorDataHandler errorDataHandler;
 
-    // 鎺ㄦ祦鐨勪笟鍔$被鐢ㄤ簬瀛樺偍鏁版嵁
+    /**
+     * 鎺ㄦ祦鐨勪笟鍔$被鐢ㄤ簬瀛樺偍鏁版嵁
+     */
     private IStreamPushService pushService;
 
-    // 榛樿娴佸獟浣撹妭鐐笽D
+    /**
+     * 榛樿娴佸獟浣撹妭鐐笽D
+     */
     private String defaultMediaServerId;
 
-    // 鐢ㄤ簬瀛樺偍涓嶅姞杩囨护鐨勬墍鏈夋暟鎹�
+    /**
+     * 鐢ㄤ簬瀛樺偍涓嶅姞杩囨护鐨勬墍鏈夋暟鎹�
+     */
     private List<StreamPushItem> streamPushItems = new ArrayList<>();
 
-    // 鐢ㄤ簬瀛樺偍鏇村叿APP+Stream杩囨护鍚庣殑鏁版嵁锛屽彲浠ョ洿鎺ュ瓨鍏tream_push琛ㄤ笌gb_stream琛�
+    /**
+     * 鐢ㄤ簬瀛樺偍鏇村叿APP+Stream杩囨护鍚庣殑鏁版嵁锛屽彲浠ョ洿鎺ュ瓨鍏tream_push琛ㄤ笌gb_stream琛�
+     */
     private Map<String,StreamPushItem> streamPushItemForSave = new HashMap<>();
 
-    // 鐢ㄤ簬瀛樺偍鎸夌収APP+Stream涓篕EY锛� 骞冲彴ID+鐩綍Id 涓簐alue鐨勬暟鎹紝鐢ㄤ簬瀛樺偍鍒癵b_stream琛ㄥ悗鑾峰彇app+Stream瀵瑰簲鐨勫钩鍙颁笌鐩綍淇℃伅锛岀劧鍚庡瓨鍏ュ叧鑱旇〃
+    /**
+     * 鐢ㄤ簬瀛樺偍鎸夌収APP+Stream涓篕EY锛� 骞冲彴ID+鐩綍Id 涓簐alue鐨勬暟鎹紝鐢ㄤ簬瀛樺偍鍒癵b_stream琛ㄥ悗鑾峰彇app+Stream瀵瑰簲鐨勫钩鍙颁笌鐩綍淇℃伅锛岀劧鍚庡瓨鍏ュ叧鑱旇〃
+     */
     private Map<String, List<String[]>> streamPushItemsForPlatform = new HashMap<>();
 
-    // 鐢ㄤ簬鍒ゆ柇鏂囦欢鏄惁瀛樺湪閲嶅鐨刟pp+Stream+骞冲彴ID
+    /**
+     * 鐢ㄤ簬鍒ゆ柇鏂囦欢鏄惁瀛樺湪閲嶅鐨刟pp+Stream+骞冲彴ID
+     */
     private Set<String> streamPushStreamSet = new HashSet<>();
 
-    // 鐢ㄤ簬瀛樺偍APP+Stream->鍥芥爣ID 鐨勬暟鎹粨鏋�, 鏁版嵁涓�涓�瀵瑰簲锛屽叏灞�鍒ゆ柇APP+Stream->鍥芥爣ID鏄惁瀛樺湪涓嶅搴�
+    /**
+     * 鐢ㄤ簬瀛樺偍APP+Stream->鍥芥爣ID 鐨勬暟鎹粨鏋�, 鏁版嵁涓�涓�瀵瑰簲锛屽叏灞�鍒ゆ柇APP+Stream->鍥芥爣ID鏄惁瀛樺湪涓嶅搴�
+     */
     private BiMap<String,String> gBMap = HashBiMap.create();
 
-    // 璁板綍閿欒鐨凙PP+Stream
+    /**
+     * 璁板綍閿欒鐨凙PP+Stream
+     */
     private List<String> errorStreamList = new ArrayList<>();
 
 
-    // 璁板綍閿欒鐨勫浗鏍嘔D
+    /**
+     * 璁板綍閿欒鐨勫浗鏍嘔D
+     */
     private List<String> errorGBList = new ArrayList<>();
 
-    // 璇诲彇鏁伴噺璁℃暟鍣�
+    /**
+     * 璇诲彇鏁伴噺璁℃暟鍣�
+     */
     private int loadedSize = 0;
 
     public StreamPushUploadFileHandler(IStreamPushService pushService, String defaultMediaServerId, ErrorDataHandler errorDataHandler) {
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
index 01d91a5..f5dc7b0 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
@@ -3,6 +3,8 @@
 import com.genersoft.iot.vmp.service.IUserService;
 import com.genersoft.iot.vmp.storager.dao.UserMapper;
 import com.genersoft.iot.vmp.storager.dao.dto.User;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
@@ -11,7 +13,7 @@
 
 @Service
 public class UserServiceImpl implements IUserService {
-    
+
     @Autowired
     private UserMapper userMapper;
 
@@ -64,4 +66,16 @@
             return userMapper.checkPushAuthorityByCallIdAndSign(callId, sign).size() > 0;
         }
     }
+
+    @Override
+    public PageInfo<User> getUsers(int page, int count) {
+        PageHelper.startPage(page, count);
+        List<User> users = userMapper.getUsers();
+        return new PageInfo<>(users);
+    }
+
+    @Override
+    public int changePushKey(int id, String pushKey) {
+        return userMapper.changePushKey(id,pushKey);
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
index 79e6b26..b9811da 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -233,4 +233,9 @@
      * @return
      */
     StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream);
+
+    /**
+     * 鍙戦�乺edis娑堟伅 鏌ヨ鎵�鏈夋帹娴佽澶囩殑鐘舵��
+     */
+    void sendStreamPushRequestedMsgForStatus();
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
index 96d4d95..b2c1e1b 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
@@ -27,22 +27,6 @@
 	public boolean exists(String deviceId);
 
 	/**
-	 * 娣诲姞璁惧閫氶亾
-	 *
-	 * @param deviceId 璁惧id
-	 * @param channel 閫氶亾
-	 */
-	public void updateChannel(String deviceId, DeviceChannel channel);
-
-	/**
-	 * 鎵归噺娣诲姞璁惧閫氶亾
-	 *
-	 * @param deviceId 璁惧id
-	 * @param channels 澶氫釜閫氶亾
-	 */
-	public int updateChannels(String deviceId, List<DeviceChannel> channels);
-
-	/**
 	 * 寮�濮嬫挱鏀�
 	 * @param deviceId 璁惧id
 	 * @param channelId 閫氶亾ID
@@ -224,13 +208,6 @@
 	List<DeviceChannelInPlatform> queryChannelListInParentPlatform(String platformId);
 
 
-	/**
-	 * 鏇存柊涓婄骇骞冲彴鐨勯�氶亾淇℃伅
-	 * @param platformId
-	 * @param channelReduces
-	 * @return
-	 */
-	int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
 
 	/**
 	 *  绉婚櫎涓婄骇骞冲彴鐨勯�氶亾淇℃伅
@@ -277,20 +254,6 @@
 	public int clearMobilePositionsByDeviceId(String deviceId);
 
 	/**
-	 * 鏂板浠g悊娴�
-	 * @param streamProxyDto
-	 * @return
-	 */
-	public boolean addStreamProxy(StreamProxyItem streamProxyDto);
-
-	/**
-	 * 鏇存柊浠g悊娴�
-	 * @param streamProxyDto
-	 * @return
-	 */
-	public boolean updateStreamProxy(StreamProxyItem streamProxyDto);
-
-	/**
 	 * 绉婚櫎浠g悊娴�
 	 * @param app
 	 * @param stream
@@ -334,19 +297,7 @@
 	 * @param platformId
 	 * @return
 	 */
-	List<GbStream> queryGbStreamListInPlatform(String platformId);
-
-	/**
-	 * 鎵归噺鏇存柊鎺ㄦ祦鍒楄〃
-	 * @param streamPushItems
-	 */
-	void updateMediaList(List<StreamPushItem> streamPushItems);
-
-	/**
-	 * 鏇存柊鍗曚釜鎺ㄦ祦
-	 * @param streamPushItem
-	 */
-	void updateMedia(StreamPushItem streamPushItem);
+	List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
 
 	/**
 	 * 绉婚櫎鍗曚釜鎺ㄦ祦
@@ -354,21 +305,6 @@
 	 * @param stream
 	 */
 	int removeMedia(String app, String stream);
-
-
-	/**
-	 * 鑾峰彇浣嗕釜鎺ㄦ祦
-	 * @param app
-	 * @param stream
-	 * @return
-	 */
-	StreamPushItem getMedia(String app, String stream);
-
-
-	/**
-	 * 娓呯┖鎺ㄦ祦鍒楄〃
-	 */
-	void clearMediaList();
 
 	/**
 	 * 璁剧疆娴佺绾�
@@ -445,7 +381,7 @@
 
 	int setDefaultCatalog(String platformId, String catalogId);
 
-	List<PlatformCatalog> queryCatalogInPlatform(String serverGBId);
+	List<DeviceChannel> queryCatalogInPlatform(String serverGBId);
 
     int delRelation(PlatformCatalog platformCatalog);
 
@@ -466,4 +402,8 @@
 	List<ChannelSourceInfo> getChannelSource(String platformId, String gbId);
 
     void updateChannelPosition(DeviceChannel deviceChannel);
+
+	void cleanContentForPlatform(String serverGBId);
+
+	List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
index ffa5cf1..bcebb94 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -140,6 +140,9 @@
     @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})
     void offline(String deviceId,  String channelId);
 
+    @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"})
+    void offlineByDeviceId(String deviceId);
+
     @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})
     void online(String deviceId,  String channelId);
 
@@ -329,5 +332,13 @@
     @Select("select * from device_channel where deviceId=#{deviceId} and SUBSTRING(channelId, 11, 3)=#{typeCode}")
     List<DeviceChannel> getBusinessGroups(String deviceId, String typeCode);
 
-
+    @Select("select dc.id, dc.channelId, dc.deviceId, dc.name, dc.manufacture,dc.model,dc.owner, pc.civilCode,dc.block, " +
+            " dc.address, '0' as parental,'0' as channelType, pc.id as parentId, dc.safetyWay, dc.registerWay,dc.certNum, dc.certifiable,  " +
+            " dc.errCode,dc.endTime, dc.secrecy,   dc.ipAddress,  dc.port,  dc.PTZType,  dc.password, dc.status, " +
+            " dc.longitudeWgs84 as longitude, dc.latitudeWgs84 as latitude,  pc.businessGroupId " +
+            " from device_channel dc" +
+            " left join platform_gb_channel pgc on  dc.id = pgc.deviceChannelId" +
+            " left join platform_catalog pc on pgc.catalogId = pc.id and pgc.platformId = pc.platformId" +
+            " where pgc.platformId=#{serverGBId}")
+    List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
index e8d23a8..7ed6b5a 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.storager.dao;
 
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
@@ -15,10 +16,10 @@
 public interface GbStreamMapper {
 
     @Insert("REPLACE INTO gb_stream (app, stream, gbId, name, " +
-            "longitude, latitude, streamType, mediaServerId, status, createTime) VALUES" +
+            "longitude, latitude, streamType, mediaServerId, createTime) VALUES" +
             "('${app}', '${stream}', '${gbId}', '${name}', " +
             "'${longitude}', '${latitude}', '${streamType}', " +
-            "'${mediaServerId}', ${status}, '${createTime}')")
+            "'${mediaServerId}', '${createTime}')")
     @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
     int add(GbStream gbStream);
 
@@ -30,8 +31,7 @@
             "streamType=#{streamType}," +
             "longitude=#{longitude}, " +
             "latitude=#{latitude}," +
-            "mediaServerId=#{mediaServerId}," +
-            "status=${status} " +
+            "mediaServerId=#{mediaServerId}" +
             "WHERE app=#{app} AND stream=#{stream}")
     int updateByAppAndStream(GbStream gbStream);
 
@@ -43,8 +43,7 @@
             "streamType=#{streamType}," +
             "longitude=#{longitude}, " +
             "latitude=#{latitude}," +
-            "mediaServerId=#{mediaServerId}," +
-            "status=${status} " +
+            "mediaServerId=#{mediaServerId}" +
             "WHERE gbStreamId=#{gbStreamId}")
     int update(GbStream gbStream);
 
@@ -60,12 +59,10 @@
             " <if test='catalogId == null'> AND gs.gbStreamId not in" +
             "(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId}) </if> " +
             " <if test='query != null'> AND (gs.app LIKE '%${query}%' OR gs.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " +
-            " <if test='pushing == true' > AND gs.status=1</if>" +
-            " <if test='pushing == false' > AND gs.status=0</if>" +
             " <if test='mediaServerId != null' > AND gs.mediaServerId=#{mediaServerId} </if>" +
             " order by gs.gbStreamId asc " +
             "</script>")
-    List<GbStream> selectAll(String platformId, String catalogId, String query, Boolean pushing, String mediaServerId);
+    List<GbStream> selectAll(String platformId, String catalogId, String query, String mediaServerId);
 
     @Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
     GbStream selectOne(String app, String stream);
@@ -78,10 +75,18 @@
             "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'")
     GbStream queryStreamInPlatform(String platformId, String gbId);
 
-    @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " +
-            "LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.gbStreamId " +
-            "WHERE pgs.platformId = #{platformId}")
-    List<GbStream> queryGbStreamListInPlatform(String platformId);
+    @Select("select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture,  st.status, gt.longitude, gt.latitude, pc.id as parentId," +
+            "       '1' as registerWay, pc.civilCode, 'live' as model, 'wvp-pro' as owner, '0' as parental,'0' as secrecy" +
+            " from gb_stream gt " +
+            " left join (" +
+            "    select sp.status, sp.app, sp.stream from stream_push sp" +
+            "    union all" +
+            "    select spxy.status, spxy.app, spxy.stream from stream_proxy spxy" +
+            " ) st on st.app = gt.app and st.stream = gt.stream" +
+            " left join platform_gb_stream pgs on  gt.gbStreamId = pgs.gbStreamId" +
+            " left join platform_catalog pc on pgs.catalogId = pc.id and pgs.platformId = pc.platformId" +
+            " where pgs.platformId=#{platformId}")
+    List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
 
 
     @Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " +
@@ -110,12 +115,12 @@
     @Insert("<script> " +
             "INSERT IGNORE into gb_stream " +
             "(app, stream, gbId, name, " +
-            "longitude, latitude, streamType, mediaServerId, status, createTime)" +
+            "longitude, latitude, streamType, mediaServerId, createTime)" +
             "values " +
             "<foreach collection='subList' index='index' item='item' separator=','> " +
             "('${item.app}', '${item.stream}', '${item.gbId}', '${item.name}', " +
             "'${item.longitude}', '${item.latitude}', '${item.streamType}', " +
-            "'${item.mediaServerId}', ${item.status}, '${item.createTime}') "+
+            "'${item.mediaServerId}', '${item.createTime}') "+
             "</foreach> " +
             "</script>")
     @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
@@ -138,4 +143,9 @@
                    "</foreach>" +
                    "</script>")
     List<GbStream> selectAllForAppAndStream(List<StreamPushItem> streamPushItems);
+
+    @Update("UPDATE gb_stream " +
+            "SET mediaServerId=#{mediaServerId}" +
+            "WHERE app=#{app} AND stream=#{stream}")
+    void updateMediaServer(String app, String stream, String mediaServerId);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
index b57e103..554354a 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
@@ -16,10 +16,10 @@
 
     @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp,  " +
             "            devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
-            "            status, shareAllLiveStream, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime) " +
+            "            status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " +
             "            VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " +
             "            '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " +
-            "            ${status}, ${shareAllLiveStream},  ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})")
+            "            ${status},  ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
     int addParentPlatform(ParentPlatform parentPlatform);
 
     @Update("UPDATE parent_platform " +
@@ -41,12 +41,12 @@
             "ptz=#{ptz}, " +
             "rtcp=#{rtcp}, " +
             "status=#{status}, " +
-            "shareAllLiveStream=#{shareAllLiveStream}, " +
             "startOfflinePush=${startOfflinePush}, " +
             "catalogGroup=#{catalogGroup}, " +
             "administrativeDivision=#{administrativeDivision}, " +
             "createTime=#{createTime}, " +
             "updateTime=#{updateTime}, " +
+            "treeType=#{treeType}, " +
             "catalogId=#{catalogId} " +
             "WHERE id=#{id}")
     int updateParentPlatform(ParentPlatform parentPlatform);
@@ -82,9 +82,6 @@
 
     @Update("UPDATE parent_platform SET status=#{online} WHERE serverGBId=#{platformGbID}" )
     int updateParentPlatformStatus(String platformGbID, boolean online);
-
-    @Select("SELECT * FROM parent_platform WHERE shareAllLiveStream=true")
-    List<ParentPlatform> selectAllAhareAllLiveStream();
 
     @Update(value = {" <script>" +
             "UPDATE parent_platform " +
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java
index 95015bd..f0baf9e 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java
@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.storager.dao;
 
+import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
 import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
@@ -14,8 +15,8 @@
 @Repository
 public interface PlatformCatalogMapper {
 
-    @Insert("INSERT INTO platform_catalog (id, name, platformId, parentId) VALUES" +
-            "(#{id}, #{name}, #{platformId}, #{parentId})")
+    @Insert("INSERT INTO platform_catalog (id, name, platformId, parentId, civilCode, businessGroupId) VALUES" +
+            "(#{id}, #{name}, #{platformId}, #{parentId}, #{civilCode}, #{businessGroupId})")
     int add(PlatformCatalog platformCatalog);
 
     @Delete("DELETE FROM platform_catalog WHERE id=#{id}")
@@ -44,4 +45,12 @@
 
     @Select("SELECT pc.* FROM  platform_catalog pc WHERE  pc.id = (SELECT pp.catalogId from parent_platform pp WHERE pp.serverGBId=#{platformId})")
     PlatformCatalog selectDefaultByPlatFormId(String platformId);
+
+
+    @Select("SELECT pc.* FROM  platform_catalog pc WHERE pc.id = #{id}")
+    PlatformCatalog selectParentCatalog(String id);
+
+    @Select("SELECT pc.id as channelId, pc.name, pc.civilCode, pc.businessGroupId,'1' as parental, pc.parentId  " +
+            " FROM platform_catalog pc WHERE pc.platformId=#{platformId}")
+    List<DeviceChannel> queryCatalogInPlatform(String platformId);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
index 6c1e72d..b4ee81e 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
@@ -2,6 +2,7 @@
 
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
+import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
 import org.apache.ibatis.annotations.*;
 // import org.omg.PortableInterceptor.INACTIVE;
 import org.springframework.stereotype.Repository;
@@ -14,9 +15,10 @@
 public interface StreamPushMapper {
 
     @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
-            "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime) VALUES" +
+            "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng, self) VALUES" +
             "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " +
-            "'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}' )")
+            "'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}', " +
+            "${pushIng}, ${self} )")
     int add(StreamPushItem streamPushItem);
 
 
@@ -29,6 +31,8 @@
             "<if test=\"originTypeStr != null\">, originTypeStr='${originTypeStr}'</if>" +
             "<if test=\"pushTime != null\">, pushTime='${pushTime}'</if>" +
             "<if test=\"aliveSecond != null\">, aliveSecond='${aliveSecond}'</if>" +
+            "<if test=\"pushIng != null\">, pushIng=${pushIng}</if>" +
+            "<if test=\"self != null\">, self=${self}</if>" +
             "WHERE app=#{app} AND stream=#{stream}"+
             " </script>"})
     int update(StreamPushItem streamPushItem);
@@ -87,10 +91,11 @@
 
     @Insert("<script>"  +
             "Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
-            "createTime, aliveSecond, mediaServerId) " +
+            "createTime, aliveSecond, mediaServerId, status, pushIng) " +
             "VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" +
             "( '${item.app}', '${item.stream}', '${item.totalReaderCount}', #{item.originType}, " +
-            "'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}' )" +
+            "'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}', ${item.status} ," +
+            " ${item.pushIng} )" +
             " </foreach>" +
             "</script>")
     @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@@ -114,7 +119,53 @@
     int updateStatus(String app, String stream, boolean status);
 
     @Update("UPDATE stream_push " +
+            "SET pushIng=${pushIng} " +
+            "WHERE app=#{app} AND stream=#{stream}")
+    int updatePushStatus(String app, String stream, boolean pushIng);
+
+    @Update("UPDATE stream_push " +
             "SET status=#{status} " +
             "WHERE mediaServerId=#{mediaServerId}")
     void updateStatusByMediaServerId(String mediaServerId, boolean status);
+
+
+    @Select("<script> "+
+            "SELECT gs.* FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream " +
+            "where sp.status = 1 and (gs.app, gs.stream) in (" +
+            "<foreach collection='offlineStreams' item='item' separator=','>" +
+            "(#{item.app}, #{item.stream}) " +
+            "</foreach>" +
+            ")</script>")
+    List<GbStream> getOnlinePusherForGbInList(List<StreamPushItemFromRedis> offlineStreams);
+
+    @Update("<script> "+
+            "UPDATE stream_push SET status=0  where (app, stream) in (" +
+            "<foreach collection='offlineStreams' item='item' separator=','>" +
+            "(#{item.app}, #{item.stream}) " +
+            "</foreach>" +
+            ")</script>")
+    void offline(List<StreamPushItemFromRedis> offlineStreams);
+
+    @Select("<script> "+
+            "SELECT * FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream " +
+            "where sp.status = 0 and (gs.app, gs.stream) in (" +
+            "<foreach collection='onlineStreams' item='item' separator=','>" +
+            "(#{item.app}, #{item.stream}) " +
+            "</foreach>" +
+            ") </script>")
+    List<GbStream> getOfflinePusherForGbInList(List<StreamPushItemFromRedis> onlineStreams);
+
+    @Update("<script> "+
+            "UPDATE stream_push SET status=1  where (app, stream) in (" +
+            "<foreach collection='onlineStreams' item='item' separator=','>" +
+            "(#{item.app}, #{item.stream}) " +
+            "</foreach>" +
+            ")</script>")
+    void online(List<StreamPushItemFromRedis> onlineStreams);
+
+    @Select("SELECT gs.* FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream where sp.status = 1")
+    List<GbStream> getOnlinePusherForGb();
+
+    @Update("UPDATE stream_push SET status=0")
+    void setAllStreamOffline();
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java
index 5ed0a57..c7a44fd 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java
@@ -55,4 +55,11 @@
 
     @Select("select * from user where md5(pushKey) = '${sign}'")
     List<User> checkPushAuthorityByCallId(String sign);
+
+    @Select("select u.id, u.username,u.pushKey,u.roleId, r.id as roleID, r.name as roleName, r.authority as roleAuthority , r.createTime as roleCreateTime , r.updateTime as roleUpdateTime FROM user u join user_role r on u.roleId=r.id")
+    @ResultMap(value="roleMap")
+    List<User> getUsers();
+
+    @Update("update user set pushKey=#{pushKey} where id=#{id}")
+    int changePushKey(int id, String pushKey);
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
index d279847..31294a0 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -479,13 +479,18 @@
     @Override
     public void sendStreamChangeMsg(String type, JSONObject jsonObject) {
         String key = VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + type;
-        logger.debug("[redis 娴佸彉鍖栦簨浠禲 {}: {}", key, jsonObject.toString());
+        logger.info("[redis 娴佸彉鍖栦簨浠禲 {}: {}", key, jsonObject.toString());
         redis.convertAndSend(key, jsonObject);
     }
 
     @Override
     public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) {
+        // 鏌ユ壘鏄惁浣跨敤浜哻allID
+        StreamAuthorityInfo streamAuthorityInfo = getStreamAuthorityInfo(app, streamId);
         String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + userSetting.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
+        if (streamAuthorityInfo != null) {
+            mediaItem.setCallId(streamAuthorityInfo.getCallId());
+        }
         redis.set(key, mediaItem);
     }
 
@@ -683,21 +688,21 @@
     @Override
     public void sendMobilePositionMsg(JSONObject jsonObject) {
         String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
-        logger.info("[redis 绉诲姩浣嶇疆璁㈤槄閫氱煡] {}: {}", key, jsonObject.toString());
+        logger.info("[redis鍙戦�侀�氱煡]绉诲姩浣嶇疆 {}: {}", key, jsonObject.toString());
         redis.convertAndSend(key, jsonObject);
     }
 
     @Override
     public void sendStreamPushRequestedMsg(MessageForPushChannel msg) {
         String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
-        logger.info("[redis 鎺ㄦ祦琚姹傞�氱煡] {}: {}/{}", key, msg.getApp(), msg.getStream());
+        logger.info("[redis鍙戦�侀�氱煡]鎺ㄦ祦琚姹� {}: {}/{}", key, msg.getApp(), msg.getStream());
         redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
     }
 
     @Override
     public void sendAlarmMsg(AlarmChannelMessage msg) {
         String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM;
-        logger.info("[redis 鎶ヨ閫氱煡] {}: {}", key, JSON.toJSON(msg));
+        logger.info("[redis鍙戦�侀�氱煡] 鎶ヨ{}: {}", key, JSON.toJSON(msg));
         redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
     }
 
@@ -707,4 +712,12 @@
     }
 
 
+    @Override
+    public void sendStreamPushRequestedMsgForStatus() {
+        String key = VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED;
+        logger.info("[redis閫氱煡]鑾峰彇鎵�鏈夋帹娴佽澶囩殑鐘舵��");
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put(key, key);
+        redis.convertAndSend(key, jsonObject);
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
index c4d1c9e..82f0947 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -48,11 +48,12 @@
 	@Autowired
 	SipConfig sipConfig;
 
-	@Autowired
-	DataSourceTransactionManager dataSourceTransactionManager;
 
 	@Autowired
 	TransactionDefinition transactionDefinition;
+
+	@Autowired
+	DataSourceTransactionManager dataSourceTransactionManager;
 
 	@Autowired
     private DeviceMapper deviceMapper;
@@ -102,96 +103,6 @@
 	@Override
 	public boolean exists(String deviceId) {
 		return deviceMapper.getDeviceByDeviceId(deviceId) != null;
-	}
-
-	@Override
-	public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
-		String channelId = channel.getChannelId();
-		channel.setDeviceId(deviceId);
-		StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
-		if (streamInfo != null) {
-			channel.setStreamId(streamInfo.getStream());
-		}
-		String now = DateUtil.getNow();
-		channel.setUpdateTime(now);
-		DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
-		if (deviceChannel == null) {
-			channel.setCreateTime(now);
-			deviceChannelMapper.add(channel);
-		}else {
-			deviceChannelMapper.update(channel);
-		}
-		deviceChannelMapper.updateChannelSubCount(deviceId,channel.getParentId());
-	}
-
-	@Override
-	public int updateChannels(String deviceId, List<DeviceChannel> channels) {
-		List<DeviceChannel> addChannels = new ArrayList<>();
-		List<DeviceChannel> updateChannels = new ArrayList<>();
-		HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
-		if (channels != null && channels.size() > 0) {
-			List<DeviceChannel> channelList = deviceChannelMapper.queryChannels(deviceId, null, null, null, null);
-			if (channelList.size() == 0) {
-				for (DeviceChannel channel : channels) {
-					channel.setDeviceId(deviceId);
-					StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
-					if (streamInfo != null) {
-						channel.setStreamId(streamInfo.getStream());
-					}
-					String now = DateUtil.getNow();
-					channel.setUpdateTime(now);
-					channel.setCreateTime(now);
-					addChannels.add(channel);
-				}
-			}else {
-				for (DeviceChannel deviceChannel : channelList) {
-					channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
-				}
-				for (DeviceChannel channel : channels) {
-					channel.setDeviceId(deviceId);
-					StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
-					if (streamInfo != null) {
-						channel.setStreamId(streamInfo.getStream());
-					}
-					String now = DateUtil.getNow();
-					channel.setUpdateTime(now);
-					if (channelsInStore.get(channel.getChannelId()) != null) {
-						updateChannels.add(channel);
-					}else {
-						addChannels.add(channel);
-						channel.setCreateTime(now);
-					}
-				}
-			}
-			int limitCount = 300;
-			if (addChannels.size() > 0) {
-				if (addChannels.size() > limitCount) {
-					for (int i = 0; i < addChannels.size(); i += limitCount) {
-						int toIndex = i + limitCount;
-						if (i + limitCount > addChannels.size()) {
-							toIndex = addChannels.size();
-						}
-						deviceChannelMapper.batchAdd(addChannels.subList(i, toIndex));
-					}
-				}else {
-					deviceChannelMapper.batchAdd(addChannels);
-				}
-			}
-			if (updateChannels.size() > 0) {
-				if (updateChannels.size() > limitCount) {
-					for (int i = 0; i < updateChannels.size(); i += limitCount) {
-						int toIndex = i + limitCount;
-						if (i + limitCount > updateChannels.size()) {
-							toIndex = updateChannels.size();
-						}
-						deviceChannelMapper.batchUpdate(updateChannels.subList(i, toIndex));
-					}
-				}else {
-					deviceChannelMapper.batchUpdate(updateChannels);
-				}
-			}
-		}
-		return addChannels.size() + updateChannels.size();
 	}
 
 	@Override
@@ -532,20 +443,6 @@
 		// 鏇存柊缂撳瓨
 		parentPlatformCatch.setParentPlatform(parentPlatform);
 		redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
-		if (parentPlatform.isEnable()) {
-			// 鍏变韩鎵�鏈夎棰戞祦锛岄渶瑕佸皢鐜版湁瑙嗛娴佹坊鍔犲埌姝ゅ钩鍙�
-			List<GbStream> gbStreams = gbStreamMapper.queryStreamNotInPlatform();
-			if (gbStreams.size() > 0) {
-				for (GbStream gbStream : gbStreams) {
-					gbStream.setCatalogId(parentPlatform.getCatalogId());
-				}
-				if (parentPlatform.isShareAllLiveStream()) {
-					gbStreamService.addPlatformInfo(gbStreams, parentPlatform.getServerGBId(), parentPlatform.getCatalogId());
-				}else {
-					gbStreamService.delPlatformInfo(parentPlatform.getServerGBId(), gbStreams);
-				}
-			}
-		}
 
 		return result > 0;
 	}
@@ -594,36 +491,6 @@
 	public List<DeviceChannelInPlatform> queryChannelListInParentPlatform(String platformId) {
 
 		return deviceChannelMapper.queryChannelByPlatformId(platformId);
-	}
-
-	@Override
-	public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
-
-		Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
-		for (ChannelReduce channelReduce : channelReduces) {
-			channelReduce.setCatalogId(catalogId);
-			deviceAndChannels.put(channelReduce.getId(), channelReduce);
-		}
-		List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
-		// 鏌ヨ褰撳墠宸茬粡瀛樺湪鐨�
-		List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
-		if (deviceAndChannelList != null) {
-			deviceAndChannelList.removeAll(channelIds);
-		}
-		for (Integer channelId : channelIds) {
-			deviceAndChannels.remove(channelId);
-		}
-		List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
-		// 瀵瑰墿涓嬬殑鏁版嵁杩涜瀛樺偍
-		int result = 0;
-		if (channelReducesToAdd.size() > 0) {
-			result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
-			// TODO 鍚庣画缁欏钩鍙板鍔犳帶鍒跺紑鍏充互鎺у埗鏄惁鍝嶅簲鐩綍璁㈤槄
-			List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId);
-			eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
-		}
-
-		return result;
 	}
 
 
@@ -701,77 +568,6 @@
 		return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
 	}
 
-	/**
-	 * 鏂板浠g悊娴�
-	 * @param streamProxyItem
-	 * @return
-	 */
-	@Override
-	public boolean addStreamProxy(StreamProxyItem streamProxyItem) {
-		TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
-		boolean result = false;
-		streamProxyItem.setStreamType("proxy");
-		streamProxyItem.setStatus(true);
-		String now = DateUtil.getNow();
-		streamProxyItem.setCreateTime(now);
-		try {
-			if (streamProxyMapper.add(streamProxyItem) > 0) {
-				if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
-					if (gbStreamMapper.add(streamProxyItem) < 0) {
-						//浜嬪姟鍥炴粴
-						dataSourceTransactionManager.rollback(transactionStatus);
-						return false;
-					}
-				}
-			}else {
-				//浜嬪姟鍥炴粴
-				dataSourceTransactionManager.rollback(transactionStatus);
-				return false;
-			}
-			result = true;
-			dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
-		}catch (Exception e) {
-			logger.error("鍚戞暟鎹簱娣诲姞娴佷唬鐞嗗け璐ワ細", e);
-			dataSourceTransactionManager.rollback(transactionStatus);
-		}
-
-
-		return result;
-	}
-
-	/**
-	 * 鏇存柊浠g悊娴�
-	 * @param streamProxyItem
-	 * @return
-	 */
-	@Override
-	public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
-		TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
-		boolean result = false;
-		streamProxyItem.setStreamType("proxy");
-		try {
-			if (streamProxyMapper.update(streamProxyItem) > 0) {
-				if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
-					if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
-						//浜嬪姟鍥炴粴
-						dataSourceTransactionManager.rollback(transactionStatus);
-						return false;
-					}
-				}
-			} else {
-				//浜嬪姟鍥炴粴
-				dataSourceTransactionManager.rollback(transactionStatus);
-				return false;
-			}
-
-			dataSourceTransactionManager.commit(transactionStatus);     //鎵嬪姩鎻愪氦
-			result = true;
-		}catch (Exception e) {
-			e.printStackTrace();
-			dataSourceTransactionManager.rollback(transactionStatus);
-		}
-		return result;
-	}
 
 	/**
 	 * 绉婚櫎浠g悊娴�
@@ -824,7 +620,7 @@
 	 * @return
 	 */
 	@Override
-	public List<GbStream> queryGbStreamListInPlatform(String platformId) {
+	public List<DeviceChannel> queryGbStreamListInPlatform(String platformId) {
 		return gbStreamMapper.queryGbStreamListInPlatform(platformId);
 	}
 
@@ -840,62 +636,8 @@
 	}
 
 	@Override
-	public void updateMediaList(List<StreamPushItem> streamPushItems) {
-		if (streamPushItems == null || streamPushItems.size() == 0) {
-			return;
-		}
-		logger.info("updateMediaList:  " + streamPushItems.size());
-		streamPushMapper.addAll(streamPushItems);
-		// TODO 寰呬紭鍖�
-		for (int i = 0; i < streamPushItems.size(); i++) {
-			int onlineResult = mediaOnline(streamPushItems.get(i).getApp(), streamPushItems.get(i).getStream());
-			if (onlineResult > 0) {
-				// 鍙戦�佷笂绾块�氱煡
-				eventPublisher.catalogEventPublishForStream(null, streamPushItems.get(i), CatalogEvent.ON);
-			}
-		}
-	}
-
-
-
-	@Override
-	public void updateMedia(StreamPushItem streamPushItem) {
-		streamPushMapper.del(streamPushItem.getApp(), streamPushItem.getStream());
-		streamPushMapper.add(streamPushItem);
-		mediaOffline(streamPushItem.getApp(), streamPushItem.getStream());
-
-		if(!StringUtils.isEmpty(streamPushItem.getGbId() )){
-			// 鏌ユ壘寮�鍚簡鍏ㄩ儴鐩存挱娴佸叡浜殑涓婄骇骞冲彴
-			List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
-			if (parentPlatforms.size() > 0) {
-				for (ParentPlatform parentPlatform : parentPlatforms) {
-					StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(streamPushItem.getApp(), streamPushItem.getStream(),
-							parentPlatform.getServerGBId());
-					if (streamProxyItem == null) {
-						streamPushItem.setCatalogId(parentPlatform.getCatalogId());
-						streamPushItem.setPlatformId(parentPlatform.getServerGBId());
-						platformGbStreamMapper.add(streamPushItem);
-						eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), streamPushItem, CatalogEvent.ADD);
-					}
-				}
-			}
-		}
-
-	}
-
-	@Override
 	public int removeMedia(String app, String stream) {
 		return streamPushMapper.del(app, stream);
-	}
-
-	@Override
-	public StreamPushItem getMedia(String app, String stream) {
-		return streamPushMapper.selectOne(app, stream);
-	}
-
-	@Override
-	public void clearMediaList() {
-		streamPushMapper.clear();
 	}
 
 	@Override
@@ -905,18 +647,19 @@
 		if ("proxy".equals(gbStream.getStreamType())) {
 			result = streamProxyMapper.updateStatus(app, stream, false);
 		}else {
-			result = streamPushMapper.updateStatus(app, stream, false);
+			result = streamPushMapper.updatePushStatus(app, stream, false);
 		}
 		return result;
 	}
 
+	@Override
 	public int mediaOnline(String app, String stream) {
 		GbStream gbStream = gbStreamMapper.selectOne(app, stream);
 		int result;
 		if ("proxy".equals(gbStream.getStreamType())) {
 			result = streamProxyMapper.updateStatus(app, stream, true);
 		}else {
-			result = streamPushMapper.updateStatus(app, stream, true);
+			result = streamPushMapper.updatePushStatus(app, stream, true);
 		}
 		return result;
 	}
@@ -954,12 +697,44 @@
 
 	@Override
 	public int addCatalog(PlatformCatalog platformCatalog) {
+		ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformCatalog.getPlatformId());
+		if (platform == null) {
+			return 0;
+		}
+		if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
+			if (platformCatalog.getPlatformId().equals(platformCatalog.getParentId())) {
+				// 绗竴灞傝妭鐐�
+				platformCatalog.setBusinessGroupId(platformCatalog.getId());
+				platformCatalog.setParentId(platform.getDeviceGBId());
+			}else {
+				// 鑾峰彇椤跺眰鐨�
+				PlatformCatalog topCatalog = getTopCatalog(platformCatalog.getParentId(), platform.getDeviceGBId());
+				platformCatalog.setBusinessGroupId(topCatalog.getId());
+			}
+		}
+		if (platform.getTreeType().equals(TreeType.CIVIL_CODE)) {
+			platformCatalog.setCivilCode(platformCatalog.getId());
+			if (platformCatalog.getPlatformId().equals(platformCatalog.getParentId())) {
+				// 绗竴灞傝妭鐐�
+				platformCatalog.setParentId(platform.getDeviceGBId());
+			}
+		}
+
 		int result = catalogMapper.add(platformCatalog);
 		if (result > 0) {
 			DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog);
 			eventPublisher.catalogEventPublish(platformCatalog.getPlatformId(), deviceChannel, CatalogEvent.ADD);
 		}
 		return result;
+	}
+
+	private PlatformCatalog getTopCatalog(String id, String platformId) {
+		PlatformCatalog catalog = catalogMapper.selectParentCatalog(id);
+		if (catalog.getParentId().equals(platformId)) {
+			return catalog;
+		}else {
+			return getTopCatalog(catalog.getParentId(), platformId);
+		}
 	}
 
 	@Override
@@ -1032,8 +807,8 @@
 	}
 
 	@Override
-	public List<PlatformCatalog> queryCatalogInPlatform(String platformId) {
-		return catalogMapper.selectByPlatForm(platformId);
+	public List<DeviceChannel> queryCatalogInPlatform(String platformId) {
+		return catalogMapper.queryCatalogInPlatform(platformId);
 	}
 
 	@Override
@@ -1076,20 +851,24 @@
 	}
 
 	private DeviceChannel getDeviceChannelByCatalog(PlatformCatalog catalog) {
-		ParentPlatform parentPlatByServerGBId = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());
+		ParentPlatform platform = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());
 		DeviceChannel deviceChannel = new DeviceChannel();
 		deviceChannel.setChannelId(catalog.getId());
 		deviceChannel.setName(catalog.getName());
 		deviceChannel.setLongitude(0.0);
 		deviceChannel.setLatitude(0.0);
-		deviceChannel.setDeviceId(parentPlatByServerGBId.getDeviceGBId());
+		deviceChannel.setDeviceId(platform.getDeviceGBId());
 		deviceChannel.setManufacture("wvp-pro");
 		deviceChannel.setStatus(1);
 		deviceChannel.setParental(1);
-		deviceChannel.setParentId(catalog.getParentId());
+
 		deviceChannel.setRegisterWay(1);
 		// 琛屾斂鍖哄垝搴旇鏄疍omain鐨勫墠鍏綅
-		deviceChannel.setCivilCode(parentPlatByServerGBId.getAdministrativeDivision());
+		if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
+			deviceChannel.setParentId(catalog.getParentId());
+			deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
+		}
+
 		deviceChannel.setModel("live");
 		deviceChannel.setOwner("wvp-pro");
 		deviceChannel.setSecrecy("0");
@@ -1151,4 +930,27 @@
 
 		deviceChannelMapper.updatePosition(deviceChannel);
 	}
+
+	@Override
+	public void cleanContentForPlatform(String serverGBId) {
+//		List<PlatformCatalog> catalogList = catalogMapper.selectByPlatForm(serverGBId);
+//		if (catalogList.size() > 0) {
+//			int result = catalogMapper.delByPlatformId(serverGBId);
+//			if (result > 0) {
+//				List<DeviceChannel> deviceChannels = new ArrayList<>();
+//				for (PlatformCatalog catalog : catalogList) {
+//					deviceChannels.add(getDeviceChannelByCatalog(catalog));
+//				}
+//				eventPublisher.catalogEventPublish(serverGBId, deviceChannels, CatalogEvent.DEL);
+//			}
+//		}
+		catalogMapper.delByPlatformId(serverGBId);
+		platformChannelMapper.delByPlatformId(serverGBId);
+		platformGbStreamMapper.delByPlatformId(serverGBId);
+	}
+
+	@Override
+	public List<DeviceChannel> queryChannelWithCatalog(String serverGBId) {
+		return deviceChannelMapper.queryChannelWithCatalog(serverGBId);
+	}
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
index 91ed22c..db937d6 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
@@ -12,6 +12,7 @@
         this.data = data;
     }
 
+
     private int code;
     private String msg;
     private T data;
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
index 767e9c4..29f9d88 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -12,6 +12,7 @@
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
+import com.genersoft.iot.vmp.service.IDeviceChannelService;
 import com.genersoft.iot.vmp.service.IDeviceService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@@ -51,6 +52,9 @@
 	
 	@Autowired
 	private IVideoManagerStorage storager;
+
+	@Autowired
+	private IDeviceChannelService deviceChannelService;
 
 	@Autowired
 	private IRedisCatchStorage redisCatchStorage;
@@ -280,7 +284,7 @@
 	})
 	@PostMapping("/channel/update/{deviceId}")
 	public ResponseEntity<PageInfo> updateChannel(@PathVariable String deviceId,DeviceChannel channel){
-		storager.updateChannel(deviceId, channel);
+		deviceChannelService.updateChannel(deviceId, channel);
 		return new ResponseEntity<>(null,HttpStatus.OK);
 	}
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
index 300546f..fba050b 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
@@ -44,7 +44,6 @@
             @ApiImplicitParam(name = "platformId", value = "骞冲彴ID", required = true , dataTypeClass = String.class),
             @ApiImplicitParam(name = "catalogId", value = "鐩綍ID", required = false , dataTypeClass = String.class),
             @ApiImplicitParam(name="query", value = "鏌ヨ鍐呭", required = false , dataTypeClass = String.class),
-            @ApiImplicitParam(name="pushing", value = "鏄惁姝e湪鎺ㄦ祦", required = false , dataTypeClass = Boolean.class),
             @ApiImplicitParam(name="mediaServerId", value = "娴佸獟浣揑D", required = false , dataTypeClass = String.class),
 
     })
@@ -55,7 +54,6 @@
                                    @RequestParam(required = true)String platformId,
                                    @RequestParam(required = false)String catalogId,
                                    @RequestParam(required = false)String query,
-                                   @RequestParam(required = false)Boolean pushing,
                                    @RequestParam(required = false)String mediaServerId){
         if (StringUtils.isEmpty(catalogId)) {
             catalogId = null;
@@ -69,7 +67,7 @@
 
         // catalogId 涓簄ull 鏌ヨ鏈湪骞冲彴涓嬪垎閰嶇殑鏁版嵁
         // catalogId 涓嶄负null 鏌ヨ骞冲彴涓嬭繖涓紝鐩綍涓嬬殑閫氶亾
-        return gbStreamService.getAll(page, count, platformId, catalogId, query, pushing, mediaServerId);
+        return gbStreamService.getAll(page, count, platformId, catalogId, query, mediaServerId);
     }
 
 
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
index 94fe8df..48973f9 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
@@ -6,6 +6,7 @@
 import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
 import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.IStreamProxyService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -37,6 +38,8 @@
 
     @Autowired
     private IMediaService mediaService;
+    @Autowired
+    private IStreamProxyService streamProxyService;
 
 
     /**
@@ -95,8 +98,30 @@
             result.setMsg("scccess");
             result.setData(streamInfo);
         }else {
-            result.setCode(-1);
-            result.setMsg("fail");
+            //鑾峰彇娴佸け璐ワ紝閲嶅惎鎷夋祦鍚庨噸璇曚竴娆�
+            streamProxyService.stop(app,stream);
+            boolean start = streamProxyService.start(app, stream);
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
+                String host = request.getHeader("Host");
+                String localAddr = host.split(":")[0];
+                logger.info("浣跨敤{}浣滀负杩斿洖娴佺殑ip", localAddr);
+                streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority);
+            }else {
+                streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
+            }
+            if (streamInfo != null){
+                result.setCode(0);
+                result.setMsg("scccess");
+                result.setData(streamInfo);
+            }else {
+                result.setCode(-1);
+                result.setMsg("fail");
+            }
         }
         return result;
     }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
index 44de6c9..7a22693 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
@@ -8,7 +8,9 @@
 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
+import com.genersoft.iot.vmp.gb28181.bean.TreeType;
 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
+import com.genersoft.iot.vmp.service.IPlatformChannelService;
 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -47,6 +49,9 @@
 
     @Autowired
     private IVideoManagerStorage storager;
+
+    @Autowired
+    private IPlatformChannelService platformChannelService;
 
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
@@ -236,6 +241,12 @@
         parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase());
         ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
         parentPlatform.setUpdateTime(DateUtil.getNow());
+        if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) {
+             // 鐩綍缁撴瀯鍙戠敓鍙樺寲锛屾竻绌轰箣鍓嶇殑鍏宠仈鍏崇郴
+             logger.info("淇濆瓨骞冲彴{}鏃跺彂鐜扮洰褰曠粨鏋勫彉鍖栵紝娓呯┖鍏宠仈鍏崇郴", parentPlatform.getDeviceGBId());
+             storager.cleanContentForPlatform(parentPlatform.getServerGBId());
+
+        }
         boolean updateResult = storager.updateParentPlatform(parentPlatform);
 
         if (updateResult) {
@@ -256,6 +267,8 @@
                 }
             } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 鍏抽棴鍚敤鏃舵敞閿�
                 commanderForPlatform.unregister(parentPlatformOld, null, null);
+                // 鍋滄璁㈤槄鐩稿叧鐨勫畾鏃朵换鍔�
+                subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
             }
             wvpResult.setCode(0);
             wvpResult.setMsg("success");
@@ -405,7 +418,7 @@
         if (logger.isDebugEnabled()) {
             logger.debug("缁欎笂绾у钩鍙版坊鍔犲浗鏍囬�氶亾API璋冪敤");
         }
-        int result = storager.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
+        int result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
 
         return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
     }
@@ -451,13 +464,20 @@
         if (logger.isDebugEnabled()) {
             logger.debug("鏌ヨ鐩綍,platformId: {}, parentId: {}", platformId, parentId);
         }
+        ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
+        if (platform == null) {
+            return new ResponseEntity<>(new WVPResult<>(400, "骞冲彴鏈壘鍒�", null), HttpStatus.OK);
+        }
+        if (platformId.equals(parentId)) {
+            parentId = platform.getDeviceGBId();
+        }
         List<PlatformCatalog> platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
-        // 鏌ヨ涓嬪睘鐨勫浗鏍囬�氶亾
-//        List<PlatformCatalog> catalogsForChannel = storager.queryChannelInParentPlatformAndCatalog(platformId, parentId);
-        // 鏌ヨ涓嬪睘鐨勭洿鎾祦閫氶亾
-//        List<PlatformCatalog> catalogsForStream = storager.queryStreamInParentPlatformAndCatalog(platformId, parentId);
-//        platformCatalogList.addAll(catalogsForChannel);
-//        platformCatalogList.addAll(catalogsForStream);
+//        if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
+//            platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
+//        }else {
+//
+//        }
+
         WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
         result.setCode(0);
         result.setMsg("success");
@@ -484,7 +504,6 @@
         }
         PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
         WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
-
 
         if (platformCatalogInStore != null) {
             result.setCode(-1);
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
index faed2c8..2311d4b 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -8,6 +8,8 @@
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.conf.VersionInfo;
+import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
+import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
@@ -38,7 +40,7 @@
 public class ServerController {
 
     @Autowired
-    private ConfigurableApplicationContext context;
+    private ZLMHttpHookSubscribe zlmHttpHookSubscribe;
 
     @Autowired
     private IMediaServerService mediaServerService;
@@ -254,6 +256,18 @@
         return result;
     }
 
+    @ApiOperation("鑾峰彇褰撳墠鎵�鏈塰ook")
+    @GetMapping(value = "/hooks")
+    @ResponseBody
+    public WVPResult<List<IHookSubscribe>> getHooks(){
+        WVPResult<List<IHookSubscribe>> result = new WVPResult<>();
+        result.setCode(0);
+        result.setMsg("success");
+        List<IHookSubscribe> all = zlmHttpHookSubscribe.getAll();
+        result.setData(all);
+        return result;
+    }
+
 //    @ApiOperation("褰撳墠杩涜涓殑鍔ㄦ�佷换鍔�")
 //    @GetMapping(value = "/dynamicTask")
 //    @ResponseBody
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
index 300f952..c978ae6 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
@@ -4,6 +4,7 @@
 import com.alibaba.excel.ExcelReader;
 import com.alibaba.excel.read.metadata.ReadSheet;
 import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
@@ -62,6 +63,9 @@
 
     @Autowired
     private IMediaService mediaService;
+
+    @Autowired
+    private UserSetting userSetting;
 
     @ApiOperation("鎺ㄦ祦鍒楄〃鏌ヨ")
     @ApiImplicitParams({
@@ -260,29 +264,63 @@
     })
     @GetMapping(value = "/getPlayUrl")
     @ResponseBody
-    public WVPResult<StreamInfo> getPlayUrl(HttpServletRequest request, @RequestParam String app,
-                                                             @RequestParam String stream,
-                                                             @RequestParam(required = false) String mediaServerId){
+    public WVPResult<StreamInfo> getPlayUrl(@RequestParam String app,@RequestParam String stream,
+                                            @RequestParam(required = false) String mediaServerId){
         boolean authority = false;
         // 鏄惁鐧婚檰鐢ㄦ埛, 鐧婚檰鐢ㄦ埛杩斿洖瀹屾暣淇℃伅
         LoginUser userInfo = SecurityUtils.getUserInfo();
         if (userInfo!= null) {
             authority = true;
         }
-
-        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
-
         WVPResult<StreamInfo> result = new WVPResult<>();
+        StreamPushItem push = streamPushService.getPush(app, stream);
+        if (push != null && !push.isSelf()) {
+            result.setCode(-1);
+            result.setMsg("鏉ヨ嚜鍏朵粬骞冲彴鐨勬帹娴佷俊鎭�");
+            return result;
+        }
+        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
         if (streamInfo != null){
             result.setCode(0);
-            result.setMsg("scccess");
+            result.setMsg("success");
             result.setData(streamInfo);
         }else {
             result.setCode(-1);
-            result.setMsg("fail");
+            result.setMsg("鑾峰彇鎾斁鍦板潃澶辫触");
         }
+
         return result;
     }
 
+    /**
+     * 鑾峰彇鎺ㄦ祦鎾斁鍦板潃
+     * @param stream 鎺ㄦ祦淇℃伅
+     * @return
+     */
+    @ApiOperation("鑾峰彇鎺ㄦ祦鎾斁鍦板潃")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "stream", value = "鎺ㄦ祦淇℃伅", dataTypeClass = StreamPushItem.class),
+    })
+    @PostMapping(value = "/add")
+    @ResponseBody
+    public WVPResult<StreamInfo> add(@RequestBody StreamPushItem stream){
+        if (StringUtils.isEmpty(stream.getGbId())) {
 
+            return new WVPResult<>(400, "鍥芥爣ID涓嶅彲涓虹┖", null);
+        }
+        if (StringUtils.isEmpty(stream.getApp()) && StringUtils.isEmpty(stream.getStream())) {
+            return new WVPResult<>(400, "app鎴杝tream涓嶅彲涓虹┖", null);
+        }
+        stream.setStatus(false);
+        stream.setPushIng(false);
+        stream.setAliveSecond(0L);
+        stream.setTotalReaderCount("0");
+        boolean result = streamPushService.add(stream);
+
+        if (result) {
+            return new WVPResult<>(0, "success", null);
+        }else {
+            return new WVPResult<>(-1, "fail", null);
+        }
+    }
 }
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
index 152122d..442832b 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
@@ -8,6 +8,7 @@
 import com.genersoft.iot.vmp.storager.dao.dto.User;
 import com.genersoft.iot.vmp.utils.DateUtil;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
+import com.github.pagehelper.PageInfo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
@@ -123,7 +124,8 @@
         User user = new User();
         user.setUsername(username);
         user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
-
+        //鏂板鐢ㄦ埛鐨刾ushKey鐨勭敓鎴愯鍒欎负md5(鏃堕棿鎴�+鐢ㄦ埛鍚�)
+        user.setPushKey(DigestUtils.md5DigestAsHex((System.currentTimeMillis()+password).getBytes()));
         Role role = roleService.getRoleById(roleId);
 
         if (role == null) {
@@ -136,6 +138,7 @@
         user.setCreateTime(DateUtil.getNow());
         user.setUpdateTime(DateUtil.getNow());
         int addResult = userService.addUser(user);
+
 
         result.setCode(addResult > 0 ? 0 : -1);
         result.setMsg(addResult > 0 ? "success" : "fail");
@@ -177,4 +180,68 @@
         result.setData(allUsers);
         return new ResponseEntity<>(result, HttpStatus.OK);
     }
+
+    /**
+     * 鍒嗛〉鏌ヨ鐢ㄦ埛
+     *
+     * @param page  褰撳墠椤�
+     * @param count 姣忛〉鏌ヨ鏁伴噺
+     * @return 鍒嗛〉鐢ㄦ埛鍒楄〃
+     */
+    @ApiOperation("鍒嗛〉鏌ヨ鐢ㄦ埛")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "page", value = "褰撳墠椤�", required = true, dataTypeClass = Integer.class),
+            @ApiImplicitParam(name = "count", value = "姣忛〉鏌ヨ鏁伴噺", required = true, dataTypeClass = Integer.class),
+    })
+    @GetMapping("/users")
+    public PageInfo<User> users(int page, int count) {
+        return userService.getUsers(page, count);
+    }
+
+    @ApiOperation("淇敼pushkey")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "userId", required = true, value = "鐢ㄦ埛Id", dataTypeClass = Integer.class),
+            @ApiImplicitParam(name = "pushKey", required = true, value = "鏂扮殑pushKey", dataTypeClass = String.class),
+    })
+    @RequestMapping("/changePushKey")
+    public ResponseEntity<WVPResult<String>> changePushKey(@RequestParam Integer userId,@RequestParam String pushKey) {
+        // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛id
+        int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
+        WVPResult<String> result = new WVPResult<>();
+        if (currenRoleId != 1) {
+            // 鍙敤瑙掕壊id涓�0鎵嶅彲浠ュ垹闄ゅ拰娣诲姞鐢ㄦ埛
+            result.setCode(-1);
+            result.setMsg("鐢ㄦ埛鏃犳潈闄�");
+            return new ResponseEntity<>(result, HttpStatus.FORBIDDEN);
+        }
+        int resetPushKeyResult = userService.changePushKey(userId,pushKey);
+
+        result.setCode(resetPushKeyResult > 0 ? 0 : -1);
+        result.setMsg(resetPushKeyResult > 0 ? "success" : "fail");
+        return new ResponseEntity<>(result, HttpStatus.OK);
+    }
+
+    @ApiOperation("绠$悊鍛樹慨鏀规櫘閫氱敤鎴峰瘑鐮�")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "adminId", required = true, value = "绠$悊鍛榠d", dataTypeClass = String.class),
+            @ApiImplicitParam(name = "userId", required = true, value = "鐢ㄦ埛id", dataTypeClass = String.class),
+            @ApiImplicitParam(name = "password", required = true, value = "鏂板瘑鐮侊紙鏈猰d5鍔犲瘑鐨勫瘑鐮侊級", dataTypeClass = String.class),
+    })
+    @PostMapping("/changePasswordForAdmin")
+    public String changePasswordForAdmin(@RequestParam int userId, @RequestParam String password) {
+        // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛id
+        LoginUser userInfo = SecurityUtils.getUserInfo();
+        if (userInfo == null) {
+            return "fail";
+        }
+        Role role = userInfo.getRole();
+        if (role != null && role.getId() == 1) {
+            boolean result = userService.changePassword(userId, DigestUtils.md5DigestAsHex(password.getBytes()));
+            if (result) {
+                return "success";
+            }
+        }
+
+        return "fail";
+    }
 }
diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml
index ef14c24..b4ec9ef 100644
--- a/src/main/resources/all-application.yml
+++ b/src/main/resources/all-application.yml
@@ -149,7 +149,7 @@
         enable: true
         # [鍙�塢 鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鐢ㄤ簬濯掍綋娴佷紶杈�, 蹇呴』鎻愬墠鍦▃lm涓婇厤缃灞炴�э紝涓嶇劧鑷姩閰嶇疆姝ゅ睘鎬у彲鑳戒笉鎴愬姛
         port-range: 30000,30500 # 绔彛鑼冨洿
-        # [鍙�塢 鍥芥爣绾ц仈鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鍙戦�佸獟浣撴祦,
+        # [鍙�塢 鍥芥爣绾ц仈鍦ㄦ鑼冨洿鍐呴�夋嫨绔彛鍙戦�佸獟浣撴祦
         send-port-range: 30000,30500 # 绔彛鑼冨洿
     # 褰曞儚杈呭姪鏈嶅姟锛� 閮ㄧ讲姝ゆ湇鍔″彲浠ュ疄鐜皕lm褰曞儚鐨勭鐞嗕笌涓嬭浇锛� 0 琛ㄧず涓嶄娇鐢�
     record-assist-port: 0
diff --git a/web_src/src/components/Login.vue b/web_src/src/components/Login.vue
index d823659..4ade744 100644
--- a/web_src/src/components/Login.vue
+++ b/web_src/src/components/Login.vue
@@ -86,7 +86,7 @@
       }).then(function (res) {
         console.log(JSON.stringify(res));
           if (res.data.code == 0 && res.data.msg == "success") {
-            that.$cookies.set("session", {"username": that.username}) ;
+            that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ;
             //鐧诲綍鎴愬姛鍚�
             that.cancelEnterkeyDefaultAction();
             that.$router.push('/');
diff --git a/web_src/src/components/ParentPlatformList.vue b/web_src/src/components/ParentPlatformList.vue
index 3ae0b65..23bebdb 100644
--- a/web_src/src/components/ParentPlatformList.vue
+++ b/web_src/src/components/ParentPlatformList.vue
@@ -143,7 +143,7 @@
         });
     },
     chooseChannel: function(platform) {
-       this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, this.initData)
+       this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, platform.treeType, this.initData)
     },
     initData: function() {
       this.getPlatformList();
diff --git a/web_src/src/components/PushVideoList.vue b/web_src/src/components/PushVideoList.vue
index 0253c1e..6b4707e 100644
--- a/web_src/src/components/PushVideoList.vue
+++ b/web_src/src/components/PushVideoList.vue
@@ -34,6 +34,8 @@
         <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;"
                    :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">鎵归噺绉婚櫎
         </el-button>
+        <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStream">娣诲姞閫氶亾
+        </el-button>
         <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
       </div>
     </div>
@@ -56,20 +58,25 @@
       <el-table-column label="寮�濮嬫椂闂�"  min-width="200">
         <template slot-scope="scope">
           <el-button-group>
-            {{ dateFormat(parseInt(scope.row.createStamp)) }}
+            {{ scope.row.pushTime == null? "-":scope.row.pushTime }}
           </el-button-group>
         </template>
       </el-table-column>
       <el-table-column label="姝e湪鎺ㄦ祦"  min-width="100">
         <template slot-scope="scope">
-          {{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '鏄�' : '鍚�' }}
+          {{scope.row.pushIng ? '鏄�' : '鍚�' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="鏈钩鍙版帹娴�"  min-width="100">
+        <template slot-scope="scope">
+          {{scope.row.pushIng && !!scope.row.self ? '鏄�' : '鍚�' }}
         </template>
       </el-table-column>
 
       <el-table-column label="鎿嶄綔" min-width="360"  fixed="right">
         <template slot-scope="scope">
           <el-button size="medium" icon="el-icon-video-play"
-                     v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status"
+                     v-if="scope.row.pushIng === true"
                      @click="playPush(scope.row)" type="text">鎾斁
           </el-button>
           <el-divider direction="vertical"></el-divider>
@@ -103,7 +110,7 @@
 <script>
 import streamProxyEdit from './dialog/StreamProxyEdit.vue'
 import devicePlayer from './dialog/devicePlayer.vue'
-import addStreamTOGB from './dialog/addStreamTOGB.vue'
+import addStreamTOGB from './dialog/pushStreamEdit.vue'
 import uiHeader from '../layout/UiHeader.vue'
 import importChannel from './dialog/importChannel.vue'
 import MediaServer from './service/MediaServer'
@@ -195,10 +202,15 @@
         }
       }).then(function (res) {
         that.getListLoading = false;
-        that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
-          streamInfo: res.data.data,
-          hasAudio: true
-        });
+        if (res.data.code === 0 ) {
+          that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
+            streamInfo: res.data.data,
+            hasAudio: true
+          });
+        }else {
+          that.$message.error(res.data.msg);
+        }
+
       }).catch(function (error) {
         console.error(error);
         that.getListLoading = false;
@@ -242,24 +254,14 @@
         console.error(error);
       });
     },
-    dateFormat: function (/** timestamp=0 **/) {
-      let ts = arguments[0] || 0;
-      let t, y, m, d, h, i, s;
-      t = ts ? new Date(ts) : new Date();
-      y = t.getFullYear();
-      m = t.getMonth() + 1;
-      d = t.getDate();
-      h = t.getHours();
-      i = t.getMinutes();
-      s = t.getSeconds();
-      // 鍙牴鎹渶瑕佸湪杩欓噷瀹氫箟鏃堕棿鏍煎紡
-      return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + ' ' + (h < 10 ? '0' + h : h) + ':' + (i < 10 ? '0' + i : i) + ':' + (s < 10 ? '0' + s : s);
-    },
     importChannel: function () {
       this.$refs.importChannel.openDialog(() => {
 
       })
     },
+    addStream: function (){
+      this.$refs.addStreamTOGB.openDialog(null, this.initData);
+    },
     batchDel: function () {
       this.$confirm(`纭畾鍒犻櫎閫変腑鐨�${this.multipleSelection.length}涓�氶亾?`, '鎻愮ず', {
         confirmButtonText: '纭畾',
diff --git a/web_src/src/components/UserManager.vue b/web_src/src/components/UserManager.vue
new file mode 100644
index 0000000..1048f53
--- /dev/null
+++ b/web_src/src/components/UserManager.vue
@@ -0,0 +1,236 @@
+<template>
+
+  <div id="app" style="width: 100%">
+    <div class="page-header">
+
+      <div class="page-title">鐢ㄦ埛鍒楄〃</div>
+      <div class="page-header-btn">
+        <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addUser">
+          娣诲姞鐢ㄦ埛
+        </el-button>
+
+      </div>
+    </div>
+    <!--鐢ㄦ埛鍒楄〃-->
+    <el-table :data="userList" style="width: 100%;font-size: 12px;" :height="winHeight"
+              header-row-class-name="table-header">
+      <el-table-column prop="username" label="鐢ㄦ埛鍚�" min-width="160"/>
+      <el-table-column prop="pushKey" label="pushkey" min-width="160"/>
+      <el-table-column prop="role.name" label="绫诲瀷" min-width="160"/>
+      <el-table-column label="鎿嶄綔" min-width="450" fixed="right">
+        <template slot-scope="scope">
+          <el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">淇敼瀵嗙爜</el-button>
+          <el-divider direction="vertical"></el-divider>
+          <el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">淇敼pushkey</el-button>
+          <el-divider direction="vertical"></el-divider>
+          <el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUser(scope.row)"
+                     style="color: #f56c6c">鍒犻櫎
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <changePasswordForAdmin ref="changePasswordForAdmin"></changePasswordForAdmin>
+    <changePushKey ref="changePushKey"></changePushKey>
+    <addUser ref="addUser"></addUser>
+    <el-pagination
+      style="float: right"
+      @size-change="handleSizeChange"
+      @current-change="currentChange"
+      :current-page="currentPage"
+      :page-size="count"
+      :page-sizes="[15, 25, 35, 50]"
+      layout="total, sizes, prev, pager, next"
+      :total="total">
+    </el-pagination>
+  </div>
+</template>
+
+<script>
+import uiHeader from '../layout/UiHeader.vue'
+import changePasswordForAdmin from './dialog/changePasswordForAdmin.vue'
+import changePushKey from './dialog/changePushKey.vue'
+import addUser from '../components/dialog/addUser.vue'
+
+export default {
+  name: 'userManager',
+  components: {
+    uiHeader,
+    changePasswordForAdmin,
+    changePushKey,
+    addUser
+  },
+  data() {
+    return {
+      userList: [], //璁惧鍒楄〃
+      currentUser: {}, //褰撳墠鎿嶄綔璁惧瀵硅薄
+
+      videoComponentList: [],
+      updateLooper: 0, //鏁版嵁鍒锋柊杞鏍囧織
+      currentUserLenth: 0,
+      winHeight: window.innerHeight - 200,
+      currentPage: 1,
+      count: 15,
+      total: 0,
+      getUserListLoading: false
+    };
+  },
+  mounted() {
+    this.initData();
+    this.updateLooper = setInterval(this.initData, 10000);
+  },
+  destroyed() {
+    this.$destroy('videojs');
+    clearTimeout(this.updateLooper);
+  },
+  methods: {
+    initData: function () {
+      this.getUserList();
+    },
+    currentChange: function (val) {
+      this.currentPage = val;
+      this.getUserList();
+    },
+    handleSizeChange: function (val) {
+      this.count = val;
+      this.getUserList();
+    },
+    getUserList: function () {
+      let that = this;
+      this.getUserListLoading = true;
+      this.$axios({
+        method: 'get',
+        url: `/api/user/users`,
+        params: {
+          page: that.currentPage,
+          count: that.count
+        }
+      }).then(function (res) {
+        that.total = res.data.total;
+        that.userList = res.data.list;
+        that.getUserListLoading = false;
+      }).catch(function (error) {
+        that.getUserListLoading = false;
+      });
+
+    },
+    edit: function (row) {
+      this.$refs.changePasswordForAdmin.openDialog(row, () => {
+        this.$refs.changePasswordForAdmin.close();
+        this.$message({
+          showClose: true,
+          message: "瀵嗙爜淇敼鎴愬姛",
+          type: "success",
+        });
+        setTimeout(this.getUserList, 200)
+
+      })
+    },
+    deleteUser: function (row) {
+      let msg = "纭畾鍒犻櫎姝ょ敤鎴凤紵"
+      if (row.online !== 0) {
+        msg = "<strong>纭畾鍒犻櫎姝ょ敤鎴凤紵</strong>"
+      }
+      this.$confirm(msg, '鎻愮ず', {
+        dangerouslyUseHTMLString: true,
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        center: true,
+        type: 'warning'
+      }).then(() => {
+        this.$axios({
+          method: 'delete',
+          url: `/api/user/delete?id=${row.id}`
+        }).then((res) => {
+          this.getUserList();
+        }).catch((error) => {
+          console.error(error);
+        });
+      }).catch(() => {
+
+      });
+
+
+    },
+
+    changePushKey: function (row) {
+      this.$refs.changePushKey.openDialog(row, () => {
+        this.$refs.changePushKey.close();
+        this.$message({
+          showClose: true,
+          message: "pushKey淇敼鎴愬姛",
+          type: "success",
+        });
+        setTimeout(this.getUserList, 200)
+
+      })
+    },
+    addUser: function () {
+      // this.$refs.addUser.openDialog()
+      this.$refs.addUser.openDialog( () => {
+        this.$refs.addUser.close();
+        this.$message({
+          showClose: true,
+          message: "鐢ㄦ埛娣诲姞鎴愬姛",
+          type: "success",
+        });
+        setTimeout(this.getUserList, 200)
+
+      })
+    }
+  }
+}
+</script>
+<style>
+.videoList {
+  display: flex;
+  flex-wrap: wrap;
+  align-content: flex-start;
+}
+
+.video-item {
+  position: relative;
+  width: 15rem;
+  height: 10rem;
+  margin-right: 1rem;
+  background-color: #000000;
+}
+
+.video-item-img {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  margin: auto;
+  width: 100%;
+  height: 100%;
+}
+
+.video-item-img:after {
+  content: "";
+  display: inline-block;
+  position: absolute;
+  z-index: 2;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  margin: auto;
+  width: 3rem;
+  height: 3rem;
+  background-image: url("../assets/loading.png");
+  background-size: cover;
+  background-color: #000000;
+}
+
+.video-item-title {
+  position: absolute;
+  bottom: 0;
+  color: #000000;
+  background-color: #ffffff;
+  line-height: 1.5rem;
+  padding: 0.3rem;
+  width: 14.4rem;
+}
+
+</style>
diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue
index 2a09c5c..f232911 100644
--- a/web_src/src/components/channelList.vue
+++ b/web_src/src/components/channelList.vue
@@ -32,7 +32,7 @@
       <el-button v-if="!showTree"  icon="iconfont icon-tree" circle size="mini" @click="switchTree()"></el-button>
     </div>
   </div>
-  <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer>
+  <devicePlayer ref="devicePlayer" ></devicePlayer>
   <el-container v-loading="isLoging" style="height: 82vh;">
     <el-aside width="auto" style="height: 82vh; background-color: #ffffff; overflow: auto" v-if="showTree" >
       <DeviceTree ref="deviceTree" :device="device" :onlyCatalog="true" :clickEvent="treeNodeClickEvent" ></DeviceTree>
@@ -124,7 +124,6 @@
 import devicePlayer from './dialog/devicePlayer.vue'
 import uiHeader from '../layout/UiHeader.vue'
 import moment from "moment";
-import DviceService from "./service/DeviceService";
 import DeviceService from "./service/DeviceService";
 import DeviceTree from "./common/DeviceTree";
 
@@ -318,7 +317,7 @@
     changeSubchannel(itemData) {
       this.beforeUrl = this.$router.currentRoute.path;
 
-      var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1`
+      var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}`
       this.$router.push(url).then(() => {
         this.searchSrt = "";
         this.channelType = "";
diff --git a/web_src/src/components/common/jessibuca.vue b/web_src/src/components/common/jessibuca.vue
index 7ab0b93..4049721 100644
--- a/web_src/src/components/common/jessibuca.vue
+++ b/web_src/src/components/common/jessibuca.vue
@@ -5,8 +5,8 @@
         <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
         <i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i>
         <i class="iconfont icon-stop jessibuca-btn" @click="destroy"></i>
-        <i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="jessibuca.mute()"></i>
-        <i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="jessibuca.cancelMute()"></i>
+        <i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="mute()"></i>
+        <i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="cancelMute()"></i>
       </div>
       <div class="buttons-box-right">
         <span class="jessibuca-btn">{{ kBps }} kb/s</span>
@@ -243,6 +243,16 @@
       this.err = "";
       this.performance = "";
     },
+    mute: function () {
+      if (jessibucaPlayer[this._uid]) {
+        jessibucaPlayer[this._uid].mute();
+      }
+    },
+    cancelMute: function () {
+      if (jessibucaPlayer[this._uid]) {
+        jessibucaPlayer[this._uid].cancelMute();
+      }
+    },
     destroy: function () {
       if (jessibucaPlayer[this._uid]) {
         jessibucaPlayer[this._uid].destroy();
diff --git a/web_src/src/components/control.vue b/web_src/src/components/control.vue
index 507cc0d..2dd15ec 100644
--- a/web_src/src/components/control.vue
+++ b/web_src/src/components/control.vue
@@ -324,7 +324,7 @@
      */
     getThreadsLoad: function () {
       let that = this;
-      if (that.mediaServerChoose != null) {
+      if (!!that.mediaServerChoose) {
         this.$axios({
           method: 'get',
           url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad'
@@ -375,7 +375,7 @@
     },
     getLoadCount: function () {
       let that = this;
-      if (that.mediaServerChoose != null) {
+      if (!!that.mediaServerChoose) {
         that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => {
           if (data.code == 0) {
             that.loadCount = data.data.count
@@ -473,42 +473,46 @@
     },
 
     getAllSession: function () {
-      let that = this;
-      that.allSessionData = [];
-      this.$axios({
-        method: 'get',
-        url: '/zlm/' + that.mediaServerChoose + '/index/api/getAllSession'
-      }).then(function (res) {
-        res.data.data.forEach(item => {
-          let data = {
-            peer_ip: item.peer_ip,
-            local_ip: item.local_ip,
-            typeid: item.typeid,
-            id: item.id
-          };
-          that.allSessionData.push(data);
+      this.allSessionData = [];
+      if (!!this.mediaServerChoose) {
+        this.$axios({
+          method: 'get',
+          url: '/zlm/' + this.mediaServerChoose + '/index/api/getAllSession'
+        }).then((res)=> {
+          res.data.data.forEach(item => {
+            let data = {
+              peer_ip: item.peer_ip,
+              local_ip: item.local_ip,
+              typeid: item.typeid,
+              id: item.id
+            };
+            this.allSessionData.push(data);
+          });
         });
-      });
+      }
+
     },
     getServerConfig: function () {
-      let that = this;
-      this.$axios({
-        method: 'get',
-        url: '/zlm/' + that.mediaServerChoose + '/index/api/getServerConfig'
-      }).then(function (res) {
-        let info = res.data.data[0];
-        let serverInfo = {}
-        for (let i = 0; i < Object.keys(info).length; i++) {
-          let key = Object.keys(info)[i];
-          let group = key.substring(0, key.indexOf("."))
-          let itemKey = key.substring(key.indexOf(".") + 1)
-          if (!serverInfo[group]) serverInfo[group] = {}
-          serverInfo[group][itemKey] = info[key]
-        }
+      if (!!this.mediaServerChoose) {
+        this.$axios({
+          method: 'get',
+          url: '/zlm/' + this.mediaServerChoose + '/index/api/getServerConfig'
+        }).then((res)=> {
+          let info = res.data.data[0];
+          let serverInfo = {}
+          for (let i = 0; i < Object.keys(info).length; i++) {
+            let key = Object.keys(info)[i];
+            let group = key.substring(0, key.indexOf("."))
+            let itemKey = key.substring(key.indexOf(".") + 1)
+            if (!serverInfo[group]) serverInfo[group] = {}
+            serverInfo[group][itemKey] = info[key]
+          }
 
-        that.serverConfig = serverInfo;
-        that.visible = true;
-      });
+          this.serverConfig = serverInfo;
+          this.visible = true;
+        });
+      }
+
     },
     getWVPServerConfig: function () {
       let that = this;
@@ -531,6 +535,14 @@
     },
     reStartServer: function () {
       let that = this;
+      if (!!!this.mediaServerChoose) {
+        this.$message({
+          type: 'info',
+          message: '鏈�夋嫨鑺傜偣'
+        });
+        return;
+      }
+
       this.$confirm('姝ゆ搷浣滃皢閲嶅惎濯掍綋鏈嶅姟鍣�, 鏄惁缁х画?', '鎻愮ず', {
         confirmButtonText: '纭畾',
         cancelButtonText: '鍙栨秷',
@@ -571,17 +583,19 @@
       console.log(JSON.stringify(tabledata[index]));
     },
     deleteSession: function (id) {
-      let that = this;
-      this.$axios({
-        method: 'get',
-        url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session?id=' + id
-      }).then(function (res) {
-        that.getAllSession();
-        that.$message({
-          type: 'success',
-          message: '鍒犻櫎鎴愬姛!'
+      if (!!this.mediaServerChoose) {
+        this.$axios({
+          method: 'get',
+          url: '/zlm/' + this.mediaServerChoose + '/index/api/kick_session?id=' + id
+        }).then((res)=>{
+          this.getAllSession();
+          this.$message({
+            type: 'success',
+            message: '鍒犻櫎鎴愬姛!'
+          });
         });
-      });
+      }
+
     },
     getNameFromKey: function (key) {
       let nameData = {
diff --git a/web_src/src/components/dialog/SyncChannelProgress.vue b/web_src/src/components/dialog/SyncChannelProgress.vue
index 246f1ae..5506d83 100644
--- a/web_src/src/components/dialog/SyncChannelProgress.vue
+++ b/web_src/src/components/dialog/SyncChannelProgress.vue
@@ -63,34 +63,39 @@
           }
 
           if (res.data.data != null) {
-            if (res.data.data.total == 0) {
-              if (res.data.data.errorMsg !== null ){
-                this.msg = res.data.data.errorMsg;
-                this.syncStatus = "exception"
-              }else {
-                this.msg = `绛夊緟鍚屾涓璥;
-                this.timmer = setTimeout(this.getProgress, 300)
-              }
-            }else  {
-              if (res.data.data.total == res.data.data.current) {
-                this.syncStatus = "success"
-                this.percentage = 100;
-                this.msg = '鍚屾鎴愬姛';
-              }else {
+            if (res.data.syncIng) {
+              if (res.data.data.total == 0) {
                 if (res.data.data.errorMsg !== null ){
                   this.msg = res.data.data.errorMsg;
                   this.syncStatus = "exception"
                 }else {
-                  this.total = res.data.data.total;
-                  this.current = res.data.data.current;
-                  this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
-                  this.msg = `鍚屾涓�...[${res.data.data.current}/${res.data.data.total}]`;
+                  this.msg = `绛夊緟鍚屾涓璥;
                   this.timmer = setTimeout(this.getProgress, 300)
                 }
+              }else  {
+                if (res.data.data.total == res.data.data.current) {
+                  this.syncStatus = "success"
+                  this.percentage = 100;
+                  this.msg = '鍚屾鎴愬姛';
+                }else {
+                  if (res.data.data.errorMsg !== null ){
+                    this.msg = res.data.data.errorMsg;
+                    this.syncStatus = "exception"
+                  }else {
+                    this.total = res.data.data.total;
+                    this.current = res.data.data.current;
+                    this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
+                    this.msg = `鍚屾涓�...[${res.data.data.current}/${res.data.data.total}]`;
+                    this.timmer = setTimeout(this.getProgress, 300)
+                  }
+                }
               }
+            }else {
+              this.syncStatus = "success"
+              this.percentage = 100;
+              this.msg = '鍚屾鎴愬姛';
             }
           }
-
         }else {
           if (this.syncFlag) {
             this.syncStatus = "success"
diff --git a/web_src/src/components/dialog/addUser.vue b/web_src/src/components/dialog/addUser.vue
new file mode 100644
index 0000000..612c1e5
--- /dev/null
+++ b/web_src/src/components/dialog/addUser.vue
@@ -0,0 +1,159 @@
+<template>
+  <div id="addUser" v-loading="isLoging">
+    <el-dialog
+      title="娣诲姞鐢ㄦ埛"
+      width="40%"
+      top="2rem"
+      :close-on-click-modal="false"
+      :visible.sync="showDialog"
+      :destroy-on-close="true"
+      @close="close()"
+    >
+      <div id="shared" style="margin-right: 20px;">
+        <el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
+          <el-form-item label="鐢ㄦ埛鍚�" prop="username">
+            <el-input v-model="username" autocomplete="off"></el-input>
+          </el-form-item>
+          <el-form-item label="鐢ㄦ埛绫诲瀷" prop="roleId" >
+            <el-select v-model="roleId"  placeholder="璇烽�夋嫨" style="width: 100%">
+              <el-option
+                v-for="item in options"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="瀵嗙爜" prop="password">
+            <el-input v-model="password" autocomplete="off"></el-input>
+          </el-form-item>
+          <el-form-item label="纭瀵嗙爜" prop="confirmPassword">
+            <el-input v-model="confirmPassword" autocomplete="off"></el-input>
+          </el-form-item>
+
+          <el-form-item>
+            <div style="float: right;">
+              <el-button type="primary" @click="onSubmit">淇濆瓨</el-button>
+              <el-button @click="close">鍙栨秷</el-button>
+            </div>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "addUser",
+  props: {},
+  computed: {},
+  created() {
+    this.getAllRole();
+  },
+  data() {
+    let validatePass1 = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('璇疯緭鍏ユ柊瀵嗙爜'));
+      } else {
+        if (this.confirmPassword !== '') {
+          this.$refs.passwordForm.validateField('confirmPassword');
+        }
+        callback();
+      }
+    };
+    let validatePass2 = (rule, value, callback) => {
+      if (this.confirmPassword === '') {
+        callback(new Error('璇峰啀娆¤緭鍏ュ瘑鐮�'));
+      } else if (this.confirmPassword !== this.password) {
+        callback(new Error('涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷�!'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      value:"",
+      options: [],
+      loading: false,
+      username: null,
+      password: null,
+      roleId: null,
+      confirmPassword: null,
+      listChangeCallback: null,
+      showDialog: false,
+      isLoging: false,
+      rules: {
+        newPassword: [{required: true, validator: validatePass1, trigger: "blur"}, {
+          pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
+          message: "瀵嗙爜闀垮害鍦�8-20浣嶄箣闂�,鐢卞瓧姣�+鏁板瓧+鐗规畩瀛楃缁勬垚",
+        },],
+        confirmPassword: [{required: true, validator: validatePass2, trigger: "blur"}],
+      },
+    };
+  },
+  methods: {
+    openDialog: function (callback) {
+      this.listChangeCallback = callback;
+      this.showDialog = true;
+    },
+    onSubmit: function () {
+      this.$axios({
+        method: 'post',
+        url: "/api/user/add",
+        params: {
+          username: this.username,
+          password: this.password,
+          roleId: this.roleId
+        }
+      }).then((res) => {
+        if (res.data.code === 0) {
+          this.$message({
+            showClose: true,
+            message: '娣诲姞鎴愬姛',
+            type: 'success',
+
+          });
+          this.showDialog = false;
+          this.listChangeCallback()
+
+        } else {
+          this.$message({
+            showClose: true,
+            message: res.data.msg,
+            type: 'error'
+          });
+        }
+      }).catch((error) => {
+        console.error(error)
+      });
+    },
+    close: function () {
+      this.showDialog = false;
+      this.password = null;
+      this.confirmPassword = null;
+      this.username = null;
+      this.roleId = null;
+    },
+    getAllRole:function () {
+
+      this.$axios({
+        method: 'get',
+        url: "/api/role/all"
+      }).then((res) => {
+        this.loading = true;
+        console.info(res)
+        res.data
+        console.info(res.data.code)
+        if (res.data.code === 0) {
+          console.info(res.data.data)
+          this.options=res.data.data
+
+        }
+      }).catch((error) => {
+        console.error(error)
+      });
+    }
+  },
+};
+</script>
diff --git a/web_src/src/components/dialog/catalogEdit.vue b/web_src/src/components/dialog/catalogEdit.vue
index 13cabfb..11dbe4e 100644
--- a/web_src/src/components/dialog/catalogEdit.vue
+++ b/web_src/src/components/dialog/catalogEdit.vue
@@ -49,11 +49,42 @@
   props: ['platformId'],
   created() {},
   data() {
+    let checkId = (rule, value, callback) => {
+      console.log("checkId")
+      console.log(this.treeType)
+      console.log(rule)
+      console.log(value)
+      console.log(value.length)
+      console.log(this.level)
+      if (!value) {
+        return callback(new Error('缂栧彿涓嶈兘涓虹┖'));
+      }
+      if (this.treeType === "BusinessGroup" && value.length !== 20) {
+        return callback(new Error('缂栧彿蹇呴』鐢�20浣嶆暟瀛楃粍鎴�'));
+      }
+      if (this.treeType === "CivilCode" && value.length <= 8 && value.length%2 !== 0) {
+        return callback(new Error('琛屾斂鍖哄垝蹇呴』鏄叓浣嶄互涓嬬殑鍋舵暟涓暟瀛楃粍鎴�'));
+      }
+      if (this.treeType === "BusinessGroup") {
+        let catalogType = value.substring(10, 13);
+        console.log(catalogType)
+        // 216 涓鸿櫄鎷熺粍缁� 215 涓轰笟鍔″垎缁勶紱鐩綍绗竴绾у繀椤讳负涓氬姟鍒嗙粍锛� 涓氬姟鍒嗙粍涓嬩负铏氭嫙缁勭粐锛岃櫄鎷熺粍缁囦笅鍙互鏈夊叾浠栬櫄鎷熺粍缁�
+        if (this.level === 1 && catalogType !== "215") {
+          return callback(new Error('涓氬姟鍒嗙粍妯″紡涓嬬涓�灞傜洰褰曠殑缂栧彿11鍒�13浣嶅繀椤讳负215'));
+        }
+        if (this.level > 1 && catalogType !== "216") {
+          return callback(new Error('涓氬姟鍒嗙粍妯″紡涓嬬涓�灞備互涓嬬洰褰曠殑缂栧彿11鍒�13浣嶅繀椤讳负216'));
+        }
+      }
+      callback();
+    }
     return {
       submitCallback: null,
       showDialog: false,
       isLoging: false,
       isEdit: false,
+      treeType: null,
+      level: 0,
       form: {
         id: null,
         name: null,
@@ -62,12 +93,12 @@
       },
       rules: {
         name: [{ required: true, message: "璇疯緭鍏ュ悕绉�", trigger: "blur" }],
-        id: [{ required: true, message: "璇疯緭鍏D", trigger: "blur" }]
+        id: [{ required: true, trigger: "blur",validator: checkId  }]
       },
     };
   },
   methods: {
-    openDialog: function (isEdit, id, name, parentId, callback) {
+    openDialog: function (isEdit, id, name, parentId, treeType, level, callback) {
       console.log("parentId: " + parentId)
       console.log(this.form)
       this.isEdit = isEdit;
@@ -77,6 +108,8 @@
       this.form.parentId = parentId;
       this.showDialog = true;
       this.submitCallback = callback;
+      this.treeType = treeType;
+      this.level = level;
     },
     onSubmit: function () {
       console.log("onSubmit");
diff --git a/web_src/src/components/dialog/changePasswordForAdmin.vue b/web_src/src/components/dialog/changePasswordForAdmin.vue
new file mode 100644
index 0000000..0e0ae22
--- /dev/null
+++ b/web_src/src/components/dialog/changePasswordForAdmin.vue
@@ -0,0 +1,121 @@
+<template>
+  <div id="changePassword" v-loading="isLoging">
+    <el-dialog
+      title="淇敼瀵嗙爜"
+      width="40%"
+      top="2rem"
+      :close-on-click-modal="false"
+      :visible.sync="showDialog"
+      :destroy-on-close="true"
+      @close="close()"
+    >
+      <div id="shared" style="margin-right: 20px;">
+        <el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
+              <el-form-item label="鏂板瘑鐮�" prop="newPassword" >
+                <el-input v-model="newPassword" autocomplete="off"></el-input>
+              </el-form-item>
+              <el-form-item label="纭瀵嗙爜" prop="confirmPassword">
+                <el-input v-model="confirmPassword" autocomplete="off"></el-input>
+              </el-form-item>
+
+              <el-form-item>
+                <div style="float: right;">
+                  <el-button type="primary" @click="onSubmit">淇濆瓨</el-button>
+                  <el-button @click="close">鍙栨秷</el-button>
+                </div>
+              </el-form-item>
+            </el-form>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "changePasswordForAdmin",
+  props: {},
+  computed: {},
+  created() {},
+  data() {
+    let validatePass1 = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('璇疯緭鍏ユ柊瀵嗙爜'));
+      } else {
+        if (this.confirmPassword !== '') {
+          this.$refs.passwordForm.validateField('confirmPassword');
+        }
+        callback();
+      }
+    };
+    let validatePass2 = (rule, value, callback) => {
+      if (this.confirmPassword === '') {
+        callback(new Error('璇峰啀娆¤緭鍏ュ瘑鐮�'));
+      } else if (this.confirmPassword !== this.newPassword) {
+        callback(new Error('涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷�!'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      newPassword: null,
+      confirmPassword: null,
+      userId: null,
+      showDialog: false,
+      isLoging: false,
+      listChangeCallback: null,
+      form: {},
+      rules: {
+        newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
+            pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
+            message: "瀵嗙爜闀垮害鍦�8-20浣嶄箣闂�,鐢卞瓧姣�+鏁板瓧+鐗规畩瀛楃缁勬垚",
+          },],
+        confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
+      },
+    };
+  },
+  methods: {
+    openDialog: function (row, callback) {
+      console.log(row)
+      this.showDialog = true;
+      this.listChangeCallback = callback;
+      if (row != null) {
+        this.form = row;
+      }
+    },
+    onSubmit: function () {
+      this.$axios({
+        method: 'post',
+        url:"/api/user/changePasswordForAdmin",
+        params: {
+          password: this.newPassword,
+          userId: this.form.id,
+        }
+      }).then((res)=> {
+        if (res.data === "success"){
+          this.$message({
+            showClose: true,
+            message: '淇敼鎴愬姛',
+            type: 'success'
+          });
+          this.showDialog = false;
+        }else {
+          this.$message({
+            showClose: true,
+            message: '淇敼瀵嗙爜澶辫触锛屾槸鍚﹀凡鐧诲綍锛堟帴鍙i壌鏉冨叧闂棤娉曚慨鏀瑰瘑鐮侊級',
+            type: 'error'
+          });
+        }
+      }).catch((error)=> {
+        console.error(error)
+      });
+    },
+    close: function () {
+      this.showDialog = false;
+      this.newPassword = null;
+      this.confirmPassword = null;
+      this.userId=null;
+      this.adminId=null;
+    },
+  },
+};
+</script>
diff --git a/web_src/src/components/dialog/changePushKey.vue b/web_src/src/components/dialog/changePushKey.vue
new file mode 100644
index 0000000..3efbf67
--- /dev/null
+++ b/web_src/src/components/dialog/changePushKey.vue
@@ -0,0 +1,102 @@
+<template>
+  <div id="changepushKey" v-loading="isLoging">
+    <el-dialog
+      title="淇敼pushKey"
+      width="42%"
+      top="2rem"
+      :close-on-click-modal="false"
+      :visible.sync="showDialog"
+      :destroy-on-close="true"
+      @close="close()"
+    >
+      <div id="shared" style="margin-right: 18px;">
+        <el-form ref="pushKeyForm" :rules="rules" status-icon label-width="86px">
+              <el-form-item label="鏂皃ushKey" prop="newPushKey" >
+                <el-input v-model="newPushKey" autocomplete="off"></el-input>
+              </el-form-item>
+              <el-form-item>
+                <div style="float: right;">
+                  <el-button type="primary" @click="onSubmit">淇濆瓨</el-button>
+                  <el-button @click="close">鍙栨秷</el-button>
+                </div>
+              </el-form-item>
+            </el-form>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "changePushKey",
+  props: {},
+  computed: {},
+  created() {},
+  data() {
+    let validatePass1 = (rule, value, callback) => {
+      if (value === '') {
+        callback(new Error('璇疯緭鍏ユ柊pushKey'));
+      } else {
+        callback();
+      }
+    };
+    return {
+      newPushKey: null,
+      confirmpushKey: null,
+      userId: null,
+      showDialog: false,
+      isLoging: false,
+      listChangeCallback: null,
+      form: {},
+      rules: {
+        newpushKey: [{ required: true, validator: validatePass1, trigger: "blur" }],
+      },
+    };
+  },
+  methods: {
+    openDialog: function (row, callback) {
+      console.log(row)
+      this.showDialog = true;
+      this.listChangeCallback = callback;
+      if (row != null) {
+        this.form = row;
+      }
+    },
+    onSubmit: function () {
+      this.$axios({
+        method: 'post',
+        url:"/api/user/changePushKey",
+        params: {
+          pushKey: this.newPushKey,
+          userId: this.form.id,
+        }
+      }).then((res)=> {
+        console.log(res.data)
+        if (res.data.msg === "success"){
+          this.$message({
+            showClose: true,
+            message: '淇敼鎴愬姛',
+            type: 'success'
+          });
+          this.showDialog = false;
+          this.listChangeCallback();
+        }else {
+          this.$message({
+            showClose: true,
+            message: '淇敼pushKey澶辫触锛屾槸鍚﹀凡鐧诲綍锛堟帴鍙i壌鏉冨叧闂棤娉曚慨鏀筽ushKey锛�',
+            type: 'error'
+          });
+        }
+      }).catch((error)=> {
+        console.error(error)
+      });
+    },
+    close: function () {
+      this.showDialog = false;
+      this.newpushKey = null;
+      this.userId=null;
+      this.adminId=null;
+    },
+  },
+};
+</script>
diff --git a/web_src/src/components/dialog/chooseChannel.vue b/web_src/src/components/dialog/chooseChannel.vue
index 599921e..cd8132a 100644
--- a/web_src/src/components/dialog/chooseChannel.vue
+++ b/web_src/src/components/dialog/chooseChannel.vue
@@ -8,7 +8,7 @@
             <el-tab-pane label="鐩綍缁撴瀯" name="catalog">
               <el-container>
                 <el-main v-bind:style="{backgroundColor: '#FFF', maxHeight:  winHeight + 'px'}">
-                  <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" ></chooseChannelForCatalog>
+                  <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" :treeType=treeType ></chooseChannelForCatalog>
                 </el-main>
               </el-container>
             </el-tab-pane>
@@ -66,18 +66,20 @@
             platformName: "",
             defaultCatalogId: "",
             showDialog: false,
+            treeType: null,
             chooseData: {},
             winHeight: window.innerHeight - 250,
 
         };
     },
     methods: {
-        openDialog(platformId, platformName, defaultCatalogId, closeCallback) {
+        openDialog(platformId, platformName, defaultCatalogId, treeType, closeCallback) {
             this.platformId = platformId
             this.platformName = platformName
             this.defaultCatalogId = defaultCatalogId
             this.showDialog = true
             this.closeCallback = closeCallback
+            this.treeType = treeType
         },
         tabClick (tab, event){
 
diff --git a/web_src/src/components/dialog/chooseChannelForCatalog.vue b/web_src/src/components/dialog/chooseChannelForCatalog.vue
index a0cb98c..86fb48d 100644
--- a/web_src/src/components/dialog/chooseChannelForCatalog.vue
+++ b/web_src/src/components/dialog/chooseChannelForCatalog.vue
@@ -38,7 +38,7 @@
 import catalogEdit from './catalogEdit.vue'
 export default {
     name: 'chooseChannelForCatalog',
-    props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange'],
+    props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'],
     created() {
         this.chooseId = this.defaultCatalogId;
         this.defaultCatalogIdSign = this.defaultCatalogId;
@@ -102,8 +102,9 @@
         },
         addCatalog: function (parentId, node){
           let that = this;
+          console.log(this.treeType)
           // 鎵撳紑娣诲姞寮圭獥
-          that.$refs.catalogEdit.openDialog(false, null, null, parentId, ()=>{
+          that.$refs.catalogEdit.openDialog(false, null, null, parentId, this.treeType, node.level, ()=>{
             node.loaded = false
             node.expand();
           });
diff --git a/web_src/src/components/dialog/chooseChannelForStream.vue b/web_src/src/components/dialog/chooseChannelForStream.vue
index d5e5ac3..1eec0b2 100644
--- a/web_src/src/components/dialog/chooseChannelForStream.vue
+++ b/web_src/src/components/dialog/chooseChannelForStream.vue
@@ -174,7 +174,6 @@
                     page: that.currentPage,
                     count: that.count,
                     query: that.searchSrt,
-                    pushing: that.pushing,
                     platformId: that.platformId,
                     catalogId: that.catalogId,
                     mediaServerId: that.mediaServerId
diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue
index f2f2e54..ba02441 100644
--- a/web_src/src/components/dialog/devicePlayer.vue
+++ b/web_src/src/components/dialog/devicePlayer.vue
@@ -388,7 +388,7 @@
                     url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId
                 }).then(function (res) {
                     that.tracksLoading = false;
-                    if (res.data.code == 0 && res.data.online) {
+                    if (res.data.code == 0 && res.data.tracks) {
                         that.tracks = res.data.tracks;
                     }else{
                         that.tracksNotLoaded = true;
diff --git a/web_src/src/components/dialog/platformEdit.vue b/web_src/src/components/dialog/platformEdit.vue
index 0caec32..819c002 100644
--- a/web_src/src/components/dialog/platformEdit.vue
+++ b/web_src/src/components/dialog/platformEdit.vue
@@ -78,6 +78,12 @@
                   <el-option label="8" value="8"></el-option>
                 </el-select>
               </el-form-item>
+              <el-form-item label="鐩綍缁撴瀯" prop="treeType" >
+                <el-select v-model="platform.treeType" style="width: 100%" >
+                  <el-option key="WGS84" label="琛屾斂鍖哄垝" value="CivilCode"></el-option>
+                  <el-option key="GCJ02" label="涓氬姟鍒嗙粍" value="BusinessGroup"></el-option>
+                </el-select>
+              </el-form-item>
               <el-form-item label="瀛楃闆�" prop="characterSet">
                 <el-select
                   v-model="platform.characterSet"
@@ -91,7 +97,6 @@
               <el-form-item label="鍏朵粬閫夐」">
                 <el-checkbox label="鍚敤" v-model="platform.enable" @change="checkExpires"></el-checkbox>
                 <el-checkbox label="浜戝彴鎺у埗" v-model="platform.ptz"></el-checkbox>
-                <el-checkbox label="鍏变韩鎵�鏈夌洿鎾祦" v-model="platform.shareAllLiveStream"></el-checkbox>
                 <el-checkbox label="鎷夎捣绂荤嚎鎺ㄦ祦" v-model="platform.startOfflinePush"></el-checkbox>
               </el-form-item>
               <el-form-item>
@@ -153,10 +158,10 @@
         keepTimeout: 60,
         transport: "UDP",
         characterSet: "GB2312",
-        shareAllLiveStream: false,
         startOfflinePush: false,
         catalogGroup: 1,
         administrativeDivision: null,
+        treeType: "BusinessGroup",
       },
       rules: {
         name: [{ required: true, message: "璇疯緭鍏ュ钩鍙板悕绉�", trigger: "blur" }],
@@ -194,6 +199,7 @@
           that.platform.devicePort = res.data.devicePort;
           that.platform.username = res.data.username;
           that.platform.password = res.data.password;
+          that.platform.treeType = "BusinessGroup";
           that.platform.administrativeDivision = res.data.username.substr(0, 6);
         }).catch(function (error) {
           console.log(error);
@@ -217,11 +223,11 @@
         this.platform.keepTimeout = platform.keepTimeout;
         this.platform.transport = platform.transport;
         this.platform.characterSet = platform.characterSet;
-        this.platform.shareAllLiveStream = platform.shareAllLiveStream;
         this.platform.catalogId = platform.catalogId;
         this.platform.startOfflinePush = platform.startOfflinePush;
         this.platform.catalogGroup = platform.catalogGroup;
         this.platform.administrativeDivision = platform.administrativeDivision;
+        this.platform.treeType = platform.treeType;
         this.onSubmit_text = "淇濆瓨";
         this.saveUrl = "/api/platform/save";
       }
@@ -242,32 +248,49 @@
 
     },
     onSubmit: function () {
+      if (this.onSubmit_text === "淇濆瓨") {
+        this.$confirm("淇敼鐩綍缁撴瀯浼氬鑷村叧鑱旂洰褰曚笌閫氶亾鏁版嵁琚竻绌�", '鎻愮ず', {
+          dangerouslyUseHTMLString: true,
+          confirmButtonText: '纭畾',
+          cancelButtonText: '鍙栨秷',
+          center: true,
+          type: 'warning'
+        }).then(() => {
+          this.saveForm()
+        }).catch(() => {
+
+        });
+      }else {
+        this.saveForm()
+      }
+    },
+    saveForm: function (){
       var that = this;
       that.$axios({
         method: 'post',
         url: this.saveUrl,
         data: that.platform
       }).then(function (res) {
-          if (res.data.code === 0) {
-            that.$message({
-              showClose: true,
-              message: "淇濆瓨鎴愬姛",
-              type: "success",
-            });
-            that.showDialog = false;
-            if (that.listChangeCallback != null) {
-              that.listChangeCallback();
-            }
-          }else {
-            that.$message({
-              showClose: true,
-              message: res.data.msg,
-              type: "error",
-            });
+        if (res.data.code === 0) {
+          that.$message({
+            showClose: true,
+            message: "淇濆瓨鎴愬姛",
+            type: "success",
+          });
+          that.showDialog = false;
+          if (that.listChangeCallback != null) {
+            that.listChangeCallback();
           }
-        }).catch(function (error) {
-          console.log(error);
-        });
+        }else {
+          that.$message({
+            showClose: true,
+            message: res.data.msg,
+            type: "error",
+          });
+        }
+      }).catch(function (error) {
+        console.log(error);
+      });
     },
     close: function () {
       this.showDialog = false;
@@ -293,7 +316,7 @@
         keepTimeout: 60,
         transport: "UDP",
         characterSet: "GB2312",
-        shareAllLiveStream: false,
+        treeType: "BusinessGroup",
         startOfflinePush: false,
         catalogGroup: 1,
       }
diff --git a/web_src/src/components/dialog/addStreamTOGB.vue b/web_src/src/components/dialog/pushStreamEdit.vue
similarity index 67%
rename from web_src/src/components/dialog/addStreamTOGB.vue
rename to web_src/src/components/dialog/pushStreamEdit.vue
index 9baf1bc..bad5077 100644
--- a/web_src/src/components/dialog/addStreamTOGB.vue
+++ b/web_src/src/components/dialog/pushStreamEdit.vue
@@ -15,20 +15,25 @@
                 <el-input v-model="proxyParam.name" clearable></el-input>
               </el-form-item>
               <el-form-item label="娴佸簲鐢ㄥ悕" prop="app">
-                <el-input v-model="proxyParam.app" clearable :disabled="true"></el-input>
+                <el-input v-model="proxyParam.app" clearable :disabled="edit"></el-input>
               </el-form-item>
               <el-form-item label="娴両D" prop="stream">
-                <el-input v-model="proxyParam.stream" clearable :disabled="true"></el-input>
+                <el-input v-model="proxyParam.stream" clearable :disabled="edit"></el-input>
               </el-form-item>
               <el-form-item label="鍥芥爣缂栫爜" prop="gbId">
                 <el-input v-model="proxyParam.gbId" placeholder="璁剧疆鍥芥爣缂栫爜鍙帹閫佸埌鍥芥爣" clearable></el-input>
+              </el-form-item>
+              <el-form-item label="缁忓害" prop="longitude" v-if="proxyParam.gbId">
+                <el-input v-model="proxyParam.longitude" placeholder="缁忓害" clearable></el-input>
+              </el-form-item>
+              <el-form-item label="绾害" prop="latitude" v-if="proxyParam.gbId">
+                <el-input v-model="proxyParam.latitude" placeholder="缁忓害" clearable></el-input>
               </el-form-item>
               <el-form-item>
                 <div style="float: right;">
                   <el-button type="primary" @click="onSubmit">淇濆瓨</el-button>
                   <el-button @click="close">鍙栨秷</el-button>
                 </div>
-                
               </el-form-item>
             </el-form>
       </div>
@@ -38,7 +43,7 @@
 
 <script>
 export default {
-  name: "streamProxyEdit",
+  name: "pushStreamEdit",
   props: {},
   computed: {},
   created() {},
@@ -63,13 +68,15 @@
       listChangeCallback: null,
       showDialog: false,
       isLoging: false,
+      edit: false,
       proxyParam: {
           name: null,
           app: null,
           stream: null,
           gbId: null,
+          longitude: null,
+          latitude: null,
       },
-      
       rules: {
         name: [{ required: true, message: "璇疯緭鍏ュ悕绉�", trigger: "blur" }],
         app: [{ required: true, message: "璇疯緭鍏ュ簲鐢ㄥ悕", trigger: "blur" }],
@@ -84,30 +91,63 @@
       this.listChangeCallback = callback;
       if (proxyParam != null) {
         this.proxyParam = proxyParam;
-      } 
+        this.edit = true
+      }else{
+        this.proxyParam= {
+          name: null,
+          app: null,
+          stream: null,
+          gbId: null,
+          longitude: null,
+          latitude: null,
+        }
+        this.edit = false
+      }
     },
     onSubmit: function () {
       console.log("onSubmit");
-      var that = this;
-      that.$axios({
-        method:"post",
-        url:`/api/push/save_to_gb`, 
-        data: that.proxyParam
-      }).then(function (res) {
+      if (this.edit) {
+        this.$axios({
+          method:"post",
+          url:`/api/push/save_to_gb`,
+          data: this.proxyParam
+        }).then( (res) => {
           if (res.data == "success") {
-            that.$message({
+            this.$message({
               showClose: true,
               message: "淇濆瓨鎴愬姛",
               type: "success",
             });
-            that.showDialog = false;
-            if (that.listChangeCallback != null) {
-              that.listChangeCallback();
+            this.showDialog = false;
+            if (this.listChangeCallback != null) {
+              this.listChangeCallback();
             }
           }
-      }).catch(function (error) {
+        }).catch((error)=> {
           console.log(error);
-      });
+        });
+      }else {
+        this.$axios({
+          method:"post",
+          url:`/api/push/add`,
+          data: this.proxyParam
+        }).then( (res) => {
+          if (res.data.code === 0) {
+            this.$message({
+              showClose: true,
+              message: "淇濆瓨鎴愬姛",
+              type: "success",
+            });
+            this.showDialog = false;
+            if (this.listChangeCallback != null) {
+              this.listChangeCallback();
+            }
+          }
+        }).catch((error)=> {
+          console.log(error);
+        });
+      }
+
     },
     close: function () {
       console.log("鍏抽棴鍔犲叆GB");
@@ -131,6 +171,9 @@
       if (this.platform.enable && this.platform.expires == "0") {
         this.platform.expires = "300";
       }
+    },
+    handleNodeClick: function (node){
+
     }
   },
 };
diff --git a/web_src/src/layout/UiHeader.vue b/web_src/src/layout/UiHeader.vue
index 3c933f1..42d617e 100644
--- a/web_src/src/layout/UiHeader.vue
+++ b/web_src/src/layout/UiHeader.vue
@@ -13,6 +13,7 @@
       <el-menu-item index="/cloudRecord">浜戠褰曞儚</el-menu-item>
       <el-menu-item index="/mediaServerManger">鑺傜偣绠$悊</el-menu-item>
       <el-menu-item index="/parentPlatformList/15/1">鍥芥爣绾ц仈</el-menu-item>
+      <el-menu-item v-if="editUser" index="/userManager">鐢ㄦ埛绠$悊</el-menu-item>
 
       <!--            <el-submenu index="/setting">-->
       <!--              <template slot="title">绯荤粺璁剧疆</template>-->
@@ -47,9 +48,11 @@
       alarmNotify: false,
       sseSource: null,
       activeIndex: this.$route.path,
+      editUser: this.$cookies.get("session").roleId==1
     };
   },
   created() {
+    console.log(this.$cookies.get("session"))
     if (this.$route.path.startsWith("/channelList")) {
       this.activeIndex = "/deviceList"
     }
diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js
index 2c9c6f3..7651a72 100644
--- a/web_src/src/router/index.js
+++ b/web_src/src/router/index.js
@@ -17,6 +17,7 @@
 import media from '../components/setting/Media.vue'
 import live from '../components/live.vue'
 import deviceTree from '../components/common/DeviceTree.vue'
+import userManager from '../components/UserManager.vue'
 
 import wasmPlayer from '../components/common/jessibuca.vue'
 import rtcPlayer from '../components/dialog/rtcPlayer.vue'
@@ -103,6 +104,11 @@
           name: 'map',
           component: map,
         },
+        {
+          path: '/userManager',
+          name: 'userManager',
+          component: userManager,
+        }
         ]
     },
     {
diff --git "a/web_src/static/file/\346\216\250\346\265\201\351\200\232\351\201\223\345\257\274\345\205\245.zip" "b/web_src/static/file/\346\216\250\346\265\201\351\200\232\351\201\223\345\257\274\345\205\245.zip"
index c5ab3ab..fb95c61 100644
--- "a/web_src/static/file/\346\216\250\346\265\201\351\200\232\351\201\223\345\257\274\345\205\245.zip"
+++ "b/web_src/static/file/\346\216\250\346\265\201\351\200\232\351\201\223\345\257\274\345\205\245.zip"
Binary files differ
diff --git a/web_src/static/js/jessibuca/decoder.wasm b/web_src/static/js/jessibuca/decoder.wasm
old mode 100755
new mode 100644
Binary files differ

--
Gitblit v1.8.0