Browse Source

合并主分支

pull/311/head
648540858 3 years ago
parent
commit
bfcb4d2335
  1. 4
      README.md
  2. 539
      sql/dump-wvp-202201051515.sql
  3. 12
      sql/mysql.sql
  4. 6
      src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
  5. 8
      src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
  6. 41
      src/main/java/com/genersoft/iot/vmp/conf/RedisKeyExpirationEventMessageListener.java
  7. 8
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/CmdType.java
  8. 21
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceNotFoundEvent.java
  9. 13
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
  10. 71
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
  11. 8
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java
  12. 78
      src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
  13. 8
      src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
  14. 20
      src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
  15. 10
      src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java
  16. 52
      src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/SubscribeListenerForPlatform.java
  17. 70
      src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java
  18. 3
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
  19. 10
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
  20. 49
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
  21. 49
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
  22. 28
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
  23. 8
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
  24. 10
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
  25. 108
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
  26. 14
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
  27. 43
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
  28. 41
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
  29. 1
      src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
  30. 21
      src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
  31. 15
      src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java
  32. 2
      src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
  33. 39
      src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java
  34. 106
      src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java
  35. 4
      src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
  36. 22
      src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java
  37. 15
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
  38. 33
      src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
  39. 31
      src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
  40. 30
      src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
  41. 3
      src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
  42. 29
      src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
  43. 14
      src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
  44. 42
      src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java
  45. 21
      src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
  46. 24
      src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java
  47. 109
      src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
  48. 106
      src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
  49. 13
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
  50. 2
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
  51. 10
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java
  52. 201
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
  53. 13
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java
  54. 9
      src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java
  55. 2
      src/main/resources/all-application.yml
  56. 2
      src/main/resources/application-dev.yml
  57. 2
      src/main/resources/application-docker.yml
  58. BIN
      src/main/resources/wvp.sqlite
  59. 14470
      web_src/package-lock.json
  60. 3
      web_src/package.json
  61. 2
      web_src/src/components/ParentPlatformList.vue
  62. 101
      web_src/src/components/dialog/catalogEdit.vue
  63. 65
      web_src/src/components/dialog/chooseChannel.vue
  64. 311
      web_src/src/components/dialog/chooseChannelForCatalog.vue
  65. 55
      web_src/src/components/dialog/chooseChannelForGb.vue
  66. 11
      web_src/src/components/dialog/chooseChannelForStream.vue
  67. 1
      web_src/src/components/dialog/platformEdit.vue
  68. 2
      web_src/src/main.js
  69. 26
      web_src/static/css/iconfont.css
  70. BIN
      web_src/static/css/iconfont.woff2

4
README.md

@ -95,15 +95,13 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 平台状态查询 - [X] 平台状态查询
- [X] 平台信息查询 - [X] 平台信息查询
- [X] 平台远程启动 - [X] 平台远程启动
- [X] 每个级联平台可自定义的虚拟目录
- [X] 添加RTSP视频 - [X] 添加RTSP视频
- [X] 添加接口鉴权 - [X] 添加接口鉴权
- [ ] 添加ONVIF探测局域网内的设备
- [X] 添加RTMP视频 - [X] 添加RTMP视频
- [X] 云端录像(需要部署单独服务配合使用) - [X] 云端录像(需要部署单独服务配合使用)
- [X] 多流媒体节点,自动选择负载最低的节点使用。 - [X] 多流媒体节点,自动选择负载最低的节点使用。
- [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。 - [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。
- [ ] 添加系统配置
- [ ] 添加用户管理
- [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。
# docker快速体验 # docker快速体验

539
sql/dump-wvp-202201051515.sql

@ -0,0 +1,539 @@
-- MySQL dump 10.13 Distrib 8.0.27, for Linux (x86_64)
--
-- Host: localhost Database: wvp
-- ------------------------------------------------------
-- Server version 8.0.27-0ubuntu0.20.04.1
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `device`
--
DROP TABLE IF EXISTS `device`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device` (
`deviceId` varchar(50) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`manufacturer` varchar(255) DEFAULT NULL,
`model` varchar(255) DEFAULT NULL,
`firmware` varchar(255) DEFAULT NULL,
`transport` varchar(50) DEFAULT NULL,
`streamMode` varchar(50) DEFAULT NULL,
`online` varchar(50) DEFAULT NULL,
`registerTime` varchar(50) DEFAULT NULL,
`keepaliveTime` varchar(50) DEFAULT NULL,
`ip` varchar(50) NOT NULL,
`createTime` varchar(50) NOT NULL,
`updateTime` varchar(50) NOT NULL,
`port` int NOT NULL,
`expires` int NOT NULL,
`subscribeCycleForCatalog` int NOT NULL,
`hostAddress` varchar(50) NOT NULL,
`charset` varchar(50) NOT NULL,
PRIMARY KEY (`deviceId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `device`
--
LOCK TABLES `device` WRITE;
/*!40000 ALTER TABLE `device` DISABLE KEYS */;
INSERT INTO `device` VALUES ('34020000001320000005','IPC-HFW4433M-I2','Dahua','IPC-HFW4433M-I2','2.622.0000000.31.R,2017-12-14','UDP','UDP','1','2022-01-05 15:08:26','2022-01-05 15:15:26','192.168.1.100','2022-01-05 15:08:26','2022-01-05 15:15:26',5060,3600,0,'192.168.1.100:5060','gb2312'),('34020000002000000005','DH-NVR5864-I','Dahua','DH-NVR5864-I','4.001.0000000.3,2020-10-22','UDP','UDP','1','2022-01-05 14:07:36','2022-01-05 15:15:25','192.168.1.19','2022-01-05 15:08:25','2022-01-05 15:15:25',5060,3600,0,'192.168.1.19:5060','gb2312'),('44010000001110008008',NULL,'Mercury','MIPC368(P)W-4','1.0.1 Build 210304 Rel.60784n','UDP','UDP','1','2022-01-05 15:08:35','2022-01-05 15:14:35','192.168.1.17','2022-01-05 15:08:35','2022-01-05 15:14:35',5060,36000,0,'192.168.1.17:5060','gb2312');
/*!40000 ALTER TABLE `device` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `device_alarm`
--
DROP TABLE IF EXISTS `device_alarm`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_alarm` (
`id` int NOT NULL AUTO_INCREMENT,
`deviceId` varchar(50) NOT NULL,
`channelId` varchar(50) NOT NULL,
`alarmPriority` varchar(50) NOT NULL,
`alarmMethod` varchar(50) DEFAULT NULL,
`alarmTime` varchar(50) NOT NULL,
`alarmDescription` varchar(255) DEFAULT NULL,
`longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL,
`alarmType` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `device_alarm`
--
LOCK TABLES `device_alarm` WRITE;
/*!40000 ALTER TABLE `device_alarm` DISABLE KEYS */;
/*!40000 ALTER TABLE `device_alarm` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `device_channel`
--
DROP TABLE IF EXISTS `device_channel`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_channel` (
`channelId` varchar(50) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`manufacture` varchar(50) DEFAULT NULL,
`model` varchar(50) DEFAULT NULL,
`owner` varchar(50) DEFAULT NULL,
`civilCode` varchar(50) DEFAULT NULL,
`block` varchar(50) DEFAULT NULL,
`address` varchar(50) DEFAULT NULL,
`parentId` varchar(50) DEFAULT NULL,
`safetyWay` int DEFAULT NULL,
`registerWay` int DEFAULT NULL,
`certNum` varchar(50) DEFAULT NULL,
`certifiable` int DEFAULT NULL,
`errCode` int DEFAULT NULL,
`endTime` varchar(50) DEFAULT NULL,
`secrecy` varchar(50) DEFAULT NULL,
`ipAddress` varchar(50) DEFAULT NULL,
`port` int DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`PTZType` int DEFAULT NULL,
`status` int DEFAULT NULL,
`longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL,
`streamId` varchar(50) DEFAULT NULL,
`deviceId` varchar(50) NOT NULL,
`parental` varchar(50) DEFAULT NULL,
`hasAudio` bit(1) DEFAULT NULL,
`createTime` varchar(50) NOT NULL,
`updateTime` varchar(50) NOT NULL,
PRIMARY KEY (`channelId`,`deviceId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `device_channel`
--
LOCK TABLES `device_channel` WRITE;
/*!40000 ALTER TABLE `device_channel` DISABLE KEYS */;
INSERT INTO `device_channel` VALUES ('34020000001310000001','IPC','Dahua','IPC-HFW4433M-I2','0','340200','','axy','34020000001320000005',0,1,'',0,0,NULL,'0','',0,'',0,1,0,0,'','34020000001320000005','0',NULL,'2022-01-05 15:11:21','2022-01-05 15:11:21'),('34020000001310000001','通道1','Dahua','DH-NVR5864-I','0','340200','','axy','34020000002000000005',0,1,'',0,0,NULL,'0','192.168.1.17',37777,'',0,1,0,0,'','34020000002000000005','0',NULL,'2022-01-05 15:11:25','2022-01-05 15:11:25'),('34020000001310000065','GB_Chn_065','Dahua','DH-NVR5864-I','0','340200','','axy','34020000002000000005',0,1,'',0,0,NULL,'0','',0,'',0,1,0,0,'','34020000002000000005','0',NULL,'2022-01-05 15:11:25','2022-01-05 15:11:25'),('34020000001320000001','IPCamera 01','Mercury','MIPC368(P)W-4','Owner','CivilCode','','Address','',0,1,'',0,0,NULL,'0','',0,'',0,1,0,0,'','44010000001110008008','0',NULL,'2022-01-05 15:11:26','2022-01-05 15:11:26');
/*!40000 ALTER TABLE `device_channel` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `device_mobile_position`
--
DROP TABLE IF EXISTS `device_mobile_position`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `device_mobile_position` (
`deviceId` varchar(50) NOT NULL,
`channelId` varchar(50) NOT NULL,
`deviceName` varchar(255) DEFAULT NULL,
`time` varchar(50) NOT NULL,
`longitude` double NOT NULL,
`latitude` double NOT NULL,
`altitude` double DEFAULT NULL,
`speed` double DEFAULT NULL,
`direction` double DEFAULT NULL,
`reportSource` varchar(50) DEFAULT NULL,
`geodeticSystem` varchar(50) DEFAULT NULL,
`cnLng` varchar(50) DEFAULT NULL,
`cnLat` varchar(50) DEFAULT NULL,
PRIMARY KEY (`deviceId`,`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `device_mobile_position`
--
LOCK TABLES `device_mobile_position` WRITE;
/*!40000 ALTER TABLE `device_mobile_position` DISABLE KEYS */;
/*!40000 ALTER TABLE `device_mobile_position` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `gb_stream`
--
DROP TABLE IF EXISTS `gb_stream`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `gb_stream` (
`app` varchar(255) NOT NULL,
`stream` varchar(255) NOT NULL,
`gbId` varchar(50) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`longitude` double DEFAULT NULL,
`latitude` double DEFAULT NULL,
`streamType` varchar(50) DEFAULT NULL,
`mediaServerId` varchar(50) DEFAULT NULL,
`status` int DEFAULT NULL,
PRIMARY KEY (`app`,`stream`,`gbId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `gb_stream`
--
LOCK TABLES `gb_stream` WRITE;
/*!40000 ALTER TABLE `gb_stream` DISABLE KEYS */;
INSERT INTO `gb_stream` VALUES ('1000','10000001_52869999','77777777777777777777','shoulei1111',0,0,'push','XR1LEpKlfQtSg9Z1',1);
/*!40000 ALTER TABLE `gb_stream` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `log`
--
DROP TABLE IF EXISTS `log`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `log` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`type` varchar(50) NOT NULL,
`uri` varchar(200) NOT NULL,
`address` varchar(50) NOT NULL,
`result` varchar(50) NOT NULL,
`timing` bigint NOT NULL,
`username` varchar(50) NOT NULL,
`createTime` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `log`
--
LOCK TABLES `log` WRITE;
/*!40000 ALTER TABLE `log` DISABLE KEYS */;
INSERT INTO `log` VALUES (1,'登录','GET','/api/user/login','127.0.0.1','200 OK',245,'admin','2022-01-05 15:09:06'),(2,'添加上级平台','POST','/api/platform/save','127.0.0.1','200 OK',88,'admin','2022-01-05 15:09:24'),(3,'[设备查询] 同步设备通道','POST','/api/device/query/devices/34020000001320000005/sync','127.0.0.1','200 OK',17,'admin','2022-01-05 15:11:21'),(4,'[设备查询] 同步设备通道','POST','/api/device/query/devices/34020000002000000005/sync','127.0.0.1','200 OK',4,'admin','2022-01-05 15:11:25'),(5,'[设备查询] 同步设备通道','POST','/api/device/query/devices/44010000001110008008/sync','127.0.0.1','200 OK',4,'admin','2022-01-05 15:11:26'),(6,'向上级平台添加国标通道','POST','/api/platform/update_channel_for_gb','127.0.0.1','200 OK',52,'admin','2022-01-05 15:11:32'),(7,'从上级平台移除国标通道','DELETE','/api/platform/del_channel_for_gb','127.0.0.1','200 OK',35,'admin','2022-01-05 15:11:34'),(8,'向上级平台添加国标通道','POST','/api/platform/update_channel_for_gb','127.0.0.1','200 OK',39,'admin','2022-01-05 15:11:35'),(9,'从上级平台移除国标通道','DELETE','/api/platform/del_channel_for_gb','127.0.0.1','200 OK',46,'admin','2022-01-05 15:14:00'),(10,'向上级平台添加国标通道','POST','/api/platform/update_channel_for_gb','127.0.0.1','200 OK',59,'admin','2022-01-05 15:14:01'),(11,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',12,'admin','2022-01-05 15:14:16'),(12,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',8,'admin','2022-01-05 15:14:17'),(13,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',6,'admin','2022-01-05 15:14:19'),(14,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',8,'admin','2022-01-05 15:14:19'),(15,'移除通道与国标的关联','DELETE','/api/gbStream/del','127.0.0.1','200 OK',11,'admin','2022-01-05 15:14:21'),(16,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',42,'admin','2022-01-05 15:14:24'),(17,'移除通道与国标的关联','DELETE','/api/gbStream/del','127.0.0.1','200 OK',43,'admin','2022-01-05 15:14:25'),(18,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',9,'admin','2022-01-05 15:14:27'),(19,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',9,'admin','2022-01-05 15:14:37'),(20,'添加通道与国标的关联','POST','/api/gbStream/add','127.0.0.1','200 OK',10,'admin','2022-01-05 15:14:38');
/*!40000 ALTER TABLE `log` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `media_server`
--
DROP TABLE IF EXISTS `media_server`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `media_server` (
`id` varchar(255) NOT NULL,
`ip` varchar(50) NOT NULL,
`hookIp` varchar(50) NOT NULL,
`sdpIp` varchar(50) NOT NULL,
`streamIp` varchar(50) NOT NULL,
`httpPort` int NOT NULL,
`httpSSlPort` int NOT NULL,
`rtmpPort` int NOT NULL,
`rtmpSSlPort` int NOT NULL,
`rtpProxyPort` int NOT NULL,
`rtspPort` int NOT NULL,
`rtspSSLPort` int NOT NULL,
`autoConfig` int NOT NULL,
`secret` varchar(50) NOT NULL,
`streamNoneReaderDelayMS` int NOT NULL,
`rtpEnable` int NOT NULL,
`rtpPortRange` varchar(50) NOT NULL,
`sendRtpPortRange` varchar(50) NOT NULL,
`recordAssistPort` int NOT NULL,
`defaultServer` int NOT NULL,
`createTime` varchar(50) NOT NULL,
`updateTime` varchar(50) NOT NULL,
`hookAliveInterval` int NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `media_server_i` (`ip`,`httpPort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `media_server`
--
LOCK TABLES `media_server` WRITE;
/*!40000 ALTER TABLE `media_server` DISABLE KEYS */;
INSERT INTO `media_server` VALUES ('XR1LEpKlfQtSg9Z1','192.168.1.3','127.0.0.1','192.168.1.3','192.168.1.3',6080,0,10935,0,10000,10554,0,1,'035c73f7-bb6b-4889-a715-d9eb2d1925cc',100000,1,'30000,30500','30000,30500',18081,1,'2022-01-05 15:08:27','2022-01-05 15:08:27',10);
/*!40000 ALTER TABLE `media_server` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `parent_platform`
--
DROP TABLE IF EXISTS `parent_platform`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `parent_platform` (
`id` int NOT NULL AUTO_INCREMENT,
`enable` int DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`serverGBId` varchar(50) NOT NULL,
`serverGBDomain` varchar(50) DEFAULT NULL,
`serverIP` varchar(50) DEFAULT NULL,
`serverPort` int DEFAULT NULL,
`deviceGBId` varchar(50) NOT NULL,
`deviceIp` varchar(50) DEFAULT NULL,
`devicePort` varchar(50) DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`expires` varchar(50) DEFAULT NULL,
`keepTimeout` varchar(50) DEFAULT NULL,
`transport` varchar(50) DEFAULT NULL,
`characterSet` varchar(50) DEFAULT NULL,
`catalogId` varchar(50) NOT NULL,
`ptz` int DEFAULT NULL,
`rtcp` int DEFAULT NULL,
`status` bit(1) DEFAULT NULL,
`shareAllLiveStream` int DEFAULT NULL,
PRIMARY KEY (`id`,`serverGBId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `parent_platform`
--
LOCK TABLES `parent_platform` WRITE;
/*!40000 ALTER TABLE `parent_platform` DISABLE KEYS */;
INSERT INTO `parent_platform` VALUES (1,1,'1112','1111111111111','1111111111','11.11.11.11',111111,'34020000002110000015','192.168.1.3','5060','34020000002110000015','12345678','300','60','UDP','GB2312','1111111111111',1,0,_binary '\0',1);
/*!40000 ALTER TABLE `parent_platform` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `platform_catalog`
--
DROP TABLE IF EXISTS `platform_catalog`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_catalog` (
`id` varchar(50) NOT NULL,
`platformId` varchar(50) NOT NULL,
`name` varchar(255) NOT NULL,
`parentId` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `platform_catalog`
--
LOCK TABLES `platform_catalog` WRITE;
/*!40000 ALTER TABLE `platform_catalog` DISABLE KEYS */;
INSERT INTO `platform_catalog` VALUES ('1111111111','1111111111111','11122','1111111111111');
/*!40000 ALTER TABLE `platform_catalog` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `platform_gb_channel`
--
DROP TABLE IF EXISTS `platform_gb_channel`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_gb_channel` (
`channelId` varchar(50) NOT NULL,
`deviceId` varchar(50) NOT NULL,
`platformId` varchar(50) NOT NULL,
`deviceAndChannelId` varchar(50) NOT NULL,
`catalogId` varchar(50) NOT NULL,
PRIMARY KEY (`deviceAndChannelId`,`platformId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `platform_gb_channel`
--
LOCK TABLES `platform_gb_channel` WRITE;
/*!40000 ALTER TABLE `platform_gb_channel` DISABLE KEYS */;
INSERT INTO `platform_gb_channel` VALUES ('34020000001310000001','34020000001320000005','1111111111111','34020000001320000005_34020000001310000001','1111111111'),('34020000001310000001','34020000002000000005','1111111111111','34020000002000000005_34020000001310000001','1111111111'),('34020000001310000065','34020000002000000005','1111111111111','34020000002000000005_34020000001310000065','1111111111'),('34020000001320000001','44010000001110008008','1111111111111','44010000001110008008_34020000001320000001','1111111111');
/*!40000 ALTER TABLE `platform_gb_channel` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `platform_gb_stream`
--
DROP TABLE IF EXISTS `platform_gb_stream`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_gb_stream` (
`platformId` varchar(50) NOT NULL,
`app` varchar(255) NOT NULL,
`stream` varchar(255) NOT NULL,
`catalogId` varchar(50) NOT NULL,
PRIMARY KEY (`platformId`,`app`,`stream`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `platform_gb_stream`
--
LOCK TABLES `platform_gb_stream` WRITE;
/*!40000 ALTER TABLE `platform_gb_stream` DISABLE KEYS */;
INSERT INTO `platform_gb_stream` VALUES ('1111111111111','1000','10000001_52869999','1111111111');
/*!40000 ALTER TABLE `platform_gb_stream` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `role`
--
DROP TABLE IF EXISTS `role`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `role` (
`id` int NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`authority` text NOT NULL,
`createTime` varchar(50) NOT NULL,
`updateTime` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `role`
--
LOCK TABLES `role` WRITE;
/*!40000 ALTER TABLE `role` DISABLE KEYS */;
INSERT INTO `role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
/*!40000 ALTER TABLE `role` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `stream_proxy`
--
DROP TABLE IF EXISTS `stream_proxy`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `stream_proxy` (
`type` varchar(50) NOT NULL,
`app` varchar(255) NOT NULL,
`stream` varchar(255) NOT NULL,
`url` varchar(255) DEFAULT NULL,
`src_url` varchar(255) DEFAULT NULL,
`dst_url` varchar(255) DEFAULT NULL,
`timeout_ms` int DEFAULT NULL,
`ffmpeg_cmd_key` varchar(255) DEFAULT NULL,
`rtp_type` varchar(50) DEFAULT NULL,
`mediaServerId` varchar(50) DEFAULT NULL,
`enable_hls` bit(1) DEFAULT NULL,
`enable_mp4` bit(1) DEFAULT NULL,
`enable` bit(1) NOT NULL,
`enable_remove_none_reader` bit(1) NOT NULL,
`createTime` varchar(50) NOT NULL,
PRIMARY KEY (`app`,`stream`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `stream_proxy`
--
LOCK TABLES `stream_proxy` WRITE;
/*!40000 ALTER TABLE `stream_proxy` DISABLE KEYS */;
/*!40000 ALTER TABLE `stream_proxy` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `stream_push`
--
DROP TABLE IF EXISTS `stream_push`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `stream_push` (
`app` varchar(255) NOT NULL,
`stream` varchar(255) NOT NULL,
`totalReaderCount` varchar(50) DEFAULT NULL,
`originType` int DEFAULT NULL,
`originTypeStr` varchar(50) DEFAULT NULL,
`createStamp` int DEFAULT NULL,
`aliveSecond` int DEFAULT NULL,
`mediaServerId` varchar(50) DEFAULT NULL,
PRIMARY KEY (`app`,`stream`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `stream_push`
--
LOCK TABLES `stream_push` WRITE;
/*!40000 ALTER TABLE `stream_push` DISABLE KEYS */;
INSERT INTO `stream_push` VALUES ('1000','10000001_52869999','0',2,'rtsp_push',1641366850,0,'XR1LEpKlfQtSg9Z1');
/*!40000 ALTER TABLE `stream_push` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `user`
--
DROP TABLE IF EXISTS `user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`roleId` int NOT NULL,
`createTime` varchar(50) NOT NULL,
`updateTime` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `user_username_uindex` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `user`
--
LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57');
/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Dumping routines for database 'wvp'
--
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2022-01-05 15:15:35

12
sql/mysql.sql

@ -171,6 +171,7 @@ create table parent_platform
keepTimeout varchar(50) null, keepTimeout varchar(50) null,
transport varchar(50) null, transport varchar(50) null,
characterSet varchar(50) null, characterSet varchar(50) null,
catalogId varchar(50) not null,
ptz int null, ptz int null,
rtcp int null, rtcp int null,
status bit null, status bit null,
@ -178,12 +179,22 @@ create table parent_platform
primary key (id, serverGBId) primary key (id, serverGBId)
); );
create table platform_catalog
(
id varchar(50) primary key,
platformId varchar(50) not null,
name varchar(255) not null,
parentId varchar(50)
);
create table platform_gb_channel create table platform_gb_channel
( (
channelId varchar(50) not null, channelId varchar(50) not null,
deviceId varchar(50) not null, deviceId varchar(50) not null,
platformId varchar(50) not null, platformId varchar(50) not null,
deviceAndChannelId varchar(50) not null, deviceAndChannelId varchar(50) not null,
catalogId varchar(50) not null,
primary key (deviceAndChannelId, platformId) primary key (deviceAndChannelId, platformId)
); );
@ -192,6 +203,7 @@ create table platform_gb_stream
platformId varchar(50) not null, platformId varchar(50) not null,
app varchar(255) not null, app varchar(255) not null,
stream varchar(255) not null, stream varchar(255) not null,
catalogId varchar(50) not null,
primary key (platformId, app, stream) primary key (platformId, app, stream)
); );

6
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java

@ -58,9 +58,15 @@ public class VideoManagerConstants {
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_"; public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
public static final String SIP_SN_PREFIX = "VMP_SIP_SN_";
public static final String SIP_SUBSCRIBE_PREFIX = "SIP_SUBSCRIBE_";
//************************** redis 消息********************************* //************************** redis 消息*********************************
public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_"; public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_";
public static final String WVP_MSG_GPS_PREFIX = "WVP_MSG_GPS_";
//************************** 第三方 **************************************** //************************** 第三方 ****************************************
public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_"; public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
} }

8
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java

@ -1,12 +1,16 @@
package com.genersoft.iot.vmp.conf; package com.genersoft.iot.vmp.conf;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.service.impl.RedisGPSMsgListener;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
@ -41,6 +45,9 @@ public class RedisConfig extends CachingConfigurerSupport {
@Value("${spring.redis.poolMaxWait:5}") @Value("${spring.redis.poolMaxWait:5}")
private int poolMaxWait; private int poolMaxWait;
@Autowired
private RedisGPSMsgListener redisGPSMsgListener;
@Bean @Bean
public JedisPool jedisPool() { public JedisPool jedisPool() {
if (StringUtils.isBlank(password)) { if (StringUtils.isBlank(password)) {
@ -85,6 +92,7 @@ public class RedisConfig extends CachingConfigurerSupport {
RedisMessageListenerContainer container = new RedisMessageListenerContainer(); RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory); container.setConnectionFactory(connectionFactory);
container.addMessageListener(redisGPSMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_GPS_PREFIX));
return container; return container;
} }

41
src/main/java/com/genersoft/iot/vmp/conf/RedisKeyExpirationEventMessageListener.java

@ -0,0 +1,41 @@
package com.genersoft.iot.vmp.conf;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.util.StringUtils;
import java.util.Properties;
public class RedisKeyExpirationEventMessageListener extends KeyExpirationEventMessageListener {
private UserSetup userSetup;
private RedisMessageListenerContainer listenerContainer;
private String keyspaceNotificationsConfigParameter = "EA";
public RedisKeyExpirationEventMessageListener(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
super(listenerContainer);
this.listenerContainer = listenerContainer;
this.userSetup = userSetup;
}
@Override
public void init() {
if (!userSetup.getRedisConfig()) {
// 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用
setKeyspaceNotificationsConfigParameter("");
}else {
RedisConnection connection = this.listenerContainer.getConnectionFactory().getConnection();
Properties config = connection.getConfig("notify-keyspace-events");
try {
if (!config.getProperty("notify-keyspace-events").equals(keyspaceNotificationsConfigParameter)) {
connection.setConfig("notify-keyspace-events", keyspaceNotificationsConfigParameter);
}
} finally {
connection.close();
}
}
super.init();
}
}

8
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CmdType.java

@ -0,0 +1,8 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class CmdType {
public static final String CATALOG = "Catalog";
public static final String ALARM = "Alarm";
public static final String MOBILE_POSITION = "MobilePosition";
}

21
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceNotFoundEvent.java

@ -0,0 +1,21 @@
package com.genersoft.iot.vmp.gb28181.bean;
import javax.sip.Dialog;
import java.util.EventObject;
public class DeviceNotFoundEvent extends EventObject {
/**
* Constructs a prototypical Event.
*
* @param dialog
* @throws IllegalArgumentException if source is null.
*/
public DeviceNotFoundEvent(Dialog dialog) {
super(dialog);
}
public Dialog getDialog() {
return (Dialog)super.getSource();
}
}

13
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java

@ -109,6 +109,11 @@ public class ParentPlatform {
*/ */
private boolean shareAllLiveStream; private boolean shareAllLiveStream;
/**
* 默认目录Id,自动添加的通道多放在这个目录下
*/
private String catalogId;
public Integer getId() { public Integer getId() {
return id; return id;
} }
@ -277,4 +282,12 @@ public class ParentPlatform {
public void setShareAllLiveStream(boolean shareAllLiveStream) { public void setShareAllLiveStream(boolean shareAllLiveStream) {
this.shareAllLiveStream = shareAllLiveStream; this.shareAllLiveStream = shareAllLiveStream;
} }
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
} }

71
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java

@ -0,0 +1,71 @@
package com.genersoft.iot.vmp.gb28181.bean;
public class PlatformCatalog {
private String id;
private String name;
private String platformId;
private String parentId;
private int childrenCount; // 子节点数
private int type; // 0 目录, 1 国标通道, 2 直播流
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPlatformId() {
return platformId;
}
public void setPlatformId(String platformId) {
this.platformId = platformId;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public int getChildrenCount() {
return childrenCount;
}
public void setChildrenCount(int childrenCount) {
this.childrenCount = childrenCount;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setTypeForCatalog() {
this.type = 0;
}
public void setTypeForGb() {
this.type = 1;
}
public void setTypeForStream() {
this.type = 2;
}
}

8
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java

@ -4,6 +4,7 @@ public class PlatformGbStream {
private String app; private String app;
private String stream; private String stream;
private String platformId; private String platformId;
private String catalogId;
public String getApp() { public String getApp() {
return app; return app;
@ -29,4 +30,11 @@ public class PlatformGbStream {
this.platformId = platformId; this.platformId = platformId;
} }
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
} }

78
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java

@ -0,0 +1,78 @@
package com.genersoft.iot.vmp.gb28181.bean;
import javax.sip.RequestEvent;
import javax.sip.header.*;
import javax.sip.message.Request;
public class SubscribeInfo {
public SubscribeInfo() {
}
public SubscribeInfo(RequestEvent evt, String id) {
this.id = id;
Request request = evt.getRequest();
CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME);
this.callId = callIdHeader.getCallId();
FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME);
this.fromTag = fromHeader.getTag();
ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME);
this.expires = expiresHeader.getExpires();
this.event = (EventHeader)request.getHeader(EventHeader.NAME);
}
private String id;
private int expires;
private String callId;
private EventHeader event;
private String fromTag;
private String toTag;
public String getId() {
return id;
}
public int getExpires() {
return expires;
}
public String getCallId() {
return callId;
}
public EventHeader getEvent() {
return event;
}
public String getFromTag() {
return fromTag;
}
public void setToTag(String toTag) {
this.toTag = toTag;
}
public String getToTag() {
return toTag;
}
public void setId(String id) {
this.id = id;
}
public void setExpires(int expires) {
this.expires = expires;
}
public void setCallId(String callId) {
this.callId = callId;
}
public void setEvent(EventHeader event) {
this.event = event;
}
public void setFromTag(String fromTag) {
this.fromTag = fromTag;
}
}

8
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.event; package com.genersoft.iot.vmp.gb28181.event;
import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
@ -91,6 +92,13 @@ public class SipSubscribe {
this.statusCode = -1024; this.statusCode = -1024;
this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId(); this.callId = dialogTerminatedEvent.getDialog().getCallId().getCallId();
this.dialog = dialogTerminatedEvent.getDialog(); this.dialog = dialogTerminatedEvent.getDialog();
}else if (event instanceof DeviceNotFoundEvent) {
DeviceNotFoundEvent deviceNotFoundEvent = (DeviceNotFoundEvent)event;
this.type = "deviceNotFoundEvent";
this.msg = "设备未找到";
this.statusCode = -1024;
this.callId = deviceNotFoundEvent.getDialog().getCallId().getCallId();
this.dialog = deviceNotFoundEvent.getDialog();
} }
} }
} }

20
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.event.offline; package com.genersoft.iot.vmp.gb28181.event.offline;
import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -7,12 +8,16 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import org.springframework.util.StringUtils;
import java.util.Properties;
/** /**
* @description:设备心跳超时监听,借助redis过期特性进行监听监听到说明设备心跳超时发送离线事件 * @description:设备心跳超时监听,借助redis过期特性进行监听监听到说明设备心跳超时发送离线事件
@ -20,7 +25,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
* @date: 2020年5月6日 上午11:35:46 * @date: 2020年5月6日 上午11:35:46
*/ */
@Component @Component
public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessageListener { public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener {
private Logger logger = LoggerFactory.getLogger(KeepaliveTimeoutListenerForPlatform.class); private Logger logger = LoggerFactory.getLogger(KeepaliveTimeoutListenerForPlatform.class);
@ -30,17 +35,8 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa
@Autowired @Autowired
private UserSetup userSetup; private UserSetup userSetup;
@Override public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
public void init() { super(listenerContainer, userSetup);
if (!userSetup.getRedisConfig()) {
// 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用
setKeyspaceNotificationsConfigParameter("");
}
super.init();
}
public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
} }

10
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.gb28181.event.offline; package com.genersoft.iot.vmp.gb28181.event.offline;
import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -20,7 +21,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
* @date: 2020年5月6日 上午11:35:46 * @date: 2020年5月6日 上午11:35:46
*/ */
@Component @Component
public class KeepliveTimeoutListener extends KeyExpirationEventMessageListener { public class KeepliveTimeoutListener extends RedisKeyExpirationEventMessageListener {
private Logger logger = LoggerFactory.getLogger(KeepliveTimeoutListener.class); private Logger logger = LoggerFactory.getLogger(KeepliveTimeoutListener.class);
@ -30,6 +31,10 @@ public class KeepliveTimeoutListener extends KeyExpirationEventMessageListener {
@Autowired @Autowired
private UserSetup userSetup; private UserSetup userSetup;
public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
super(listenerContainer, userSetup);
}
@Override @Override
public void init() { public void init() {
if (!userSetup.getRedisConfig()) { if (!userSetup.getRedisConfig()) {
@ -39,9 +44,6 @@ public class KeepliveTimeoutListener extends KeyExpirationEventMessageListener {
super.init(); super.init();
} }
public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/** /**
* 监听失效的keykey格式为keeplive_deviceId * 监听失效的keykey格式为keeplive_deviceId

52
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/SubscribeListenerForPlatform.java

@ -0,0 +1,52 @@
package com.genersoft.iot.vmp.gb28181.event.subscribe;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import org.checkerframework.checker.units.qual.A;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
/**
* 平台订阅到期事件
*/
@Component
public class SubscribeListenerForPlatform extends RedisKeyExpirationEventMessageListener {
private Logger logger = LoggerFactory.getLogger(SubscribeListenerForPlatform.class);
@Autowired
private UserSetup userSetup;
@Autowired
private DynamicTask dynamicTask;
public SubscribeListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
super(listenerContainer, userSetup);
}
/**
* 监听失效的key
* @param message
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {
// 获取失效的key
String expiredKey = message.toString();
logger.debug(expiredKey);
// 订阅到期
String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_";
if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) {
// 取消定时任务
dynamicTask.stopCron(expiredKey);
}
}
}

70
src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java

@ -0,0 +1,70 @@
package com.genersoft.iot.vmp.gb28181.task;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import java.text.SimpleDateFormat;
import java.util.List;
public class GPSSubscribeTask implements Runnable{
private IRedisCatchStorage redisCatchStorage;
private IVideoManagerStorager storager;
private ISIPCommanderForPlatform sipCommanderForPlatform;
private String platformId;
private String sn;
private String key;
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public GPSSubscribeTask(IRedisCatchStorage redisCatchStorage, ISIPCommanderForPlatform sipCommanderForPlatform, IVideoManagerStorager storager, String platformId, String sn, String key) {
this.redisCatchStorage = redisCatchStorage;
this.storager = storager;
this.platformId = platformId;
this.sn = sn;
this.key = key;
this.sipCommanderForPlatform = sipCommanderForPlatform;
}
@Override
public void run() {
SubscribeInfo subscribe = redisCatchStorage.getSubscribe(key);
if (subscribe != null) {
System.out.println("发送GPS消息");
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId);
if (parentPlatform == null || parentPlatform.isStatus()) {
// TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platformId);
if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) {
String gbId = gbStream.getGbId();
GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
if (gbStream.isStatus()) {
if (gpsMsgInfo != null) {
// 发送GPS消息
sipCommanderForPlatform.sendMobilePosition(parentPlatform, gpsMsgInfo, subscribe);
}else {
// 没有在redis找到新的消息就使用数据库的消息
gpsMsgInfo = new GPSMsgInfo();
gpsMsgInfo.setId(gbId);
gpsMsgInfo.setLat(gbStream.getLongitude());
gpsMsgInfo.setLng(gbStream.getLongitude());
// 发送GPS消息
sipCommanderForPlatform.sendMobilePosition(parentPlatform, gpsMsgInfo, subscribe);
}
}
}
}
}
}
}
}

3
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java

@ -94,7 +94,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
logger.debug(responseEvent.getResponse().toString()); logger.debug(responseEvent.getResponse().toString());
int status = response.getStatusCode(); int status = response.getStatusCode();
if (((status >= 200) && (status < 300)) || status == 401) { // Success! if (((status >= 200) && (status < 300)) || status == 401) { // Success!
// ISIPResponseProcessor processor = processorFactory.createResponseProcessor(evt);
CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
String method = cseqHeader.getMethod(); String method = cseqHeader.getMethod();
ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method); ISIPResponseProcessor sipRequestProcessor = responseProcessorMap.get(method);
@ -108,6 +107,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
if (subscribe != null) { if (subscribe != null) {
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
subscribe.response(eventResult); subscribe.response(eventResult);
sipSubscribe.removeOkSubscribe(callIdHeader.getCallId());
} }
} }
} }
@ -122,6 +122,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver {
if (subscribe != null) { if (subscribe != null) {
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
subscribe.response(eventResult); subscribe.response(eventResult);
sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
} }
} }
} }

10
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java

@ -2,7 +2,9 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import javax.sip.header.WWWAuthenticateHeader; import javax.sip.header.WWWAuthenticateHeader;
@ -61,4 +63,12 @@ public interface ISIPCommanderForPlatform {
*/ */
boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag); boolean deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag);
/**
* 向上级回复移动位置订阅消息
* @param parentPlatform 平台信息
* @param gpsMsgInfo GPS信息
* @param subscribeInfo 订阅相关的信息
* @return
*/
boolean sendMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo);
} }

49
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import gov.nist.javax.sip.message.MessageFactoryImpl; import gov.nist.javax.sip.message.MessageFactoryImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -32,6 +33,9 @@ public class SIPRequestHeaderPlarformProvider {
@Autowired @Autowired
private SipFactory sipFactory; private SipFactory sipFactory;
@Autowired
private IRedisCatchStorage redisCatchStorage;
public Request createKeetpaliveMessageRequest(ParentPlatform parentPlatform, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException { public Request createKeetpaliveMessageRequest(ParentPlatform parentPlatform, String content, String viaTag, String fromTag, String toTag, CallIdHeader callIdHeader) throws ParseException, InvalidArgumentException, PeerUnavailableException {
Request request = null; Request request = null;
@ -57,7 +61,7 @@ public class SIPRequestHeaderPlarformProvider {
// Forwards // Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
// ceq // ceq
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.MESSAGE); CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.MESSAGE), Request.MESSAGE);
request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwards); toHeader, viaHeaders, maxForwards);
@ -122,7 +126,7 @@ public class SIPRequestHeaderPlarformProvider {
String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader) throws ParseException, PeerUnavailableException, InvalidArgumentException { String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader) throws ParseException, PeerUnavailableException, InvalidArgumentException {
Request registerRequest = createRegisterRequest(parentPlatform, 2L, fromTag, viaTag, callIdHeader); Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader);
String realm = www.getRealm(); String realm = www.getRealm();
String nonce = www.getNonce(); String nonce = www.getNonce();
@ -208,7 +212,7 @@ public class SIPRequestHeaderPlarformProvider {
// Forwards // Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
// ceq // ceq
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(1L, Request.MESSAGE); CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.MESSAGE), Request.MESSAGE);
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory(); MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
// 设置编码, 防止中文乱码 // 设置编码, 防止中文乱码
messageFactory.setDefaultContentEncodingCharset("gb2312"); messageFactory.setDefaultContentEncodingCharset("gb2312");
@ -219,6 +223,45 @@ public class SIPRequestHeaderPlarformProvider {
UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
request.addHeader(userAgentHeader); request.addHeader(userAgentHeader);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
request.setContent(content, contentTypeHeader);
return request;
}
public Request createNotifyRequest(ParentPlatform parentPlatform, String content, String fromTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException {
Request request = null;
// sipuri
SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort());
// via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()),
parentPlatform.getTransport(), null);
viaHeader.setRPort();
viaHeaders.add(viaHeader);
// from
SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(),
parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort());
Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag);
// to
SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain());
Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag);
// Forwards
MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70);
// ceq
CSeqHeader cSeqHeader = sipFactory.createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(Request.NOTIFY), Request.NOTIFY);
MessageFactoryImpl messageFactory = (MessageFactoryImpl) sipFactory.createMessageFactory();
// 设置编码, 防止中文乱码
messageFactory.setDefaultContentEncodingCharset("gb2312");
request = messageFactory.createRequest(requestURI, Request.NOTIFY, callIdHeader, cSeqHeader, fromHeader,
toHeader, viaHeaders, maxForwards);
List<String> agentParam = new ArrayList<>();
agentParam.add("wvp-pro");
UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam);
request.addHeader(userAgentHeader);
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
request.setContent(content, contentTypeHeader); request.setContent(content, contentTypeHeader);
return request; return request;

49
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java

@ -3,9 +3,11 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd.impl;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -92,7 +94,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
callIdHeader = udpSipProvider.getNewCallId(); callIdHeader = udpSipProvider.getNewCallId();
} }
request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, 1L, "FromRegister" + tm, null, callIdHeader); request = headerProviderPlarformProvider.createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), "FromRegister" + tm, null, callIdHeader);
// 将 callid 写入缓存, 等注册成功可以更新状态 // 将 callid 写入缓存, 等注册成功可以更新状态
redisCatchStorage.updatePlatformRegisterInfo(callIdHeader.getCallId(), parentPlatform.getServerGBId()); redisCatchStorage.updatePlatformRegisterInfo(callIdHeader.getCallId(), parentPlatform.getServerGBId());
@ -222,7 +224,13 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n"); catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");
catalogXml.append("<Info></Info>\r\n"); catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n");
catalogXml.append("<Latitude>" + channel.getLatitude() + "</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");
} }
@ -319,4 +327,41 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
} }
return true; return true;
} }
@Override
public boolean sendMobilePosition(ParentPlatform parentPlatform, GPSMsgInfo gpsMsgInfo, SubscribeInfo subscribeInfo) {
if (parentPlatform == null) {
return false;
}
try {
StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
deviceStatusXml.append("<Notify>\r\n");
deviceStatusXml.append("<CmdType>MobilePosition</CmdType>\r\n");
deviceStatusXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
deviceStatusXml.append("<DeviceID>" + gpsMsgInfo.getId() + "</DeviceID>\r\n");
deviceStatusXml.append("<Time>" + gpsMsgInfo.getTime() + "</Time>\r\n");
deviceStatusXml.append("<Longitude>" + gpsMsgInfo.getLng() + "</Longitude>\r\n");
deviceStatusXml.append("<Latitude>" + gpsMsgInfo.getLat() + "</Latitude>\r\n");
deviceStatusXml.append("<Speed>" + gpsMsgInfo.getSpeed() + "</Speed>\r\n");
deviceStatusXml.append("<Direction>" + gpsMsgInfo.getDirection() + "</Direction>\r\n");
deviceStatusXml.append("<Altitude>" + gpsMsgInfo.getAltitude() + "</Altitude>\r\n");
deviceStatusXml.append("</Notify>\r\n");
CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
: udpSipProvider.getNewCallId();
callIdHeader.setCallId(subscribeInfo.getCallId());
String tm = Long.toString(System.currentTimeMillis());
Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, deviceStatusXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader);
transmitRequest(parentPlatform, request);
} catch (SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
return false;
}
return true;
}
} }

28
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java

@ -18,6 +18,7 @@ import javax.sip.address.Address;
import javax.sip.address.AddressFactory; import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI; import javax.sip.address.SipURI;
import javax.sip.header.ContentTypeHeader; import javax.sip.header.ContentTypeHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.HeaderFactory; import javax.sip.header.HeaderFactory;
import javax.sip.header.ViaHeader; import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory; import javax.sip.message.MessageFactory;
@ -153,7 +154,7 @@ public abstract class SIPRequestProcessorParent {
* @throws InvalidArgumentException * @throws InvalidArgumentException
* @throws ParseException * @throws ParseException
*/ */
public void responseAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { public void responseSdpAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException {
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
SipFactory sipFactory = SipFactory.getInstance(); SipFactory sipFactory = SipFactory.getInstance();
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
@ -168,6 +169,31 @@ public abstract class SIPRequestProcessorParent {
getServerTransaction(evt).sendResponse(response); getServerTransaction(evt).sendResponse(response);
} }
/**
* 回复带xml的200
* @param evt
* @param xml
* @throws SipException
* @throws InvalidArgumentException
* @throws ParseException
*/
public Response responseXmlAck(RequestEvent evt, String xml) throws SipException, InvalidArgumentException, ParseException {
Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest());
SipFactory sipFactory = SipFactory.getInstance();
ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml");
response.setContent(xml, contentTypeHeader);
SipURI sipURI = (SipURI)evt.getRequest().getRequestURI();
Address concatAddress = sipFactory.createAddressFactory().createAddress(
sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort()
));
response.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress));
response.addHeader(evt.getRequest().getHeader(ExpiresHeader.NAME));
getServerTransaction(evt).sendResponse(response);
return response;
}
public Element getRootElement(RequestEvent evt) throws DocumentException { public Element getRootElement(RequestEvent evt) throws DocumentException {
return getRootElement(evt, "gb2312"); return getRootElement(evt, "gb2312");
} }

8
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java

@ -107,6 +107,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
// 查询平台下是否有该通道 // 查询平台下是否有该通道
DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId);
List<GbStream> gbStreams = storager.queryStreamInParentPlatform(requesterId, channelId); List<GbStream> gbStreams = storager.queryStreamInParentPlatform(requesterId, channelId);
PlatformCatalog catalog = storager.getCatalog(channelId);
GbStream gbStream = gbStreams.size() > 0? gbStreams.get(0):null; GbStream gbStream = gbStreams.size() > 0? gbStreams.get(0):null;
MediaServerItem mediaServerItem = null; MediaServerItem mediaServerItem = null;
// 不是通道可能是直播流 // 不是通道可能是直播流
@ -132,6 +133,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
return; return;
} }
responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
}else if (catalog != null) {
responseAck(evt, Response.BAD_REQUEST, "catalog channel can not play"); // 目录不支持点播
return;
} else { } else {
logger.info("通道不存在,返回404"); logger.info("通道不存在,返回404");
responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在 responseAck(evt, Response.NOT_FOUND); // 通道不存在,发404,资源不存在
@ -249,7 +253,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
content.append("f=\r\n"); content.append("f=\r\n");
try { try {
responseAck(evt, content.toString()); responseSdpAck(evt, content.toString());
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
@ -306,7 +310,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
content.append("f=\r\n"); content.append("f=\r\n");
try { try {
responseAck(evt, content.toString()); responseSdpAck(evt, content.toString());
} catch (SipException e) { } catch (SipException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {

10
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java

@ -62,9 +62,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
@Autowired @Autowired
private DeviceOffLineDetector offLineDetector; private DeviceOffLineDetector offLineDetector;
private static final String NOTIFY_CATALOG = "Catalog";
private static final String NOTIFY_ALARM = "Alarm";
private static final String NOTIFY_MOBILE_POSITION = "MobilePosition";
private String method = "NOTIFY"; private String method = "NOTIFY";
@Autowired @Autowired
@ -82,13 +80,13 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
Element rootElement = getRootElement(evt); Element rootElement = getRootElement(evt);
String cmd = XmlUtil.getText(rootElement, "CmdType"); String cmd = XmlUtil.getText(rootElement, "CmdType");
if (NOTIFY_CATALOG.equals(cmd)) { if (CmdType.CATALOG.equals(cmd)) {
logger.info("接收到Catalog通知"); logger.info("接收到Catalog通知");
processNotifyCatalogList(evt); processNotifyCatalogList(evt);
} else if (NOTIFY_ALARM.equals(cmd)) { } else if (CmdType.ALARM.equals(cmd)) {
logger.info("接收到Alarm通知"); logger.info("接收到Alarm通知");
processNotifyAlarm(evt); processNotifyAlarm(evt);
} else if (NOTIFY_MOBILE_POSITION.equals(cmd)) { } else if (CmdType.MOBILE_POSITION.equals(cmd)) {
logger.info("接收到MobilePosition通知"); logger.info("接收到MobilePosition通知");
processNotifyMobilePosition(evt); processNotifyMobilePosition(evt);
} else { } else {

108
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java

@ -1,8 +1,21 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.bean.CmdType;
import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
@ -13,7 +26,10 @@ import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.ServerTransaction; import javax.sip.ServerTransaction;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ExpiresHeader; import javax.sip.header.ExpiresHeader;
import javax.sip.header.Header;
import javax.sip.header.ToHeader;
import javax.sip.message.Request; import javax.sip.message.Request;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -30,6 +46,21 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
@Autowired @Autowired
private SIPProcessorObserver sipProcessorObserver; private SIPProcessorObserver sipProcessorObserver;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private ISIPCommanderForPlatform sipCommanderForPlatform;
@Autowired
private IVideoManagerStorager storager;
@Autowired
private DynamicTask dynamicTask;
@Autowired
private UserSetup userSetup;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
// 添加消息处理的订阅 // 添加消息处理的订阅
@ -46,6 +77,21 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
Request request = evt.getRequest(); Request request = evt.getRequest();
try { try {
Element rootElement = getRootElement(evt);
String cmd = XmlUtil.getText(rootElement, "CmdType");
if (CmdType.MOBILE_POSITION.equals(cmd)) {
logger.info("接收到MobilePosition订阅");
processNotifyMobilePosition(evt, rootElement);
// } else if (CmdType.ALARM.equals(cmd)) {
// logger.info("接收到Alarm订阅");
// processNotifyAlarm(evt, rootElement);
// } else if (CmdType.CATALOG.equals(cmd)) {
// logger.info("接收到Catalog订阅");
// processNotifyCatalogList(evt, rootElement);
} else {
logger.info("接收到消息:" + cmd);
// responseAck(evt, Response.OK);
Response response = null; Response response = null;
response = getMessageFactory().createResponse(200, request); response = getMessageFactory().createResponse(200, request);
if (response != null) { if (response != null) {
@ -61,6 +107,9 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
} else { } else {
logger.info("processRequest serverTransactionId is null."); logger.info("processRequest serverTransactionId is null.");
} }
}
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
@ -68,8 +117,67 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
e.printStackTrace(); e.printStackTrace();
} catch (InvalidArgumentException e) { } catch (InvalidArgumentException e) {
e.printStackTrace(); e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} }
} }
/**
* 处理移动位置订阅消息
*/
private void processNotifyMobilePosition(RequestEvent evt, Element rootElement) {
String platformId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
String deviceID = XmlUtil.getText(rootElement, "DeviceID");
SubscribeInfo subscribeInfo = new SubscribeInfo(evt, platformId);
String sn = XmlUtil.getText(rootElement, "SN");
String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_MobilePosition_" + platformId;
StringBuilder resultXml = new StringBuilder(200);
resultXml.append("<?xml version=\"1.0\" ?>\r\n")
.append("<Response>\r\n")
.append("<CmdType>MobilePosition</CmdType>\r\n")
.append("<SN>" + sn + "</SN>\r\n")
.append("<DeviceID>" + deviceID + "</DeviceID>\r\n")
.append("<Result>OK</Result>\r\n")
.append("</Response>\r\n");
if (subscribeInfo.getExpires() > 0) {
if (redisCatchStorage.getSubscribe(key) != null) {
dynamicTask.stopCron(key);
}
String interval = XmlUtil.getText(rootElement, "Interval"); // GPS上报时间间隔
dynamicTask.startCron(key, new GPSSubscribeTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, sn, key), Integer.parseInt(interval));
redisCatchStorage.updateSubscribe(key, subscribeInfo);
}else if (subscribeInfo.getExpires() == 0) {
dynamicTask.stopCron(key);
redisCatchStorage.delSubscribe(key);
}
try {
Response response = responseXmlAck(evt, resultXml.toString());
ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);
subscribeInfo.setToTag(toHeader.getTag());
redisCatchStorage.updateSubscribe(key, subscribeInfo);
} catch (SipException e) {
e.printStackTrace();
} catch (InvalidArgumentException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
private void processNotifyAlarm(RequestEvent evt, Element rootElement) {
}
private void processNotifyCatalogList(RequestEvent evt, Element rootElement) {
}
} }

14
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java

@ -1,7 +1,9 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceNotFoundEvent;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@ -19,6 +21,7 @@ import org.springframework.stereotype.Component;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
import java.util.Map; import java.util.Map;
@ -39,6 +42,9 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
@Autowired @Autowired
private IVideoManagerStorager storage; private IVideoManagerStorager storage;
@Autowired
private SipSubscribe sipSubscribe;
@Autowired @Autowired
private IRedisCatchStorage redisCatchStorage; private IRedisCatchStorage redisCatchStorage;
@ -56,6 +62,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
logger.debug("接收到消息:" + evt.getRequest()); logger.debug("接收到消息:" + evt.getRequest());
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
// 查询设备是否存在 // 查询设备是否存在
Device device = redisCatchStorage.getDevice(deviceId); Device device = redisCatchStorage.getDevice(deviceId);
// 查询上级平台是否存在 // 查询上级平台是否存在
@ -63,7 +70,12 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
try { try {
if (device == null && parentPlatform == null) { if (device == null && parentPlatform == null) {
// 不存在则回复404 // 不存在则回复404
responseAck(evt, Response.NOT_FOUND, "device id not found"); responseAck(evt, Response.NOT_FOUND, "device "+ deviceId +" not found");
logger.warn("[设备未找到 ]: {}", deviceId);
if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(new DeviceNotFoundEvent(evt.getDialog()));
sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult);
};
}else { }else {
Element rootElement = getRootElement(evt); Element rootElement = getRootElement(evt);
String name = rootElement.getName(); String name = rootElement.getName();

43
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java

@ -1,10 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.*;
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.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
@ -71,11 +68,41 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
// 查询关联的直播通道 // 查询关联的直播通道
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
int size = channelReduces.size() + gbStreams.size(); int size = channelReduces.size() + gbStreams.size();
// 回复目录信息
List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
if (catalogs.size() > 0) {
for (PlatformCatalog catalog : catalogs) {
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);
deviceChannel.setCivilCode(config.getDomain());
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快
Thread.sleep(10);
}
}
// 回复级联的通道 // 回复级联的通道
if (channelReduces.size() > 0) { if (channelReduces.size() > 0) {
for (ChannelReduce channelReduce : channelReduces) { for (ChannelReduce channelReduce : channelReduces) {
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
// TODO 目前暂时认为这里只用通道没有目录
deviceChannel.setParental(0);
deviceChannel.setParentId(channelReduce.getCatalogId());
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快
Thread.sleep(10);
} }
} }
// 回复直播的通道 // 回复直播的通道
@ -89,16 +116,16 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro"); deviceChannel.setManufacture("wvp-pro");
deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setStatus(gbStream.isStatus()?1:0);
// deviceChannel.setParentId(parentPlatform.getDeviceGBId()); deviceChannel.setParentId(gbStream.getCatalogId());
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(config.getDomain()); deviceChannel.setCivilCode(config.getDomain());
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0); deviceChannel.setParental(0);
deviceChannel.setSecrecy("0"); deviceChannel.setSecrecy("0");
deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快
Thread.sleep(10);
} }
} }
if (size == 0) { if (size == 0) {
@ -111,6 +138,8 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
e.printStackTrace(); e.printStackTrace();
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} }
} }

41
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java

@ -1,10 +1,7 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.cmd;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.*;
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.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
@ -73,12 +70,41 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); List<ChannelReduce> channelReduces = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
// 查询关联的直播通道 // 查询关联的直播通道
List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
int size = channelReduces.size() + gbStreams.size(); // 回复目录信息
List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
int size = catalogs.size() + channelReduces.size() + gbStreams.size();
if (catalogs.size() > 0) {
for (PlatformCatalog catalog : catalogs) {
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);
deviceChannel.setCivilCode(config.getDomain());
deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro");
deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快
Thread.sleep(10);
}
}
// 回复级联的通道 // 回复级联的通道
if (channelReduces.size() > 0) { if (channelReduces.size() > 0) {
for (ChannelReduce channelReduce : channelReduces) { for (ChannelReduce channelReduce : channelReduces) {
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
// TODO 目前暂时认为这里只用通道没有目录
deviceChannel.setParental(0);
deviceChannel.setParentId(channelReduce.getCatalogId());
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 防止发送过快
Thread.sleep(10);
} }
} }
// 回复直播的通道 // 回复直播的通道
@ -92,14 +118,13 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
deviceChannel.setDeviceId(parentPlatform.getDeviceGBId()); deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());
deviceChannel.setManufacture("wvp-pro"); deviceChannel.setManufacture("wvp-pro");
deviceChannel.setStatus(gbStream.isStatus()?1:0); deviceChannel.setStatus(gbStream.isStatus()?1:0);
// deviceChannel.setParentId(parentPlatform.getDeviceGBId()); deviceChannel.setParentId(gbStream.getCatalogId());
deviceChannel.setRegisterWay(1); deviceChannel.setRegisterWay(1);
deviceChannel.setCivilCode(config.getDomain()); deviceChannel.setCivilCode(config.getDomain());
deviceChannel.setModel("live"); deviceChannel.setModel("live");
deviceChannel.setOwner("wvp-pro"); deviceChannel.setOwner("wvp-pro");
deviceChannel.setParental(0); deviceChannel.setParental(0);
deviceChannel.setSecrecy("0"); deviceChannel.setSecrecy("0");
deviceChannel.setSecrecy("0");
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
} }
@ -114,6 +139,8 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
e.printStackTrace(); e.printStackTrace();
} catch (ParseException e) { } catch (ParseException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} }
} }

1
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java

@ -91,7 +91,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
// 遍历DeviceList // 遍历DeviceList
while (deviceListIterator.hasNext()) { while (deviceListIterator.hasNext()) {
Element itemDevice = deviceListIterator.next(); Element itemDevice = deviceListIterator.next();
Element channelDeviceElement = itemDevice.element("DeviceID"); Element channelDeviceElement = itemDevice.element("DeviceID");
if (channelDeviceElement == null) { if (channelDeviceElement == null) {
continue; continue;

21
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java

@ -4,7 +4,6 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
@ -322,10 +321,8 @@ public class ZLMHttpHookListener {
String schema = item.getSchema(); String schema = item.getSchema();
List<MediaItem.MediaTrack> tracks = item.getTracks(); List<MediaItem.MediaTrack> tracks = item.getTracks();
boolean regist = item.isRegist(); boolean regist = item.isRegist();
if (tracks != null) {
logger.info("[stream: " + streamId + "] on_stream_changed->>" + schema);
}
if ("rtmp".equals(schema)){ if ("rtmp".equals(schema)){
logger.info("on_stream_changed:注册->{}, app->{}, stream->{}", regist, app, streamId);
if (regist) { if (regist) {
mediaServerService.addCount(mediaServerId); mediaServerService.addCount(mediaServerId);
}else { }else {
@ -346,24 +343,16 @@ public class ZLMHttpHookListener {
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem != null){ if (mediaServerItem != null){
if (regist) { if (regist) {
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks); redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
redisCatchStorage.addStream(mediaServerItem, type, app, streamId, streamInfo);
if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|| item.getOriginType() == OriginType.RTMP_PUSH.ordinal() || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
|| item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) {
zlmMediaListManager.addPush(item); zlmMediaListManager.addPush(item);
} }
}else { }else {
// 兼容流注销时类型错误的问题,等zlm更新后删除 // 兼容流注销时类型从redis记录获取
StreamPushItem streamPushItem = streamPushService.getPush(app, streamId); MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, streamId, mediaServerId);
if (streamPushItem != null) { type = OriginType.values()[mediaItem.getOriginType()].getType();
type = "PUSH";
}else {
StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(app, streamId);
if (streamProxyByAppAndStream != null) {
type = "PULL";
}
}
zlmMediaListManager.removeMedia(app, streamId); zlmMediaListManager.removeMedia(app, streamId);
redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId); redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId);
} }

15
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.media.zlm.event;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
@ -21,7 +22,7 @@ import org.springframework.stereotype.Component;
* @date: 2020年5月6日 上午11:35:46 * @date: 2020年5月6日 上午11:35:46
*/ */
@Component @Component
public class ZLMKeepliveTimeoutListener extends KeyExpirationEventMessageListener { public class ZLMKeepliveTimeoutListener extends RedisKeyExpirationEventMessageListener {
private Logger logger = LoggerFactory.getLogger(ZLMKeepliveTimeoutListener.class); private Logger logger = LoggerFactory.getLogger(ZLMKeepliveTimeoutListener.class);
@ -37,18 +38,10 @@ public class ZLMKeepliveTimeoutListener extends KeyExpirationEventMessageListene
@Autowired @Autowired
private IMediaServerService mediaServerService; private IMediaServerService mediaServerService;
@Override public ZLMKeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetup userSetup) {
public void init() { super(listenerContainer, userSetup);
if (!userSetup.getRedisConfig()) {
// 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用
setKeyspaceNotificationsConfigParameter("");
}
super.init();
} }
public ZLMKeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer) {
super(listenerContainer);
}
/** /**
* 监听失效的keykey格式为keeplive_deviceId * 监听失效的keykey格式为keeplive_deviceId

2
src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java

@ -30,7 +30,7 @@ public interface IGbStreamService {
* 保存国标关联 * 保存国标关联
* @param gbStreams * @param gbStreams
*/ */
boolean addPlatformInfo(List<GbStream> gbStreams, String platformId); boolean addPlatformInfo(List<GbStream> gbStreams, String platformId, String catalogId);
/** /**
* 移除国标关联 * 移除国标关联

39
src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java

@ -0,0 +1,39 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 定时查找redis中的GPS推送消息并保存到对应的流中
*/
@Component
public class StreamGPSSubscribeTask {
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private IVideoManagerStorager storager;
@Scheduled(fixedRate = 30 * 1000) //每30秒执行一次
public void execute(){
List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();
if (gpsMsgInfo.size() > 0) {
storager.updateStreamGPS(gpsMsgInfo);
for (GPSMsgInfo msgInfo : gpsMsgInfo) {
msgInfo.setStored(true);
redisCatchStorage.updateGpsMsgInfo(msgInfo);
}
}
}
}

106
src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java

@ -0,0 +1,106 @@
package com.genersoft.iot.vmp.service.bean;
public class GPSMsgInfo {
/**
*
*/
private String id;
/**
* 经度 (必选)
*/
private double lng;
/**
* 纬度 (必选)
*/
private double lat;
/**
* 速度,单位:km/h (可选)
*/
private double speed;
/**
* 产生通知时间, 时间格式 2020-01-14T14:32:12
*/
private String time;
/**
* 方向,取值为当前摄像头方向与正北方的顺时针夹角,取值范围0°~360°,单位:(°)(可选)
*/
private String direction;
/**
* 海拔高度,单位:m(可选)
*/
private String altitude;
private boolean stored;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public String getAltitude() {
return altitude;
}
public void setAltitude(String altitude) {
this.altitude = altitude;
}
public boolean isStored() {
return stored;
}
public void setStored(boolean stored) {
this.stored = stored;
}
}

4
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java

@ -47,13 +47,15 @@ public class GbStreamServiceImpl implements IGbStreamService {
@Override @Override
public boolean addPlatformInfo(List<GbStream> gbStreams, String platformId) { public boolean addPlatformInfo(List<GbStream> gbStreams, String platformId, String catalogId) {
// 放在事务内执行 // 放在事务内执行
boolean result = false; boolean result = false;
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
try { try {
for (GbStream gbStream : gbStreams) { for (GbStream gbStream : gbStreams) {
gbStream.setCatalogId(catalogId);
gbStream.setPlatformId(platformId); gbStream.setPlatformId(platformId);
// TODO 修改为批量提交
platformGbStreamMapper.add(gbStream); platformGbStreamMapper.add(gbStream);
} }
dataSourceTransactionManager.commit(transactionStatus); //手动提交 dataSourceTransactionManager.commit(transactionStatus); //手动提交

22
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java

@ -0,0 +1,22 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
@Component
public class RedisGPSMsgListener implements MessageListener {
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Override
public void onMessage(Message message, byte[] bytes) {
GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);
redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
}
}

15
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java

@ -130,7 +130,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if ( !StringUtils.isEmpty(param.getPlatformGbId()) && streamLive) { if ( !StringUtils.isEmpty(param.getPlatformGbId()) && streamLive) {
List<GbStream> gbStreams = new ArrayList<>(); List<GbStream> gbStreams = new ArrayList<>();
gbStreams.add(param); gbStreams.add(param);
if (gbStreamService.addPlatformInfo(gbStreams, param.getPlatformGbId())){ if (gbStreamService.addPlatformInfo(gbStreams, param.getPlatformGbId(), param.getCatalogId())){
result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]成功"); result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]成功");
}else { }else {
result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败"); result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败");
@ -141,6 +141,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
if (parentPlatforms.size() > 0) { if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) { for (ParentPlatform parentPlatform : parentPlatforms) {
param.setPlatformId(parentPlatform.getServerGBId()); param.setPlatformId(parentPlatform.getServerGBId());
param.setCatalogId(parentPlatform.getCatalogId());
String stream = param.getStream(); String stream = param.getStream();
StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(param.getApp(), stream, parentPlatform.getServerGBId()); StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(param.getApp(), stream, parentPlatform.getServerGBId());
if (streamProxyItems == null) { if (streamProxyItems == null) {
@ -278,18 +279,18 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
String type = "PULL"; String type = "PULL";
// 发送redis消息 // 发送redis消息
List<StreamInfo> streamInfoList = redisCatchStorage.getStreams(mediaServerId, type); List<MediaItem> mediaItems = redisCatchStorage.getStreams(mediaServerId, type);
if (streamInfoList.size() > 0) { if (mediaItems.size() > 0) {
for (StreamInfo streamInfo : streamInfoList) { for (MediaItem mediaItem : mediaItems) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("serverId", userSetup.getServerId()); jsonObject.put("serverId", userSetup.getServerId());
jsonObject.put("app", streamInfo.getApp()); jsonObject.put("app", mediaItem.getApp());
jsonObject.put("stream", streamInfo.getStreamId()); jsonObject.put("stream", mediaItem.getStream());
jsonObject.put("register", false); jsonObject.put("register", false);
jsonObject.put("mediaServerId", mediaServerId); jsonObject.put("mediaServerId", mediaServerId);
redisCatchStorage.sendStreamChangeMsg(type, jsonObject); redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
// 移除redis内流的信息 // 移除redis内流的信息
redisCatchStorage.removeStream(mediaServerId, type, streamInfo.getApp(), streamInfo.getStreamId()); redisCatchStorage.removeStream(mediaServerId, type, mediaItem.getApp(), mediaItem.getStream());
} }
} }
} }

33
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java

@ -119,6 +119,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream(); List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
if (parentPlatforms.size() > 0) { if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) { for (ParentPlatform parentPlatform : parentPlatforms) {
stream.setCatalogId(parentPlatform.getCatalogId());
stream.setPlatformId(parentPlatform.getServerGBId()); stream.setPlatformId(parentPlatform.getServerGBId());
String streamId = stream.getStream(); String streamId = stream.getStream();
StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId()); StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());
@ -172,16 +173,16 @@ public class StreamPushServiceImpl implements IStreamPushService {
List<StreamPushItem> pushList = getPushList(mediaServerId); List<StreamPushItem> pushList = getPushList(mediaServerId);
Map<String, StreamPushItem> pushItemMap = new HashMap<>(); Map<String, StreamPushItem> pushItemMap = new HashMap<>();
// redis记录 // redis记录
List<StreamInfo> streamInfoPushList = redisCatchStorage.getStreams(mediaServerId, "PUSH"); List<MediaItem> mediaItems = redisCatchStorage.getStreams(mediaServerId, "PUSH");
Map<String, StreamInfo> streamInfoPushItemMap = new HashMap<>(); Map<String, MediaItem> streamInfoPushItemMap = new HashMap<>();
if (pushList.size() > 0) { if (pushList.size() > 0) {
for (StreamPushItem streamPushItem : pushList) { for (StreamPushItem streamPushItem : pushList) {
pushItemMap.put(streamPushItem.getApp() + streamPushItem.getStream(), streamPushItem); pushItemMap.put(streamPushItem.getApp() + streamPushItem.getStream(), streamPushItem);
} }
} }
if (streamInfoPushList.size() > 0) { if (mediaItems.size() > 0) {
for (StreamInfo streamInfo : streamInfoPushList) { for (MediaItem mediaItem : mediaItems) {
streamInfoPushItemMap.put(streamInfo.getApp() + streamInfo.getStreamId(), streamInfo); streamInfoPushItemMap.put(mediaItem.getApp() + mediaItem.getStream(), mediaItem);
} }
} }
zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{ zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{
@ -220,19 +221,19 @@ public class StreamPushServiceImpl implements IStreamPushService {
} }
} }
Collection<StreamInfo> offlineStreamInfoItems = streamInfoPushItemMap.values(); Collection<MediaItem> offlineMediaItemList = streamInfoPushItemMap.values();
if (offlineStreamInfoItems.size() > 0) { if (offlineMediaItemList.size() > 0) {
String type = "PUSH"; String type = "PUSH";
for (StreamInfo offlineStreamInfoItem : offlineStreamInfoItems) { for (MediaItem offlineMediaItem : offlineMediaItemList) {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("serverId", userSetup.getServerId()); jsonObject.put("serverId", userSetup.getServerId());
jsonObject.put("app", offlineStreamInfoItem.getApp()); jsonObject.put("app", offlineMediaItem.getApp());
jsonObject.put("stream", offlineStreamInfoItem.getStreamId()); jsonObject.put("stream", offlineMediaItem.getStream());
jsonObject.put("register", false); jsonObject.put("register", false);
jsonObject.put("mediaServerId", mediaServerId); jsonObject.put("mediaServerId", mediaServerId);
redisCatchStorage.sendStreamChangeMsg(type, jsonObject); redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
// 移除redis内流的信息 // 移除redis内流的信息
redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineStreamInfoItem.getApp(), offlineStreamInfoItem.getStreamId()); redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineMediaItem.getApp(), offlineMediaItem.getStream());
} }
} }
})); }));
@ -249,15 +250,15 @@ public class StreamPushServiceImpl implements IStreamPushService {
// 发送流停止消息 // 发送流停止消息
String type = "PUSH"; String type = "PUSH";
// 发送redis消息 // 发送redis消息
List<StreamInfo> streamInfoList = redisCatchStorage.getStreams(mediaServerId, type); List<MediaItem> streamInfoList = redisCatchStorage.getStreams(mediaServerId, type);
if (streamInfoList.size() > 0) { if (streamInfoList.size() > 0) {
for (StreamInfo streamInfo : streamInfoList) { for (MediaItem mediaItem : streamInfoList) {
// 移除redis内流的信息 // 移除redis内流的信息
redisCatchStorage.removeStream(mediaServerId, type, streamInfo.getApp(), streamInfo.getStreamId()); redisCatchStorage.removeStream(mediaServerId, type, mediaItem.getApp(), mediaItem.getStream());
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
jsonObject.put("serverId", userSetup.getServerId()); jsonObject.put("serverId", userSetup.getServerId());
jsonObject.put("app", streamInfo.getApp()); jsonObject.put("app", mediaItem.getApp());
jsonObject.put("stream", streamInfo.getStreamId()); jsonObject.put("stream", mediaItem.getStream());
jsonObject.put("register", false); jsonObject.put("register", false);
jsonObject.put("mediaServerId", mediaServerId); jsonObject.put("mediaServerId", mediaServerId);
redisCatchStorage.sendStreamChangeMsg(type, jsonObject); redisCatchStorage.sendStreamChangeMsg(type, jsonObject);

31
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java

@ -2,11 +2,11 @@ package com.genersoft.iot.vmp.storager;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 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.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
import java.util.List; import java.util.List;
@ -145,7 +145,7 @@ public interface IRedisCatchStorage {
* @param app * @param app
* @param streamId * @param streamId
*/ */
void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, StreamInfo streamInfo); void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem item);
/** /**
* 移除流信息从redis * 移除流信息从redis
@ -177,7 +177,7 @@ public interface IRedisCatchStorage {
*/ */
ThirdPartyGB queryMemberNoGBId(String queryKey); ThirdPartyGB queryMemberNoGBId(String queryKey);
List<StreamInfo> getStreams(String mediaServerId, String pull); List<MediaItem> getStreams(String mediaServerId, String pull);
/** /**
* 将device信息写入redis * 将device信息写入redis
@ -185,10 +185,29 @@ public interface IRedisCatchStorage {
*/ */
void updateDevice(Device device); void updateDevice(Device device);
void removeDevice(String deviceId);
/** /**
* 获取Device * 获取Device
*/ */
Device getDevice(String deviceId); Device getDevice(String deviceId);
void resetAllCSEQ(); void resetAllCSEQ();
void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo);
GPSMsgInfo getGpsMsgInfo(String gbId);
List<GPSMsgInfo> getAllGpsMsgInfo();
Long getSN(String method);
void resetAllSN();
void updateSubscribe(String key, SubscribeInfo subscribeInfo);
SubscribeInfo getSubscribe(String key);
void delSubscribe(String key);
MediaItem getStreamInfo(String app, String streamId, String mediaServerId);
} }

30
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -243,7 +244,7 @@ public interface IVideoManagerStorager {
* @param channelReduces * @param channelReduces
* @return * @return
*/ */
int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces); int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
/** /**
* 移除上级平台的通道信息 * 移除上级平台的通道信息
@ -256,6 +257,9 @@ public interface IVideoManagerStorager {
DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId);
List<PlatformCatalog> queryStreamInParentPlatformAndCatalog(String platformId, String catalogId);
Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
@ -431,4 +435,28 @@ public interface IVideoManagerStorager {
* @param deviceChannelList * @param deviceChannelList
*/ */
boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList); boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList);
/**
* 获取目录信息
* @param platformId
* @param parentId
* @return
*/
List<PlatformCatalog> getChildrenCatalogByPlatform(String platformId, String parentId);
int addCatalog(PlatformCatalog platformCatalog);
PlatformCatalog getCatalog(String id);
int delCatalog(String id);
int updateCatalog(PlatformCatalog platformCatalog);
int setDefaultCatalog(String platformId, String catalogId);
List<PlatformCatalog> queryCatalogInPlatform(String serverGBId);
int delRelation(PlatformCatalog platformCatalog);
int updateStreamGPS(List<GPSMsgInfo> gpsMsgInfo);
} }

3
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java

@ -91,7 +91,8 @@ public interface DeviceChannelMapper {
"SELECT * FROM ( "+ "SELECT * FROM ( "+
" SELECT dc.channelId, dc.deviceId, dc.name, de.manufacturer, de.hostAddress, " + " SELECT dc.channelId, dc.deviceId, dc.name, de.manufacturer, de.hostAddress, " +
"(SELECT count(0) FROM device_channel WHERE parentId=dc.channelId) as subCount, " + "(SELECT count(0) FROM device_channel WHERE parentId=dc.channelId) as subCount, " +
"(SELECT pc.platformId FROM platform_gb_channel pc WHERE pc.deviceId=dc.deviceId AND pc.channelId = dc.channelId ) as platformId " + "(SELECT pc.platformId FROM platform_gb_channel pc WHERE pc.deviceId=dc.deviceId AND pc.channelId = dc.channelId ) as platformId, " +
"(SELECT pc.catalogId FROM platform_gb_channel pc WHERE pc.deviceId=dc.deviceId AND pc.channelId = dc.channelId ) as catalogId " +
"FROM device_channel dc " + "FROM device_channel dc " +
"LEFT JOIN device de ON dc.deviceId = de.deviceId " + "LEFT JOIN device de ON dc.deviceId = de.deviceId " +
" WHERE 1=1 " + " WHERE 1=1 " +

29
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.GbStream; 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.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@ -35,7 +36,7 @@ public interface GbStreamMapper {
@Delete("DELETE FROM gb_stream WHERE app=#{app} AND stream=#{stream}") @Delete("DELETE FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
int del(String app, String stream); int del(String app, String stream);
@Select("SELECT gs.*, pgs.platformId FROM gb_stream gs LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream") @Select("SELECT gs.*, pgs.platformId AS platformId, pgs.catalogId AS catalogId FROM gb_stream gs LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream")
List<GbStream> selectAll(); List<GbStream> selectAll();
@Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}") @Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
@ -44,32 +45,31 @@ public interface GbStreamMapper {
@Select("SELECT * FROM gb_stream WHERE gbId=#{gbId}") @Select("SELECT * FROM gb_stream WHERE gbId=#{gbId}")
List<GbStream> selectByGBId(String gbId); List<GbStream> selectByGBId(String gbId);
@Select("SELECT gs.*, pgs.platformId FROM gb_stream gs " + @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " +
"LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream " + "LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream " +
"WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'") "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'")
List<GbStream> queryStreamInPlatform(String platformId, String gbId); List<GbStream> queryStreamInPlatform(String platformId, String gbId);
@Select("SELECT gs.*, pgs.platformId FROM gb_stream gs " + @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " +
"LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream " + "LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream " +
"WHERE pgs.platformId = '${platformId}'") "WHERE pgs.platformId = '${platformId}'")
List<GbStream> queryGbStreamListInPlatform(String platformId); List<GbStream> queryGbStreamListInPlatform(String platformId);
@Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " +
"ON gs.app = pgs.app and gs.stream = pgs.stream WHERE pgs.app is NULL and pgs.stream is NULL")
List<GbStream> queryStreamNotInPlatform();
@Update("UPDATE gb_stream " + @Update("UPDATE gb_stream " +
"SET status=${status} " + "SET status=${status} " +
"WHERE app=#{app} AND stream=#{stream}") "WHERE app=#{app} AND stream=#{stream}")
int setStatus(String app, String stream, boolean status); int setStatus(String app, String stream, boolean status);
@Select("SELECT gs.*, pgs.platformId FROM gb_stream gs LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream WHERE mediaServerId=#{mediaServerId} ")
List<GbStream> selectAllByMediaServerId(String mediaServerId);
@Update("UPDATE gb_stream " + @Update("UPDATE gb_stream " +
"SET status=${status} " + "SET status=${status} " +
"WHERE mediaServerId=#{mediaServerId} ") "WHERE mediaServerId=#{mediaServerId} ")
void updateStatusByMediaServerId(String mediaServerId, boolean status); void updateStatusByMediaServerId(String mediaServerId, boolean status);
@Select("SELECT * FROM gb_stream WHERE mediaServerId=#{mediaServerId}")
void delByMediaServerId(String mediaServerId);
@Delete("DELETE FROM gb_stream WHERE streamType=#{type} AND gbId=NULL AND mediaServerId=#{mediaServerId}") @Delete("DELETE FROM gb_stream WHERE streamType=#{type} AND gbId=NULL AND mediaServerId=#{mediaServerId}")
void deleteWithoutGBId(String type, String mediaServerId); void deleteWithoutGBId(String type, String mediaServerId);
@ -93,4 +93,15 @@ public interface GbStreamMapper {
"</foreach> " + "</foreach> " +
"</script>") "</script>")
void batchAdd(List<StreamPushItem> subList); void batchAdd(List<StreamPushItem> subList);
@Update({"<script>" +
"<foreach collection='gpsMsgInfos' item='item' separator=';'>" +
" UPDATE" +
" gb_stream" +
" SET longitude=${item.lng}, latitude=${item.lat} " +
"WHERE gbId=#{item.id}"+
"</foreach>" +
"</script>"})
int updateStreamGPS(List<GPSMsgInfo> gpsMsgInfos);
} }

14
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java

@ -15,10 +15,10 @@ public interface ParentPlatformMapper {
@Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " +
" devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " + " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
" status, shareAllLiveStream) " + " status, shareAllLiveStream, catalogId) " +
" VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " + " VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " +
" '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " + " '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " +
" ${status}, ${shareAllLiveStream})") " ${status}, ${shareAllLiveStream}, #{catalogId})")
int addParentPlatform(ParentPlatform parentPlatform); int addParentPlatform(ParentPlatform parentPlatform);
@Update("UPDATE parent_platform " + @Update("UPDATE parent_platform " +
@ -40,7 +40,8 @@ public interface ParentPlatformMapper {
"ptz=#{ptz}, " + "ptz=#{ptz}, " +
"rtcp=#{rtcp}, " + "rtcp=#{rtcp}, " +
"status=#{status}, " + "status=#{status}, " +
"shareAllLiveStream=#{shareAllLiveStream} " + "shareAllLiveStream=#{shareAllLiveStream}, " +
"catalogId=#{catalogId} " +
"WHERE id=#{id}") "WHERE id=#{id}")
int updateParentPlatform(ParentPlatform parentPlatform); int updateParentPlatform(ParentPlatform parentPlatform);
@ -74,4 +75,11 @@ public interface ParentPlatformMapper {
@Select("SELECT * FROM parent_platform WHERE shareAllLiveStream=true") @Select("SELECT * FROM parent_platform WHERE shareAllLiveStream=true")
List<ParentPlatform> selectAllAhareAllLiveStream(); List<ParentPlatform> selectAllAhareAllLiveStream();
@Update(value = {" <script>" +
"UPDATE parent_platform " +
"SET catalogId=#{catalogId}" +
"WHERE serverGBId=#{platformId}"+
"</script>"})
int setDefaultCatalog(String platformId, String catalogId);
} }

42
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java

@ -0,0 +1,42 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface PlatformCatalogMapper {
@Insert("INSERT INTO platform_catalog (id, name, platformId, parentId) VALUES" +
"(#{id}, #{name}, #{platformId}, #{parentId})")
int add(PlatformCatalog platformCatalog);
@Delete("DELETE FROM platform_catalog WHERE id=#{id}")
int del(String id);
@Delete("DELETE FROM platform_catalog WHERE platformId=#{platformId}")
int delByPlatformId(String platformId);
@Select("SELECT *, (SELECT COUNT(1) from platform_catalog where parentId = pc.id AND platformId=#{platformId}) as childrenCount FROM platform_catalog pc WHERE parentId=#{parentId} AND platformId=#{platformId}")
List<PlatformCatalog> selectByParentId(String platformId, String parentId);
@Select("SELECT *, (SELECT COUNT(1) from platform_catalog where parentId = pc.id) as childrenCount FROM platform_catalog pc WHERE pc.id=#{id}")
PlatformCatalog select(String id);
@Update(value = {" <script>" +
"UPDATE platform_catalog " +
"SET name=#{name}" +
"WHERE id=#{id}"+
"</script>"})
int update(PlatformCatalog platformCatalog);
@Select("SELECT *, (SELECT COUNT(1) from platform_catalog where parentId = pc.id) as childrenCount FROM platform_catalog pc WHERE pc.platformId=#{platformId}")
List<PlatformCatalog> selectByPlatForm(String platformId);
}

21
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java

@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Insert;
@ -25,9 +26,9 @@ public interface PlatformChannelMapper {
List<String> findChannelRelatedPlatform(String platformId, List<String> deviceAndChannelIds); List<String> findChannelRelatedPlatform(String platformId, List<String> deviceAndChannelIds);
@Insert("<script> "+ @Insert("<script> "+
"INSERT INTO platform_gb_channel (channelId, deviceId, platformId, deviceAndChannelId) VALUES" + "INSERT INTO platform_gb_channel (channelId, deviceId, platformId, deviceAndChannelId, catalogId) VALUES" +
"<foreach collection='channelReducesToAdd' item='item' separator=','>" + "<foreach collection='channelReducesToAdd' item='item' separator=','>" +
" ('${item.channelId}','${item.deviceId}', '${platformId}', '${item.deviceId}_${item.channelId}' )" + " ('${item.channelId}','${item.deviceId}', '${platformId}', '${item.deviceId}_${item.channelId}' , '${item.catalogId}' )" +
"</foreach>" + "</foreach>" +
"</script>") "</script>")
int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd); int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd);
@ -54,6 +55,22 @@ public interface PlatformChannelMapper {
"platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'") "platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'")
DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); DeviceChannel queryChannelInParentPlatform(String platformId, String channelId);
@Select("select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " +
"from device_channel dc left join platform_gb_channel pgc on dc.deviceId = pgc.deviceId and dc.channelId = pgc.channelId " +
"where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}")
List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId);
@Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE platformId='${platformId}' AND channelId='${channelId}')") @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE platformId='${platformId}' AND channelId='${channelId}')")
Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId);
@Delete("<script> "+
"DELETE FROM platform_gb_channel WHERE catalogId=#{id}" +
"</script>")
int delByCatalogId(String id);
@Delete("<script> "+
"DELETE FROM platform_gb_channel WHERE catalogId=#{parentId} AND platformId=#{platformId} AND channelId=#{id}" +
"</script>")
int delByCatalogIdAndChannelIdAndPlatformId(PlatformCatalog platformCatalog);
} }

24
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java

@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.storager.dao; package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.gb28181.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream; import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
@ -12,8 +14,8 @@ import java.util.List;
@Repository @Repository
public interface PlatformGbStreamMapper { public interface PlatformGbStreamMapper {
@Insert("INSERT INTO platform_gb_stream (app, stream, platformId) VALUES" + @Insert("INSERT INTO platform_gb_stream (app, stream, platformId, catalogId) VALUES" +
"('${app}', '${stream}', '${platformId}')") "('${app}', '${stream}', '${platformId}', '${catalogId}')")
int add(PlatformGbStream platformGbStream); int add(PlatformGbStream platformGbStream);
@Delete("DELETE FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream}") @Delete("DELETE FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream}")
@ -27,4 +29,22 @@ public interface PlatformGbStreamMapper {
@Select("SELECT * FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream} AND platformId=#{serverGBId}") @Select("SELECT * FROM platform_gb_stream WHERE app=#{app} AND stream=#{stream} AND platformId=#{serverGBId}")
StreamProxyItem selectOne(String app, String stream, String serverGBId); StreamProxyItem selectOne(String app, String stream, String serverGBId);
@Select("select gs.* \n" +
"from gb_stream gs\n" +
" left join platform_gb_stream pgs\n" +
" on gs.app = pgs.app and gs.stream = pgs.stream\n" +
"where pgs.platformId=#{platformId} and pgs.catalogId=#{catalogId}")
List<GbStream> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId);
@Select("select gs.gbId as id, gs.name as name, pgs.platformId as platformId, pgs.catalogId as catalogId , 0 as childrenCount, 2 as type\n" +
"from gb_stream gs\n" +
" left join platform_gb_stream pgs\n" +
" on gs.app = pgs.app and gs.stream = pgs.stream\n" +
"where pgs.platformId=#{platformId} and pgs.catalogId=#{catalogId}")
List<PlatformCatalog> queryChannelInParentPlatformAndCatalogForCatlog(String platformId, String catalogId);
@Delete("DELETE FROM platform_gb_stream WHERE catalogId=#{id}")
int delByCatalogId(String id);
} }

109
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java

@ -5,7 +5,10 @@ import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.bean.*; 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.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
@ -48,6 +51,18 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
return result; return result;
} }
@Override
public Long getSN(String method) {
String key = VideoManagerConstants.SIP_SN_PREFIX + userSetup.getServerId() + "_" + method;
long result = redis.incr(key, 1L);
if (result > Integer.MAX_VALUE) {
redis.set(key, 1);
result = 1;
}
return result;
}
@Override @Override
public void resetAllCSEQ() { public void resetAllCSEQ() {
String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetup.getServerId() + "_*"; String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetup.getServerId() + "_*";
@ -58,6 +73,16 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
} }
} }
@Override
public void resetAllSN() {
String scanKey = VideoManagerConstants.SIP_SN_PREFIX + userSetup.getServerId() + "_*";
List<Object> keys = redis.scan(scanKey);
for (int i = 0; i < keys.size(); i++) {
String key = (String) keys.get(i);
redis.set(key, 1);
}
}
/** /**
* 开始播放时将流存入redis * 开始播放时将流存入redis
* *
@ -318,6 +343,15 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
redis.del(key.toString()); redis.del(key.toString());
} }
} }
List<Object> deviceCache = redis.scan(String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX,
userSetup.getServerId(),
deviceId));
if (deviceCache.size() > 0) {
for (Object key : deviceCache) {
redis.del(key.toString());
}
}
} }
@Override @Override
@ -354,9 +388,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
} }
@Override @Override
public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, StreamInfo streamInfo) { public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) {
String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId(); String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
redis.set(key, streamInfo); redis.set(key, mediaItem);
} }
@Override @Override
@ -389,13 +423,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
} }
@Override @Override
public List<StreamInfo> getStreams(String mediaServerId, String type) { public List<MediaItem> getStreams(String mediaServerId, String type) {
List<StreamInfo> result = new ArrayList<>(); List<MediaItem> result = new ArrayList<>();
String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_*_*_" + mediaServerId; String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_*_*_" + mediaServerId;
List<Object> streams = redis.scan(key); List<Object> streams = redis.scan(key);
for (Object stream : streams) { for (Object stream : streams) {
StreamInfo streamInfo = (StreamInfo)redis.get((String) stream); MediaItem mediaItem = (MediaItem)redis.get((String) stream);
result.add(streamInfo); result.add(mediaItem);
} }
return result; return result;
} }
@ -406,9 +440,72 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
redis.set(key, device); redis.set(key, device);
} }
@Override
public void removeDevice(String deviceId) {
String key = VideoManagerConstants.DEVICE_PREFIX + userSetup.getServerId() + "_" + deviceId;
redis.del(key);
}
@Override @Override
public Device getDevice(String deviceId) { public Device getDevice(String deviceId) {
String key = VideoManagerConstants.DEVICE_PREFIX + userSetup.getServerId() + "_" + deviceId; String key = VideoManagerConstants.DEVICE_PREFIX + userSetup.getServerId() + "_" + deviceId;
return (Device)redis.get(key); return (Device)redis.get(key);
} }
@Override
public void updateGpsMsgInfo(GPSMsgInfo gpsMsgInfo) {
String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetup.getServerId() + "_" + gpsMsgInfo.getId();
redis.set(key, gpsMsgInfo, 60); // 默认GPS消息保存1分钟
}
@Override
public GPSMsgInfo getGpsMsgInfo(String gbId) {
String key = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetup.getServerId() + "_" + gbId;
return (GPSMsgInfo)redis.get(key);
}
@Override
public void updateSubscribe(String key, SubscribeInfo subscribeInfo) {
redis.set(key, subscribeInfo, subscribeInfo.getExpires());
}
@Override
public SubscribeInfo getSubscribe(String key) {
return (SubscribeInfo)redis.get(key);
}
@Override
public void delSubscribe(String key) {
redis.del(key);
}
@Override
public List<GPSMsgInfo> getAllGpsMsgInfo() {
String scanKey = VideoManagerConstants.WVP_STREAM_GPS_MSG_PREFIX + userSetup.getServerId() + "_*";
List<GPSMsgInfo> result = new ArrayList<>();
List<Object> keys = redis.scan(scanKey);
for (int i = 0; i < keys.size(); i++) {
String key = (String) keys.get(i);
GPSMsgInfo gpsMsgInfo = (GPSMsgInfo) redis.get(key);
if (!gpsMsgInfo.isStored()) { // 只取没有存过得
result.add((GPSMsgInfo)redis.get(key));
}
}
return result;
}
@Override
public MediaItem getStreamInfo(String app, String streamId, String mediaServerId) {
String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_*_" + app + "_" + streamId + "_" + mediaServerId;
MediaItem result = null;
List<Object> keys = redis.scan(scanKey);
if (keys.size() > 0) {
String key = (String) keys.get(0);
result = (MediaItem)redis.get(key);
}
return result;
}
} }

106
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java

@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.IGbStreamService; import com.genersoft.iot.vmp.service.IGbStreamService;
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.storager.dao.*;
@ -68,6 +69,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
@Autowired @Autowired
private GbStreamMapper gbStreamMapper; private GbStreamMapper gbStreamMapper;
@Autowired
private PlatformCatalogMapper catalogMapper;
; ;
@Autowired @Autowired
@ -466,6 +470,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
@Override @Override
public boolean addParentPlatform(ParentPlatform parentPlatform) { public boolean addParentPlatform(ParentPlatform parentPlatform) {
if (parentPlatform.getCatalogId() == null) {
parentPlatform.setCatalogId(parentPlatform.getServerGBId());
}
int result = platformMapper.addParentPlatform(parentPlatform); int result = platformMapper.addParentPlatform(parentPlatform);
return result > 0; return result > 0;
} }
@ -475,6 +482,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
int result = 0; int result = 0;
ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); // .getDeviceGBId()); ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); // .getDeviceGBId());
if (parentPlatform.getId() == null ) { if (parentPlatform.getId() == null ) {
if (parentPlatform.getCatalogId() == null) {
parentPlatform.setCatalogId(parentPlatform.getServerGBId());
}
result = platformMapper.addParentPlatform(parentPlatform); result = platformMapper.addParentPlatform(parentPlatform);
if (parentPlatformCatch == null) { if (parentPlatformCatch == null) {
parentPlatformCatch = new ParentPlatformCatch(); parentPlatformCatch = new ParentPlatformCatch();
@ -494,15 +504,21 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
// 更新缓存 // 更新缓存
parentPlatformCatch.setParentPlatform(parentPlatform); parentPlatformCatch.setParentPlatform(parentPlatform);
redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
if (parentPlatform.isEnable()) {
// 共享所有视频流,需要将现有视频流添加到此平台 // 共享所有视频流,需要将现有视频流添加到此平台
List<GbStream> gbStreams = gbStreamMapper.selectAll(); List<GbStream> gbStreams = gbStreamMapper.queryStreamNotInPlatform();
if (gbStreams.size() > 0) { if (gbStreams.size() > 0) {
for (GbStream gbStream : gbStreams) {
gbStream.setCatalogId(parentPlatform.getCatalogId());
}
if (parentPlatform.isShareAllLiveStream()) { if (parentPlatform.isShareAllLiveStream()) {
gbStreamService.addPlatformInfo(gbStreams, parentPlatform.getServerGBId()); gbStreamService.addPlatformInfo(gbStreams, parentPlatform.getServerGBId(), parentPlatform.getCatalogId());
}else { }else {
gbStreamService.delPlatformInfo(gbStreams); gbStreamService.delPlatformInfo(gbStreams);
} }
} }
}
return result > 0; return result > 0;
} }
@ -553,10 +569,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
} }
@Override @Override
public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces) { public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
Map<String, ChannelReduce> deviceAndChannels = new HashMap<>(); Map<String, ChannelReduce> deviceAndChannels = new HashMap<>();
for (ChannelReduce channelReduce : channelReduces) { for (ChannelReduce channelReduce : channelReduces) {
channelReduce.setCatalogId(catalogId);
deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce); deviceAndChannels.put(channelReduce.getDeviceId() + "_" + channelReduce.getChannelId(), channelReduce);
} }
List<String> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet()); List<String> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
@ -593,6 +610,18 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
return channel; return channel;
} }
@Override
public List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId) {
List<PlatformCatalog> catalogs = platformChannelMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId);
return catalogs;
}
@Override
public List<PlatformCatalog> queryStreamInParentPlatformAndCatalog(String platformId, String catalogId) {
List<PlatformCatalog> catalogs = platformGbStreamMapper.queryChannelInParentPlatformAndCatalogForCatlog(platformId, catalogId);
return catalogs;
}
@Override @Override
public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) { public Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId) {
Device device = platformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId); Device device = platformChannelMapper.queryVideoDeviceByPlatformIdAndChannelId(platformId, channelId);
@ -756,6 +785,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream(); List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();
if (parentPlatforms.size() > 0) { if (parentPlatforms.size() > 0) {
for (ParentPlatform parentPlatform : parentPlatforms) { for (ParentPlatform parentPlatform : parentPlatforms) {
streamPushItem.setCatalogId(parentPlatform.getCatalogId());
streamPushItem.setPlatformId(parentPlatform.getServerGBId()); streamPushItem.setPlatformId(parentPlatform.getServerGBId());
String stream = streamPushItem.getStream(); String stream = streamPushItem.getStream();
StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(streamPushItem.getApp(), stream, parentPlatform.getServerGBId()); StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(streamPushItem.getApp(), stream, parentPlatform.getServerGBId());
@ -821,4 +851,74 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
return streamProxyMapper.selectOne(app, streamId); return streamProxyMapper.selectOne(app, streamId);
} }
@Override
public List<PlatformCatalog> getChildrenCatalogByPlatform(String platformId, String parentId) {
return catalogMapper.selectByParentId(platformId, parentId);
}
@Override
public int addCatalog(PlatformCatalog platformCatalog) {
return catalogMapper.add(platformCatalog);
}
@Override
public PlatformCatalog getCatalog(String id) {
return catalogMapper.select(id);
}
@Override
public int delCatalog(String id) {
PlatformCatalog platformCatalog = catalogMapper.select(id);
if (platformCatalog.getChildrenCount() > 0) {
List<PlatformCatalog> platformCatalogList = catalogMapper.selectByParentId(platformCatalog.getPlatformId(), platformCatalog.getId());
for (PlatformCatalog catalog : platformCatalogList) {
if (catalog.getChildrenCount() == 0) {
catalogMapper.del(catalog.getId());
platformGbStreamMapper.delByCatalogId(catalog.getId());
platformChannelMapper.delByCatalogId(catalog.getId());
}else {
delCatalog(catalog.getId());
}
}
}
int delresult = catalogMapper.del(id);
int delStreamresult = platformGbStreamMapper.delByCatalogId(id);
int delChanneresult = platformChannelMapper.delByCatalogId(id);
return delresult + delChanneresult + delStreamresult;
}
@Override
public int updateCatalog(PlatformCatalog platformCatalog) {
return catalogMapper.update(platformCatalog);
}
@Override
public int setDefaultCatalog(String platformId, String catalogId) {
return platformMapper.setDefaultCatalog(platformId, catalogId);
}
@Override
public List<PlatformCatalog> queryCatalogInPlatform(String platformId) {
return catalogMapper.selectByPlatForm(platformId);
}
@Override
public int delRelation(PlatformCatalog platformCatalog) {
if (platformCatalog.getType() == 1) {
return platformChannelMapper.delByCatalogIdAndChannelIdAndPlatformId(platformCatalog);
}else if (platformCatalog.getType() == 2) {
List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformCatalog.getPlatformId(), platformCatalog.getParentId());
for (GbStream gbStream : gbStreams) {
if (gbStream.getGbId().equals(platformCatalog.getId())) {
return platformGbStreamMapper.delByAppAndStream(gbStream.getApp(), gbStream.getStream());
}
}
}
return 0;
}
@Override
public int updateStreamGPS(List<GPSMsgInfo> gpsMsgInfos) {
return gbStreamMapper.updateStreamGPS(gpsMsgInfos);
}
} }

13
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java

@ -153,12 +153,15 @@ public class DeviceQuery {
// 默认超时时间为30分钟 // 默认超时时间为30分钟
DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(30*60*1000L); DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(30*60*1000L);
result.onTimeout(()->{ result.onTimeout(()->{
logger.warn(String.format("设备通道信息同步超时")); logger.warn("设备[{}]通道信息同步超时", deviceId);
// 释放rtpserver
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setKey(key);
msg.setId(uuid);
WVPResult<Object> wvpResult = new WVPResult<>(); WVPResult<Object> wvpResult = new WVPResult<>();
wvpResult.setCode(0); wvpResult.setCode(-1);
wvpResult.setMsg("Timeout"); wvpResult.setData(device);
wvpResult.setMsg("更新超时");
msg.setData(wvpResult); msg.setData(wvpResult);
resultHolder.invokeAllResult(msg); resultHolder.invokeAllResult(msg);
@ -170,8 +173,10 @@ public class DeviceQuery {
cmder.catalogQuery(device, event -> { cmder.catalogQuery(device, event -> {
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
msg.setKey(key); msg.setKey(key);
msg.setId(uuid);
WVPResult<Object> wvpResult = new WVPResult<>(); WVPResult<Object> wvpResult = new WVPResult<>();
wvpResult.setCode(0); wvpResult.setCode(-1);
wvpResult.setData(device);
wvpResult.setMsg(String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg)); wvpResult.setMsg(String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg));
msg.setData(wvpResult); msg.setData(wvpResult);
resultHolder.invokeAllResult(msg); resultHolder.invokeAllResult(msg);

2
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java

@ -82,7 +82,7 @@ public class GbStreamController {
@PostMapping(value = "/add") @PostMapping(value = "/add")
@ResponseBody @ResponseBody
public Object add(@RequestBody GbStreamParam gbStreamParam){ public Object add(@RequestBody GbStreamParam gbStreamParam){
if (gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId())) { if (gbStreamService.addPlatformInfo(gbStreamParam.getGbStreams(), gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId())) {
return "success"; return "success";
}else { }else {
return "fail"; return "fail";

10
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/bean/GbStreamParam.java

@ -8,12 +8,22 @@ public class GbStreamParam {
private String platformId; private String platformId;
private String catalogId;
private List<GbStream> gbStreams; private List<GbStream> gbStreams;
public String getPlatformId() { public String getPlatformId() {
return platformId; return platformId;
} }
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
public void setPlatformId(String platformId) { public void setPlatformId(String platformId) {
this.platformId = platformId; this.platformId = platformId;
} }

201
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java

@ -1,10 +1,15 @@
package com.genersoft.iot.vmp.vmanager.gb28181.platform; package com.genersoft.iot.vmp.vmanager.gb28181.platform;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.gb28181.bean.CatalogData;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.UpdateChannelParam;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
@ -21,6 +26,8 @@ import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.SipConfig;
import java.util.List;
/** /**
* 级联平台管理 * 级联平台管理
*/ */
@ -253,7 +260,7 @@ public class PlatformController {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("给上级平台添加国标通道API调用"); logger.debug("给上级平台添加国标通道API调用");
} }
int result = storager.updateChannelForGB(param.getPlatformId(), param.getChannelReduces()); int result = storager.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK); return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
} }
@ -279,5 +286,197 @@ public class PlatformController {
return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK); return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
} }
/**
* 获取目录
* @param platformId 平台ID
* @param parentId 目录父ID
* @return
*/
@ApiOperation("获取目录")
@ApiImplicitParams({
@ApiImplicitParam(name = "platformId", value = "平台ID", dataTypeClass = String.class, required = true),
@ApiImplicitParam(name = "parentId", value = "目录父ID", dataTypeClass = String.class, required = true),
})
@GetMapping("/catalog")
@ResponseBody
public ResponseEntity<WVPResult<List<PlatformCatalog>>> getCatalogByPlatform(String platformId, String parentId){
if (logger.isDebugEnabled()) {
logger.debug("查询目录,platformId: {}, parentId: {}", platformId, parentId);
}
List<PlatformCatalog> platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
// 查询下属的国标通道
List<PlatformCatalog> catalogsForChannel = storager.queryChannelInParentPlatformAndCatalog(platformId, parentId);
List<PlatformCatalog> catalogsForStream = storager.queryStreamInParentPlatformAndCatalog(platformId, parentId);
platformCatalogList.addAll(catalogsForChannel);
platformCatalogList.addAll(catalogsForStream);
WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
result.setCode(0);
result.setMsg("success");
result.setData(platformCatalogList);
return new ResponseEntity<>(result, HttpStatus.OK);
}
/**
* 添加目录
* @param platformCatalog 目录
* @return
*/
@ApiOperation("添加目录")
@ApiImplicitParams({
@ApiImplicitParam(name = "platformCatalog", value = "目录信息", dataTypeClass = PlatformCatalog.class, required = true),
})
@PostMapping("/catalog/add")
@ResponseBody
public ResponseEntity<WVPResult<List<PlatformCatalog>>> addCatalog(@RequestBody PlatformCatalog platformCatalog){
if (logger.isDebugEnabled()) {
logger.debug("添加目录,{}", JSON.toJSONString(platformCatalog));
}
PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
if (platformCatalogInStore != null) {
result.setCode(-1);
result.setMsg( platformCatalog.getId() + " already exists");
return new ResponseEntity<>(result, HttpStatus.OK);
}
int addResult = storager.addCatalog(platformCatalog);
if (addResult > 0) {
result.setCode(0);
result.setMsg("success");
return new ResponseEntity<>(result, HttpStatus.OK);
}else {
result.setCode(-500);
result.setMsg("save error");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
/**
* 编辑目录
* @param platformCatalog 目录
* @return
*/
@ApiOperation("编辑目录")
@ApiImplicitParams({
@ApiImplicitParam(name = "platformCatalog", value = "目录信息", dataTypeClass = PlatformCatalog.class, required = true),
})
@PostMapping("/catalog/edit")
@ResponseBody
public ResponseEntity<WVPResult<List<PlatformCatalog>>> editCatalog(@RequestBody PlatformCatalog platformCatalog){
if (logger.isDebugEnabled()) {
logger.debug("编辑目录,{}", JSON.toJSONString(platformCatalog));
}
PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
result.setCode(0);
if (platformCatalogInStore == null) {
result.setMsg( platformCatalog.getId() + " not exists");
return new ResponseEntity<>(result, HttpStatus.OK);
}
int addResult = storager.updateCatalog(platformCatalog);
if (addResult > 0) {
result.setMsg("success");
return new ResponseEntity<>(result, HttpStatus.OK);
}else {
result.setMsg("save error");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
/**
* 删除目录
* @param id 目录Id
* @return
*/
@ApiOperation("删除目录")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "目录Id", dataTypeClass = String.class, required = true),
})
@DeleteMapping("/catalog/del")
@ResponseBody
public ResponseEntity<WVPResult<List<PlatformCatalog>>> delCatalog(String id){
if (logger.isDebugEnabled()) {
logger.debug("删除目录,{}", id);
}
int delResult = storager.delCatalog(id);
WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
result.setCode(0);
if (delResult > 0) {
result.setMsg("success");
return new ResponseEntity<>(result, HttpStatus.OK);
}else {
result.setMsg("save error");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
/**
* 删除关联
* @param platformCatalog 关联的信息
* @return
*/
@ApiOperation("删除关联")
@ApiImplicitParams({
@ApiImplicitParam(name = "platformCatalog", value = "关联的信息", dataTypeClass = PlatformCatalog.class, required = true),
})
@DeleteMapping("/catalog/relation/del")
@ResponseBody
public ResponseEntity<WVPResult<List<PlatformCatalog>>> delRelation(@RequestBody PlatformCatalog platformCatalog){
if (logger.isDebugEnabled()) {
logger.debug("删除关联,{}", JSON.toJSONString(platformCatalog));
}
int delResult = storager.delRelation(platformCatalog);
WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
result.setCode(0);
if (delResult > 0) {
result.setMsg("success");
return new ResponseEntity<>(result, HttpStatus.OK);
}else {
result.setMsg("save error");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
/**
* 修改默认目录
* @param platformId 平台Id
* @param catalogId 目录Id
* @return
*/
@ApiOperation("修改默认目录")
@ApiImplicitParams({
@ApiImplicitParam(name = "platformId", value = "平台Id", dataTypeClass = String.class, required = true),
@ApiImplicitParam(name = "catalogId", value = "目录Id", dataTypeClass = String.class, required = true),
})
@PostMapping("/catalog/default/update")
@ResponseBody
public ResponseEntity<WVPResult<String>> setDefaultCatalog(String platformId, String catalogId){
if (logger.isDebugEnabled()) {
logger.debug("修改默认目录,{},{}", platformId, catalogId);
}
int updateResult = storager.setDefaultCatalog(platformId, catalogId);
WVPResult<String> result = new WVPResult<>();
result.setCode(0);
if (updateResult > 0) {
result.setMsg("success");
return new ResponseEntity<>(result, HttpStatus.OK);
}else {
result.setMsg("save error");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
} }

13
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/ChannelReduce.java

@ -40,6 +40,11 @@ public class ChannelReduce {
*/ */
private String platformId; private String platformId;
/**
* 目录Id
*/
private String catalogId;
public String getChannelId() { public String getChannelId() {
return channelId; return channelId;
@ -96,4 +101,12 @@ public class ChannelReduce {
public void setPlatformId(String platformId) { public void setPlatformId(String platformId) {
this.platformId = platformId; this.platformId = platformId;
} }
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
} }

9
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/bean/UpdateChannelParam.java

@ -4,6 +4,7 @@ import java.util.List;
public class UpdateChannelParam { public class UpdateChannelParam {
private String platformId; private String platformId;
private String catalogId;
private List<ChannelReduce> channelReduces; private List<ChannelReduce> channelReduces;
public String getPlatformId() { public String getPlatformId() {
@ -21,4 +22,12 @@ public class UpdateChannelParam {
public void setChannelReduces(List<ChannelReduce> channelReduces) { public void setChannelReduces(List<ChannelReduce> channelReduces) {
this.channelReduces = channelReduces; this.channelReduces = channelReduces;
} }
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
} }

2
src/main/resources/all-application.yml

@ -27,7 +27,7 @@ spring:
datasource: datasource:
# 使用mysql 打开23-28行注释, 删除29-36行 # 使用mysql 打开23-28行注释, 删除29-36行
# name: wvp # name: wvp
# url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true # url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true
# username: # username:
# password: # password:
# type: com.alibaba.druid.pool.DruidDataSource # type: com.alibaba.druid.pool.DruidDataSource

2
src/main/resources/application-dev.yml

@ -15,7 +15,7 @@ spring:
datasource: datasource:
# 使用mysql 打开23-28行注释, 删除29-36行 # 使用mysql 打开23-28行注释, 删除29-36行
# name: wvp # name: wvp
# url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true # url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true
# username: # username:
# password: # password:
# type: com.alibaba.druid.pool.DruidDataSource # type: com.alibaba.druid.pool.DruidDataSource

2
src/main/resources/application-docker.yml

@ -15,7 +15,7 @@ spring:
datasource: datasource:
# 使用mysql 打开23-28行注释, 删除29-36行 # 使用mysql 打开23-28行注释, 删除29-36行
# name: wvp # name: wvp
# url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true # url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true
# username: # username:
# password: # password:
# type: com.alibaba.druid.pool.DruidDataSource # type: com.alibaba.druid.pool.DruidDataSource

BIN
src/main/resources/wvp.sqlite

Binary file not shown.

14470
web_src/package-lock.json

File diff suppressed because it is too large

3
web_src/package.json

@ -10,7 +10,7 @@
"build": "node build/build.js" "build": "node build/build.js"
}, },
"dependencies": { "dependencies": {
"axios": "^0.19.2", "axios": "^0.24.0",
"core-js": "^2.6.5", "core-js": "^2.6.5",
"echarts": "^4.9.0", "echarts": "^4.9.0",
"element-ui": "^2.15.1", "element-ui": "^2.15.1",
@ -21,6 +21,7 @@
"vue-baidu-map": "^0.21.22", "vue-baidu-map": "^0.21.22",
"vue-clipboard2": "^0.3.1", "vue-clipboard2": "^0.3.1",
"vue-clipboards": "^1.3.0", "vue-clipboards": "^1.3.0",
"vue-contextmenujs": "^1.3.13",
"vue-cookies": "^1.7.4", "vue-cookies": "^1.7.4",
"vue-router": "^3.1.6" "vue-router": "^3.1.6"
}, },

2
web_src/src/components/ParentPlatformList.vue

@ -138,7 +138,7 @@ export default {
}); });
}, },
chooseChannel: function(platform) { chooseChannel: function(platform) {
this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, this.initData) this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, this.initData)
}, },
initData: function() { initData: function() {
this.getPlatformList(); this.getPlatformList();

101
web_src/src/components/dialog/catalogEdit.vue

@ -0,0 +1,101 @@
<template>
<div id="catalogEdit" v-loading="isLoging">
<el-dialog
title="节点编辑"
width="40%"
top="2rem"
:append-to-body="true"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
<el-form ref="form" :rules="rules" :model="form" label-width="140px" >
<el-form-item label="节点编号" prop="id" >
<el-input v-model="form.id" :disabled="isEdit"></el-input>
</el-form-item>
<el-form-item label="节点名称" prop="name">
<el-input v-model="form.name" clearable></el-input>
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" @click="onSubmit" >确认</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: "catalogEdit",
computed: {},
props: ['platformId'],
created() {},
data() {
return {
submitCallback: null,
showDialog: false,
isLoging: false,
isEdit: false,
form: {
id: null,
name: null,
platformId: null,
parentId: null,
},
rules: {
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
id: [{ required: true, message: "请输入id", trigger: "blur" }]
},
};
},
methods: {
openDialog: function (isEdit, id, name, parentId, callback) {
console.log("parentId: " + parentId)
this.isEdit = isEdit;
this.form.id = id;
this.form.name = name;
this.form.platformId = this.platformId;
this.form.parentId = parentId;
this.showDialog = true;
this.submitCallback = callback;
},
onSubmit: function () {
console.log("onSubmit");
console.log(this.form);
this.$axios({
method:"post",
url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
data: this.form
})
.then((res)=> {
if (res.data.code === 0) {
console.log("添加/修改成功")
if (this.submitCallback)this.submitCallback()
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
this.close();
})
.catch((error)=> {
console.log(error);
});
},
close: function () {
this.showDialog = false;
this.$refs.form.resetFields();
},
},
};
</script>

65
web_src/src/components/dialog/chooseChannel.vue

@ -1,25 +1,40 @@
<template> <template>
<div id="chooseChannel" v-loading="isLoging"> <div id="chooseChannel" v-loading="isLoging">
<el-dialog title="选择通道" v-if="showDialog" top="2rem" width="70%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()"> <el-dialog title="选择通道" v-if="showDialog" top="2rem" width="90%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()">
<el-tabs v-model="tabActiveName" > <el-row>
<el-tab-pane label="国标通道" name="gbChannel"> <el-col :span="10">
<el-tabs v-model="catalogTabActiveName" >
<el-tab-pane label="目录结构" name="catalog">
<el-container> <el-container>
<el-main style="background-color: #FFF;"> <el-main style="background-color: #FFF;">
<chooseChannelForGb :platformId=platformId ></chooseChannelForGb> <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange"></chooseChannelForCatalog>
</el-main> </el-main>
</el-container> </el-container>
</el-tab-pane>
</el-tabs>
</el-col>
<el-col :span="14">
<el-tabs v-model="tabActiveName" @tab-click="tabClick">
<el-tab-pane label="国标通道" name="gbChannel">
<el-container>
<el-main style="background-color: #FFF;">
<chooseChannelForGb ref="chooseChannelForGb" :platformId=platformId :updateChoosedCallback="updateChooseChannelCallback"></chooseChannelForGb>
</el-main>
</el-container>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="直播流通道" name="streamchannel"> <el-tab-pane label="直播流通道" name="streamchannel">
<el-container> <el-container>
<el-main style="background-color: #FFF;"> <el-main style="background-color: #FFF;">
<chooseChannelFoStream :platformId=platformId ></chooseChannelFoStream> <chooseChannelFoStream ref="chooseChannelFoStream" :platformId=platformId :updateChoosedCallback="updateChooseChannelCallback"></chooseChannelFoStream>
</el-main> </el-main>
</el-container> </el-container>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</el-col>
</el-row>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
@ -27,12 +42,14 @@
<script> <script>
import chooseChannelForGb from '../dialog/chooseChannelForGb.vue' import chooseChannelForGb from '../dialog/chooseChannelForGb.vue'
import chooseChannelFoStream from '../dialog/chooseChannelForStream.vue' import chooseChannelFoStream from '../dialog/chooseChannelForStream.vue'
import chooseChannelForCatalog from '../dialog/chooseChannelForCatalog.vue'
export default { export default {
name: 'chooseChannel', name: 'chooseChannel',
props: {}, props: {},
components: { components: {
chooseChannelForGb, chooseChannelForGb,
chooseChannelFoStream, chooseChannelFoStream,
chooseChannelForCatalog,
}, },
computed: { computed: {
// getPlayerShared: function () { // getPlayerShared: function () {
@ -47,20 +64,35 @@ export default {
return { return {
isLoging: false, isLoging: false,
tabActiveName: "gbChannel", tabActiveName: "gbChannel",
catalogTabActiveName: "catalog",
platformId: "", platformId: "",
isLoging: false, catalogId: "",
platformName: "",
defaultCatalogId: "",
showDialog: false, showDialog: false,
chooseData: {} chooseData: {}
}; };
}, },
methods: { methods: {
openDialog: function (platformId, closeCallback) { openDialog(platformId, platformName, defaultCatalogId, closeCallback) {
console.log(platformId)
this.platformId = platformId this.platformId = platformId
this.platformName = platformName
this.defaultCatalogId = defaultCatalogId
this.showDialog = true this.showDialog = true
this.closeCallback = closeCallback this.closeCallback = closeCallback
}, },
tabClick (tab, event){
console.log(tab.label)
if (tab.label === "gbChannel") {
this.$refs.chooseChannelForGb.catalogIdChange(this.catalogId);
this.$refs.chooseChannelForGb.initData();
}else {
this.$refs.chooseChannelFoStream.catalogIdChange(this.catalogId);
this.$refs.chooseChannelFoStream.initData();
}
},
close: function() { close: function() {
this.closeCallback() this.closeCallback()
}, },
@ -88,6 +120,21 @@ export default {
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
},
catalogIdChange: function (id) {
console.log("中间模块收到: " + id)
this.catalogId = id;
if (this.tabActiveName === "gbChannel") {
this.$refs.chooseChannelForGb.catalogIdChange(id);
}else {
this.$refs.chooseChannelFoStream.catalogIdChange(id);
}
},
updateChooseChannelCallback (id, nodeIds){
console.log("中间模块收到选择通道变化: " + id)
console.log("中间模块收到选择通道变化: " + nodeIds)
console.log("中间模块收到选择通道变化: " + typeof (nodeIds))
this.$refs.chooseChannelForCatalog.refreshCatalogById(id, nodeIds)
} }
} }
}; };

311
web_src/src/components/dialog/chooseChannelForCatalog.vue

@ -0,0 +1,311 @@
<template>
<div id="chooseChannelForCatalog" >
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
<el-tree class="el-scrollbar"
ref="tree"
id="catalogTree"
empty-text="未知节点"
node-key="id"
default-expand-all
:highlight-current="true"
:expand-on-click-node="false"
:props="props"
:load="loadNode"
@node-contextmenu="contextmenuEventHandler"
lazy>
<span class="custom-tree-node" slot-scope="{ node, data }" style="width: 100%">
<el-radio v-if="node.data.type === 0" style="margin-right: 0" v-model="chooseId" :label="node.data.id">{{''}}</el-radio>
<span v-if="node.data.type === 0 && node.level === 1" class="el-icon-s-home"></span>
<span v-if="node.data.type === 0 && node.level > 1" class="el-icon-folder-opened"></span>
<span v-if="node.data.type === 1" class="iconfont icon-shexiangtou"></span>
<span v-if="node.data.type === 2" class="iconfont icon-zhibo"></span>
<span style="padding-left: 1px">{{ node.label }}</span>
<span>
<i style="margin-left: 5rem; color: #9d9d9d; padding-right: 20px" v-if="node.data.id === defaultCatalogId">默认</i>
</span>
</span>
</el-tree>
</div>
<catalogEdit ref="catalogEdit" :platformId="platformId"></catalogEdit>
</div>
</template>
<script>
import catalogEdit from './catalogEdit.vue'
export default {
name: 'chooseChannelForCatalog',
props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange'],
created() {
this.initData();
setTimeout(()=>{
if (this.catalogIdChange)this.catalogIdChange(this.defaultCatalogId);
}, 100)
},
components: {
catalogEdit,
},
data() {
return {
props: {
label: 'name',
children: 'children',
isLeaf: 'leaf'
},
chooseNode: null,
chooseId: this.defaultCatalogId,
catalogTree: null,
contextmenuShow: false
};
},
watch:{
platformId(newData, oldData){
console.log(newData)
this.initData()
},
chooseId(newData, oldData){
console.log("发送: " + newData)
if (this.catalogIdChange)this.catalogIdChange(newData);
},
},
methods: {
initData: function () {
this.getCatalog();
},
getCatalog: function(parentId, callback) {
let that = this;
this.$axios({
method:"get",
url:`/api/platform/catalog`,
params: {
platformId: that.platformId,
parentId: parentId
}
})
.then((res)=> {
if (res.data.code === 0) {
if (typeof(callback) === 'function') {
callback(res.data.data)
}
//
// if (typeof (this.$refs.tree.setCurrentKey) == "undefined") {
// this.$refs.tree.setCurrentKey(this.defaultCatalogId)
// let data = this.$refs.tree.getCurrentNode()
// if (data != null && data.id === this.defaultCatalogId) {
// this.currentCatalogChange(data, this.$refs.tree.getNode(data.id))
// }
// }
}
})
.catch(function (error) {
console.log(error);
});
},
addCatalog: function (parentId, node){
let that = this;
//
that.$refs.catalogEdit.openDialog(false, null, null, parentId, ()=>{
node.loaded = false
node.expand();
});
},
refreshCatalog: function (node){
node.loaded = false
node.expand();
},
refreshCatalogById: function (id, nodeIds) {
if (id) {
console.log("refreshCatalogById: " + id)
let node = this.$refs.tree.getNode(id);
console.log(node)
this.refreshCatalog(node);
}
if (nodeIds !== null) {
let refreshNode = {}
for (let i = 0; i < nodeIds.length; i++) {
let node = this.$refs.tree.getNode(nodeIds[i]);
refreshNode[node.parent.data.id] = node.parent
}
if (Object.values(refreshNode).length > 0) {
for (let j = 0; j < Object.values(refreshNode).length; j++) {
this.refreshCatalog(Object.values(refreshNode)[j]);
}
}
}
},
editCatalog: function (data, node){
let that = this;
//
that.$refs.catalogEdit.openDialog(true, data.id, data.name, data.parentId, (data)=>{
node.parent.loaded = false
node.parent.expand();
});
},
removeCatalog: function (id, node){
this.$axios({
method:"delete",
url:`/api/platform/catalog/del`,
params: {
id: id,
}
})
.then((res) => {
if (res.data.code === 0) {
console.log("移除成功")
node.parent.loaded = false
node.parent.expand();
}
})
.catch(function (error) {
console.log(error);
});
},
setDefaultCatalog: function (id){
this.$axios({
method:"post",
url:`/api/platform/catalog/default/update`,
params: {
platformId: this.platformId,
catalogId: id,
}
})
.then((res)=> {
if (res.data.code === 0) {
this.defaultCatalogId = id;
}
})
.catch(function (error) {
console.log(error);
});
},
loadNode: function(node, resolve){
if (node.level === 0) {
resolve([{
name: this.platformName,
id: this.platformId,
type: 0
}]);
}
if (node.level >= 1){
this.getCatalog(node.data.id, resolve)
}
},
contextmenuEventHandler: function (event,data,node,element){
if (node.data.type !== 0) {
data.parentId = node.parent.data.id;
this.$contextmenu({
items: [
{
label: "移除通道",
icon: "el-icon-delete",
disabled: false,
onClick: () => {
this.$axios({
method:"delete",
url:"/api/platform/catalog/relation/del",
data: data
}).then((res)=>{
console.log("移除成功")
node.parent.loaded = false
node.parent.expand();
}).catch(function (error) {
console.log(error);
});
}
}
],
event, //
customClass: "custom-class", // class
zIndex: 3000, // z-index
});
}else {
this.$contextmenu({
items: [
{
label: "刷新节点",
icon: "el-icon-refresh",
disabled: false,
onClick: () => {
this.refreshCatalog(node);
}
},
{
label: "新建节点",
icon: "el-icon-plus",
disabled: false,
onClick: () => {
this.addCatalog(data.id, node);
}
},
{
label: "修改节点",
icon: "el-icon-edit",
disabled: node.level === 1,
onClick: () => {
this.editCatalog(data, node);
}
},
{
label: "删除节点",
icon: "el-icon-delete",
disabled: node.level === 1,
divided: true,
onClick: () => {
this.removeCatalog(data.id, node)
}
},
{
label: "设为默认",
icon: "el-icon-folder-checked",
disabled: node.data.id === this.defaultCatalogId,
onClick: () => {
this.setDefaultCatalog(data.id)
},
},
// {
// label: "",
// icon: "el-icon-download",
// disabled: false,
// children: [
// {
// label: "",
// onClick: () => {
//
// },
// },
// {
// label: "",
// onClick: () => {
//
// },
// }
// ]
// },
],
event, //
customClass: "custom-class", // class
zIndex: 3000, // z-index
});
}
return false;
},
}
};
</script>
<style>
#catalogTree{
display: inline-block;
}
</style>

55
web_src/src/components/dialog/chooseChannelForGb.vue

@ -21,9 +21,9 @@
<el-option label="离线" value="false"></el-option> <el-option label="离线" value="false"></el-option>
</el-select> </el-select>
<el-checkbox @change="shareAllCheckedChanage">全部共享</el-checkbox> <el-checkbox @change="shareAllCheckedChange">全部共享</el-checkbox>
</div> </div>
<el-table ref="gbChannelsTable" :data="gbChannels" border style="width: 100%" @selection-change="checkedChanage" > <el-table ref="gbChannelsTable" :data="gbChannels" border style="width: 100%" @selection-change="checkedChange" >
<el-table-column type="selection" width="55" align="center" fixed > </el-table-column> <el-table-column type="selection" width="55" align="center" fixed > </el-table-column>
<el-table-column prop="channelId" label="通道编号" width="210"> <el-table-column prop="channelId" label="通道编号" width="210">
</el-table-column> </el-table-column>
@ -49,7 +49,6 @@
<script> <script>
export default { export default {
name: 'chooseChannelForGb', name: 'chooseChannelForGb',
props: {},
computed: { computed: {
// getPlayerShared: function () { // getPlayerShared: function () {
// return { // return {
@ -59,7 +58,7 @@ export default {
// }; // };
// } // }
}, },
props: ['platformId'], props: ['platformId', 'updateChoosedCallback'],
created() { created() {
this.initData(); this.initData();
}, },
@ -71,6 +70,7 @@ export default {
channelType: "", channelType: "",
online: "", online: "",
choosed: "", choosed: "",
catalogId: null,
currentPage: 1, currentPage: 1,
count: 10, count: 10,
total: 0, total: 0,
@ -97,28 +97,28 @@ export default {
this.count = val; this.count = val;
console.log(val) console.log(val)
this.initData(); this.initData();
}, },
rowcheckedChanage: function (val, row) { rowcheckedChange: function (val, row) {
console.log(val) console.log(val)
console.log(row) console.log(row)
}, },
checkedChanage: function (val) { // selectDisable: function (){
var that = this; // if (this.catalogId == null) {
// return false;
// }
// },
checkedChange: function (val) {
let that = this;
if (!that.eventEnanle) { if (!that.eventEnanle) {
return; return;
} }
var tabelData = JSON.parse(JSON.stringify(this.$refs.gbChannelsTable.data)); let newData = {};
console.log("checkedChanage") let addData = [];
console.log(val) let delData = [];
var newData = {};
var addData = [];
var delData = [];
if (val.length > 0) { if (val.length > 0) {
for (let i = 0; i < val.length; i++) { for (let i = 0; i < val.length; i++) {
const element = val[i]; const element = val[i];
var key = element.deviceId + "_" + element.channelId; let key = element.deviceId + "_" + element.channelId;
newData[key] = element; newData[key] = element;
if (!!!that.gbChoosechannel[key]){ if (!!!that.gbChoosechannel[key]){
addData.push(element) addData.push(element)
@ -127,7 +127,7 @@ export default {
} }
} }
var oldKeys = Object.keys(that.gbChoosechannel); let oldKeys = Object.keys(that.gbChoosechannel);
if (oldKeys.length > 0) { if (oldKeys.length > 0) {
for (let i = 0; i < oldKeys.length; i++) { for (let i = 0; i < oldKeys.length; i++) {
const key = oldKeys[i]; const key = oldKeys[i];
@ -136,7 +136,7 @@ export default {
} }
}else{ }else{
var oldKeys = Object.keys(that.gbChoosechannel); let oldKeys = Object.keys(that.gbChoosechannel);
if (oldKeys.length > 0) { if (oldKeys.length > 0) {
for (let i = 0; i < oldKeys.length; i++) { for (let i = 0; i < oldKeys.length; i++) {
const key = oldKeys[i]; const key = oldKeys[i];
@ -152,15 +152,17 @@ export default {
url:"/api/platform/update_channel_for_gb", url:"/api/platform/update_channel_for_gb",
data:{ data:{
platformId: that.platformId, platformId: that.platformId,
channelReduces: addData channelReduces: addData,
catalogId: that.catalogId
} }
}).then((res)=>{ }).then((res)=>{
console.log("保存成功") console.log("保存成功")
if(that.updateChoosedCallback)that.updateChoosedCallback(that.catalogId)
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
} }
if (Object.keys(delData).length >0) { if (delData.length >0) {
that.$axios({ that.$axios({
method:"delete", method:"delete",
url:"/api/platform/del_channel_for_gb", url:"/api/platform/del_channel_for_gb",
@ -170,13 +172,18 @@ export default {
} }
}).then((res)=>{ }).then((res)=>{
console.log("移除成功") console.log("移除成功")
let nodeIds = new Array();
for (let i = 0; i < delData.length; i++) {
nodeIds.push(delData[i].channelId)
}
if(that.updateChoosedCallback)that.updateChoosedCallback(null, nodeIds)
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
} }
}, },
shareAllCheckedChanage: function (val) { shareAllCheckedChange: function (val) {
this.chooseChanage(null, val) this.chooseChanage(null, val)
}, },
getChannelList: function () { getChannelList: function () {
@ -215,7 +222,7 @@ export default {
} }
} }
that.eventEnanle = true; that.eventEnanle = true;
// that.checkedChanage(chooseGBS) // that.checkedChange(chooseGBS)
}) })
console.log(that.gbChoosechannel) console.log(that.gbChoosechannel)
}) })
@ -230,6 +237,10 @@ export default {
handleGBSelectionChange: function() { handleGBSelectionChange: function() {
this.initData(); this.initData();
}, },
catalogIdChange: function(id) {
this.catalogId = id;
console.log("通道选择模块收到: " + id)
},
} }
}; };
</script> </script>

11
web_src/src/components/dialog/chooseChannelForStream.vue

@ -27,7 +27,6 @@
<script> <script>
export default { export default {
name: 'chooseChannelFoStream', name: 'chooseChannelFoStream',
props: {},
computed: { computed: {
// getPlayerShared: function () { // getPlayerShared: function () {
// return { // return {
@ -37,7 +36,7 @@ export default {
// }; // };
// } // }
}, },
props: ['platformId'], props: ['platformId', 'updateChoosedCallback'],
created() { created() {
this.initData(); this.initData();
}, },
@ -49,6 +48,7 @@ export default {
channelType: "", channelType: "",
online: "", online: "",
choosed: "", choosed: "",
catalogId: null,
currentPage: 1, currentPage: 1,
count: 10, count: 10,
total: 0, total: 0,
@ -131,10 +131,12 @@ export default {
url:"/api/gbStream/add", url:"/api/gbStream/add",
data:{ data:{
platformId: that.platformId, platformId: that.platformId,
catalogId: that.catalogId,
gbStreams: addData, gbStreams: addData,
} }
}).then((res)=>{ }).then((res)=>{
console.log("保存成功") console.log("保存成功")
if(this.updateChoosedCallback)this.updateChoosedCallback(this.catalogId)
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
@ -149,6 +151,7 @@ export default {
} }
}).then((res)=>{ }).then((res)=>{
console.log("移除成功") console.log("移除成功")
if(this.updateChoosedCallback)this.updateChoosedCallback(this.catalogId)
}).catch(function (error) { }).catch(function (error) {
console.log(error); console.log(error);
}); });
@ -207,6 +210,10 @@ export default {
handleGBSelectionChange: function() { handleGBSelectionChange: function() {
this.initData(); this.initData();
}, },
catalogIdChange: function(id) {
this.catalogId = id;
console.log("直播通道选择模块收到: " + id)
},
} }
}; };
</script> </script>

1
web_src/src/components/dialog/platformEdit.vue

@ -196,6 +196,7 @@ export default {
this.platform.transport = platform.transport; this.platform.transport = platform.transport;
this.platform.characterSet = platform.characterSet; this.platform.characterSet = platform.characterSet;
this.platform.shareAllLiveStream = platform.shareAllLiveStream; this.platform.shareAllLiveStream = platform.shareAllLiveStream;
this.platform.catalogId = platform.catalogId;
this.onSubmit_text = "保存"; this.onSubmit_text = "保存";
} }
this.showDialog = true; this.showDialog = true;

2
web_src/src/main.js

@ -12,6 +12,7 @@ import VueClipboard from 'vue-clipboard2';
import { Notification } from 'element-ui'; import { Notification } from 'element-ui';
import Fingerprint2 from 'fingerprintjs2'; import Fingerprint2 from 'fingerprintjs2';
import VueClipboards from 'vue-clipboards'; import VueClipboards from 'vue-clipboards';
import Contextmenu from "vue-contextmenujs"
// 生成唯一ID // 生成唯一ID
@ -37,6 +38,7 @@ Vue.use(VueCookies);
Vue.use(VueClipboards); Vue.use(VueClipboards);
Vue.prototype.$axios = axios; Vue.prototype.$axios = axios;
Vue.prototype.$notify = Notification; Vue.prototype.$notify = Notification;
Vue.use(Contextmenu);
axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : ""; axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : "";

26
web_src/static/css/iconfont.css

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 1291092 */ font-family: "iconfont"; /* Project id 1291092 */
src: url('iconfont.woff2?t=1637741914969') format('woff2'), src: url('iconfont.woff2?t=1640922722742') format('woff2'),
url('iconfont.woff?t=1637741914969') format('woff'), url('iconfont.woff?t=1640922722742') format('woff'),
url('iconfont.ttf?t=1637741914969') format('truetype'); url('iconfont.ttf?t=1640922722742') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,22 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-wxbzhuye:before {
content: "\e7d1";
}
.icon-mulu:before {
content: "\e7d2";
}
.icon-zhibo:before {
content: "\e8c1";
}
.icon-shexiangtou:before {
content: "\e7d3";
}
.icon-suoxiao:before { .icon-suoxiao:before {
content: "\e79a"; content: "\e79a";
} }
@ -49,7 +65,7 @@
content: "\e7a2"; content: "\e7a2";
} }
.icon-kuaijin:before { .icon-houtui:before {
content: "\e7a3"; content: "\e7a3";
} }
@ -57,7 +73,7 @@
content: "\e7a4"; content: "\e7a4";
} }
.icon-kuaitui:before { .icon-kuaijin:before {
content: "\e7a5"; content: "\e7a5";
} }

BIN
web_src/static/css/iconfont.woff2

Binary file not shown.
Loading…
Cancel
Save