From 8d87741dea3d174f098269073429a0f6b982baa1 Mon Sep 17 00:00:00 2001
From: mrjackwang <30337754+mrjackwang@users.noreply.github.com>
Date: 星期三, 20 七月 2022 13:51:30 +0800
Subject: [PATCH] Merge branch '648540858:wvp-28181-2.0' into wvp-28181-2.0

---
 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/vmanager/gb28181/media/MediaController.java                                                        |   57 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java                                                                 |    7 
 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java                                                                 |  100 +
 src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java                                                                             |   11 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java              |   42 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java                                                           |    6 
 web_src/src/components/dialog/chooseChannelForCatalog.vue                                                                              |    5 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPublishHookParam.java                                                              |   82 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java            |   76 -
 web_src/src/components/Login.vue                                                                                                       |    2 
 sql/mysql.sql                                                                                                                          |   31 
 src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java                                                                   |   31 
 src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java                                                                       |   18 
 src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java                                          |   16 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java                                                      |   44 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java                                                              |    4 
 src/main/java/com/genersoft/iot/vmp/service/bean/PushStreamStatusChangeFromRedisDto.java                                               |   41 
 src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java                                                                              |   23 
 src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java                                            |   18 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPlayHookParam.java                                                                 |   82 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java    |    2 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java                                                                  |   13 
 web_src/src/components/dialog/platformEdit.vue                                                                                         |   69 
 src/main/java/com/genersoft/iot/vmp/storager/dao/dto/User.java                                                                         |    9 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java                                                                  |   35 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java                                                                  |    2 
 src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java                                                                              |    9 
 src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java                                                                   |    5 
 src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java                                                      |   47 
 src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java                                                  |   41 
 src/main/java/com/genersoft/iot/vmp/service/bean/StreamPushItemFromRedis.java                                                          |   34 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java                                                                |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java                              |    1 
 src/main/java/com/genersoft/iot/vmp/service/IUserService.java                                                                          |    7 
 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java                                                                  |   14 
 web_src/src/components/dialog/chooseChannelForStream.vue                                                                               |    1 
 web_src/src/components/dialog/chooseChannel.vue                                                                                        |    6 
 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java                                                                 |   55 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java                                                  |   15 
 src/main/resources/8042900_www.wvp-pro.cn.jks                                                                                          |    0 
 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java                                                                |    4 
 web_src/src/router/index.js                                                                                                            |    6 
 src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java                                                       |  106 +
 web_src/src/layout/UiHeader.vue                                                                                                        |    7 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java                                                                 |   74 
 src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java                                                                   |   47 
 sql/update.sql                                                                                                                         |   21 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java                                    |   88 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java                                                                       |   16 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java                                                 |   92 +
 src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java                                                                    |   35 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java                                                                         |   10 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java                                                            |   86 
 web_src/src/components/dialog/changePasswordForAdmin.vue                                                                               |  121 +
 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 
 web_src/src/components/dialog/catalogEdit.vue                                                                                          |   38 
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java                                                         |  165 ++
 web_src/src/components/PushVideoList.vue                                                                                               |   24 
 src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java                                                                  |   25 
 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java                                                                 |   74 
 src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java                                                                  |    8 
 src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java                                                               |   22 
 src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java                                                           |    7 
 src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java                                                         |  325 +---
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java                                                             |  114 +
 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java                                                           |   38 
 web_src/src/components/dialog/addUser.vue                                                                                              |  159 ++
 src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java                                                            |   13 
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java                                                           |    1 
 src/main/java/com/genersoft/iot/vmp/service/IMediaService.java                                                                         |    8 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java     |    1 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java                                                  |    4 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java              |   76 -
 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java                                                                |   33 
 src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java                                                                         |  227 +-
 web_src/src/components/UserManager.vue                                                                                                 |  236 +++
 web_src/static/file/推流通道导入.zip                                                                                                         |    0 
 src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java                                                                   |   27 
 src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java                                                                              |    2 
 web_src/src/components/ParentPlatformList.vue                                                                                          |    2 
 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookParam.java                                                                       |   17 
 src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java                                                             |    9 
 src/main/resources/all-application.yml                                                                                                 |    2 
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java        |    6 
 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java                                                                 |  158 +
 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java                                             |   72 
 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java                                                          |    2 
 src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java                                                                  |   69 
 src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java                                                              |   40 
 src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java                                                           |  121 +
 web_src/src/components/dialog/changePushKey.vue                                                                                        |  102 +
 src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java                                                              |   10 
 95 files changed, 2,976 insertions(+), 1,157 deletions(-)

diff --git a/sql/mysql.sql b/sql/mysql.sql
index ffe39c3..7d0996f 100644
--- a/sql/mysql.sql
+++ b/sql/mysql.sql
@@ -50,7 +50,7 @@
                           `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=37 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -142,7 +142,7 @@
                                   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=19324 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=19336 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -179,7 +179,7 @@
                                           `latitudeWgs84` double DEFAULT NULL,
                                           `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
                                           PRIMARY KEY (`id`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=5649 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=6751 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -208,13 +208,12 @@
                              `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,
-                             `status` int 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;
+) ENGINE=InnoDB AUTO_INCREMENT=301740 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -244,7 +243,7 @@
                        `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=29943 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=37760 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -329,16 +328,16 @@
                                    `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,
+                                   `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=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -362,6 +361,8 @@
                                     `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 */;
@@ -388,7 +389,7 @@
                                        `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;
+) ENGINE=InnoDB AUTO_INCREMENT=4912 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -414,7 +415,7 @@
                                       `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;
+) ENGINE=InnoDB AUTO_INCREMENT=302134 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -455,7 +456,7 @@
                                 `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=65 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -487,9 +488,10 @@
                                `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=305304 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
+) ENGINE=InnoDB AUTO_INCREMENT=305390 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
 --
@@ -515,6 +517,7 @@
                         `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;
@@ -526,7 +529,7 @@
 
 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');
+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 */;
 UNLOCK TABLES;
 
@@ -566,4 +569,4 @@
 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 
--- Dump completed on 2022-07-06  9:43:54
+-- Dump completed on 2022-07-17 23:15:09
diff --git a/sql/update.sql b/sql/update.sql
index 4341355..91f725e 100644
--- a/sql/update.sql
+++ b/sql/update.sql
@@ -52,9 +52,30 @@
 alter table stream_push
     add pushTime varchar(50) default null;
 alter table stream_push
+    add status int DEFAULT NULL;
+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
+    drop column status;
+
+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;
+
 
 
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/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
index 4e4ba15..b5788ae 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -9,6 +9,9 @@
     private String deviceID;
     private String channelId;
     private String flv;
+
+    private String ip;
+
     private String https_flv;
     private String ws_flv;
     private String wss_flv;
@@ -292,4 +295,12 @@
     public void setProgress(double progress) {
         this.progress = progress;
     }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public void setIp(String ip) {
+        this.ip = ip;
+    }
 }
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 57f764b..40a7352 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -58,6 +58,8 @@
 
 	public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
 
+	public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_";
+
 	public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
 
 	public static final String SIP_SN_PREFIX = "VMP_SIP_SN_";
@@ -71,6 +73,8 @@
 	public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_";
 
 
+
+
 	//************************** redis 娑堟伅*********************************
 
 	// 娴佸彉鍖栫殑閫氱煡
@@ -79,8 +83,14 @@
 	// 鎺ユ敹鎺ㄦ祦璁惧鐨凣PS鍙樺寲閫氱煡
 	public static final String VM_MSG_GPS = "VM_MSG_GPS";
 
+	// 鎺ユ敹鎺ㄦ祦璁惧鐨凣PS鍙樺寲閫氱煡
+	public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE";
+
 	// redis 娑堟伅閫氱煡璁惧鎺ㄦ祦鍒板钩鍙�
 	public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED";
+
+	// redis 娑堟伅璇锋眰鎵�鏈夌殑鍦ㄧ嚎閫氶亾
+	public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED";
 
 	// 绉诲姩浣嶇疆璁㈤槄閫氱煡
 	public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition";
@@ -94,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/DynamicTask.java b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
index ade2e62..1885632 100644
--- a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
+++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java
@@ -5,6 +5,7 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
 import org.springframework.stereotype.Component;
 
@@ -103,12 +104,9 @@
 
     public void stop(String key) {
         if (futureMap.get(key) != null && !futureMap.get(key).isCancelled()) {
-//            Runnable runnable = runnableMap.get(key);
-//            if (runnable instanceof ISubscribeTask) {
-//                ISubscribeTask subscribeTask = (ISubscribeTask) runnable;
-//                subscribeTask.stop();
-//            }
             futureMap.get(key).cancel(false);
+            futureMap.remove(key);
+            runnableMap.remove(key);
         }
     }
 
@@ -123,4 +121,19 @@
     public Runnable get(String key) {
         return runnableMap.get(key);
     }
+
+    /**
+     * 姣忎簲鍒嗛挓妫�鏌ュけ鏁堢殑浠诲姟锛屽苟绉婚櫎
+     */
+    @Scheduled(cron="0 0/5 * * * ?")
+    public void execute(){
+        if (futureMap.size() > 0) {
+            for (String key : futureMap.keySet()) {
+                if (futureMap.get(key).isDone()) {
+                    futureMap.remove(key);
+                    runnableMap.remove(key);
+                }
+            }
+        }
+    }
 }
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/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/domain/req/PresetQuerySipReq.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java
similarity index 90%
rename from src/main/java/com/genersoft/iot/vmp/domain/req/PresetQuerySipReq.java
rename to src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java
index e2f3ec6..d1971a2 100644
--- a/src/main/java/com/genersoft/iot/vmp/domain/req/PresetQuerySipReq.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java
@@ -1,4 +1,4 @@
-package com.genersoft.iot.vmp.domain.req;
+package com.genersoft.iot.vmp.gb28181.bean;
 
 
 /**
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/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/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
index 73f9c4f..10f428b 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/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
index 376d74b..c8a221b 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;
@@ -70,6 +71,9 @@
 
 	@Autowired
 	private SIPProcessorObserver sipProcessorObserver;
+
+	@Autowired
+	private IDeviceChannelService deviceChannelService;
 
 	private boolean taskQueueHandlerRun = false;
 
@@ -173,28 +177,7 @@
 			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 +185,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 +271,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: 闇�瑕佸疄鐜板瓨鍌ㄦ姤璀︿俊鎭�佹姤璀﹀垎绫�
@@ -364,7 +344,7 @@
 					}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());
 					switch (event) {
@@ -389,7 +369,7 @@
 						case CatalogEvent.ADD:
 							// 澧炲姞
 							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑澧炲姞閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId());
-							storager.updateChannel(deviceId, channel);
+							deviceChannelService.updateChannel(deviceId, channel);
 							break;
 						case CatalogEvent.DEL:
 							// 鍒犻櫎
@@ -399,7 +379,7 @@
 						case CatalogEvent.UPDATE:
 							// 鏇存柊
 							logger.info("鏀跺埌鏉ヨ嚜璁惧銆恵}銆戠殑鏇存柊閫氶亾銆恵}銆戦�氱煡", device.getDeviceId(), channel.getChannelId());
-							storager.updateChannel(deviceId, channel);
+							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/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..265694a 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;
@@ -57,6 +58,9 @@
 
     @Autowired
     private IDeviceAlarmService deviceAlarmService;
+
+    @Autowired
+    private IDeviceChannelService deviceChannelService;
 
     @Override
     public void afterPropertiesSet() throws Exception {
@@ -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/response/cmd/CatalogResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
index 2766474..66e92c5 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
@@ -125,11 +125,7 @@
                                     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);
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/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
index 3662600..45265c5 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java
@@ -1,6 +1,6 @@
 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
 
-import com.genersoft.iot.vmp.domain.req.PresetQuerySipReq;
+import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
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 7f6ea02..055cccb 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
@@ -1,7 +1,8 @@
 package com.genersoft.iot.vmp.media.zlm;
 
-import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.alibaba.fastjson.JSON;
 import com.genersoft.iot.vmp.common.StreamInfo;
@@ -21,6 +22,7 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -80,7 +82,13 @@
 	private UserSetting userSetting;
 
 	@Autowired
+	private IUserService userService;
+
+	@Autowired
 	private VideoStreamSessionManager sessionManager;
+
+	@Autowired
+	private AssistRESTfulUtils assistRESTfulUtils;
 
 	/**
 	 * 鏈嶅姟鍣ㄥ畾鏃朵笂鎶ユ椂闂达紝涓婃姤闂撮殧鍙厤缃紝榛樿10s涓婃姤涓�娆�
@@ -151,12 +159,14 @@
 	 */
 	@ResponseBody
 	@PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8")
-	public ResponseEntity<String> onPlay(@RequestBody JSONObject json){
-		
+	public ResponseEntity<String> onPlay(@RequestBody OnPlayHookParam param){
+
+		JSONObject json = (JSONObject)JSON.toJSON(param);
+
 		if (logger.isDebugEnabled()) {
-			logger.debug("[ ZLM HOOK ]on_play API璋冪敤锛屽弬鏁帮細" + json.toString());
+			logger.debug("[ ZLM HOOK ]on_play API璋冪敤锛屽弬鏁帮細" + JSON.toJSONString(param));
 		}
-		String mediaServerId = json.getString("mediaServerId");
+		String mediaServerId = param.getMediaServerId();
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json);
 		if (subscribe != null ) {
 			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
@@ -165,9 +175,20 @@
 			}
 		}
 		JSONObject ret = new JSONObject();
+		if (!"rtp".equals(param.getApp())) {
+			Map<String, String> paramMap = urlParamToMap(param.getParams());
+			StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
+			if (streamAuthorityInfo == null
+					|| (streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId")))) {
+				ret.put("code", 401);
+				ret.put("msg", "Unauthorized");
+				return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
+			}
+		}
+
 		ret.put("code", 0);
 		ret.put("msg", "success");
-		return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
+		return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
 	}
 	
 	/**
@@ -176,23 +197,61 @@
 	 */
 	@ResponseBody
 	@PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8")
-	public ResponseEntity<String> onPublish(@RequestBody JSONObject json) {
+	public ResponseEntity<String> onPublish(@RequestBody OnPublishHookParam param) {
+
+		JSONObject json = (JSONObject) JSON.toJSON(param);
 
 		logger.info("[ ZLM HOOK ]on_publish API璋冪敤锛屽弬鏁帮細" + json.toString());
 		JSONObject ret = new JSONObject();
+		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)");
+				ret.put("code", 401);
+				ret.put("msg", "Unauthorized");
+				return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
+			}
+			Map<String, String> paramMap = urlParamToMap(param.getParams());
+			String sign = paramMap.get("sign");
+			if (sign == null) {
+				logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯涓嶈鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)");
+				ret.put("code", 401);
+				ret.put("msg", "Unauthorized");
+				return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
+			}
+			// 鎺ㄦ祦鑷畾涔夋挱鏀鹃壌鏉冪爜
+			String callId = paramMap.get("callId");
+			// 閴存潈閰嶇疆
+			boolean hasAuthority = userService.checkPushAuthority(callId, sign);
+			if (!hasAuthority) {
+				logger.info("鎺ㄦ祦閴存潈澶辫触锛� sign 鏃犳潈闄�: callId={}. sign={}", callId, sign);
+				ret.put("code", 401);
+				ret.put("msg", "Unauthorized");
+				return new ResponseEntity<>(ret.toString(), HttpStatus.OK);
+			}
+			StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
+			streamAuthorityInfo.setCallId(callId);
+			streamAuthorityInfo.setSign(sign);
+			// 閴存潈閫氳繃
+			redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
+			// 閫氱煡assist鏂扮殑callId
+			if (mediaInfo != null) {
+				assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
+			}
+		}
+
 		ret.put("code", 0);
 		ret.put("msg", "success");
 		ret.put("enable_hls", true);
-		if (json.getInteger("originType") == 1
-				|| json.getInteger("originType") == 2
-				|| json.getInteger("originType") == 3) {
+		if (!"rtp".equals(param.getApp())) {
 			ret.put("enable_audio", true);
 		}
 
-		String mediaServerId = json.getString("mediaServerId");
+
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
 		if (subscribe != null) {
-			MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
 			if (mediaInfo != null) {
 				subscribe.response(mediaInfo, json);
 			}else {
@@ -200,14 +259,13 @@
 				ret.put("msg", "zlm not register");
 			}
 		}
-	 	String app = json.getString("app");
-	 	String stream = json.getString("stream");
-		if ("rtp".equals(app)) {
+
+		if ("rtp".equals(param.getApp())) {
 			ret.put("enable_mp4", userSetting.getRecordSip());
 		}else {
 			ret.put("enable_mp4", userSetting.isRecordPushLive());
 		}
-		List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, stream);
+		List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream());
 		if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) {
 			String deviceId = ssrcTransactionForAll.get(0).getDeviceId();
 			String channelId = ssrcTransactionForAll.get(0).getChannelId();
@@ -220,14 +278,17 @@
 				ret.put("mp4_max_second", 10);
 				ret.put("enable_mp4", true);
 				ret.put("enable_audio", true);
-			}
 
+			}
 		}
+
 
 
 		return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
 	}
-	
+
+
+
 	/**
 	 * 褰曞埗mp4瀹屾垚鍚庨�氱煡浜嬩欢锛涙浜嬩欢瀵瑰洖澶嶄笉鏁忔劅銆�
 	 *  
@@ -312,9 +373,6 @@
 		if (logger.isDebugEnabled()) {
 			logger.debug("[ ZLM HOOK ]on_shell_login API璋冪敤锛屽弬鏁帮細" + json.toString());
 		}
-		// TODO 濡傛灉鏄甫鏈塺tpstream鍒欏紑鍚寜闇�鎷夋祦
-		// String app = json.getString("app");
-		// String stream = json.getString("stream");
 		String mediaServerId = json.getString("mediaServerId");
 		ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json);
 		if (subscribe != null ) {
@@ -351,12 +409,24 @@
 		}
 		// 娴佹秷澶辩Щ闄edis play
 		String app = item.getApp();
-		String streamId = item.getStream();
+		String stream = item.getStream();
 		String schema = item.getSchema();
 		List<MediaItem.MediaTrack> tracks = item.getTracks();
 		boolean regist = item.isRegist();
+		if (regist) {
+			StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
+			if (streamAuthorityInfo == null) {
+				streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(item);
+			}else {
+				streamAuthorityInfo.setOriginType(item.getOriginType());
+				streamAuthorityInfo.setOriginTypeStr(item.getOriginTypeStr());
+			}
+			redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo);
+		}else {
+			redisCatchStorage.removeStreamAuthorityInfo(app, stream);
+		}
 		if ("rtmp".equals(schema)){
-			logger.info("on_stream_changed锛氭敞鍐�->{}, app->{}, stream->{}", regist, app, streamId);
+			logger.info("on_stream_changed锛氭敞鍐�->{}, app->{}, stream->{}", regist, app, stream);
 			if (regist) {
 				mediaServerService.addCount(mediaServerId);
 			}else {
@@ -365,15 +435,15 @@
 			if (item.getOriginType() == OriginType.PULL.ordinal()
 					|| item.getOriginType() == OriginType.FFMPEG_PULL.ordinal()) {
 				// 璁剧疆鎷夋祦浠g悊涓婄嚎/绂荤嚎
-				streamProxyService.updateStatus(regist, app, streamId);
+				streamProxyService.updateStatus(regist, app, stream);
 			}
 			if ("rtp".equals(app) && !regist ) {
-				StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
+				StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(stream);
 				if (streamInfo!=null){
 					redisCatchStorage.stopPlay(streamInfo);
 					storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
 				}else{
-					streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
+					streamInfo = redisCatchStorage.queryPlayback(null, null, stream, null);
 					if (streamInfo != null) {
 						redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(),
 								streamInfo.getStream(), null);
@@ -387,10 +457,12 @@
 
 					if (mediaServerItem != null){
 						if (regist) {
-							StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks);
+							StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
+							StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
+									app, stream, tracks, streamAuthorityInfo.getCallId());
 							item.setStreamInfo(streamInfoByAppAndStream);
-
-							redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
+							item.setSeverId(userSetting.getServerId());
+							redisCatchStorage.addStream(mediaServerItem, type, app, stream, item);
 							if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
 									|| item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
 									|| item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) {
@@ -413,23 +485,23 @@
 
 						}else {
 							// 鍏煎娴佹敞閿�鏃剁被鍨嬩粠redis璁板綍鑾峰彇
-							MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, streamId, mediaServerId);
+							MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, stream, mediaServerId);
 							if (mediaItem != null) {
 								type = OriginType.values()[mediaItem.getOriginType()].getType();
-								redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId);
+								redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, stream);
 							}
-							GbStream gbStream = storager.getGbStream(app, streamId);
+							GbStream gbStream = storager.getGbStream(app, stream);
 							if (gbStream != null) {
 //								eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
 							}
-							zlmMediaListManager.removeMedia(app, streamId);
+							zlmMediaListManager.removeMedia(app, stream);
 						}
 						if (type != null) {
 							// 鍙戦�佹祦鍙樺寲redis娑堟伅
 							JSONObject jsonObject = new JSONObject();
 							jsonObject.put("serverId", userSetting.getServerId());
 							jsonObject.put("app", app);
-							jsonObject.put("stream", streamId);
+							jsonObject.put("stream", stream);
 							jsonObject.put("register", regist);
 							jsonObject.put("mediaServerId", mediaServerId);
 							redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
@@ -565,4 +637,22 @@
 		ret.put("msg", "success");
 		return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
 	}
+
+	private Map<String, String> urlParamToMap(String params) {
+		HashMap<String, String> map = new HashMap<>();
+		if (StringUtils.isEmpty(params)) {
+			return map;
+		}
+		String[] paramsArray = params.split("&");
+		if (paramsArray.length == 0) {
+			return map;
+		}
+		for (String param : paramsArray) {
+			String[] paramArray = param.split("=");
+			if (paramArray.length == 2){
+				map.put(paramArray[0], paramArray[1]);
+			}
+		}
+		return map;
+	}
 }
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 35069aa..3d9b7cb 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
@@ -115,64 +115,16 @@
     public StreamPushItem addPush(MediaItem mediaItem) {
         // 鏌ユ壘姝ょ洿鎾祦鏄惁瀛樺湪redis棰勮gbId
         StreamPushItem transform = streamPushService.transform(mediaItem);
-        // 浠巗treamId鍙栧嚭鏌ヨ鍏抽敭鍊�
-        Pattern pattern = Pattern.compile(userSetting.getThirdPartyGBIdReg());
-        Matcher matcher = pattern.matcher(mediaItem.getStream());// 鎸囧畾瑕佸尮閰嶇殑瀛楃涓�
-        String queryKey = null;
-        if (matcher.find()) { //姝ゅfind锛堬級姣忔琚皟鐢ㄥ悗锛屼細鍋忕Щ鍒颁笅涓�涓尮閰�
-            queryKey = matcher.group();
+        StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
+        transform.setPushIng(true);
+        transform.setUpdateTime(DateUtil.getNow());
+        transform.setPushTime(DateUtil.getNow());
+        if (pushInDb == null) {
+            transform.setCreateTime(DateUtil.getNow());
+            streamPushMapper.add(transform);
+        }else {
+            streamPushMapper.update(transform);
         }
-        if (queryKey != null) {
-            ThirdPartyGB thirdPartyGB = redisCatchStorage.queryMemberNoGBId(queryKey);
-            if (thirdPartyGB != null && !StringUtils.isEmpty(thirdPartyGB.getNationalStandardNo())) {
-                transform.setGbId(thirdPartyGB.getNationalStandardNo());
-                transform.setName(thirdPartyGB.getName());
-            }
-        }
-        if (!StringUtils.isEmpty(transform.getGbId())) {
-            // 濡傛灉杩欎釜鍥芥爣ID宸茬粡缁欎簡鍏朵粬鎺ㄦ祦涓旀祦宸茬绾匡紝鍒欑Щ闄ゅ叾浠栨帹娴�
-            List<GbStream> gbStreams = gbStreamMapper.selectByGBId(transform.getGbId());
-            if (gbStreams.size() > 0) {
-                for (GbStream gbStream : gbStreams) {
-                    // 鍑虹幇浣跨敤鐩稿悓鍥芥爣Id鐨勮棰戞祦鏃讹紝浣跨敤鏂版祦鏇挎崲鏃ф祦锛�
-                    if (queryKey != null && gbStream.getApp().equals(mediaItem.getApp())) {
-                        Matcher matcherForStream = pattern.matcher(gbStream.getStream());
-                        String queryKeyForStream = null;
-                        if (matcherForStream.find()) { //姝ゅfind锛堬級姣忔琚皟鐢ㄥ悗锛屼細鍋忕Щ鍒颁笅涓�涓尮閰�
-                            queryKeyForStream = matcherForStream.group();
-                        }
-                        if (queryKeyForStream == null || !queryKeyForStream.equals(queryKey)) {
-                            // 姝ゆ椂涓嶆槸鍚屼竴涓祦
-                            gbStreamMapper.del(gbStream.getApp(), gbStream.getStream());
-                            if (!gbStream.isStatus()) {
-                                streamPushMapper.del(gbStream.getApp(), gbStream.getStream());
-                            }
-                        }
-                    }
-                }
-            }
-            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());
-                }
-            }
-        }
-
-        storager.updateMedia(transform);
         return transform;
     }
 
@@ -206,13 +158,13 @@
 
     public int removeMedia(String app, String streamId) {
         // 鏌ユ壘鏄惁鍏宠仈浜嗗浗鏍囷紝 鍏宠仈浜嗕笉鍒犻櫎锛� 缃负绂荤嚎
-        StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(app, streamId);
-        int result = 0;
-        if (streamProxyItem == null) {
+        GbStream gbStream = gbStreamMapper.selectOne(app, streamId);
+        int result;
+        if (gbStream == null) {
             result = storager.removeMedia(app, streamId);
         }else {
             // TODO 鏆備笉璁剧疆涓虹绾�
-            result =storager.mediaOutline(app, streamId);
+            result =storager.mediaOffline(app, streamId);
         }
         return result;
     }
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 2a99b1b..cbef9ce 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
@@ -66,7 +66,7 @@
         String stream = UUID.randomUUID().toString();
         param.put("enable_tcp", 1);
         param.put("stream_id", stream);
-        param.put("port", 0);
+//        param.put("port", 0);
         JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
 
         if (openRtpServerResultJson != null) {
@@ -101,9 +101,10 @@
         }
 
         Map<String, Object> param = new HashMap<>();
-        // 鎺ㄦ祦绔彛璁剧疆0鍒欎娇鐢ㄩ殢鏈虹鍙�
+
         param.put("enable_tcp", 1);
         param.put("stream_id", streamId);
+        // 鎺ㄦ祦绔彛璁剧疆0鍒欎娇鐢ㄩ殢鏈虹鍙�
         param.put("port", 0);
         param.put("ssrc", ssrc);
         JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
@@ -291,7 +292,7 @@
             logger.warn("鏌ヨ娴�({}/{})鏄惁鏈夊叾瀹冭鐪嬭�呮椂寰楀埌锛� {}", app, streamId, mediaInfo.getString("msg"));
             return -1;
         }
-        if ( code == 0 && ! mediaInfo.getBoolean("online")) {
+        if ( code == 0 && mediaInfo.getBoolean("online") != null && !mediaInfo.getBoolean("online")) {
             logger.warn("鏌ヨ娴�({}/{})鏄惁鏈夊叾瀹冭鐪嬭�呮椂寰楀埌锛� {}", app, streamId, mediaInfo.getString("msg"));
             return -1;
         }
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookParam.java
new file mode 100644
index 0000000..50e3723
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookParam.java
@@ -0,0 +1,17 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+/**
+ * zlm hook浜嬩欢鐨勫弬鏁�
+ * @author lin
+ */
+public class HookParam {
+    private String mediaServerId;
+
+    public String getMediaServerId() {
+        return mediaServerId;
+    }
+
+    public void setMediaServerId(String mediaServerId) {
+        this.mediaServerId = mediaServerId;
+    }
+}
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/OnPlayHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPlayHookParam.java
new file mode 100644
index 0000000..92ecb47
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPlayHookParam.java
@@ -0,0 +1,82 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+/**
+ * zlm hook浜嬩欢涓殑on_play浜嬩欢鐨勫弬鏁�
+ * @author lin
+ */
+public class OnPlayHookParam extends HookParam{
+    private String id;
+    private String app;
+    private String stream;
+    private String ip;
+    private String params;
+    private int port;
+    private String schema;
+    private String vhost;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
+    public String getStream() {
+        return stream;
+    }
+
+    public void setStream(String stream) {
+        this.stream = stream;
+    }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public void setIp(String ip) {
+        this.ip = ip;
+    }
+
+    public String getParams() {
+        return params;
+    }
+
+    public void setParams(String params) {
+        this.params = params;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getSchema() {
+        return schema;
+    }
+
+    public void setSchema(String schema) {
+        this.schema = schema;
+    }
+
+    public String getVhost() {
+        return vhost;
+    }
+
+    public void setVhost(String vhost) {
+        this.vhost = vhost;
+    }
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPublishHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPublishHookParam.java
new file mode 100644
index 0000000..354c119
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/OnPublishHookParam.java
@@ -0,0 +1,82 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+/**
+ * zlm hook浜嬩欢涓殑on_publish浜嬩欢鐨勫弬鏁�
+ * @author lin
+ */
+public class OnPublishHookParam extends HookParam{
+    private String id;
+    private String app;
+    private String stream;
+    private String ip;
+    private String params;
+    private int port;
+    private String schema;
+    private String vhost;
+
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
+    public String getStream() {
+        return stream;
+    }
+
+    public void setStream(String stream) {
+        this.stream = stream;
+    }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public void setIp(String ip) {
+        this.ip = ip;
+    }
+
+    public String getParams() {
+        return params;
+    }
+
+    public void setParams(String params) {
+        this.params = params;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getSchema() {
+        return schema;
+    }
+
+    public void setSchema(String schema) {
+        this.schema = schema;
+    }
+
+    public String getVhost() {
+        return vhost;
+    }
+
+    public void setVhost(String vhost) {
+        this.vhost = vhost;
+    }
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java
new file mode 100644
index 0000000..36a0363
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java
@@ -0,0 +1,114 @@
+package com.genersoft.iot.vmp.media.zlm.dto;
+
+/**
+ * 娴佺殑閴存潈淇℃伅
+ * @author lin
+ */
+public class StreamAuthorityInfo {
+
+    private String id;
+    private String app;
+    private String stream;
+
+    /**
+     * 浜х敓婧愮被鍨嬶紝
+     * unknown = 0,
+     * rtmp_push=1,
+     * rtsp_push=2,
+     * rtp_push=3,
+     * pull=4,
+     * ffmpeg_pull=5,
+     * mp4_vod=6,
+     * device_chn=7
+     */
+    private int originType;
+
+    /**
+     * 浜х敓婧愮被鍨嬬殑瀛楃涓叉弿杩�
+     */
+    private String originTypeStr;
+
+    /**
+     * 鎺ㄦ祦鏃惰嚜瀹氫箟鐨勬挱鏀鹃壌鏉僆D
+     */
+    private String callId;
+
+    /**
+     * 鎺ㄦ祦鐨勯壌鏉冪鍚�
+     */
+    private String sign;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
+    public String getStream() {
+        return stream;
+    }
+
+    public void setStream(String stream) {
+        this.stream = stream;
+    }
+
+    public int getOriginType() {
+        return originType;
+    }
+
+    public void setOriginType(int originType) {
+        this.originType = originType;
+    }
+
+    public String getOriginTypeStr() {
+        return originTypeStr;
+    }
+
+    public void setOriginTypeStr(String originTypeStr) {
+        this.originTypeStr = originTypeStr;
+    }
+
+    public String getCallId() {
+        return callId;
+    }
+
+    public void setCallId(String callId) {
+        this.callId = callId;
+    }
+
+    public String getSign() {
+        return sign;
+    }
+
+    public void setSign(String sign) {
+        this.sign = sign;
+    }
+
+    public static StreamAuthorityInfo getInstanceByHook(OnPublishHookParam hookParam) {
+        StreamAuthorityInfo streamAuthorityInfo = new StreamAuthorityInfo();
+        streamAuthorityInfo.setApp(hookParam.getApp());
+        streamAuthorityInfo.setStream(hookParam.getStream());
+        streamAuthorityInfo.setId(hookParam.getId());
+        return streamAuthorityInfo;
+    }
+
+    public static StreamAuthorityInfo getInstanceByHook(MediaItem mediaItem) {
+        StreamAuthorityInfo streamAuthorityInfo = new StreamAuthorityInfo();
+        streamAuthorityInfo.setApp(mediaItem.getApp());
+        streamAuthorityInfo.setStream(mediaItem.getStream());
+        streamAuthorityInfo.setId(mediaItem.getMediaServerId());
+        streamAuthorityInfo.setOriginType(mediaItem.getOriginType());
+        streamAuthorityInfo.setOriginTypeStr(mediaItem.getOriginTypeStr());
+        return streamAuthorityInfo;
+    }
+}
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..d583006 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,11 @@
      */
     private String createTime;
 
+    /**
+     * 鏄惁姝e湪鎺ㄦ祦
+     */
+    private boolean pushIng;
+
     public String getVhost() {
         return vhost;
     }
@@ -277,5 +282,13 @@
     public void setCreateTime(String createTime) {
         this.createTime = createTime;
     }
+
+    public boolean isPushIng() {
+        return pushIng;
+    }
+
+    public void setPushIng(boolean pushIng) {
+        this.pushIng = pushIng;
+    }
 }
 
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/IMediaService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
index 8c05b85..b5431c9 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java
@@ -15,7 +15,7 @@
      * @param stream
      * @return
      */
-    StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr);
+    StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr, boolean authority);
 
 
     /**
@@ -24,7 +24,7 @@
      * @param stream
      * @return
      */
-    StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId);
+    StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority);
 
     /**
      * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴
@@ -32,7 +32,7 @@
      * @param stream
      * @return
      */
-    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Object tracks);
+    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Object tracks, String callId);
 
     /**
      * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴锛岃繑鍥炵殑ip浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌
@@ -40,5 +40,5 @@
      * @param stream
      * @return
      */
-    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr);
+    StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId);
 }
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..5dd45ef 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,55 @@
      * 鍋滄涓�璺帹娴�
      * @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);
+
 }
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 c170c02..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;
 
@@ -19,4 +20,10 @@
     List<User> getAllUsers();
 
     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/bean/PushStreamStatusChangeFromRedisDto.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PushStreamStatusChangeFromRedisDto.java
new file mode 100644
index 0000000..5bb7b77
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/bean/PushStreamStatusChangeFromRedisDto.java
@@ -0,0 +1,41 @@
+package com.genersoft.iot.vmp.service.bean;
+
+import java.util.List;
+
+/**
+ * 鏀跺埌redis閫氱煡淇敼鎺ㄦ祦閫氶亾鐘舵��
+ * @author lin
+ */
+public class PushStreamStatusChangeFromRedisDto {
+
+    private boolean setAllOffline;
+
+    private List<StreamPushItemFromRedis> onlineStreams;
+
+    private List<StreamPushItemFromRedis> offlineStreams;
+
+
+    public boolean isSetAllOffline() {
+        return setAllOffline;
+    }
+
+    public void setSetAllOffline(boolean setAllOffline) {
+        this.setAllOffline = setAllOffline;
+    }
+
+    public List<StreamPushItemFromRedis> getOnlineStreams() {
+        return onlineStreams;
+    }
+
+    public void setOnlineStreams(List<StreamPushItemFromRedis> onlineStreams) {
+        this.onlineStreams = onlineStreams;
+    }
+
+    public List<StreamPushItemFromRedis> getOfflineStreams() {
+        return offlineStreams;
+    }
+
+    public void setOfflineStreams(List<StreamPushItemFromRedis> offlineStreams) {
+        this.offlineStreams = offlineStreams;
+    }
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/StreamPushItemFromRedis.java b/src/main/java/com/genersoft/iot/vmp/service/bean/StreamPushItemFromRedis.java
new file mode 100644
index 0000000..ff32d79
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/bean/StreamPushItemFromRedis.java
@@ -0,0 +1,34 @@
+package com.genersoft.iot.vmp.service.bean;
+
+
+public class StreamPushItemFromRedis {
+    private String app;
+    private String stream;
+    private long timeStamp;
+
+    public String getApp() {
+        return app;
+    }
+
+    public void setApp(String app) {
+        this.app = app;
+    }
+
+    public String getStream() {
+        return stream;
+    }
+
+    public void setStream(String stream) {
+        this.stream = stream;
+    }
+
+    public long getTimeStamp() {
+        return timeStamp;
+    }
+
+    public void setTimeStamp(long timeStamp) {
+        this.timeStamp = timeStamp;
+    }
+}
+
+
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..579184c 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;
@@ -54,6 +55,9 @@
 
     @Autowired
     private DeviceMapper deviceMapper;
+
+    @Autowired
+    private IDeviceChannelService deviceChannelService;
 
     @Autowired
     private DeviceChannelMapper deviceChannelMapper;
@@ -324,23 +328,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 +345,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 +379,7 @@
 
         }
         // 浣跨敤涓氬姟鍒嗙粍灞曠ず鏍�
-        if ("BusinessGroup".equals(device.getTreeType())) {
+        if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
             if (parentId.length() < 14 ) {
                 return null;
             }
@@ -406,11 +399,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 +424,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 c813b11..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);
@@ -149,9 +157,9 @@
         if (gbStream.getGbId() != null) {
             gbStreams.add(gbStream);
         }else {
-            StreamProxyItem streamProxyItem = gbStreamMapper.selectOne(gbStream.getApp(), gbStream.getStream());
-            if (streamProxyItem != null && streamProxyItem.getGbId() != null){
-                gbStreams.add(streamProxyItem);
+            GbStream gbStreamIndb  = gbStreamMapper.selectOne(gbStream.getApp(), gbStream.getStream());
+            if (gbStreamIndb != null && gbStreamIndb.getGbId() != null){
+                gbStreams.add(gbStreamIndb);
             }
         }
         sendCatalogMsgs(gbStreams, type);
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 2c084a5..fb7cea0 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
@@ -7,12 +7,15 @@
 import com.genersoft.iot.vmp.conf.MediaConfig;
 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+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.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.service.IMediaService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
 
 @Service
 public class MediaServiceImpl implements IMediaService {
@@ -36,18 +39,22 @@
 
 
     @Override
-    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks) {
-        return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
+    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String callId) {
+        return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, callId);
     }
 
     @Override
-    public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) {
+    public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr, boolean authority) {
         StreamInfo streamInfo = null;
         if (mediaServerId == null) {
             mediaServerId = mediaConfig.getId();
         }
-        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);;
+        MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
         if (mediaInfo == null) {
+            return null;
+        }
+        StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
+        if (streamAuthorityInfo == null) {
             return null;
         }
         JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream);
@@ -59,7 +66,12 @@
                 }
                 JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
                 JSONArray tracks = mediaJSON.getJSONArray("tracks");
-                streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks);
+                if (authority) {
+                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, streamAuthorityInfo.getCallId());
+                }else {
+                    streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null);
+                }
+
             }
         }
         return streamInfo;
@@ -68,46 +80,48 @@
 
 
     @Override
-    public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId) {
-        return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null);
+    public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority) {
+        return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null, authority);
     }
 
     @Override
-    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) {
+    public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId) {
         StreamInfo streamInfoResult = new StreamInfo();
         streamInfoResult.setStream(stream);
         streamInfoResult.setApp(app);
         if (addr == null) {
             addr = mediaInfo.getStreamIp();
         }
+        streamInfoResult.setIp(addr);
         streamInfoResult.setMediaServerId(mediaInfo.getId());
-        streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", addr, mediaInfo.getRtmpPort(), app,  stream));
+        String callIdParam = StringUtils.isEmpty(callId)?"":"?callId=" + callId;
+        streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s%s", addr, mediaInfo.getRtmpPort(), app,  stream, callIdParam));
         if (mediaInfo.getRtmpSSlPort() != 0) {
-            streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s", addr, mediaInfo.getRtmpSSlPort(), app,  stream));
+            streamInfoResult.setRtmps(String.format("rtmps://%s:%s/%s/%s%s", addr, mediaInfo.getRtmpSSlPort(), app,  stream, callIdParam));
         }
-        streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", addr, mediaInfo.getRtspPort(), app,  stream));
+        streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s%s", addr, mediaInfo.getRtspPort(), app,  stream, callIdParam));
         if (mediaInfo.getRtspSSLPort() != 0) {
-            streamInfoResult.setRtsps(String.format("rtsps://%s:%s/%s/%s", addr, mediaInfo.getRtspSSLPort(), app,  stream));
+            streamInfoResult.setRtsps(String.format("rtsps://%s:%s/%s/%s%s", addr, mediaInfo.getRtspSSLPort(), app,  stream, callIdParam));
         }
-        streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpPort(), app,  stream));
-        streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpPort(), app,  stream));
+        streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
+        streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpPort(), app,  stream, callIdParam));
         if (mediaInfo.getHttpSSlPort() != 0) {
-            streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setHttps_hls(String.format("https://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setWss_hls(String.format("wss://%s:%s/%s/%s/hls.m3u8", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setHttps_fmp4(String.format("https://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setWss_fmp4(String.format("wss://%s:%s/%s/%s.live.mp4", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts", addr, mediaInfo.getHttpSSlPort(), app,  stream));
-            streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app,  stream));
+            streamInfoResult.setHttps_flv(String.format("https://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setWss_flv(String.format("wss://%s:%s/%s/%s.live.flv%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setHttps_hls(String.format("https://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setWss_hls(String.format("wss://%s:%s/%s/%s/hls.m3u8%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setHttps_fmp4(String.format("https://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setWss_fmp4(String.format("wss://%s:%s/%s/%s.live.mp4%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setHttps_ts(String.format("https://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setWss_ts(String.format("wss://%s:%s/%s/%s.live.ts%s", addr, mediaInfo.getHttpSSlPort(), app,  stream, callIdParam));
+            streamInfoResult.setRtc(String.format("https://%s:%s/index/api/webrtc?app=%s&stream=%s&type=play%s", mediaInfo.getStreamIp(), mediaInfo.getHttpSSlPort(), app,  stream, StringUtils.isEmpty(callId)?"":"&callId=" + callId));
         }
 
         streamInfoResult.setTracks(tracks);
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 041fdf0..ddfbc79 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
@@ -620,7 +620,7 @@
     public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) {
         String streamId = resonse.getString("stream");
         JSONArray tracks = resonse.getJSONArray("tracks");
-        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
+        StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks, null);
         streamInfo.setDeviceID(deviceId);
         streamInfo.setChannelId(channelId);
         return streamInfo;
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 238aafd..7482833 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
@@ -25,9 +25,7 @@
 
     @Override
     public void onMessage(@NotNull Message message, byte[] bytes) {
-        if (logger.isDebugEnabled()) {
-            logger.debug("鏀跺埌鏉ヨ嚜REDIS鐨凣PS閫氱煡锛� {}", new String(message.getBody()));
-        }
+        // TODO 鍔犳秷鎭槦鍒�
         GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
         redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
     }
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..27e4a7d
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java
@@ -0,0 +1,92 @@
+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.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.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.data.redis.connection.Message;
+import org.springframework.data.redis.connection.MessageListener;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 鎺ユ敹redis鍙戦�佺殑鎺ㄦ祦璁惧涓婄嚎涓嬬嚎閫氱煡
+ * @author lin
+ */
+@Component
+public class RedisPushStreamStatusMsgListener implements MessageListener, ApplicationRunner {
+
+    private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusMsgListener.class);
+
+    @Autowired
+    private IRedisCatchStorage redisCatchStorage;
+
+    @Autowired
+    private IStreamPushService streamPushService;
+
+    @Autowired
+    private EventPublisher eventPublisher;
+
+    @Autowired
+    private UserSetting userSetting;
+
+    @Autowired
+    private DynamicTask dynamicTask;
+
+    @Override
+    public void onMessage(Message message, byte[] bytes) {
+        PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(message.getBody(), PushStreamStatusChangeFromRedisDto.class);
+        if (statusChangeFromPushStream == null) {
+            logger.warn("[REDIS 娑堟伅]鎺ㄦ祦璁惧鐘舵�佸彉鍖栨秷鎭В鏋愬け璐�");
+            return;
+        }
+        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());
+        }
+    }
+
+    @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..83116f3 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
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 67dfb6f..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;
@@ -319,7 +382,7 @@
         }
         streamProxyMapper.deleteAutoRemoveItemByMediaServerId(mediaServerId);
         // 鍏朵粬鐨勬祦璁剧疆绂荤嚎
-        streamProxyMapper.updateStatusByMediaServerId(false, mediaServerId);
+        streamProxyMapper.updateStatusByMediaServerId(mediaServerId, false);
         String type = "PULL";
 
         // 鍙戦�乺edis娑堟伅
@@ -346,7 +409,7 @@
 
     @Override
     public int updateStatus(boolean status, String app, String stream) {
-        return streamProxyMapper.updateStatus(status, app, stream);
+        return streamProxyMapper.updateStatus(app, stream, status);
     }
 
     private void syncPullStream(String mediaServerId){
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 a8ef108..62cf20f 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
@@ -13,6 +13,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;
@@ -37,6 +38,9 @@
 
     @Autowired
     private StreamPushMapper streamPushMapper;
+
+    @Autowired
+    private StreamProxyMapper streamProxyMapper;
 
     @Autowired
     private ParentPlatformMapper parentPlatformMapper;
@@ -130,29 +134,6 @@
         stream.setStatus(true);
         stream.setCreateTime(DateUtil.getNow());
         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;
     }
 
@@ -178,7 +159,6 @@
 
     @Override
     public StreamPushItem getPush(String app, String streamId) {
-
         return streamPushMapper.selectOne(app, streamId);
     }
 
@@ -285,7 +265,8 @@
         streamPushMapper.deleteWithoutGBId(mediaServerId);
         gbStreamMapper.deleteWithoutGBId("push", mediaServerId);
         // 鍏朵粬鐨勬祦璁剧疆鏈惎鐢�
-        gbStreamMapper.updateStatusByMediaServerId(mediaServerId, false);
+        streamPushMapper.updateStatusByMediaServerId(mediaServerId, false);
+        streamProxyMapper.updateStatusByMediaServerId(mediaServerId, false);
         // 鍙戦�佹祦鍋滄娑堟伅
         String type = "PUSH";
         // 鍙戦�乺edis娑堟伅
@@ -341,31 +322,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
@@ -477,4 +433,34 @@
         }
         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);
+    }
 }
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 9f156d2..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,14 +3,17 @@
 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;
 
 import java.util.List;
 
 @Service
 public class UserServiceImpl implements IUserService {
-    
+
     @Autowired
     private UserMapper userMapper;
 
@@ -55,4 +58,24 @@
     }
 
 
+    @Override
+    public boolean checkPushAuthority(String callId, String sign) {
+        if (StringUtils.isEmpty(callId)) {
+            return userMapper.checkPushAuthorityByCallId(sign).size() > 0;
+        }else {
+            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 4a3aa78..b9811da 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -3,9 +3,7 @@
 import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.common.StreamInfo;
 import com.genersoft.iot.vmp.gb28181.bean.*;
-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.media.zlm.dto.*;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -213,4 +211,31 @@
      */
     public boolean deviceIsOnline(String deviceId);
 
+    /**
+     * 瀛樺偍鎺ㄦ祦鐨勯壌鏉冧俊鎭�
+     * @param app 搴旂敤鍚�
+     * @param stream 娴�
+     * @param streamAuthorityInfo 閴存潈淇℃伅
+     */
+    void updateStreamAuthorityInfo(String app, String stream, StreamAuthorityInfo streamAuthorityInfo);
+
+    /**
+     * 绉婚櫎鎺ㄦ祦鐨勯壌鏉冧俊鎭�
+     * @param app 搴旂敤鍚�
+     * @param streamId 娴�
+     */
+    void removeStreamAuthorityInfo(String app, String streamId);
+
+    /**
+     * 鑾峰彇鎺ㄦ祦鐨勯壌鏉冧俊鎭�
+     * @param app 搴旂敤鍚�
+     * @param stream 娴�
+     * @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 4ee9094..543d8c1 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,7 +297,7 @@
 	 * @param platformId
 	 * @return
 	 */
-	List<GbStream> queryGbStreamListInPlatform(String platformId);
+	List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
 
 	/**
 	 * 鎵归噺鏇存柊鎺ㄦ祦鍒楄〃
@@ -372,14 +335,16 @@
 
 	/**
 	 * 璁剧疆娴佺绾�
-	 * @param app
-	 * @param streamId
 	 */
-	int mediaOutline(String app, String streamId);
+	int mediaOffline(String app, String streamId);
+
+	/**
+	 * 璁剧疆娴佷笂绾�
+	 */
+	int mediaOnline(String app, String streamId);
 
 	/**
 	 * 璁剧疆骞冲彴鍦ㄧ嚎/绂荤嚎
-	 * @param online
 	 */
 	void updateParentPlatformStatus(String platformGbID, boolean online);
 
@@ -443,7 +408,7 @@
 
 	int setDefaultCatalog(String platformId, String catalogId);
 
-	List<PlatformCatalog> queryCatalogInPlatform(String serverGBId);
+	List<DeviceChannel> queryCatalogInPlatform(String serverGBId);
 
     int delRelation(PlatformCatalog platformCatalog);
 
@@ -464,4 +429,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..653e39d 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
@@ -329,5 +329,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 fa8381c..73fff57 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,15 +59,13 @@
             " <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}")
-    StreamProxyItem selectOne(String app, String stream);
+    GbStream selectOne(String app, String stream);
 
     @Select("SELECT * FROM gb_stream WHERE gbId=#{gbId}")
     List<GbStream> selectByGBId(String gbId);
@@ -78,25 +75,23 @@
             "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 " +
             "ON gs.gbStreamId = pgs.gbStreamId WHERE pgs.gbStreamId is NULL")
     List<GbStream> queryStreamNotInPlatform();
-
-    @Update("UPDATE gb_stream " +
-            "SET status=${status} " +
-            "WHERE app=#{app} AND stream=#{stream}")
-    int setStatus(String app, String stream, boolean status);
-
-    @Update("UPDATE gb_stream " +
-            "SET status=${status} " +
-            "WHERE mediaServerId=#{mediaServerId} ")
-    void updateStatusByMediaServerId(String mediaServerId, boolean status);
 
     @Delete("DELETE FROM gb_stream WHERE streamType=#{type} AND gbId=NULL AND mediaServerId=#{mediaServerId}")
     void deleteWithoutGBId(String type, String mediaServerId);
@@ -120,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")
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..4ed0f32 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,'0' 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/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
index 29c0b01..c05910e 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
@@ -62,12 +62,12 @@
     @Update("UPDATE stream_proxy " +
             "SET status=#{status} " +
             "WHERE mediaServerId=#{mediaServerId}")
-    void updateStatusByMediaServerId(boolean status, String mediaServerId);
+    void updateStatusByMediaServerId(String mediaServerId, boolean status);
 
     @Update("UPDATE stream_proxy " +
             "SET status=${status} " +
             "WHERE app=#{app} AND stream=#{stream}")
-    int updateStatus(boolean status, String app, String stream);
+    int updateStatus(String app, String stream, boolean status);
 
     @Delete("DELETE FROM stream_proxy WHERE enable_remove_none_reader=true AND mediaServerId=#{mediaServerId}")
     void deleteAutoRemoveItemByMediaServerId(String mediaServerId);
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 ebd3478..9921a70 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,21 +15,24 @@
 public interface StreamPushMapper {
 
     @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
-            "createStamp, aliveSecond, mediaServerId, serverId) VALUES" +
+            "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng) VALUES" +
             "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " +
-            "'${createStamp}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' )")
+            "'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}', ${pushIng} )")
     int add(StreamPushItem streamPushItem);
 
-    @Update("UPDATE stream_push " +
-            "SET app=#{app}," +
-            "stream=#{stream}," +
-            "mediaServerId=#{mediaServerId}," +
-            "totalReaderCount=#{totalReaderCount}, " +
-            "originType=#{originType}," +
-            "originTypeStr=#{originTypeStr}, " +
-            "createStamp=#{createStamp}, " +
-            "aliveSecond=#{aliveSecond} " +
-            "WHERE app=#{app} AND stream=#{stream}")
+
+    @Update(value = {" <script>" +
+            "UPDATE stream_push " +
+            "SET updateTime='${updateTime}'" +
+            "<if test=\"mediaServerId != null\">, mediaServerId='${mediaServerId}'</if>" +
+            "<if test=\"totalReaderCount != null\">, totalReaderCount='${totalReaderCount}'</if>" +
+            "<if test=\"originType != null\">, originType=${originType}</if>" +
+            "<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>" +
+            "WHERE app=#{app} AND stream=#{stream}"+
+            " </script>"})
     int update(StreamPushItem streamPushItem);
 
     @Delete("DELETE FROM stream_push WHERE app=#{app} AND stream=#{stream}")
@@ -62,7 +66,7 @@
     @Select(value = {" <script>" +
             "SELECT " +
             "st.*, " +
-            "gs.gbId, gs.status, gs.name, gs.longitude, gs.latitude, gs.gbStreamId " +
+            "gs.gbId, gs.name, gs.longitude, gs.latitude, gs.gbStreamId " +
             "from " +
             "stream_push st " +
             "LEFT JOIN gb_stream gs " +
@@ -70,25 +74,26 @@
             "WHERE " +
             "1=1 " +
             " <if test='query != null'> AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " +
-            " <if test='pushing == true' > AND (gs.gbId is null OR gs.status=1)</if>" +
-            " <if test='pushing == false' > AND gs.status=0</if>" +
+            " <if test='pushing == true' > AND (gs.gbId is null OR st.status=1)</if>" +
+            " <if test='pushing == false' > AND st.status=0</if>" +
             " <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" +
-            "order by st.createStamp desc" +
+            "order by st.createTime desc" +
             " </script>"})
     List<StreamPushItem> selectAllForList(String query, Boolean pushing, String mediaServerId);
 
-    @Select("SELECT st.*, gs.gbId, gs.status, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream order by st.createStamp desc")
+    @Select("SELECT st.*, gs.gbId, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream order by st.createTime desc")
     List<StreamPushItem> selectAll();
 
-    @Select("SELECT st.*, gs.gbId, gs.status, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream WHERE st.app=#{app} AND st.stream=#{stream}")
+    @Select("SELECT st.*, gs.gbId, gs.name, gs.longitude, gs.latitude FROM stream_push st LEFT JOIN gb_stream gs on st.app = gs.app AND st.stream = gs.stream WHERE st.app=#{app} AND st.stream=#{stream}")
     StreamPushItem selectOne(String app, String stream);
 
     @Insert("<script>"  +
             "Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
-            "createStamp, 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.createStamp}, #{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")
@@ -106,4 +111,59 @@
     @Select("SELECT sp.* FROM stream_push sp left join gb_stream gs on gs.app = sp.app and gs.stream= sp.stream WHERE sp.mediaServerId=#{mediaServerId} and gs.gbId is null")
     List<StreamPushItem> selectAllByMediaServerIdWithOutGbID(String mediaServerId);
 
+    @Update("UPDATE stream_push " +
+            "SET status=${status} " +
+            "WHERE app=#{app} AND stream=#{stream}")
+    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 status);
+
+    @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 addb27d..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
@@ -10,13 +10,14 @@
 @Repository
 public interface UserMapper {
 
-    @Insert("INSERT INTO user (username, password, roleId, createTime, updateTime) VALUES" +
-            "('${username}', '${password}', '${role.id}', '${createTime}', '${updateTime}')")
+    @Insert("INSERT INTO user (username, password, roleId, pushKey, createTime, updateTime) VALUES" +
+            "('${username}', '${password}', '${role.id}', '${pushKey}', '${createTime}', '${updateTime}')")
     int add(User user);
 
     @Update(value = {" <script>" +
             "UPDATE user " +
             "SET updateTime='${updateTime}' " +
+            "<if test=\"pushKey != null\">, pushKey='${pushKey}'</if>" +
             "<if test=\"role != null\">, roleId='${role.id}'</if>" +
             "<if test=\"password != null\">, password='${password}'</if>" +
             "<if test=\"username != null\">, username='${username}'</if>" +
@@ -48,4 +49,17 @@
     @Select("select u.*, r.id as roleID, r.name as roleName, r.authority as roleAuthority , r.createTime as roleCreateTime , r.updateTime as roleUpdateTime FROM user u, user_role r WHERE u.roleId=r.id")
     @ResultMap(value="roleMap")
     List<User> selectAll();
+
+    @Select("select * from (select user.*, concat('${callId}_', pushKey) as str1 from user) as u where md5(u.str1) = '${sign}'")
+    List<User> checkPushAuthorityByCallIdAndSign(String callId, String sign);
+
+    @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/dao/dto/User.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/dto/User.java
index 950a8ca..c9b4002 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/dao/dto/User.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/dto/User.java
@@ -7,6 +7,7 @@
     private String password;
     private String createTime;
     private String updateTime;
+    private String pushKey;
     private Role role;
 
     public int getId() {
@@ -56,4 +57,12 @@
     public void setRole(Role role) {
         this.role = role;
     }
+
+    public String getPushKey() {
+        return pushKey;
+    }
+
+    public void setPushKey(String pushKey) {
+        this.pushKey = 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 5377e23..b8b97ce 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
@@ -9,6 +9,8 @@
 import com.genersoft.iot.vmp.gb28181.bean.*;
 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.OnPublishHookParam;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
@@ -20,6 +22,7 @@
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
 
 import java.util.*;
 
@@ -482,7 +485,12 @@
 
     @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);
     }
 
@@ -599,6 +607,26 @@
     }
 
     @Override
+    public void updateStreamAuthorityInfo(String app, String stream, StreamAuthorityInfo streamAuthorityInfo) {
+        String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream;
+        redis.set(key, streamAuthorityInfo);
+    }
+
+    @Override
+    public void removeStreamAuthorityInfo(String app, String stream) {
+        String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
+        redis.del(key);
+    }
+
+    @Override
+    public StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream) {
+        String key = VideoManagerConstants.MEDIA_STREAM_AUTHORITY + userSetting.getServerId() + "_" + app+ "_" + stream ;
+        return (StreamAuthorityInfo) redis.get(key);
+
+    }
+
+
+    @Override
     public MediaItem getStreamInfo(String app, String streamId, String mediaServerId) {
         String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX  + userSetting.getServerId() + "_*_" + app + "_" + streamId + "_" + mediaServerId;
 
@@ -682,4 +710,14 @@
     public boolean deviceIsOnline(String deviceId) {
         return getDevice(deviceId).getOnline() == 1;
     }
+
+
+    @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 9a5be6e..c18c5d2 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);
 	}
 
@@ -848,7 +644,7 @@
 		streamPushMapper.addAll(streamPushItems);
 		// TODO 寰呬紭鍖�
 		for (int i = 0; i < streamPushItems.size(); i++) {
-			int onlineResult = gbStreamMapper.setStatus(streamPushItems.get(i).getApp(), streamPushItems.get(i).getStream(), true);
+			int onlineResult = mediaOnline(streamPushItems.get(i).getApp(), streamPushItems.get(i).getStream());
 			if (onlineResult > 0) {
 				// 鍙戦�佷笂绾块�氱煡
 				eventPublisher.catalogEventPublishForStream(null, streamPushItems.get(i), CatalogEvent.ON);
@@ -856,29 +652,13 @@
 		}
 	}
 
+
+
 	@Override
 	public void updateMedia(StreamPushItem streamPushItem) {
 		streamPushMapper.del(streamPushItem.getApp(), streamPushItem.getStream());
 		streamPushMapper.add(streamPushItem);
-		gbStreamMapper.setStatus(streamPushItem.getApp(), streamPushItem.getStream(), true);
-
-		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);
-					}
-				}
-			}
-		}
-
+		mediaOffline(streamPushItem.getApp(), streamPushItem.getStream());
 	}
 
 	@Override
@@ -897,8 +677,27 @@
 	}
 
 	@Override
-	public int mediaOutline(String app, String streamId) {
-		return gbStreamMapper.setStatus(app, streamId, false);
+	public int mediaOffline(String app, String stream) {
+		GbStream gbStream = gbStreamMapper.selectOne(app, stream);
+		int result;
+		if ("proxy".equals(gbStream.getStreamType())) {
+			result = streamProxyMapper.updateStatus(app, stream, false);
+		}else {
+			result = streamPushMapper.updateStatus(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);
+		}
+		return result;
 	}
 
 	@Override
@@ -934,12 +733,39 @@
 
 	@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());
+			}else {
+				// 鑾峰彇椤跺眰鐨�
+				PlatformCatalog topCatalog = getTopCatalog(platformCatalog.getParentId(), platformCatalog.getPlatformId());
+				platformCatalog.setBusinessGroupId(topCatalog.getId());
+			}
+		}
+		if (platform.getTreeType().equals(TreeType.CIVIL_CODE)) {
+			platformCatalog.setCivilCode(platformCatalog.getId());
+		}
+
 		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
@@ -1012,8 +838,8 @@
 	}
 
 	@Override
-	public List<PlatformCatalog> queryCatalogInPlatform(String platformId) {
-		return catalogMapper.selectByPlatForm(platformId);
+	public List<DeviceChannel> queryCatalogInPlatform(String platformId) {
+		return catalogMapper.queryCatalogInPlatform(platformId);
 	}
 
 	@Override
@@ -1056,20 +882,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");
@@ -1131,4 +961,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/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 d4995a0..94fe8df 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
@@ -1,9 +1,14 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.media;
 
 import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.conf.security.SecurityUtils;
+import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
+import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
 import com.genersoft.iot.vmp.service.IMediaServerService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.IMediaService;
+import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
 import io.swagger.annotations.Api;
@@ -16,6 +21,8 @@
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
+
 
 @Api(tags = "濯掍綋娴佺浉鍏�")
 @Controller
@@ -26,16 +33,10 @@
     private final static Logger logger = LoggerFactory.getLogger(MediaController.class);
 
     @Autowired
-    private IVideoManagerStorage storager;
-
-    @Autowired
-    private IStreamPushService streamPushService;
+    private IRedisCatchStorage redisCatchStorage;
 
     @Autowired
     private IMediaService mediaService;
-
-    @Autowired
-    private IMediaServerService mediaServerService;
 
 
     /**
@@ -52,13 +53,47 @@
     })
     @GetMapping(value = "/stream_info_by_app_and_stream")
     @ResponseBody
-    public WVPResult<StreamInfo> getStreamInfoByAppAndStream(@RequestParam String app, @RequestParam String stream, @RequestParam(required = false) String mediaServerId){
-        StreamInfo streamInfoByAppAndStreamWithCheck = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId);
+    public WVPResult<StreamInfo> getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
+                                                             @RequestParam String stream,
+                                                             @RequestParam(required = false) String mediaServerId,
+                                                             @RequestParam(required = false) String callId,
+                                                             @RequestParam(required = false) Boolean useSourceIpAsStreamIp){
+        boolean authority = false;
+        if (callId != null) {
+            // 鏉冮檺鏍¢獙
+            StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream);
+            if (streamAuthorityInfo.getCallId().equals(callId)) {
+                authority = true;
+            }else {
+                WVPResult<StreamInfo> result = new WVPResult<>();
+                result.setCode(401);
+                result.setMsg("fail");
+                return result;
+            }
+        }else {
+            // 鏄惁鐧婚檰鐢ㄦ埛, 鐧婚檰鐢ㄦ埛杩斿洖瀹屾暣淇℃伅
+            LoginUser userInfo = SecurityUtils.getUserInfo();
+            if (userInfo!= null) {
+                authority = true;
+            }
+        }
+
+        StreamInfo streamInfo;
+
+        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);
+        }
+
         WVPResult<StreamInfo> result = new WVPResult<>();
-        if (streamInfoByAppAndStreamWithCheck != null){
+        if (streamInfo != null){
             result.setCode(0);
             result.setMsg("scccess");
-            result.setData(streamInfoByAppAndStreamWithCheck);
+            result.setData(streamInfo);
         }else {
             result.setCode(-1);
             result.setMsg("fail");
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..8d2278e 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
@@ -9,6 +9,7 @@
 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
 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 +48,9 @@
 
     @Autowired
     private IVideoManagerStorage storager;
+
+    @Autowired
+    private IPlatformChannelService platformChannelService;
 
     @Autowired
     private IRedisCatchStorage redisCatchStorage;
@@ -236,6 +240,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 +266,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 +417,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);
     }
@@ -484,7 +496,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/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
index 20ffc00..db7f8fd 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -193,7 +193,7 @@
 				JSONObject data = jsonObject.getJSONObject("data");
 				if (data != null) {
 				   	result.put("key", data.getString("key"));
-					StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId());
+					StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId(), false);
 					result.put("data", streamInfoResult);
 				}
 			}else {
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 cf0fed8..300f952 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
@@ -3,11 +3,16 @@
 import com.alibaba.excel.EasyExcel;
 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.security.SecurityUtils;
+import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
+import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
 import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.IMediaService;
 import com.genersoft.iot.vmp.service.IStreamPushService;
 import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler;
 import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam;
@@ -30,6 +35,7 @@
 import org.springframework.web.context.request.async.DeferredResult;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
@@ -53,6 +59,9 @@
 
     @Autowired
     private DeferredResultHolder resultHolder;
+
+    @Autowired
+    private IMediaService mediaService;
 
     @ApiOperation("鎺ㄦ祦鍒楄〃鏌ヨ")
     @ApiImplicitParams({
@@ -237,5 +246,43 @@
         return result;
     }
 
+    /**
+     * 鑾峰彇鎺ㄦ祦鎾斁鍦板潃
+     * @param app 搴旂敤鍚�
+     * @param stream 娴乮d
+     * @return
+     */
+    @ApiOperation("鑾峰彇鎺ㄦ祦鎾斁鍦板潃")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "app", value = "搴旂敤鍚�", dataTypeClass = String.class),
+            @ApiImplicitParam(name = "stream", value = "娴乮d", dataTypeClass = String.class),
+            @ApiImplicitParam(name = "mediaServerId", value = "濯掍綋鏈嶅姟鍣╥d", dataTypeClass = String.class, required = false),
+    })
+    @GetMapping(value = "/getPlayUrl")
+    @ResponseBody
+    public WVPResult<StreamInfo> getPlayUrl(HttpServletRequest request, @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<>();
+        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/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/8042900_www.wvp-pro.cn.jks b/src/main/resources/8042900_www.wvp-pro.cn.jks
new file mode 100644
index 0000000..3e51206
--- /dev/null
+++ b/src/main/resources/8042900_www.wvp-pro.cn.jks
Binary files differ
diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml
index 9dedcb1..ef14c24 100644
--- a/src/main/resources/all-application.yml
+++ b/src/main/resources/all-application.yml
@@ -185,8 +185,6 @@
     record-sip: true
     # 鏄惁灏嗘棩蹇楀瓨鍌ㄨ繘鏁版嵁搴�
     logInDatebase: true
-    # 绗笁鏂瑰尮閰嶏紝鐢ㄤ簬浠巗tream閽熻幏鍙栨湁鏁堜俊鎭�
-    thirdPartyGBIdReg: "[\\s\\S]*"
 
 # 鍦ㄧ嚎鏂囨。锛� swagger-ui锛堢敓浜х幆澧冨缓璁叧闂級
 swagger-ui:
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 678d13f..58ce8a2 100644
--- a/web_src/src/components/PushVideoList.vue
+++ b/web_src/src/components/PushVideoList.vue
@@ -56,13 +56,18 @@
       <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.serverId ? '鏄�' : '鍚�' }}
         </template>
       </el-table-column>
 
@@ -187,7 +192,7 @@
       this.getListLoading = true;
       this.$axios({
         method: 'get',
-        url: '/api/media/stream_info_by_app_and_stream',
+        url: '/api/push/getPlayUrl',
         params: {
           app: row.app,
           stream: row.stream,
@@ -241,19 +246,6 @@
       }).catch(function (error) {
         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(() => {
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/dialog/addUser.vue b/web_src/src/components/dialog/addUser.vue
new file mode 100644
index 0000000..403eceb
--- /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="璇烽�夋嫨">
+              <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..22ff181 100644
--- a/web_src/src/components/dialog/catalogEdit.vue
+++ b/web_src/src/components/dialog/catalogEdit.vue
@@ -49,11 +49,43 @@
   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('涓氬姟鍒嗙粍妯″紡涓嬬涓�灞傜洰褰曠殑缂栧彿10鍒�13浣嶅繀椤讳负215'));
+        }
+        if (this.level > 1 && catalogType !== "216") {
+          return callback(new Error('涓氬姟鍒嗙粍妯″紡涓嬬涓�灞備互涓嬬洰褰曠殑缂栧彿10鍒�13浣嶅繀椤讳负216'));
+        }
+
+      }
+      callback();
+    }
     return {
       submitCallback: null,
       showDialog: false,
       isLoging: false,
       isEdit: false,
+      treeType: null,
+      level: 0,
       form: {
         id: null,
         name: null,
@@ -62,12 +94,12 @@
       },
       rules: {
         name: [{ required: true, message: "璇疯緭鍏ュ悕绉�", trigger: "blur" }],
-        id: [{ required: true, message: "璇疯緭鍏D", trigger: "blur" }]
+        id: [{ 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 +109,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..9f18475
--- /dev/null
+++ b/web_src/src/components/dialog/changePushKey.vue
@@ -0,0 +1,102 @@
+<template>
+  <div id="changepushKey" v-loading="isLoging">
+    <el-dialog
+      title="淇敼瀵嗙爜"
+      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: '淇敼瀵嗙爜澶辫触锛屾槸鍚﹀凡鐧诲綍锛堟帴鍙i壌鏉冨叧闂棤娉曚慨鏀瑰瘑鐮侊級',
+            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/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/layout/UiHeader.vue b/web_src/src/layout/UiHeader.vue
index 8e104bd..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>-->
@@ -23,12 +24,12 @@
       <!--            <el-menu-item style="float: right;" @click="loginout">閫�鍑�</el-menu-item>-->
       <el-submenu index="" style="float: right;">
         <template slot="title">娆㈣繋锛寋{ this.$cookies.get("session").username }}</template>
-        <el-menu-item @click="changePassword">淇敼瀵嗙爜</el-menu-item>
-        <el-menu-item @click="loginout">娉ㄩ攢</el-menu-item>
         <el-menu-item @click="openDoc">鍦ㄧ嚎鏂囨。</el-menu-item>
         <el-menu-item >
           <el-switch v-model="alarmNotify" inactive-text="鎶ヨ淇℃伅鎺ㄩ��" @change="alarmNotifyChannge"></el-switch>
         </el-menu-item>
+        <el-menu-item @click="changePassword">淇敼瀵嗙爜</el-menu-item>
+        <el-menu-item @click="loginout">娉ㄩ攢</el-menu-item>
       </el-submenu>
     </el-menu>
     <changePasswordDialog ref="changePasswordDialog"></changePasswordDialog>
@@ -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

--
Gitblit v1.8.0